mirror of
https://invent.kde.org/frameworks/kimageformats.git
synced 2025-07-16 19:34:17 -04:00
Compare commits
6 Commits
v5.75.0-rc
...
v5.76.0
Author | SHA1 | Date | |
---|---|---|---|
1acb5a6177 | |||
f2ccbf1724 | |||
5825c83235 | |||
b742cb7cc7 | |||
2e6eeebdfc | |||
db0b5d571a |
@ -5,7 +5,7 @@ project(KImageFormats)
|
||||
set (CMAKE_CXX_STANDARD 14)
|
||||
|
||||
include(FeatureSummary)
|
||||
find_package(ECM 5.75.0 NO_MODULE)
|
||||
find_package(ECM 5.76.0 NO_MODULE)
|
||||
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)
|
||||
|
||||
@ -51,7 +51,7 @@ 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
|
||||
# https://codereview.qt-project.org/c/qt/qtbase/+/279215
|
||||
add_definitions(-DQT_DISABLE_DEPRECATED_BEFORE=0x050c00)
|
||||
add_definitions(-DKF_DISABLE_DEPRECATED_BEFORE_AND_AT=0x054900)
|
||||
add_definitions(-DKF_DISABLE_DEPRECATED_BEFORE_AND_AT=0x054B00)
|
||||
add_subdirectory(src)
|
||||
if (BUILD_TESTING)
|
||||
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: 628 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: 534 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.
@ -87,7 +87,7 @@ static bool IsSupported(const PSDHeader &header)
|
||||
if (header.channel_count > 16) {
|
||||
return false;
|
||||
}
|
||||
if (header.depth != 8) {
|
||||
if (header.depth != 8 && header.depth != 16) {
|
||||
return false;
|
||||
}
|
||||
if (header.color_mode != CM_RGB) {
|
||||
@ -104,11 +104,18 @@ static void skip_section(QDataStream &s)
|
||||
s.skipRawData(section_length);
|
||||
}
|
||||
|
||||
static quint8 readPixel(QDataStream &stream) {
|
||||
static quint8 readPixel_u16(QDataStream &stream) {
|
||||
quint16 pixel;
|
||||
stream >> pixel;
|
||||
return pixel / (1 << 8);
|
||||
}
|
||||
|
||||
static int readPixel_u8(QDataStream &stream) {
|
||||
quint8 pixel;
|
||||
stream >> pixel;
|
||||
return pixel;
|
||||
}
|
||||
|
||||
static QRgb updateRed(QRgb oldPixel, quint8 redPixel) {
|
||||
return qRgba(redPixel, qGreen(oldPixel), qBlue(oldPixel), qAlpha(oldPixel));
|
||||
}
|
||||
@ -158,6 +165,14 @@ static bool LoadPSD(QDataStream &stream, const PSDHeader &header, QImage &img)
|
||||
// Ignore the other channels.
|
||||
channel_num = 4;
|
||||
}
|
||||
|
||||
if (compression == 1 && header.depth == 16) {
|
||||
fmt = QImage::Format_RGBX64;
|
||||
if (channel_num >= 4) {
|
||||
fmt = QImage::Format_RGBA64;
|
||||
}
|
||||
}
|
||||
|
||||
img = QImage(header.width, header.height, fmt);
|
||||
if (img.isNull()) {
|
||||
qWarning() << "Failed to allocate image, invalid dimensions?" << QSize(header.width, header.height);
|
||||
@ -186,6 +201,14 @@ static bool LoadPSD(QDataStream &stream, const PSDHeader &header, QImage &img)
|
||||
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) {
|
||||
// Skip row lengths.
|
||||
int skip_count = header.height * header.channel_count * sizeof(quint16);
|
||||
@ -194,9 +217,18 @@ static bool LoadPSD(QDataStream &stream, const PSDHeader &header, QImage &img)
|
||||
}
|
||||
|
||||
for (unsigned short channel = 0; channel < channel_num; channel++) {
|
||||
bool success = decodeRLEData(RLEVariant::PackBits, stream,
|
||||
bool success = false;
|
||||
if (header.depth == 8) {
|
||||
success = decodeRLEData(RLEVariant::PackBits, stream,
|
||||
image_data, pixel_count,
|
||||
&readPixel, updaters[channel]);
|
||||
&readPixel_u8, updaters[channel]);
|
||||
} else if (header.depth == 16) {
|
||||
QRgba64 *image_data = reinterpret_cast<QRgba64*>(img.bits());
|
||||
success = decodeRLEData(RLEVariant::PackBits16, stream,
|
||||
image_data, pixel_count * 2,
|
||||
&readPixel_u8, updaters64[channel]);
|
||||
}
|
||||
|
||||
if (!success) {
|
||||
qDebug() << "decodeRLEData on channel" << channel << "failed";
|
||||
return false;
|
||||
@ -205,7 +237,10 @@ static bool LoadPSD(QDataStream &stream, const PSDHeader &header, QImage &img)
|
||||
} else {
|
||||
for (unsigned short channel = 0; channel < channel_num; channel++) {
|
||||
for (unsigned i = 0; i < pixel_count; ++i) {
|
||||
image_data[i] = updaters[channel](image_data[i], readPixel(stream));
|
||||
image_data[i] = updaters[channel](
|
||||
image_data[i],
|
||||
header.depth == 8 ? readPixel_u8(stream)
|
||||
: readPixel_u16(stream));
|
||||
}
|
||||
// make sure we didn't try to read past the end of the stream
|
||||
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.
|
||||
*/
|
||||
PackBits,
|
||||
/**
|
||||
* Same as PackBits, but treat unpacked data as
|
||||
* 16-bit integers.
|
||||
*/
|
||||
PackBits16,
|
||||
/**
|
||||
* PIC-style RLE
|
||||
*
|
||||
@ -67,6 +72,8 @@ static inline bool decodeRLEData(RLEVariant variant,
|
||||
Func2 updateItem)
|
||||
{
|
||||
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) {
|
||||
unsigned remaining = length - offset;
|
||||
quint8 count1;
|
||||
@ -85,7 +92,7 @@ static inline bool decodeRLEData(RLEVariant variant,
|
||||
// 2 to 128 repetitions
|
||||
length = count1 - 127u;
|
||||
}
|
||||
} else if (variant == RLEVariant::PackBits) {
|
||||
} else if (variant == RLEVariant::PackBits || variant == RLEVariant::PackBits16) {
|
||||
if (count1 == 128u) {
|
||||
// Ignore value 128
|
||||
continue;
|
||||
@ -102,8 +109,19 @@ static inline bool decodeRLEData(RLEVariant variant,
|
||||
}
|
||||
auto datum = readData(stream);
|
||||
for (unsigned i = offset; i < offset + length; ++i) {
|
||||
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;
|
||||
} else {
|
||||
// No repetitions
|
||||
@ -114,8 +132,19 @@ static inline bool decodeRLEData(RLEVariant variant,
|
||||
}
|
||||
for (unsigned i = offset; i < offset + length; ++i) {
|
||||
auto datum = readData(stream);
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user