diff options
Diffstat (limited to 'src/gui/image')
-rw-r--r-- | src/gui/image/qbitmap.h | 2 | ||||
-rw-r--r-- | src/gui/image/qicon.cpp | 2 | ||||
-rw-r--r-- | src/gui/image/qicon.h | 8 | ||||
-rw-r--r-- | src/gui/image/qimage.cpp | 148 | ||||
-rw-r--r-- | src/gui/image/qimage.h | 28 | ||||
-rw-r--r-- | src/gui/image/qimage_conversions.cpp | 4 | ||||
-rw-r--r-- | src/gui/image/qimage_p.h | 6 | ||||
-rw-r--r-- | src/gui/image/qpicture.h | 4 | ||||
-rw-r--r-- | src/gui/image/qpixmap.h | 4 | ||||
-rw-r--r-- | src/gui/image/qpixmapcache.cpp | 2 | ||||
-rw-r--r-- | src/gui/image/qpixmapcache.h | 8 | ||||
-rw-r--r-- | src/gui/image/qpixmapcache_p.h | 2 | ||||
-rw-r--r-- | src/gui/image/qpnghandler.cpp | 72 | ||||
-rw-r--r-- | src/gui/image/qppmhandler_p.h | 2 |
14 files changed, 248 insertions, 44 deletions
diff --git a/src/gui/image/qbitmap.h b/src/gui/image/qbitmap.h index f7895bb1e0..3cc360f670 100644 --- a/src/gui/image/qbitmap.h +++ b/src/gui/image/qbitmap.h @@ -61,7 +61,7 @@ public: QBitmap(const QBitmap &other) : QPixmap(other) {} // QBitmap(QBitmap &&other) : QPixmap(std::move(other)) {} // QPixmap doesn't, yet, have a move ctor QBitmap &operator=(const QBitmap &other) { QPixmap::operator=(other); return *this; } - QBitmap &operator=(QBitmap &&other) Q_DECL_NOTHROW { QPixmap::operator=(std::move(other)); return *this; } + QBitmap &operator=(QBitmap &&other) noexcept { QPixmap::operator=(std::move(other)); return *this; } ~QBitmap(); #endif diff --git a/src/gui/image/qicon.cpp b/src/gui/image/qicon.cpp index c3c4b24678..892a686c89 100644 --- a/src/gui/image/qicon.cpp +++ b/src/gui/image/qicon.cpp @@ -663,7 +663,7 @@ QFactoryLoader *qt_iconEngineFactoryLoader() /*! Constructs a null icon. */ -QIcon::QIcon() Q_DECL_NOEXCEPT +QIcon::QIcon() noexcept : d(0) { } diff --git a/src/gui/image/qicon.h b/src/gui/image/qicon.h index 8870950982..0f834fc2cb 100644 --- a/src/gui/image/qicon.h +++ b/src/gui/image/qicon.h @@ -58,11 +58,11 @@ public: enum Mode { Normal, Disabled, Active, Selected }; enum State { On, Off }; - QIcon() Q_DECL_NOEXCEPT; + QIcon() noexcept; QIcon(const QPixmap &pixmap); QIcon(const QIcon &other); #ifdef Q_COMPILER_RVALUE_REFS - QIcon(QIcon &&other) Q_DECL_NOEXCEPT + QIcon(QIcon &&other) noexcept : d(other.d) { other.d = nullptr; } #endif @@ -71,10 +71,10 @@ public: ~QIcon(); QIcon &operator=(const QIcon &other); #ifdef Q_COMPILER_RVALUE_REFS - inline QIcon &operator=(QIcon &&other) Q_DECL_NOEXCEPT + inline QIcon &operator=(QIcon &&other) noexcept { swap(other); return *this; } #endif - inline void swap(QIcon &other) Q_DECL_NOEXCEPT + inline void swap(QIcon &other) noexcept { qSwap(d, other.d); } operator QVariant() const; diff --git a/src/gui/image/qimage.cpp b/src/gui/image/qimage.cpp index ebd9037e44..917dde3b0f 100644 --- a/src/gui/image/qimage.cpp +++ b/src/gui/image/qimage.cpp @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2016 The Qt Company Ltd. +** Copyright (C) 2018 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the QtGui module of the Qt Toolkit. @@ -38,8 +38,10 @@ ****************************************************************************/ #include "qimage.h" -#include "qdatastream.h" + #include "qbuffer.h" +#include "qdatastream.h" +#include "qcolortransform.h" #include "qmap.h" #include "qmatrix.h" #include "qtransform.h" @@ -54,6 +56,7 @@ #include <stdlib.h> #include <limits.h> #include <qpa/qplatformpixmap.h> +#include <private/qcolortransform_p.h> #include <private/qdrawhelper_p.h> #include <private/qmemrotate_p.h> #include <private/qimagescale_p.h> @@ -738,7 +741,7 @@ bool QImageData::checkForAlphaPixels() const \sa isNull() */ -QImage::QImage() Q_DECL_NOEXCEPT +QImage::QImage() noexcept : QPaintDevice() { d = 0; @@ -1103,6 +1106,7 @@ static void copyMetadata(QImageData *dst, const QImageData *src) // Doesn't copy colortable and alpha_clut, or offset. copyPhysicalMetadata(dst, src); dst->text = src->text; + dst->colorSpace = src->colorSpace; } static void copyMetadata(QImage *dst, const QImage &src) @@ -1392,7 +1396,7 @@ void QImage::setColorTable(const QVector<QRgb> colors) #if QT_VERSION >= QT_VERSION_CHECK(6,0,0) d->colortable = colors; #else - d->colortable = qMove(const_cast<QVector<QRgb>&>(colors)); + d->colortable = std::move(const_cast<QVector<QRgb>&>(colors)); #endif d->has_alpha_clut = false; for (int i = 0; i < d->colortable.size(); ++i) { @@ -4686,12 +4690,14 @@ QImage QImage::smoothScaled(int w, int h) const { case QImage::Format_RGBX8888: #endif case QImage::Format_RGBA8888_Premultiplied: +#if QT_CONFIG(raster_64bit) case QImage::Format_RGBX64: case QImage::Format_RGBA64_Premultiplied: break; case QImage::Format_RGBA64: src = src.convertToFormat(QImage::Format_RGBA64_Premultiplied); break; +#endif default: if (src.hasAlphaChannel()) src = src.convertToFormat(QImage::Format_ARGB32_Premultiplied); @@ -4949,6 +4955,132 @@ QTransform QImage::trueMatrix(const QTransform &matrix, int w, int h) return matrix * QTransform().translate(-delta.x(), -delta.y()); } +/*! + \since 5.14 + + Sets the image color space to \a colorSpace without performing any conversions on image data. + + \sa colorSpace() +*/ +void QImage::setColorSpace(const QColorSpace &colorSpace) +{ + if (!d) + return; + if (d->colorSpace == colorSpace) + return; + if (!isDetached()) // Detach only if shared, not for read-only data. + detach(); + d->colorSpace = colorSpace; +} + +/*! + \since 5.14 + + Converts the image to \a colorSpace. + + If the image has no valid color space, the method does nothing. + + \sa convertedToColorSpace(), setColorSpace() +*/ +void QImage::convertToColorSpace(const QColorSpace &colorSpace) +{ + if (!d) + return; + if (!d->colorSpace.isValid()) + return; + if (!colorSpace.isValid()) { + qWarning() << "QImage::convertToColorSpace: Output colorspace is not valid"; + return; + } + detach(); + applyColorTransform(d->colorSpace.transformationToColorSpace(colorSpace)); + d->colorSpace = colorSpace; +} + +/*! + \since 5.14 + + Returns the image converted to \a colorSpace. + + If the image has no valid color space, a null QImage is returned. + + \sa convertToColorSpace() +*/ +QImage QImage::convertedToColorSpace(const QColorSpace &colorSpace) const +{ + if (!d || !d->colorSpace.isValid() || !colorSpace.isValid()) + return QImage(); + QImage image = copy(); + image.convertToColorSpace(colorSpace); + return image; +} + +/*! + \since 5.14 + + Returns the color space of the image if a color space is defined. +*/ +QColorSpace QImage::colorSpace() const +{ + if (!d) + return QColorSpace::Undefined; + return d->colorSpace; +} + +/*! + \since 5.14 + + Applies the color transformation \a transform to all pixels in the image. +*/ +void QImage::applyColorTransform(const QColorTransform &transform) +{ + QImage::Format oldFormat = format(); + if (depth() > 32) { + if (format() != QImage::Format_RGBX64 && format() != QImage::Format_RGBA64 + && format() != QImage::Format_RGBA64_Premultiplied) + *this = std::move(*this).convertToFormat(QImage::Format_RGBA64); + } else if (format() != QImage::Format_ARGB32 && format() != QImage::Format_RGB32 + && format() != QImage::Format_ARGB32_Premultiplied) { + if (hasAlphaChannel()) + *this = std::move(*this).convertToFormat(QImage::Format_ARGB32); + else + *this = std::move(*this).convertToFormat(QImage::Format_RGB32); + } + + QColorTransformPrivate::TransformFlags flags = QColorTransformPrivate::Unpremultiplied; + switch (format()) { + case Format_ARGB32_Premultiplied: + case Format_RGBA64_Premultiplied: + flags = QColorTransformPrivate::Premultiplied; + break; + case Format_RGB32: + case Format_RGBX64: + flags = QColorTransformPrivate::InputOpaque; + break; + case Format_ARGB32: + case Format_RGBA64: + break; + default: + Q_UNREACHABLE(); + } + + if (depth() > 32) { + for (int i = 0; i < height(); ++i) { + QRgba64 *scanline = reinterpret_cast<QRgba64 *>(scanLine(i)); + transform.d_func()->apply(scanline, scanline, width(), flags); + } + } else { + for (int i = 0; i < height(); ++i) { + QRgb *scanline = reinterpret_cast<QRgb *>(scanLine(i)); + transform.d_func()->apply(scanline, scanline, width(), flags); + } + } + + if (oldFormat != format()) + *this = std::move(*this).convertToFormat(oldFormat); +} + + bool QImageData::convertInPlace(QImage::Format newFormat, Qt::ImageConversionFlags flags) { if (format == newFormat) @@ -5424,7 +5556,7 @@ Q_STATIC_ASSERT(sizeof(pixelformats) / sizeof(*pixelformats) == QImage::NImageFo /*! Returns the QImage::Format as a QPixelFormat */ -QPixelFormat QImage::pixelFormat() const Q_DECL_NOTHROW +QPixelFormat QImage::pixelFormat() const noexcept { return toPixelFormat(format()); } @@ -5432,7 +5564,7 @@ QPixelFormat QImage::pixelFormat() const Q_DECL_NOTHROW /*! Converts \a format into a QPixelFormat */ -QPixelFormat QImage::toPixelFormat(QImage::Format format) Q_DECL_NOTHROW +QPixelFormat QImage::toPixelFormat(QImage::Format format) noexcept { Q_ASSERT(static_cast<int>(format) < NImageFormats); return pixelformats[format]; @@ -5441,7 +5573,7 @@ QPixelFormat QImage::toPixelFormat(QImage::Format format) Q_DECL_NOTHROW /*! Converts \a format into a QImage::Format */ -QImage::Format QImage::toImageFormat(QPixelFormat format) Q_DECL_NOTHROW +QImage::Format QImage::toImageFormat(QPixelFormat format) noexcept { for (int i = 0; i < NImageFormats; i++) { if (format == pixelformats[i]) @@ -5457,7 +5589,7 @@ Q_GUI_EXPORT void qt_imageTransform(QImage &src, QImageIOHandler::Transformation if (orient == QImageIOHandler::TransformationRotate270) { src = rotated270(src); } else { - src = qMove(src).mirrored(orient & QImageIOHandler::TransformationMirror, + src = std::move(src).mirrored(orient & QImageIOHandler::TransformationMirror, orient & QImageIOHandler::TransformationFlip); if (orient & QImageIOHandler::TransformationRotate90) src = rotated90(src); diff --git a/src/gui/image/qimage.h b/src/gui/image/qimage.h index 8335e117f2..9d177142d9 100644 --- a/src/gui/image/qimage.h +++ b/src/gui/image/qimage.h @@ -61,9 +61,11 @@ Q_FORWARD_DECLARE_MUTABLE_CG_TYPE(CGImage); QT_BEGIN_NAMESPACE +class QColorSpace; +class QColorTransform; class QIODevice; -class QStringList; class QMatrix; +class QStringList; class QTransform; class QVariant; template <class T> class QList; @@ -135,7 +137,7 @@ public: }; Q_ENUM(Format) - QImage() Q_DECL_NOEXCEPT; + QImage() noexcept; QImage(const QSize &size, Format format); QImage(int width, int height, Format format); QImage(uchar *data, int width, int height, Format format, QImageCleanupFunction cleanupFunction = nullptr, void *cleanupInfo = nullptr); @@ -150,7 +152,7 @@ public: QImage(const QImage &); #ifdef Q_COMPILER_RVALUE_REFS - inline QImage(QImage &&other) Q_DECL_NOEXCEPT + inline QImage(QImage &&other) noexcept : QPaintDevice(), d(nullptr) { qSwap(d, other.d); } #endif @@ -158,10 +160,10 @@ public: QImage &operator=(const QImage &); #ifdef Q_COMPILER_RVALUE_REFS - inline QImage &operator=(QImage &&other) Q_DECL_NOEXCEPT + inline QImage &operator=(QImage &&other) noexcept { qSwap(d, other.d); return *this; } #endif - inline void swap(QImage &other) Q_DECL_NOEXCEPT + inline void swap(QImage &other) noexcept { qSwap(d, other.d); } bool isNull() const; @@ -289,17 +291,23 @@ public: QImage mirrored(bool horizontally = false, bool vertically = true) const & { return mirrored_helper(horizontally, vertically); } QImage &&mirrored(bool horizontally = false, bool vertically = true) && - { mirrored_inplace(horizontally, vertically); return qMove(*this); } + { mirrored_inplace(horizontally, vertically); return std::move(*this); } QImage rgbSwapped() const & { return rgbSwapped_helper(); } QImage &&rgbSwapped() && - { rgbSwapped_inplace(); return qMove(*this); } + { rgbSwapped_inplace(); return std::move(*this); } #else QImage mirrored(bool horizontally = false, bool vertically = true) const; QImage rgbSwapped() const; #endif void invertPixels(InvertMode = InvertRgb); + QColorSpace colorSpace() const; + QImage convertedToColorSpace(const QColorSpace &) const; + void convertToColorSpace(const QColorSpace &); + void setColorSpace(const QColorSpace &); + + void applyColorTransform(const QColorTransform &transform); bool load(QIODevice *device, const char* format); bool load(const QString &fileName, const char *format = nullptr); @@ -333,9 +341,9 @@ public: QString text(const QString &key = QString()) const; void setText(const QString &key, const QString &value); - QPixelFormat pixelFormat() const Q_DECL_NOTHROW; - static QPixelFormat toPixelFormat(QImage::Format format) Q_DECL_NOTHROW; - static QImage::Format toImageFormat(QPixelFormat format) Q_DECL_NOTHROW; + QPixelFormat pixelFormat() const noexcept; + static QPixelFormat toPixelFormat(QImage::Format format) noexcept; + static QImage::Format toImageFormat(QPixelFormat format) noexcept; // Platform specific conversion functions #if defined(Q_OS_DARWIN) || defined(Q_QDOC) diff --git a/src/gui/image/qimage_conversions.cpp b/src/gui/image/qimage_conversions.cpp index 82ffb8af8b..837ac88470 100644 --- a/src/gui/image/qimage_conversions.cpp +++ b/src/gui/image/qimage_conversions.cpp @@ -39,7 +39,7 @@ #include <private/qdrawhelper_p.h> #include <private/qguiapplication_p.h> -#include <private/qcolorprofile_p.h> +#include <private/qcolortrclut_p.h> #include <private/qendian_p.h> #include <private/qsimd_p.h> #include <private/qimage_p.h> @@ -100,7 +100,7 @@ const uchar *qt_get_bitflip_array() void qGamma_correct_back_to_linear_cs(QImage *image) { - const QColorProfile *cp = QGuiApplicationPrivate::instance()->colorProfileForA32Text(); + const QColorTrcLut *cp = QGuiApplicationPrivate::instance()->colorProfileForA32Text(); if (!cp) return; // gamma correct the pixels back to linear color space... diff --git a/src/gui/image/qimage_p.h b/src/gui/image/qimage_p.h index d88ad2d1d2..9da6acd0a7 100644 --- a/src/gui/image/qimage_p.h +++ b/src/gui/image/qimage_p.h @@ -51,7 +51,9 @@ // We mean it. // +#include <QtGui/qcolorspace.h> #include <QtGui/private/qtguiglobal_p.h> +#include <QtGui/qimage.h> #include <QtCore/private/qnumeric_p.h> #include <QMap> @@ -65,7 +67,7 @@ struct Q_GUI_EXPORT QImageData { // internal image data QImageData(); ~QImageData(); static QImageData *create(const QSize &size, QImage::Format format); - static QImageData *create(uchar *data, int w, int h, int bpl, QImage::Format format, bool readOnly, QImageCleanupFunction cleanupFunction = 0, void *cleanupInfo = 0); + static QImageData *create(uchar *data, int w, int h, int bpl, QImage::Format format, bool readOnly, QImageCleanupFunction cleanupFunction = nullptr, void *cleanupInfo = nullptr); QAtomicInt ref; @@ -106,6 +108,8 @@ struct Q_GUI_EXPORT QImageData { // internal image data QPaintEngine *paintEngine; + QColorSpace colorSpace; + struct ImageSizeParameters { qsizetype bytesPerLine; qsizetype totalSize; diff --git a/src/gui/image/qpicture.h b/src/gui/image/qpicture.h index ec7b4bd7e3..cac2ef5dfc 100644 --- a/src/gui/image/qpicture.h +++ b/src/gui/image/qpicture.h @@ -79,10 +79,10 @@ public: QPicture& operator=(const QPicture &p); #ifdef Q_COMPILER_RVALUE_REFS - inline QPicture &operator=(QPicture &&other) Q_DECL_NOEXCEPT + inline QPicture &operator=(QPicture &&other) noexcept { qSwap(d_ptr, other.d_ptr); return *this; } #endif - inline void swap(QPicture &other) Q_DECL_NOEXCEPT + inline void swap(QPicture &other) noexcept { d_ptr.swap(other.d_ptr); } void detach(); bool isDetached() const; diff --git a/src/gui/image/qpixmap.h b/src/gui/image/qpixmap.h index 13c81f18d0..2103fcc58c 100644 --- a/src/gui/image/qpixmap.h +++ b/src/gui/image/qpixmap.h @@ -74,10 +74,10 @@ public: QPixmap &operator=(const QPixmap &); #ifdef Q_COMPILER_RVALUE_REFS - inline QPixmap &operator=(QPixmap &&other) Q_DECL_NOEXCEPT + inline QPixmap &operator=(QPixmap &&other) noexcept { qSwap(data, other.data); return *this; } #endif - inline void swap(QPixmap &other) Q_DECL_NOEXCEPT + inline void swap(QPixmap &other) noexcept { qSwap(data, other.data); } operator QVariant() const; diff --git a/src/gui/image/qpixmapcache.cpp b/src/gui/image/qpixmapcache.cpp index 66907bebd7..a41ec8f35c 100644 --- a/src/gui/image/qpixmapcache.cpp +++ b/src/gui/image/qpixmapcache.cpp @@ -176,7 +176,7 @@ bool QPixmapCache::Key::operator ==(const Key &key) const Otherwise, if pixmap was flushed, the key is no longer valid. \since 5.7 */ -bool QPixmapCache::Key::isValid() const Q_DECL_NOTHROW +bool QPixmapCache::Key::isValid() const noexcept { return d && d->isValid; } diff --git a/src/gui/image/qpixmapcache.h b/src/gui/image/qpixmapcache.h index 12d05b00f3..c5bedb27ab 100644 --- a/src/gui/image/qpixmapcache.h +++ b/src/gui/image/qpixmapcache.h @@ -56,8 +56,8 @@ public: Key(); Key(const Key &other); #ifdef Q_COMPILER_RVALUE_REFS - Key(Key &&other) Q_DECL_NOTHROW : d(other.d) { other.d = nullptr; } - Key &operator =(Key &&other) Q_DECL_NOTHROW { swap(other); return *this; } + Key(Key &&other) noexcept : d(other.d) { other.d = nullptr; } + Key &operator =(Key &&other) noexcept { swap(other); return *this; } #endif ~Key(); bool operator ==(const Key &key) const; @@ -65,8 +65,8 @@ public: { return !operator==(key); } Key &operator =(const Key &other); - void swap(Key &other) Q_DECL_NOTHROW { qSwap(d, other.d); } - bool isValid() const Q_DECL_NOTHROW; + void swap(Key &other) noexcept { qSwap(d, other.d); } + bool isValid() const noexcept; private: KeyData *d; diff --git a/src/gui/image/qpixmapcache_p.h b/src/gui/image/qpixmapcache_p.h index 3c57367514..ab8e2b7558 100644 --- a/src/gui/image/qpixmapcache_p.h +++ b/src/gui/image/qpixmapcache_p.h @@ -87,7 +87,7 @@ public: && !d->image.d->paintEngine->isActive()) { delete d->image.d->paintEngine; - d->image.d->paintEngine = 0; + d->image.d->paintEngine = nullptr; } } } diff --git a/src/gui/image/qpnghandler.cpp b/src/gui/image/qpnghandler.cpp index 1c269213e2..39d0807606 100644 --- a/src/gui/image/qpnghandler.cpp +++ b/src/gui/image/qpnghandler.cpp @@ -42,6 +42,7 @@ #ifndef QT_NO_IMAGEFORMAT_PNG #include <qcoreapplication.h> +#include <qdebug.h> #include <qiodevice.h> #include <qimage.h> #include <qlist.h> @@ -50,6 +51,10 @@ #include <private/qimage_p.h> // for qt_getImageText +#include <qcolorspace.h> +#include <private/qcolorspace_p.h> +#include <private/qicc_p.h> + #include <png.h> #include <pngconf.h> @@ -96,9 +101,16 @@ public: ReadingEnd, Error }; + // Defines the order of how the various ways of setting colorspace overrides eachother: + enum ColorSpaceState { + Undefined = 0, + GammaChrm = 1, // gAMA+cHRM chunks + Srgb = 2, // sRGB chunk + Icc = 3 // iCCP chunk + }; QPngHandlerPrivate(QPngHandler *qq) - : gamma(0.0), fileGamma(0.0), quality(50), compression(50), png_ptr(0), info_ptr(0), end_info(0), state(Ready), q(qq) + : gamma(0.0), fileGamma(0.0), quality(50), compression(50), colorSpaceState(Undefined), png_ptr(0), info_ptr(0), end_info(0), state(Ready), q(qq) { } float gamma; @@ -108,6 +120,8 @@ public: QString description; QSize scaledSize; QStringList readTexts; + QColorSpace colorSpace; + ColorSpaceState colorSpaceState; png_struct *png_ptr; png_info *info_ptr; @@ -226,11 +240,8 @@ void qpiw_flush_fn(png_structp /* png_ptr */) } static -void setup_qt(QImage& image, png_structp png_ptr, png_infop info_ptr, QSize scaledSize, bool *doScaledRead, float screen_gamma=0.0, float file_gamma=0.0) +void setup_qt(QImage& image, png_structp png_ptr, png_infop info_ptr, QSize scaledSize, bool *doScaledRead) { - if (screen_gamma != 0.0 && file_gamma != 0.0) - png_set_gamma(png_ptr, 1.0f / screen_gamma, file_gamma); - png_uint_32 width = 0; png_uint_32 height = 0; int bit_depth = 0; @@ -585,10 +596,45 @@ bool QPngHandlerPrivate::readPngHeader() readPngTexts(info_ptr); +#ifdef PNG_iCCP_SUPPORTED + if (png_get_valid(png_ptr, info_ptr, PNG_INFO_iCCP)) { + png_charp name = nullptr; + int compressionType = 0; +#if (PNG_LIBPNG_VER < 10500) + png_charp profileData = nullptr; +#else + png_bytep profileData = nullptr; +#endif + png_uint_32 profLen; + png_get_iCCP(png_ptr, info_ptr, &name, &compressionType, &profileData, &profLen); + if (!QIcc::fromIccProfile(QByteArray::fromRawData((const char *)profileData, profLen), &colorSpace)) { + qWarning() << "QPngHandler: Failed to parse ICC profile"; + } else { + colorSpaceState = Icc; + } + } +#endif + if (png_get_valid(png_ptr, info_ptr, PNG_INFO_sRGB)) { + int rendering_intent = -1; + png_get_sRGB(png_ptr, info_ptr, &rendering_intent); + // We don't actually care about the rendering_intent, just that it is valid + if (rendering_intent >= 0 && rendering_intent <= 3 && colorSpaceState <= Srgb) { + colorSpace = QColorSpace::SRgb; + colorSpaceState = Srgb; + } + } if (png_get_valid(png_ptr, info_ptr, PNG_INFO_gAMA)) { double file_gamma = 0.0; png_get_gAMA(png_ptr, info_ptr, &file_gamma); fileGamma = file_gamma; + if (fileGamma > 0.0f && colorSpaceState <= GammaChrm) { + QColorSpacePrivate *csPrivate = colorSpace.d_func(); + csPrivate->gamut = QColorSpace::Gamut::SRgb; + csPrivate->transferFunction = QColorSpace::TransferFunction::Gamma; + csPrivate->gamma = fileGamma; + csPrivate->initialize(); + colorSpaceState = GammaChrm; + } } state = ReadHeader; @@ -613,8 +659,19 @@ bool QPngHandlerPrivate::readPngImage(QImage *outImage) return false; } + if (gamma != 0.0 && fileGamma != 0.0) { + // This configuration forces gamma correction and + // thus changes the output colorspace + png_set_gamma(png_ptr, 1.0f / gamma, fileGamma); + QColorSpacePrivate *csPrivate = colorSpace.d_func(); + csPrivate->transferFunction = QColorSpace::TransferFunction::Gamma; + csPrivate->gamma = gamma; + csPrivate->initialize(); + colorSpaceState = GammaChrm; + } + bool doScaledRead = false; - setup_qt(*outImage, png_ptr, info_ptr, scaledSize, &doScaledRead, gamma, fileGamma); + setup_qt(*outImage, png_ptr, info_ptr, scaledSize, &doScaledRead); if (outImage->isNull()) { png_destroy_read_struct(&png_ptr, &info_ptr, &end_info); @@ -683,6 +740,9 @@ bool QPngHandlerPrivate::readPngImage(QImage *outImage) if (scaledSize.isValid() && outImage->size() != scaledSize) *outImage = outImage->scaled(scaledSize, Qt::IgnoreAspectRatio, Qt::SmoothTransformation); + if (colorSpaceState > Undefined && colorSpace.isValid()) + outImage->setColorSpace(colorSpace); + return true; } diff --git a/src/gui/image/qppmhandler_p.h b/src/gui/image/qppmhandler_p.h index f3c9d0f139..2f3811b759 100644 --- a/src/gui/image/qppmhandler_p.h +++ b/src/gui/image/qppmhandler_p.h @@ -71,7 +71,7 @@ public: QByteArray name() const override; #endif - static bool canRead(QIODevice *device, QByteArray *subType = 0); + static bool canRead(QIODevice *device, QByteArray *subType = nullptr); QVariant option(ImageOption option) const override; void setOption(ImageOption option, const QVariant &value) override; |