diff options
author | Allan Sandfeld Jensen <allan.jensen@qt.io> | 2018-06-26 17:12:02 +0200 |
---|---|---|
committer | Allan Sandfeld Jensen <allan.jensen@qt.io> | 2019-02-08 10:12:05 +0000 |
commit | 90a8de656fe689b6aa856e70e2d22de6630ea855 (patch) | |
tree | c1402760952701c854bb92cb12407283ead9dd6f /src/gui/image/qimage.cpp | |
parent | 17512d497d7eaf01aefe8140f5010818c0103a95 (diff) |
Long live QColorSpace and friends
Adds QColorSpace and QColorTransform classes,
and parsing of a common subset of ICC profiles
found in images, and also parses the ICC profiles
in PNG and JPEGs.
For backwards compatibility no automatic color
handling is done by this patch.
[ChangeLog][QtGui] A QColorSpace class has been added,
and color spaces are now parsed from PNG and JPEG images.
No automatic color space conversion is done however, and
applications must request it.
Change-Id: Ic09935f84640a716467fa3a9ed1e73c02daf3675
Reviewed-by: Eirik Aavitsland <eirik.aavitsland@qt.io>
Diffstat (limited to 'src/gui/image/qimage.cpp')
-rw-r--r-- | src/gui/image/qimage.cpp | 134 |
1 files changed, 132 insertions, 2 deletions
diff --git a/src/gui/image/qimage.cpp b/src/gui/image/qimage.cpp index 16de045cf0..204729b551 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> @@ -1098,6 +1101,7 @@ static void copyMetadata(QImageData *dst, const QImageData *src) dst->dpmy = src->dpmy; dst->devicePixelRatio = src->devicePixelRatio; dst->text = src->text; + dst->colorSpace = src->colorSpace; } /*! @@ -4920,6 +4924,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) |