diff options
Diffstat (limited to 'src/gui/image/qimage_conversions.cpp')
-rw-r--r-- | src/gui/image/qimage_conversions.cpp | 76 |
1 files changed, 54 insertions, 22 deletions
diff --git a/src/gui/image/qimage_conversions.cpp b/src/gui/image/qimage_conversions.cpp index fa75bed3c8..a806954df2 100644 --- a/src/gui/image/qimage_conversions.cpp +++ b/src/gui/image/qimage_conversions.cpp @@ -4,6 +4,7 @@ #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> @@ -15,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 @@ -164,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 @@ -203,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); @@ -258,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); @@ -312,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); @@ -382,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 @@ -419,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; @@ -484,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) { @@ -513,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; @@ -579,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) { @@ -608,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; @@ -1033,8 +1033,7 @@ static inline uint qUnpremultiplyRgb30(uint rgb30) case 3: return rgb30; } - Q_UNREACHABLE(); - return 0; + Q_UNREACHABLE_RETURN(0); } template<bool rgbswap> @@ -1323,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; } } @@ -1425,7 +1424,7 @@ static void convert_ARGB_to_gray8(QImageData *dest, const QImageData *src, Qt::I 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; } @@ -1462,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; @@ -1499,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; @@ -1534,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; } @@ -2456,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] = {}; @@ -2592,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; |