mirror of
https://invent.kde.org/frameworks/kimageformats.git
synced 2025-07-14 19:04:17 -04:00
Compare commits
11 Commits
Author | SHA1 | Date | |
---|---|---|---|
a6ec69d276 | |||
02cbf3889f | |||
6cf05cf305 | |||
938b8126b5 | |||
d36c191351 | |||
1acb5a6177 | |||
f2ccbf1724 | |||
5825c83235 | |||
b742cb7cc7 | |||
2e6eeebdfc | |||
db0b5d571a |
@ -5,7 +5,7 @@ project(KImageFormats)
|
|||||||
set (CMAKE_CXX_STANDARD 14)
|
set (CMAKE_CXX_STANDARD 14)
|
||||||
|
|
||||||
include(FeatureSummary)
|
include(FeatureSummary)
|
||||||
find_package(ECM 5.75.0 NO_MODULE)
|
find_package(ECM 5.77.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)
|
||||||
|
|
||||||
@ -19,7 +19,7 @@ include(KDECMakeSettings)
|
|||||||
|
|
||||||
include(CheckIncludeFiles)
|
include(CheckIncludeFiles)
|
||||||
|
|
||||||
set(REQUIRED_QT_VERSION 5.12.0)
|
set(REQUIRED_QT_VERSION 5.13.0)
|
||||||
find_package(Qt5Gui ${REQUIRED_QT_VERSION} REQUIRED NO_MODULE)
|
find_package(Qt5Gui ${REQUIRED_QT_VERSION} REQUIRED NO_MODULE)
|
||||||
|
|
||||||
find_package(KF5Archive)
|
find_package(KF5Archive)
|
||||||
@ -50,8 +50,8 @@ set_package_properties(OpenEXR PROPERTIES
|
|||||||
add_definitions(-DQT_NO_FOREACH)
|
add_definitions(-DQT_NO_FOREACH)
|
||||||
# 050d00 (5.13) triggers a BIC in qimageiohandler.h, in Qt 5.13, so do not enable that until we can require 5.14
|
# 050d00 (5.13) triggers a BIC in qimageiohandler.h, in Qt 5.13, so do not enable that until we can require 5.14
|
||||||
# https://codereview.qt-project.org/c/qt/qtbase/+/279215
|
# https://codereview.qt-project.org/c/qt/qtbase/+/279215
|
||||||
add_definitions(-DQT_DISABLE_DEPRECATED_BEFORE=0x050c00)
|
add_definitions(-DQT_DISABLE_DEPRECATED_BEFORE=0x050d00)
|
||||||
add_definitions(-DKF_DISABLE_DEPRECATED_BEFORE_AND_AT=0x054900)
|
add_definitions(-DKF_DISABLE_DEPRECATED_BEFORE_AND_AT=0x054B00)
|
||||||
add_subdirectory(src)
|
add_subdirectory(src)
|
||||||
if (BUILD_TESTING)
|
if (BUILD_TESTING)
|
||||||
add_subdirectory(autotests)
|
add_subdirectory(autotests)
|
||||||
|
BIN
autotests/read/psd/16bit-rle.png
Normal file
BIN
autotests/read/psd/16bit-rle.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 78 KiB |
BIN
autotests/read/psd/16bit-rle.psd
Normal file
BIN
autotests/read/psd/16bit-rle.psd
Normal file
Binary file not shown.
BIN
autotests/read/psd/argb16-raw-affinityphoto-1.8.5.png
Normal file
BIN
autotests/read/psd/argb16-raw-affinityphoto-1.8.5.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 983 B |
BIN
autotests/read/psd/argb16-raw-affinityphoto-1.8.5.psd
Normal file
BIN
autotests/read/psd/argb16-raw-affinityphoto-1.8.5.psd
Normal file
Binary file not shown.
BIN
autotests/read/psd/rgb16-raw-affinityphoto-1.8.5.png
Normal file
BIN
autotests/read/psd/rgb16-raw-affinityphoto-1.8.5.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 827 B |
BIN
autotests/read/psd/rgb16-raw-affinityphoto-1.8.5.psd
Normal file
BIN
autotests/read/psd/rgb16-raw-affinityphoto-1.8.5.psd
Normal file
Binary file not shown.
@ -36,14 +36,17 @@ static void writeImageData(const char *name, const QString &filename, const QIma
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// allow each byte to be different by up to 1, to allow for rounding errors
|
template<class Trait>
|
||||||
static bool fuzzyeq(const QImage &im1, const QImage &im2, uchar fuzziness)
|
static bool fuzzyeq(const QImage &im1, const QImage &im2, uchar fuzziness)
|
||||||
{
|
{
|
||||||
|
Q_ASSERT(im1.format() == im2.format());
|
||||||
|
Q_ASSERT(im1.depth() == 24 || im1.depth() == 32 || im1.depth() == 64);
|
||||||
|
|
||||||
const int height = im1.height();
|
const int height = im1.height();
|
||||||
const int width = im1.width();
|
const int width = im1.width();
|
||||||
for (int i = 0; i < height; ++i) {
|
for (int i = 0; i < height; ++i) {
|
||||||
const uchar *line1 = im1.scanLine(i);
|
const Trait *line1 = reinterpret_cast<const Trait*>(im1.scanLine(i));
|
||||||
const uchar *line2 = im2.scanLine(i);
|
const Trait *line2 = reinterpret_cast<const Trait*>(im2.scanLine(i));
|
||||||
for (int j = 0; j < width; ++j) {
|
for (int j = 0; j < width; ++j) {
|
||||||
if (line1[j] > line2[j]) {
|
if (line1[j] > line2[j]) {
|
||||||
if (line1[j] - line2[j] > fuzziness)
|
if (line1[j] - line2[j] > fuzziness)
|
||||||
@ -57,6 +60,30 @@ static bool fuzzyeq(const QImage &im1, const QImage &im2, uchar fuzziness)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// allow each byte to be different by up to 1, to allow for rounding errors
|
||||||
|
static bool fuzzyeq(const QImage &im1, const QImage &im2, uchar fuzziness)
|
||||||
|
{
|
||||||
|
return (im1.depth() == 64) ? fuzzyeq<quint16>(im1, im2, fuzziness)
|
||||||
|
: fuzzyeq<quint8>(im1, im2, fuzziness);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Returns the original format if we support, or returns
|
||||||
|
// format which we preferred to use for `fuzzyeq()`.
|
||||||
|
// We do only support formats with 8-bits/16-bits pre pixel.
|
||||||
|
// If that changed, don't forget to update `fuzzyeq()` too
|
||||||
|
static QImage::Format preferredFormat(QImage::Format fmt)
|
||||||
|
{
|
||||||
|
switch (fmt) {
|
||||||
|
case QImage::Format_RGB32:
|
||||||
|
case QImage::Format_ARGB32:
|
||||||
|
case QImage::Format_RGBX64:
|
||||||
|
case QImage::Format_RGBA64:
|
||||||
|
return fmt;
|
||||||
|
default:
|
||||||
|
return QImage::Format_ARGB32;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
int main(int argc, char ** argv)
|
int main(int argc, char ** argv)
|
||||||
{
|
{
|
||||||
QCoreApplication app(argc, argv);
|
QCoreApplication app(argc, argv);
|
||||||
@ -168,19 +195,23 @@ int main(int argc, char ** argv)
|
|||||||
<< expImage.height() << "\n";
|
<< expImage.height() << "\n";
|
||||||
++failed;
|
++failed;
|
||||||
} else {
|
} else {
|
||||||
if (inputImage.format() != QImage::Format_ARGB32) {
|
QImage::Format inputFormat = preferredFormat(inputImage.format());
|
||||||
|
QImage::Format expFormat = preferredFormat(expImage.format());
|
||||||
|
QImage::Format cmpFormat = inputFormat == expFormat ? inputFormat : QImage::Format_ARGB32;
|
||||||
|
|
||||||
|
if (inputImage.format() != cmpFormat) {
|
||||||
QTextStream(stdout) << "INFO : " << fi.fileName()
|
QTextStream(stdout) << "INFO : " << fi.fileName()
|
||||||
<< ": converting " << fi.fileName()
|
<< ": converting " << fi.fileName()
|
||||||
<< " from " << formatToString(inputImage.format())
|
<< " from " << formatToString(inputImage.format())
|
||||||
<< " to ARGB32\n";
|
<< " to " << formatToString(cmpFormat) << '\n';
|
||||||
inputImage = inputImage.convertToFormat(QImage::Format_ARGB32);
|
inputImage = inputImage.convertToFormat(cmpFormat);
|
||||||
}
|
}
|
||||||
if (expImage.format() != QImage::Format_ARGB32) {
|
if (expImage.format() != cmpFormat) {
|
||||||
QTextStream(stdout) << "INFO : " << fi.fileName()
|
QTextStream(stdout) << "INFO : " << fi.fileName()
|
||||||
<< ": converting " << expfilename
|
<< ": converting " << expfilename
|
||||||
<< " from " << formatToString(expImage.format())
|
<< " from " << formatToString(expImage.format())
|
||||||
<< " to ARGB32\n";
|
<< " to " << formatToString(cmpFormat) << '\n';
|
||||||
expImage = expImage.convertToFormat(QImage::Format_ARGB32);
|
expImage = expImage.convertToFormat(cmpFormat);
|
||||||
}
|
}
|
||||||
if (fuzzyeq(inputImage, expImage, fuzziness)) {
|
if (fuzzyeq(inputImage, expImage, fuzziness)) {
|
||||||
QTextStream(stdout) << "PASS : " << fi.fileName() << "\n";
|
QTextStream(stdout) << "PASS : " << fi.fileName() << "\n";
|
||||||
|
@ -87,7 +87,7 @@ static bool IsSupported(const PSDHeader &header)
|
|||||||
if (header.channel_count > 16) {
|
if (header.channel_count > 16) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (header.depth != 8) {
|
if (header.depth != 8 && header.depth != 16) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (header.color_mode != CM_RGB) {
|
if (header.color_mode != CM_RGB) {
|
||||||
@ -104,11 +104,13 @@ static void skip_section(QDataStream &s)
|
|||||||
s.skipRawData(section_length);
|
s.skipRawData(section_length);
|
||||||
}
|
}
|
||||||
|
|
||||||
static quint8 readPixel(QDataStream &stream) {
|
template <class Trait>
|
||||||
quint8 pixel;
|
static Trait readPixel(QDataStream &stream) {
|
||||||
|
Trait pixel;
|
||||||
stream >> pixel;
|
stream >> pixel;
|
||||||
return pixel;
|
return pixel;
|
||||||
}
|
}
|
||||||
|
|
||||||
static QRgb updateRed(QRgb oldPixel, quint8 redPixel) {
|
static QRgb updateRed(QRgb oldPixel, quint8 redPixel) {
|
||||||
return qRgba(redPixel, qGreen(oldPixel), qBlue(oldPixel), qAlpha(oldPixel));
|
return qRgba(redPixel, qGreen(oldPixel), qBlue(oldPixel), qAlpha(oldPixel));
|
||||||
}
|
}
|
||||||
@ -149,15 +151,18 @@ static bool LoadPSD(QDataStream &stream, const PSDHeader &header, QImage &img)
|
|||||||
|
|
||||||
quint32 channel_num = header.channel_count;
|
quint32 channel_num = header.channel_count;
|
||||||
|
|
||||||
QImage::Format fmt = QImage::Format_RGB32;
|
QImage::Format fmt = header.depth == 8 ? QImage::Format_RGB32
|
||||||
|
: QImage::Format_RGBX64;
|
||||||
// Clear the image.
|
// Clear the image.
|
||||||
if (channel_num >= 4) {
|
if (channel_num >= 4) {
|
||||||
// Enable alpha.
|
// Enable alpha.
|
||||||
fmt = QImage::Format_ARGB32;
|
fmt = header.depth == 8 ? QImage::Format_ARGB32
|
||||||
|
: QImage::Format_RGBA64;
|
||||||
|
|
||||||
// Ignore the other channels.
|
// Ignore the other channels.
|
||||||
channel_num = 4;
|
channel_num = 4;
|
||||||
}
|
}
|
||||||
|
|
||||||
img = QImage(header.width, header.height, fmt);
|
img = QImage(header.width, header.height, fmt);
|
||||||
if (img.isNull()) {
|
if (img.isNull()) {
|
||||||
qWarning() << "Failed to allocate image, invalid dimensions?" << QSize(header.width, header.height);
|
qWarning() << "Failed to allocate image, invalid dimensions?" << QSize(header.width, header.height);
|
||||||
@ -166,9 +171,10 @@ static bool LoadPSD(QDataStream &stream, const PSDHeader &header, QImage &img)
|
|||||||
img.fill(qRgb(0,0,0));
|
img.fill(qRgb(0,0,0));
|
||||||
|
|
||||||
const quint32 pixel_count = header.height * header.width;
|
const quint32 pixel_count = header.height * header.width;
|
||||||
|
const quint32 channel_size = pixel_count * header.depth / 8;
|
||||||
|
|
||||||
// Verify this, as this is used to write into the memory of the QImage
|
// Verify this, as this is used to write into the memory of the QImage
|
||||||
if (pixel_count > img.sizeInBytes() / sizeof(QRgb)) {
|
if (pixel_count > img.sizeInBytes() / (header.depth == 8 ? sizeof(QRgb) : sizeof(QRgba64))) {
|
||||||
qWarning() << "Invalid pixel count!" << pixel_count << "bytes available:" << img.sizeInBytes();
|
qWarning() << "Invalid pixel count!" << pixel_count << "bytes available:" << img.sizeInBytes();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -186,6 +192,14 @@ static bool LoadPSD(QDataStream &stream, const PSDHeader &header, QImage &img)
|
|||||||
updateAlpha
|
updateAlpha
|
||||||
};
|
};
|
||||||
|
|
||||||
|
typedef QRgba64(*channelUpdater16)(QRgba64, quint16);
|
||||||
|
static const channelUpdater16 updaters64[4] = {
|
||||||
|
[](QRgba64 oldPixel, quint16 redPixel) {return qRgba64((oldPixel & ~(0xFFFFull << 0)) | (quint64( redPixel) << 0));},
|
||||||
|
[](QRgba64 oldPixel, quint16 greenPixel){return qRgba64((oldPixel & ~(0xFFFFull << 16)) | (quint64(greenPixel) << 16));},
|
||||||
|
[](QRgba64 oldPixel, quint16 bluePixel) {return qRgba64((oldPixel & ~(0xFFFFull << 32)) | (quint64( bluePixel) << 32));},
|
||||||
|
[](QRgba64 oldPixel, quint16 alphaPixel){return qRgba64((oldPixel & ~(0xFFFFull << 48)) | (quint64(alphaPixel) << 48));}
|
||||||
|
};
|
||||||
|
|
||||||
if (compression) {
|
if (compression) {
|
||||||
// Skip row lengths.
|
// Skip row lengths.
|
||||||
int skip_count = header.height * header.channel_count * sizeof(quint16);
|
int skip_count = header.height * header.channel_count * sizeof(quint16);
|
||||||
@ -194,9 +208,18 @@ static bool LoadPSD(QDataStream &stream, const PSDHeader &header, QImage &img)
|
|||||||
}
|
}
|
||||||
|
|
||||||
for (unsigned short channel = 0; channel < channel_num; channel++) {
|
for (unsigned short channel = 0; channel < channel_num; channel++) {
|
||||||
bool success = decodeRLEData(RLEVariant::PackBits, stream,
|
bool success = false;
|
||||||
image_data, pixel_count,
|
if (header.depth == 8) {
|
||||||
&readPixel, updaters[channel]);
|
success = decodeRLEData(RLEVariant::PackBits, stream,
|
||||||
|
image_data, channel_size,
|
||||||
|
&readPixel<quint8>, updaters[channel]);
|
||||||
|
} else if (header.depth == 16) {
|
||||||
|
QRgba64 *image_data = reinterpret_cast<QRgba64*>(img.bits());
|
||||||
|
success = decodeRLEData(RLEVariant::PackBits16, stream,
|
||||||
|
image_data, channel_size,
|
||||||
|
&readPixel<quint8>, updaters64[channel]);
|
||||||
|
}
|
||||||
|
|
||||||
if (!success) {
|
if (!success) {
|
||||||
qDebug() << "decodeRLEData on channel" << channel << "failed";
|
qDebug() << "decodeRLEData on channel" << channel << "failed";
|
||||||
return false;
|
return false;
|
||||||
@ -204,8 +227,15 @@ static bool LoadPSD(QDataStream &stream, const PSDHeader &header, QImage &img)
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
for (unsigned short channel = 0; channel < channel_num; channel++) {
|
for (unsigned short channel = 0; channel < channel_num; channel++) {
|
||||||
for (unsigned i = 0; i < pixel_count; ++i) {
|
if (header.depth == 8) {
|
||||||
image_data[i] = updaters[channel](image_data[i], readPixel(stream));
|
for (unsigned i = 0; i < pixel_count; ++i) {
|
||||||
|
image_data[i] = updaters[channel](image_data[i], readPixel<quint8>(stream));
|
||||||
|
}
|
||||||
|
} else if (header.depth == 16) {
|
||||||
|
QRgba64 *image_data = reinterpret_cast<QRgba64*>(img.bits());
|
||||||
|
for (unsigned i = 0; i < pixel_count; ++i) {
|
||||||
|
image_data[i] = updaters64[channel](image_data[i], readPixel<quint16>(stream));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
// make sure we didn't try to read past the end of the stream
|
// make sure we didn't try to read past the end of the stream
|
||||||
if (stream.status() != QDataStream::Ok) {
|
if (stream.status() != QDataStream::Ok) {
|
||||||
|
@ -24,6 +24,11 @@ enum class RLEVariant {
|
|||||||
* of size 2, 130 of size 3, up to 255 of size 128.
|
* of size 2, 130 of size 3, up to 255 of size 128.
|
||||||
*/
|
*/
|
||||||
PackBits,
|
PackBits,
|
||||||
|
/**
|
||||||
|
* Same as PackBits, but treat unpacked data as
|
||||||
|
* 16-bit integers.
|
||||||
|
*/
|
||||||
|
PackBits16,
|
||||||
/**
|
/**
|
||||||
* PIC-style RLE
|
* PIC-style RLE
|
||||||
*
|
*
|
||||||
@ -67,6 +72,8 @@ static inline bool decodeRLEData(RLEVariant variant,
|
|||||||
Func2 updateItem)
|
Func2 updateItem)
|
||||||
{
|
{
|
||||||
unsigned offset = 0; // in dest
|
unsigned offset = 0; // in dest
|
||||||
|
bool is_msb = true; // only used for 16-bit PackBits, data is big-endian
|
||||||
|
quint16 temp_data = 0;
|
||||||
while (offset < length) {
|
while (offset < length) {
|
||||||
unsigned remaining = length - offset;
|
unsigned remaining = length - offset;
|
||||||
quint8 count1;
|
quint8 count1;
|
||||||
@ -85,7 +92,7 @@ static inline bool decodeRLEData(RLEVariant variant,
|
|||||||
// 2 to 128 repetitions
|
// 2 to 128 repetitions
|
||||||
length = count1 - 127u;
|
length = count1 - 127u;
|
||||||
}
|
}
|
||||||
} else if (variant == RLEVariant::PackBits) {
|
} else if (variant == RLEVariant::PackBits || variant == RLEVariant::PackBits16) {
|
||||||
if (count1 == 128u) {
|
if (count1 == 128u) {
|
||||||
// Ignore value 128
|
// Ignore value 128
|
||||||
continue;
|
continue;
|
||||||
@ -102,7 +109,18 @@ static inline bool decodeRLEData(RLEVariant variant,
|
|||||||
}
|
}
|
||||||
auto datum = readData(stream);
|
auto datum = readData(stream);
|
||||||
for (unsigned i = offset; i < offset + length; ++i) {
|
for (unsigned i = offset; i < offset + length; ++i) {
|
||||||
dest[i] = updateItem(dest[i], datum);
|
if (variant == RLEVariant::PackBits16) {
|
||||||
|
if (is_msb) {
|
||||||
|
temp_data = datum << 8;
|
||||||
|
is_msb = false;
|
||||||
|
} else {
|
||||||
|
temp_data |= datum;
|
||||||
|
dest[i >> 1] = updateItem(dest[i >> 1], temp_data);
|
||||||
|
is_msb = true;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
dest[i] = updateItem(dest[i], datum);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
offset += length;
|
offset += length;
|
||||||
} else {
|
} else {
|
||||||
@ -114,7 +132,18 @@ static inline bool decodeRLEData(RLEVariant variant,
|
|||||||
}
|
}
|
||||||
for (unsigned i = offset; i < offset + length; ++i) {
|
for (unsigned i = offset; i < offset + length; ++i) {
|
||||||
auto datum = readData(stream);
|
auto datum = readData(stream);
|
||||||
dest[i] = updateItem(dest[i], datum);
|
if (variant == RLEVariant::PackBits16) {
|
||||||
|
if (is_msb) {
|
||||||
|
temp_data = datum << 8;
|
||||||
|
is_msb = false;
|
||||||
|
} else {
|
||||||
|
temp_data |= datum;
|
||||||
|
dest[i >> 1] = updateItem(dest[i >> 1], temp_data);
|
||||||
|
is_msb = true;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
dest[i] = updateItem(dest[i], datum);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
offset += length;
|
offset += length;
|
||||||
}
|
}
|
||||||
|
@ -7,56 +7,24 @@
|
|||||||
#ifndef FORMAT_ENUM_H
|
#ifndef FORMAT_ENUM_H
|
||||||
#define FORMAT_ENUM_H
|
#define FORMAT_ENUM_H
|
||||||
|
|
||||||
|
#include <QMetaEnum>
|
||||||
#include <QImage>
|
#include <QImage>
|
||||||
|
|
||||||
// Generated from QImage::Format enum
|
|
||||||
static const char * qimage_format_enum_names[] = {
|
|
||||||
"Invalid",
|
|
||||||
"Mono",
|
|
||||||
"MonoLSB",
|
|
||||||
"Indexed8",
|
|
||||||
"RGB32",
|
|
||||||
"ARGB32",
|
|
||||||
"ARGB32_Premultiplied",
|
|
||||||
"RGB16",
|
|
||||||
"ARGB8565_Premultiplied",
|
|
||||||
"RGB666",
|
|
||||||
"ARGB6666_Premultiplied",
|
|
||||||
"RGB555",
|
|
||||||
"ARGB8555_Premultiplied",
|
|
||||||
"RGB888",
|
|
||||||
"RGB444",
|
|
||||||
"ARGB4444_Premultiplied",
|
|
||||||
"RGBX8888",
|
|
||||||
"RGBA8888",
|
|
||||||
"RGBA8888_Premultiplied"
|
|
||||||
};
|
|
||||||
// Never claim there are more than QImage::NImageFormats supported formats.
|
|
||||||
// This is future-proofing against the above list being extended.
|
|
||||||
static const int qimage_format_enum_names_count =
|
|
||||||
(sizeof(qimage_format_enum_names) / sizeof(*qimage_format_enum_names) > int(QImage::NImageFormats))
|
|
||||||
? int(QImage::NImageFormats)
|
|
||||||
: (sizeof(qimage_format_enum_names) / sizeof(*qimage_format_enum_names));
|
|
||||||
|
|
||||||
QImage::Format formatFromString(const QString &str)
|
QImage::Format formatFromString(const QString &str)
|
||||||
{
|
{
|
||||||
for (int i = 0; i < qimage_format_enum_names_count; ++i) {
|
const QMetaEnum metaEnum = QMetaEnum::fromType<QImage::Format>();
|
||||||
if (str.compare(QLatin1String(qimage_format_enum_names[i]), Qt::CaseInsensitive) == 0) {
|
const QString enumString = QStringLiteral("Format_") + str;
|
||||||
return (QImage::Format)(i);
|
|
||||||
}
|
bool ok;
|
||||||
}
|
const int res = metaEnum.keyToValue(enumString.toLatin1().constData(), &ok);
|
||||||
return QImage::Format_Invalid;
|
|
||||||
|
return ok ? static_cast<QImage::Format>(res) : QImage::Format_Invalid;
|
||||||
}
|
}
|
||||||
|
|
||||||
QString formatToString(QImage::Format format)
|
QString formatToString(QImage::Format format)
|
||||||
{
|
{
|
||||||
int index = int(format);
|
const QMetaEnum metaEnum = QMetaEnum::fromType<QImage::Format>();
|
||||||
if (index > 0 && index < qimage_format_enum_names_count) {
|
return QString::fromLatin1(metaEnum.valueToKey(format)).remove(QStringLiteral("Format_"));
|
||||||
return QLatin1String(qimage_format_enum_names[index]);
|
|
||||||
}
|
|
||||||
return QLatin1String("<unknown:") +
|
|
||||||
QString::number(index) +
|
|
||||||
QLatin1String(">");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -67,8 +67,8 @@ int main(int argc, char **argv)
|
|||||||
QTextStream out(stdout);
|
QTextStream out(stdout);
|
||||||
out << "QImage formats:\n";
|
out << "QImage formats:\n";
|
||||||
// skip QImage::Format_Invalid
|
// skip QImage::Format_Invalid
|
||||||
for (int i = 1; i < qimage_format_enum_names_count; ++i) {
|
for (int i = 1; i < QImage::NImageFormats; ++i) {
|
||||||
out << " " << qimage_format_enum_names[i] << '\n';
|
out << " " << formatToString(static_cast<QImage::Format>(i)) << '\n';
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user