diff options
author | Giuseppe D'Angelo <giuseppe.dangelo@kdab.com> | 2024-03-09 14:34:50 +0100 |
---|---|---|
committer | Giuseppe D'Angelo <giuseppe.dangelo@kdab.com> | 2024-03-10 11:59:32 +0100 |
commit | 003cef9d40f2e840f2690bd465994deaab5c2b95 (patch) | |
tree | 98ec3ec9882c5dea77f2cab6f356e891122e8e91 /src/gui/image | |
parent | 0804109d686e0a99ab0de0f1c70e3422183c6e98 (diff) |
PNG: preserve ICC profiles that QColorSpace does not handle
QColorSpace::isValid() returns true if QColorSpace can handle the
profile. When called on a QColorSpace obtained via
QColorSpace::fromIccProfile, this doesn't necessarily mean that the ICC
profile itself was invalid; it could be that the ICC data was valid, but
QColorSpace didn't know how to use it. This is especially true on Qt <=
6.7, where only XYZ/RGB matrix profiles were supported.
We don't fully parse ICC v4, and we're lacking an API to differentiate
between "ICC data was valid but QColorSpace doesn't handle it" vs "ICC
data was invalid".
Still, an invalid QColorSpace will still the original ICC data, so it
can be saved again without loss of information.
So: 1) when loading a PNG with embedded ICC data, keep the loaded profile
even if it's "invalid"; 2) when writing a PNG, check if we have ICC data
to save, and unconditionally write it if it's the case.
This avoids data loss in the two directions.
This work has been kindly sponsored by the QGIS project
(https://qgis.org/).
Pick-to: 6.7 6.6 6.5
Change-Id: I1f27f603acbca1590c820e80f52f3b994f5ea5c7
Reviewed-by: Allan Sandfeld Jensen <allan.jensen@qt.io>
Diffstat (limited to 'src/gui/image')
-rw-r--r-- | src/gui/image/qpnghandler.cpp | 20 |
1 files changed, 10 insertions, 10 deletions
diff --git a/src/gui/image/qpnghandler.cpp b/src/gui/image/qpnghandler.cpp index c9b12c15f8..615a36fa36 100644 --- a/src/gui/image/qpnghandler.cpp +++ b/src/gui/image/qpnghandler.cpp @@ -554,10 +554,10 @@ bool QPngHandlerPrivate::readPngHeader() #endif png_uint_32 profLen; png_get_iCCP(png_ptr, info_ptr, &name, &compressionType, &profileData, &profLen); - colorSpace = QColorSpace::fromIccProfile(QByteArray((const char *)profileData, profLen)); - if (!colorSpace.isValid()) { - qCDebug(lcImageIo) << "QPngHandler: Failed to parse ICC profile"; - } else { + Q_UNUSED(name); + Q_UNUSED(compressionType); + if (profLen > 0) { + colorSpace = QColorSpace::fromIccProfile(QByteArray((const char *)profileData, profLen)); QColorSpacePrivate *csD = QColorSpacePrivate::get(colorSpace); if (csD->description.isEmpty()) csD->description = QString::fromLatin1((const char *)name); @@ -926,15 +926,15 @@ bool QPNGImageWriter::writeImage(const QImage& image, int compression_in, const color_type, 0, 0, 0); // sets #channels #ifdef PNG_iCCP_SUPPORTED - if (image.colorSpace().isValid()) { - QColorSpace cs = image.colorSpace(); - // Support the old gamma making it override transferfunction. - if (gamma != 0.0 && !qFuzzyCompare(cs.gamma(), 1.0f / gamma)) - cs = cs.withTransferFunction(QColorSpace::TransferFunction::Gamma, 1.0f / gamma); + QColorSpace cs = image.colorSpace(); + // Support the old gamma making it override transferfunction (if possible) + if (cs.isValid() && gamma != 0.0 && !qFuzzyCompare(cs.gamma(), 1.0f / gamma)) + cs = cs.withTransferFunction(QColorSpace::TransferFunction::Gamma, 1.0f / gamma); + QByteArray iccProfile = cs.iccProfile(); + if (!iccProfile.isEmpty()) { QByteArray iccProfileName = cs.description().toLatin1(); if (iccProfileName.isEmpty()) iccProfileName = QByteArrayLiteral("Custom"); - QByteArray iccProfile = cs.iccProfile(); png_set_iCCP(png_ptr, info_ptr, #if PNG_LIBPNG_VER < 10500 iccProfileName.data(), PNG_COMPRESSION_TYPE_BASE, iccProfile.data(), |