diff options
Diffstat (limited to 'src/gui/image/qimage.cpp')
-rw-r--r-- | src/gui/image/qimage.cpp | 156 |
1 files changed, 144 insertions, 12 deletions
diff --git a/src/gui/image/qimage.cpp b/src/gui/image/qimage.cpp index f23debd931..8e0bbb6907 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; @@ -1079,10 +1082,10 @@ QImage::operator QVariant() const void QImage::detach() { if (d) { - if (d->is_cached && d->ref.load() == 1) + if (d->is_cached && d->ref.loadRelaxed() == 1) QImagePixmapCleanupHooks::executeImageHooks(cacheKey()); - if (d->ref.load() != 1 || d->ro_data) + if (d->ref.loadRelaxed() != 1 || d->ro_data) *this = copy(); if (d) @@ -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) { @@ -4418,7 +4422,7 @@ qint64 QImage::cacheKey() const bool QImage::isDetached() const { - return d && d->ref.load() == 1; + return d && d->ref.loadRelaxed() == 1; } @@ -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,13 +4955,139 @@ 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->apply(scanline, scanline, width(), flags); + } + } else { + for (int i = 0; i < height(); ++i) { + QRgb *scanline = reinterpret_cast<QRgb *>(scanLine(i)); + transform.d->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) return true; // No in-place conversion if we have to detach - if (ref.load() > 1 || !own_data) + if (ref.loadRelaxed() > 1 || !own_data) return false; InPlace_Image_Converter converter = qimage_inplace_converter_map[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); |