summaryrefslogtreecommitdiffstats
path: root/src/gui/image/qimage_conversions.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/gui/image/qimage_conversions.cpp')
-rw-r--r--src/gui/image/qimage_conversions.cpp124
1 files changed, 60 insertions, 64 deletions
diff --git a/src/gui/image/qimage_conversions.cpp b/src/gui/image/qimage_conversions.cpp
index cae52ca330..a806954df2 100644
--- a/src/gui/image/qimage_conversions.cpp
+++ b/src/gui/image/qimage_conversions.cpp
@@ -1,45 +1,10 @@
-/****************************************************************************
-**
-** Copyright (C) 2021 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2021 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include <private/qguiapplication_p.h>
#include <private/qcolortransform_p.h>
#include <private/qcolortrclut_p.h>
+#include <private/qcmyk_p.h>
#include <private/qdrawhelper_p.h>
#include <private/qendian_p.h>
#include <private/qpixellayout_p.h>
@@ -51,6 +16,7 @@
#if QT_CONFIG(thread)
#include <qsemaphore.h>
#include <qthreadpool.h>
+#include <private/qthreadpool_p.h>
#ifdef Q_OS_WASM
// WebAssembly has threads; however we can't block the main thread.
#else
@@ -200,7 +166,7 @@ void convert_generic(QImageData *dest, const QImageData *src, Qt::ImageConversio
if (srcLayout->hasAlphaChannel && !srcLayout->premultiplied &&
!destLayout->hasAlphaChannel && destLayout->storeFromRGB32) {
// Avoid unnecessary premultiply and unpremultiply when converting from unpremultiplied src format.
- fetch = qPixelLayouts[src->format + 1].fetchToARGB32PM;
+ fetch = qPixelLayouts[qt_toPremultipliedFormat(src->format)].fetchToARGB32PM;
if (dest->format == QImage::Format_RGB32)
store = storeRGB32FromARGB32;
else
@@ -239,7 +205,7 @@ void convert_generic(QImageData *dest, const QImageData *src, Qt::ImageConversio
int segments = (qsizetype(src->width) * src->height) >> 16;
segments = std::min(segments, src->height);
- QThreadPool *threadPool = QThreadPool::globalInstance();
+ QThreadPool *threadPool = QThreadPoolPrivate::qtGuiInstance();
if (segments <= 1 || !threadPool || threadPool->contains(QThread::currentThread()))
return convertSegment(0, src->height);
@@ -294,7 +260,7 @@ void convert_generic_over_rgb64(QImageData *dest, const QImageData *src, Qt::Ima
int segments = (qsizetype(src->width) * src->height) >> 16;
segments = std::min(segments, src->height);
- QThreadPool *threadPool = QThreadPool::globalInstance();
+ QThreadPool *threadPool = QThreadPoolPrivate::qtGuiInstance();
if (segments <= 1 || !threadPool || threadPool->contains(QThread::currentThread()))
return convertSegment(0, src->height);
@@ -348,7 +314,7 @@ void convert_generic_over_rgba32f(QImageData *dest, const QImageData *src, Qt::I
int segments = (qsizetype(src->width) * src->height) >> 16;
segments = std::min(segments, src->height);
- QThreadPool *threadPool = QThreadPool::globalInstance();
+ QThreadPool *threadPool = QThreadPoolPrivate::qtGuiInstance();
if (segments <= 1 || !threadPool || threadPool->contains(QThread::currentThread()))
return convertSegment(0, src->height);
@@ -418,7 +384,7 @@ bool convert_generic_inplace(QImageData *data, QImage::Format dst_format, Qt::Im
if (srcLayout->hasAlphaChannel && !srcLayout->premultiplied &&
!destLayout->hasAlphaChannel && destLayout->storeFromRGB32) {
// Avoid unnecessary premultiply and unpremultiply when converting from unpremultiplied src format.
- fetch = qPixelLayouts[data->format + 1].fetchToARGB32PM;
+ fetch = qPixelLayouts[qt_toPremultipliedFormat(data->format)].fetchToARGB32PM;
if (data->format == QImage::Format_RGB32)
store = storeRGB32FromARGB32;
else
@@ -455,7 +421,7 @@ bool convert_generic_inplace(QImageData *data, QImage::Format dst_format, Qt::Im
#ifdef QT_USE_THREAD_PARALLEL_IMAGE_CONVERSIONS
int segments = (qsizetype(data->width) * data->height) >> 16;
segments = std::min(segments, data->height);
- QThreadPool *threadPool = QThreadPool::globalInstance();
+ QThreadPool *threadPool = QThreadPoolPrivate::qtGuiInstance();
if (segments > 1 && threadPool && !threadPool->contains(QThread::currentThread())) {
QSemaphore semaphore;
int y = 0;
@@ -520,9 +486,8 @@ bool convert_generic_inplace_over_rgb64(QImageData *data, QImage::Format dst_for
if (srcLayout->hasAlphaChannel && !srcLayout->premultiplied &&
destLayout->hasAlphaChannel && !destLayout->premultiplied) {
// Avoid unnecessary premultiply and unpremultiply when converting between two unpremultiplied formats.
- // This abuses the fact unpremultiplied formats are always before their premultiplied counterparts.
- fetch = qPixelLayouts[data->format + 1].fetchToRGBA64PM;
- store = qStoreFromRGBA64PM[dst_format + 1];
+ fetch = qPixelLayouts[qt_toPremultipliedFormat(data->format)].fetchToRGBA64PM;
+ store = qStoreFromRGBA64PM[qt_toPremultipliedFormat(dst_format)];
}
auto convertSegment = [=](int yStart, int yEnd) {
@@ -549,7 +514,7 @@ bool convert_generic_inplace_over_rgb64(QImageData *data, QImage::Format dst_for
#ifdef QT_USE_THREAD_PARALLEL_IMAGE_CONVERSIONS
int segments = (qsizetype(data->width) * data->height) >> 16;
segments = std::min(segments, data->height);
- QThreadPool *threadPool = QThreadPool::globalInstance();
+ QThreadPool *threadPool = QThreadPoolPrivate::qtGuiInstance();
if (segments > 1 && threadPool && !threadPool->contains(QThread::currentThread())) {
QSemaphore semaphore;
int y = 0;
@@ -615,9 +580,8 @@ bool convert_generic_inplace_over_rgba32f(QImageData *data, QImage::Format dst_f
if (srcLayout->hasAlphaChannel && !srcLayout->premultiplied &&
destLayout->hasAlphaChannel && !destLayout->premultiplied) {
// Avoid unnecessary premultiply and unpremultiply when converting between two unpremultiplied formats.
- // This abuses the fact unpremultiplied formats are always before their premultiplied counterparts.
- fetch = qFetchToRGBA32F[data->format + 1];
- store = qStoreFromRGBA32F[dst_format + 1];
+ fetch = qFetchToRGBA32F[qt_toPremultipliedFormat(data->format)];
+ store = qStoreFromRGBA32F[qt_toPremultipliedFormat(dst_format)];
}
auto convertSegment = [=](int yStart, int yEnd) {
@@ -644,7 +608,7 @@ bool convert_generic_inplace_over_rgba32f(QImageData *data, QImage::Format dst_f
#ifdef QT_USE_THREAD_PARALLEL_IMAGE_CONVERSIONS
int segments = (qsizetype(data->width) * data->height) >> 16;
segments = std::min(segments, data->height);
- QThreadPool *threadPool = QThreadPool::globalInstance();
+ QThreadPool *threadPool = QThreadPoolPrivate::qtGuiInstance();
if (segments > 1 && threadPool && !threadPool->contains(QThread::currentThread())) {
QSemaphore semaphore;
int y = 0;
@@ -1069,8 +1033,7 @@ static inline uint qUnpremultiplyRgb30(uint rgb30)
case 3:
return rgb30;
}
- Q_UNREACHABLE();
- return 0;
+ Q_UNREACHABLE_RETURN(0);
}
template<bool rgbswap>
@@ -1359,11 +1322,11 @@ static void convert_ARGB32_to_RGBA64(QImageData *dest, const QImageData *src, Qt
const uchar *src_data = src->data;
uchar *dest_data = dest->data;
- const FetchAndConvertPixelsFunc64 fetch = qPixelLayouts[src->format + 1].fetchToRGBA64PM;
+ const FetchAndConvertPixelsFunc64 fetch = qPixelLayouts[qt_toPremultipliedFormat(src->format)].fetchToRGBA64PM;
for (int i = 0; i < src->height; ++i) {
fetch(reinterpret_cast<QRgba64 *>(dest_data), src_data, 0, src->width, nullptr, nullptr);
- src_data += src->bytes_per_line;;
+ src_data += src->bytes_per_line;
dest_data += dest->bytes_per_line;
}
}
@@ -1454,14 +1417,14 @@ static void convert_ARGB_to_gray8(QImageData *dest, const QImageData *src, Qt::I
QColorSpace fromCS = src->colorSpace.isValid() ? src->colorSpace : QColorSpace::SRgb;
QColorTransform tf = QColorSpacePrivate::get(fromCS)->transformationToXYZ();
- QColorTransformPrivate *tfd = QColorTransformPrivate::get(tf);
+ const QColorTransformPrivate *tfd = QColorTransformPrivate::get(tf);
QColorTransformPrivate::TransformFlags flags = Premultiplied
? QColorTransformPrivate::InputPremultiplied
: QColorTransformPrivate::Unpremultiplied;
for (int i = 0; i < src->height; ++i) {
const QRgb *src_line = reinterpret_cast<const QRgb *>(src_data);
- tfd->apply(dest_data, src_line, src->width, flags);
+ tfd->applyReturnGray(dest_data, src_line, src->width, flags);
src_data += sbpl;
dest_data += dbpl;
}
@@ -1484,7 +1447,7 @@ static void convert_ARGB_to_gray16(QImageData *dest, const QImageData *src, Qt::
QColorSpace fromCS = src->colorSpace.isValid() ? src->colorSpace : QColorSpace::SRgb;
QColorTransform tf = QColorSpacePrivate::get(fromCS)->transformationToXYZ();
- QColorTransformPrivate *tfd = QColorTransformPrivate::get(tf);
+ const QColorTransformPrivate *tfd = QColorTransformPrivate::get(tf);
QColorTransformPrivate::TransformFlags flags = Premultiplied
? QColorTransformPrivate::InputPremultiplied
: QColorTransformPrivate::Unpremultiplied;
@@ -1498,7 +1461,7 @@ static void convert_ARGB_to_gray16(QImageData *dest, const QImageData *src, Qt::
const int len = std::min(src->width - j, BufferSize);
for (int k = 0; k < len; ++k)
tmp_line[k] = QRgba64::fromArgb32(src_line[j + k]);
- tfd->apply(dest_line + j, tmp_line, len, flags);
+ tfd->applyReturnGray(dest_line + j, tmp_line, len, flags);
j += len;
}
src_data += sbpl;
@@ -1523,7 +1486,7 @@ static void convert_RGBA64_to_gray8(QImageData *dest, const QImageData *src, Qt:
QColorSpace fromCS = src->colorSpace.isValid() ? src->colorSpace : QColorSpace::SRgb;
QColorTransform tf = QColorSpacePrivate::get(fromCS)->transformationToXYZ();
- QColorTransformPrivate *tfd = QColorTransformPrivate::get(tf);
+ const QColorTransformPrivate *tfd = QColorTransformPrivate::get(tf);
QColorTransformPrivate::TransformFlags flags = Premultiplied
? QColorTransformPrivate::InputPremultiplied
: QColorTransformPrivate::Unpremultiplied;
@@ -1535,7 +1498,7 @@ static void convert_RGBA64_to_gray8(QImageData *dest, const QImageData *src, Qt:
int j = 0;
while (j < src->width) {
const int len = std::min(src->width - j, BufferSize);
- tfd->apply(gray_line, src_line + j, len, flags);
+ tfd->applyReturnGray(gray_line, src_line + j, len, flags);
for (int k = 0; k < len; ++k)
dest_line[j + k] = qt_div_257(gray_line[k]);
j += len;
@@ -1562,7 +1525,7 @@ static void convert_RGBA64_to_gray16(QImageData *dest, const QImageData *src, Qt
QColorSpace fromCS = src->colorSpace.isValid() ? src->colorSpace : QColorSpace::SRgb;
QColorTransform tf = QColorSpacePrivate::get(fromCS)->transformationToXYZ();
- QColorTransformPrivate *tfd = QColorTransformPrivate::get(tf);
+ const QColorTransformPrivate *tfd = QColorTransformPrivate::get(tf);
QColorTransformPrivate::TransformFlags flags = Premultiplied
? QColorTransformPrivate::InputPremultiplied
: QColorTransformPrivate::Unpremultiplied;
@@ -1570,7 +1533,7 @@ static void convert_RGBA64_to_gray16(QImageData *dest, const QImageData *src, Qt
for (int i = 0; i < src->height; ++i) {
const QRgba64 *src_line = reinterpret_cast<const QRgba64 *>(src_data);
quint16 *dest_line = reinterpret_cast<quint16 *>(dest_data);
- tfd->apply(dest_line, src_line, src->width, flags);
+ tfd->applyReturnGray(dest_line, src_line, src->width, flags);
src_data += sbpl;
dest_data += dbpl;
}
@@ -2492,6 +2455,34 @@ static bool convert_Grayscale8_to_Indexed8_inplace(QImageData *data, Qt::ImageCo
return true;
}
+template <bool SourceIsPremultiplied>
+static void convert_ARGB32_to_CMYK8888(QImageData *dest, const QImageData *src, Qt::ImageConversionFlags)
+{
+ Q_ASSERT(src->format == QImage::Format_RGB32 ||
+ src->format == QImage::Format_ARGB32 ||
+ src->format == QImage::Format_ARGB32_Premultiplied);
+ Q_ASSERT(dest->format == QImage::Format_CMYK8888);
+ Q_ASSERT(src->width == dest->width);
+ Q_ASSERT(src->height == dest->height);
+
+ const uchar *src_data = src->data;
+ uchar *dest_data = dest->data;
+ for (int y = 0; y < src->height; ++y) {
+ const QRgb *srcRgba = reinterpret_cast<const QRgb *>(src_data);
+ uint *destCmyk = reinterpret_cast<uint *>(dest_data);
+
+ for (int x = 0; x < src->width; ++x) {
+ QRgb sourcePixel = srcRgba[x];
+ if constexpr (SourceIsPremultiplied)
+ sourcePixel = qUnpremultiply(sourcePixel);
+
+ destCmyk[x] = QCmyk32::fromRgba(sourcePixel).toUint();
+ }
+
+ src_data += src->bytes_per_line;;
+ dest_data += dest->bytes_per_line;
+ }
+}
// first index source, second dest
Image_Converter qimage_converter_map[QImage::NImageFormats][QImage::NImageFormats] = {};
@@ -2628,6 +2619,11 @@ static void qInitImageConversions()
qimage_converter_map[QImage::Format_RGBX32FPx4][QImage::Format_RGBA32FPx4] = convert_passthrough;
qimage_converter_map[QImage::Format_RGBX32FPx4][QImage::Format_RGBA32FPx4_Premultiplied] = convert_passthrough;
+ qimage_converter_map[QImage::Format_CMYK8888][QImage::Format_CMYK8888] = convert_passthrough;
+ qimage_converter_map[QImage::Format_RGB32][QImage::Format_CMYK8888] = convert_ARGB32_to_CMYK8888<false>;
+ qimage_converter_map[QImage::Format_ARGB32][QImage::Format_CMYK8888] = convert_ARGB32_to_CMYK8888<false>;
+ qimage_converter_map[QImage::Format_ARGB32_Premultiplied][QImage::Format_CMYK8888] = convert_ARGB32_to_CMYK8888<true>;
+
// Inline converters:
qimage_inplace_converter_map[QImage::Format_Indexed8][QImage::Format_Grayscale8] =
convert_Indexed8_to_Grayscale8_inplace;