mirror of
https://invent.kde.org/frameworks/kimageformats.git
synced 2025-07-15 11:14:18 -04:00
Compare commits
8 Commits
Author | SHA1 | Date | |
---|---|---|---|
5b2c190823 | |||
1b94554323 | |||
c2c12b1d7e | |||
c169296fbf | |||
29aec82e67 | |||
95ee381195 | |||
8e5951471d | |||
0710bc65f6 |
@ -1,9 +1,11 @@
|
|||||||
cmake_minimum_required(VERSION 3.16)
|
cmake_minimum_required(VERSION 3.16)
|
||||||
|
|
||||||
project(KImageFormats)
|
set(KF_VERSION "6.2.0") # handled by release scripts
|
||||||
|
set(KF_DEP_VERSION "6.2.0") # handled by release scripts
|
||||||
|
project(KImageFormats VERSION ${KF_VERSION})
|
||||||
|
|
||||||
include(FeatureSummary)
|
include(FeatureSummary)
|
||||||
find_package(ECM 6.0.0 NO_MODULE)
|
find_package(ECM 6.2.0 NO_MODULE)
|
||||||
set_package_properties(ECM PROPERTIES TYPE REQUIRED DESCRIPTION "Extra CMake Modules." URL "https://commits.kde.org/extra-cmake-modules")
|
set_package_properties(ECM PROPERTIES TYPE REQUIRED DESCRIPTION "Extra CMake Modules." URL "https://commits.kde.org/extra-cmake-modules")
|
||||||
feature_summary(WHAT REQUIRED_PACKAGES_NOT_FOUND FATAL_ON_MISSING_REQUIRED_PACKAGES)
|
feature_summary(WHAT REQUIRED_PACKAGES_NOT_FOUND FATAL_ON_MISSING_REQUIRED_PACKAGES)
|
||||||
|
|
||||||
@ -22,7 +24,7 @@ include(FindPkgConfig)
|
|||||||
set(REQUIRED_QT_VERSION 6.5.0)
|
set(REQUIRED_QT_VERSION 6.5.0)
|
||||||
find_package(Qt6Gui ${REQUIRED_QT_VERSION} REQUIRED NO_MODULE)
|
find_package(Qt6Gui ${REQUIRED_QT_VERSION} REQUIRED NO_MODULE)
|
||||||
|
|
||||||
find_package(KF6Archive)
|
find_package(KF6Archive ${KF_DEP_VERSION})
|
||||||
set_package_properties(KF6Archive PROPERTIES
|
set_package_properties(KF6Archive PROPERTIES
|
||||||
TYPE OPTIONAL
|
TYPE OPTIONAL
|
||||||
PURPOSE "Required for the QImage plugin for Krita and OpenRaster images"
|
PURPOSE "Required for the QImage plugin for Krita and OpenRaster images"
|
||||||
|
Binary file not shown.
Before Width: | Height: | Size: 91 KiB After Width: | Height: | Size: 93 KiB |
Binary file not shown.
Before Width: | Height: | Size: 91 KiB After Width: | Height: | Size: 93 KiB |
@ -88,10 +88,6 @@ static QDataStream &operator>>(QDataStream &s, TgaHeader &head)
|
|||||||
s >> head.height;
|
s >> head.height;
|
||||||
s >> head.pixel_size;
|
s >> head.pixel_size;
|
||||||
s >> head.flags;
|
s >> head.flags;
|
||||||
/*qDebug() << "id_length: " << head.id_length << " - colormap_type: " << head.colormap_type << " - image_type: " << head.image_type;
|
|
||||||
qDebug() << "colormap_index: " << head.colormap_index << " - colormap_length: " << head.colormap_length << " - colormap_size: " << head.colormap_size;
|
|
||||||
qDebug() << "x_origin: " << head.x_origin << " - y_origin: " << head.y_origin << " - width:" << head.width << " - height:" << head.height << " - pixelsize:
|
|
||||||
" << head.pixel_size << " - flags: " << head.flags;*/
|
|
||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -117,6 +113,10 @@ static bool IsSupported(const TgaHeader &head)
|
|||||||
if (head.pixel_size != 8 && head.pixel_size != 16 && head.pixel_size != 24 && head.pixel_size != 32) {
|
if (head.pixel_size != 8 && head.pixel_size != 16 && head.pixel_size != 24 && head.pixel_size != 32) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
// If the colormap_type field is set to zero, indicating that no color map exists, then colormap_size, colormap_index and colormap_length should be set to zero.
|
||||||
|
if (head.colormap_type == 0 && (head.colormap_size != 0 || head.colormap_index != 0 || head.colormap_length != 0)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -170,10 +170,57 @@ struct TgaHeaderInfo {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static QImage::Format imageFormat(const TgaHeader &head)
|
||||||
|
{
|
||||||
|
auto format = QImage::Format_Invalid;
|
||||||
|
if (IsSupported(head)) {
|
||||||
|
// Bits 0-3 are the numbers of alpha bits (can be zero!)
|
||||||
|
const int numAlphaBits = head.flags & 0xf;
|
||||||
|
// However alpha exists only in the 32 bit format.
|
||||||
|
if ((head.pixel_size == 32) && (head.flags & 0xf)) {
|
||||||
|
if (numAlphaBits <= 8) {
|
||||||
|
format = QImage::Format_ARGB32;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
format = QImage::Format_RGB32;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return format;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief peekHeader
|
||||||
|
* Reads the header but does not change the position in the device.
|
||||||
|
*/
|
||||||
|
static bool peekHeader(QIODevice *device, TgaHeader &header)
|
||||||
|
{
|
||||||
|
qint64 oldPos = device->pos();
|
||||||
|
QByteArray head = device->read(TgaHeader::SIZE);
|
||||||
|
int readBytes = head.size();
|
||||||
|
|
||||||
|
if (device->isSequential()) {
|
||||||
|
for (int pos = readBytes - 1; pos >= 0; --pos) {
|
||||||
|
device->ungetChar(head[pos]);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
device->seek(oldPos);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (readBytes < TgaHeader::SIZE) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
QDataStream stream(head);
|
||||||
|
stream.setByteOrder(QDataStream::LittleEndian);
|
||||||
|
stream >> header;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
static bool LoadTGA(QDataStream &s, const TgaHeader &tga, QImage &img)
|
static bool LoadTGA(QDataStream &s, const TgaHeader &tga, QImage &img)
|
||||||
{
|
{
|
||||||
// Create image.
|
img = imageAlloc(tga.width, tga.height, imageFormat(tga));
|
||||||
img = imageAlloc(tga.width, tga.height, QImage::Format_RGB32);
|
|
||||||
if (img.isNull()) {
|
if (img.isNull()) {
|
||||||
qWarning() << "Failed to allocate image, invalid dimensions?" << QSize(tga.width, tga.height);
|
qWarning() << "Failed to allocate image, invalid dimensions?" << QSize(tga.width, tga.height);
|
||||||
return false;
|
return false;
|
||||||
@ -181,21 +228,7 @@ static bool LoadTGA(QDataStream &s, const TgaHeader &tga, QImage &img)
|
|||||||
|
|
||||||
TgaHeaderInfo info(tga);
|
TgaHeaderInfo info(tga);
|
||||||
|
|
||||||
// Bits 0-3 are the numbers of alpha bits (can be zero!)
|
|
||||||
const int numAlphaBits = tga.flags & 0xf;
|
const int numAlphaBits = tga.flags & 0xf;
|
||||||
// However alpha exists only in the 32 bit format.
|
|
||||||
if ((tga.pixel_size == 32) && (tga.flags & 0xf)) {
|
|
||||||
img = imageAlloc(tga.width, tga.height, QImage::Format_ARGB32);
|
|
||||||
if (img.isNull()) {
|
|
||||||
qWarning() << "Failed to allocate image, invalid dimensions?" << QSize(tga.width, tga.height);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (numAlphaBits > 8) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
uint pixel_size = (tga.pixel_size / 8);
|
uint pixel_size = (tga.pixel_size / 8);
|
||||||
qint64 size = qint64(tga.width) * qint64(tga.height) * pixel_size;
|
qint64 size = qint64(tga.width) * qint64(tga.height) * pixel_size;
|
||||||
|
|
||||||
@ -391,23 +424,25 @@ bool TGAHandler::read(QImage *outImage)
|
|||||||
{
|
{
|
||||||
// qDebug() << "Loading TGA file!";
|
// qDebug() << "Loading TGA file!";
|
||||||
|
|
||||||
QDataStream s(device());
|
auto d = device();
|
||||||
s.setByteOrder(QDataStream::LittleEndian);
|
|
||||||
|
|
||||||
// Read image header.
|
|
||||||
TgaHeader tga;
|
TgaHeader tga;
|
||||||
s >> tga;
|
if (!peekHeader(d, tga) || !IsSupported(tga)) {
|
||||||
s.device()->seek(TgaHeader::SIZE + tga.id_length);
|
|
||||||
|
|
||||||
// Check image file format.
|
|
||||||
if (s.atEnd()) {
|
|
||||||
// qDebug() << "This TGA file is not valid.";
|
// qDebug() << "This TGA file is not valid.";
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check supported file types.
|
if (d->isSequential()) {
|
||||||
if (!IsSupported(tga)) {
|
d->read(TgaHeader::SIZE + tga.id_length);
|
||||||
// qDebug() << "This TGA file is not supported.";
|
} else {
|
||||||
|
d->seek(TgaHeader::SIZE + tga.id_length);
|
||||||
|
}
|
||||||
|
|
||||||
|
QDataStream s(d);
|
||||||
|
s.setByteOrder(QDataStream::LittleEndian);
|
||||||
|
|
||||||
|
// Check image file format.
|
||||||
|
if (s.atEnd()) {
|
||||||
|
// qDebug() << "This TGA file is not valid.";
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -468,6 +503,42 @@ bool TGAHandler::write(const QImage &image)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool TGAHandler::supportsOption(ImageOption option) const
|
||||||
|
{
|
||||||
|
if (option == QImageIOHandler::Size) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (option == QImageIOHandler::ImageFormat) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
QVariant TGAHandler::option(ImageOption option) const
|
||||||
|
{
|
||||||
|
QVariant v;
|
||||||
|
|
||||||
|
if (option == QImageIOHandler::Size) {
|
||||||
|
if (auto d = device()) {
|
||||||
|
TgaHeader header;
|
||||||
|
if (peekHeader(d, header) && IsSupported(header)) {
|
||||||
|
v = QVariant::fromValue(QSize(header.width, header.height));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (option == QImageIOHandler::ImageFormat) {
|
||||||
|
if (auto d = device()) {
|
||||||
|
TgaHeader header;
|
||||||
|
if (peekHeader(d, header) && IsSupported(header)) {
|
||||||
|
v = QVariant::fromValue(imageFormat(header));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return v;
|
||||||
|
}
|
||||||
|
|
||||||
bool TGAHandler::canRead(QIODevice *device)
|
bool TGAHandler::canRead(QIODevice *device)
|
||||||
{
|
{
|
||||||
if (!device) {
|
if (!device) {
|
||||||
@ -491,10 +562,12 @@ bool TGAHandler::canRead(QIODevice *device)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
QDataStream stream(head);
|
|
||||||
stream.setByteOrder(QDataStream::LittleEndian);
|
|
||||||
TgaHeader tga;
|
TgaHeader tga;
|
||||||
stream >> tga;
|
if (!peekHeader(device, tga)) {
|
||||||
|
qWarning("TGAHandler::canRead() error while reading the header");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
return IsSupported(tga);
|
return IsSupported(tga);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -19,6 +19,9 @@ public:
|
|||||||
bool read(QImage *image) override;
|
bool read(QImage *image) override;
|
||||||
bool write(const QImage &image) override;
|
bool write(const QImage &image) override;
|
||||||
|
|
||||||
|
bool supportsOption(QImageIOHandler::ImageOption option) const override;
|
||||||
|
QVariant option(QImageIOHandler::ImageOption option) const override;
|
||||||
|
|
||||||
static bool canRead(QIODevice *device);
|
static bool canRead(QIODevice *device);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -963,7 +963,7 @@ bool XCFImageFormat::loadImageProperties(QDataStream &xcf_io, XCFImage &xcf_imag
|
|||||||
#if QT_VERSION < QT_VERSION_CHECK(6, 7, 0)
|
#if QT_VERSION < QT_VERSION_CHECK(6, 7, 0)
|
||||||
quint32 size;
|
quint32 size;
|
||||||
#else
|
#else
|
||||||
qsizetype size;
|
qint64 size;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
property.readBytes(tag, size);
|
property.readBytes(tag, size);
|
||||||
|
Reference in New Issue
Block a user