diff options
Diffstat (limited to 'src/gui/painting/qpixellayout.cpp')
-rw-r--r-- | src/gui/painting/qpixellayout.cpp | 1010 |
1 files changed, 931 insertions, 79 deletions
diff --git a/src/gui/painting/qpixellayout.cpp b/src/gui/painting/qpixellayout.cpp index ca6bca344f..4f2f0ae13a 100644 --- a/src/gui/painting/qpixellayout.cpp +++ b/src/gui/painting/qpixellayout.cpp @@ -1,41 +1,5 @@ -/**************************************************************************** -** -** Copyright (C) 2020 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 <qglobal.h> @@ -43,6 +7,7 @@ #include "qpixellayout_p.h" #include "qrgba64_p.h" #include <QtCore/private/qsimd_p.h> +#include <QtGui/private/qcmyk_p.h> QT_BEGIN_NAMESPACE @@ -55,6 +20,9 @@ template<QImage::Format> constexpr uint blueShift(); template<QImage::Format> constexpr uint alphaWidth(); template<QImage::Format> constexpr uint alphaShift(); +template<> constexpr uint redWidth<QImage::Format_RGB32>() { return 8; } +template<> constexpr uint redWidth<QImage::Format_ARGB32>() { return 8; } +template<> constexpr uint redWidth<QImage::Format_ARGB32_Premultiplied>() { return 8; } template<> constexpr uint redWidth<QImage::Format_RGB16>() { return 5; } template<> constexpr uint redWidth<QImage::Format_RGB444>() { return 4; } template<> constexpr uint redWidth<QImage::Format_RGB555>() { return 5; } @@ -69,6 +37,9 @@ template<> constexpr uint redWidth<QImage::Format_RGBX8888>() { return 8; } template<> constexpr uint redWidth<QImage::Format_RGBA8888>() { return 8; } template<> constexpr uint redWidth<QImage::Format_RGBA8888_Premultiplied>() { return 8; } +template<> constexpr uint redShift<QImage::Format_RGB32>() { return 16; } +template<> constexpr uint redShift<QImage::Format_ARGB32>() { return 16; } +template<> constexpr uint redShift<QImage::Format_ARGB32_Premultiplied>() { return 16; } template<> constexpr uint redShift<QImage::Format_RGB16>() { return 11; } template<> constexpr uint redShift<QImage::Format_RGB444>() { return 8; } template<> constexpr uint redShift<QImage::Format_RGB555>() { return 10; } @@ -88,6 +59,9 @@ template<> constexpr uint redShift<QImage::Format_RGBX8888>() { return 0; } template<> constexpr uint redShift<QImage::Format_RGBA8888>() { return 0; } template<> constexpr uint redShift<QImage::Format_RGBA8888_Premultiplied>() { return 0; } #endif +template<> constexpr uint greenWidth<QImage::Format_RGB32>() { return 8; } +template<> constexpr uint greenWidth<QImage::Format_ARGB32>() { return 8; } +template<> constexpr uint greenWidth<QImage::Format_ARGB32_Premultiplied>() { return 8; } template<> constexpr uint greenWidth<QImage::Format_RGB16>() { return 6; } template<> constexpr uint greenWidth<QImage::Format_RGB444>() { return 4; } template<> constexpr uint greenWidth<QImage::Format_RGB555>() { return 5; } @@ -102,6 +76,9 @@ template<> constexpr uint greenWidth<QImage::Format_RGBX8888>() { return 8; } template<> constexpr uint greenWidth<QImage::Format_RGBA8888>() { return 8; } template<> constexpr uint greenWidth<QImage::Format_RGBA8888_Premultiplied>() { return 8; } +template<> constexpr uint greenShift<QImage::Format_RGB32>() { return 8; } +template<> constexpr uint greenShift<QImage::Format_ARGB32>() { return 8; } +template<> constexpr uint greenShift<QImage::Format_ARGB32_Premultiplied>() { return 8; } template<> constexpr uint greenShift<QImage::Format_RGB16>() { return 5; } template<> constexpr uint greenShift<QImage::Format_RGB444>() { return 4; } template<> constexpr uint greenShift<QImage::Format_RGB555>() { return 5; } @@ -121,6 +98,9 @@ template<> constexpr uint greenShift<QImage::Format_RGBX8888>() { return 8; } template<> constexpr uint greenShift<QImage::Format_RGBA8888>() { return 8; } template<> constexpr uint greenShift<QImage::Format_RGBA8888_Premultiplied>() { return 8; } #endif +template<> constexpr uint blueWidth<QImage::Format_RGB32>() { return 8; } +template<> constexpr uint blueWidth<QImage::Format_ARGB32>() { return 8; } +template<> constexpr uint blueWidth<QImage::Format_ARGB32_Premultiplied>() { return 8; } template<> constexpr uint blueWidth<QImage::Format_RGB16>() { return 5; } template<> constexpr uint blueWidth<QImage::Format_RGB444>() { return 4; } template<> constexpr uint blueWidth<QImage::Format_RGB555>() { return 5; } @@ -135,6 +115,9 @@ template<> constexpr uint blueWidth<QImage::Format_RGBX8888>() { return 8; } template<> constexpr uint blueWidth<QImage::Format_RGBA8888>() { return 8; } template<> constexpr uint blueWidth<QImage::Format_RGBA8888_Premultiplied>() { return 8; } +template<> constexpr uint blueShift<QImage::Format_RGB32>() { return 0; } +template<> constexpr uint blueShift<QImage::Format_ARGB32>() { return 0; } +template<> constexpr uint blueShift<QImage::Format_ARGB32_Premultiplied>() { return 0; } template<> constexpr uint blueShift<QImage::Format_RGB16>() { return 0; } template<> constexpr uint blueShift<QImage::Format_RGB444>() { return 0; } template<> constexpr uint blueShift<QImage::Format_RGB555>() { return 0; } @@ -154,6 +137,9 @@ template<> constexpr uint blueShift<QImage::Format_RGBX8888>() { return 16; } template<> constexpr uint blueShift<QImage::Format_RGBA8888>() { return 16; } template<> constexpr uint blueShift<QImage::Format_RGBA8888_Premultiplied>() { return 16; } #endif +template<> constexpr uint alphaWidth<QImage::Format_RGB32>() { return 0; } +template<> constexpr uint alphaWidth<QImage::Format_ARGB32>() { return 8; } +template<> constexpr uint alphaWidth<QImage::Format_ARGB32_Premultiplied>() { return 8; } template<> constexpr uint alphaWidth<QImage::Format_RGB16>() { return 0; } template<> constexpr uint alphaWidth<QImage::Format_RGB444>() { return 0; } template<> constexpr uint alphaWidth<QImage::Format_RGB555>() { return 0; } @@ -168,6 +154,9 @@ template<> constexpr uint alphaWidth<QImage::Format_RGBX8888>() { return 0; } template<> constexpr uint alphaWidth<QImage::Format_RGBA8888>() { return 8; } template<> constexpr uint alphaWidth<QImage::Format_RGBA8888_Premultiplied>() { return 8; } +template<> constexpr uint alphaShift<QImage::Format_RGB32>() { return 24; } +template<> constexpr uint alphaShift<QImage::Format_ARGB32>() { return 24; } +template<> constexpr uint alphaShift<QImage::Format_ARGB32_Premultiplied>() { return 24; } template<> constexpr uint alphaShift<QImage::Format_RGB16>() { return 0; } template<> constexpr uint alphaShift<QImage::Format_RGB444>() { return 0; } template<> constexpr uint alphaShift<QImage::Format_RGB555>() { return 0; } @@ -189,6 +178,9 @@ template<> constexpr uint alphaShift<QImage::Format_RGBA8888_Premultiplied>() { #endif template<QImage::Format> constexpr QPixelLayout::BPP bitsPerPixel(); +template<> constexpr QPixelLayout::BPP bitsPerPixel<QImage::Format_RGB32>() { return QPixelLayout::BPP32; } +template<> constexpr QPixelLayout::BPP bitsPerPixel<QImage::Format_ARGB32>() { return QPixelLayout::BPP32; } +template<> constexpr QPixelLayout::BPP bitsPerPixel<QImage::Format_ARGB32_Premultiplied>() { return QPixelLayout::BPP32; } template<> constexpr QPixelLayout::BPP bitsPerPixel<QImage::Format_RGB16>() { return QPixelLayout::BPP16; } template<> constexpr QPixelLayout::BPP bitsPerPixel<QImage::Format_RGB444>() { return QPixelLayout::BPP16; } template<> constexpr QPixelLayout::BPP bitsPerPixel<QImage::Format_RGB555>() { return QPixelLayout::BPP16; } @@ -218,6 +210,75 @@ inline void QT_FASTCALL storePixel<QPixelLayout::BPP24>(uchar *dest, int index, reinterpret_cast<quint24 *>(dest)[index] = quint24(pixel); } +template <QPixelLayout::BPP bpp> static +inline uint QT_FASTCALL fetchPixel(const uchar *, int) +{ + Q_UNREACHABLE_RETURN(0); +} + +template <> +inline uint QT_FASTCALL fetchPixel<QPixelLayout::BPP1LSB>(const uchar *src, int index) +{ + return (src[index >> 3] >> (index & 7)) & 1; +} + +template <> +inline uint QT_FASTCALL fetchPixel<QPixelLayout::BPP1MSB>(const uchar *src, int index) +{ + return (src[index >> 3] >> (~index & 7)) & 1; +} + +template <> +inline uint QT_FASTCALL fetchPixel<QPixelLayout::BPP8>(const uchar *src, int index) +{ + return src[index]; +} + +template <> +inline uint QT_FASTCALL fetchPixel<QPixelLayout::BPP16>(const uchar *src, int index) +{ + return reinterpret_cast<const quint16 *>(src)[index]; +} + +template <> +inline uint QT_FASTCALL fetchPixel<QPixelLayout::BPP24>(const uchar *src, int index) +{ + return reinterpret_cast<const quint24 *>(src)[index]; +} + +template <> +inline uint QT_FASTCALL fetchPixel<QPixelLayout::BPP32>(const uchar *src, int index) +{ + return reinterpret_cast<const uint *>(src)[index]; +} + +template <> +[[maybe_unused]] +inline uint QT_FASTCALL fetchPixel<QPixelLayout::BPP64>(const uchar *src, int index) +{ + // We have to do the conversion in fetch to fit into a 32bit uint + QRgba64 c = reinterpret_cast<const QRgba64 *>(src)[index]; + return c.toArgb32(); +} + +template <> +[[maybe_unused]] +inline uint QT_FASTCALL fetchPixel<QPixelLayout::BPP16FPx4>(const uchar *src, int index) +{ + // We have to do the conversion in fetch to fit into a 32bit uint + QRgbaFloat16 c = reinterpret_cast<const QRgbaFloat16 *>(src)[index]; + return c.toArgb32(); +} + +template <> +[[maybe_unused]] +inline uint QT_FASTCALL fetchPixel<QPixelLayout::BPP32FPx4>(const uchar *src, int index) +{ + // We have to do the conversion in fetch to fit into a 32bit uint + QRgbaFloat32 c = reinterpret_cast<const QRgbaFloat32 *>(src)[index]; + return c.toArgb32(); +} + template<QImage::Format Format> static inline uint convertPixelToRGB32(uint s) { @@ -269,7 +330,7 @@ static const uint *QT_FASTCALL fetchRGBToRGB32(uint *buffer, const uchar *src, i } #endif for (int i = 0; i < count; ++i) - buffer[i] = convertPixelToRGB32<Format>(qFetchPixel<BPP>(src, index + i)); + buffer[i] = convertPixelToRGB32<Format>(fetchPixel<BPP>(src, index + i)); return buffer; } @@ -293,7 +354,22 @@ static const QRgba64 *QT_FASTCALL fetchRGBToRGB64(QRgba64 *buffer, const uchar * const QList<QRgb> *, QDitherInfo *) { for (int i = 0; i < count; ++i) - buffer[i] = convertPixelToRGB64<Format>(qFetchPixel<bitsPerPixel<Format>()>(src, index + i)); + buffer[i] = convertPixelToRGB64<Format>(fetchPixel<bitsPerPixel<Format>()>(src, index + i)); + return buffer; +} + +template<QImage::Format Format> +static Q_ALWAYS_INLINE QRgbaFloat32 convertPixelToRGB32F(uint s) +{ + return QRgbaFloat32::fromArgb32(convertPixelToRGB32<Format>(s)); +} + +template<QImage::Format Format> +static const QRgbaFloat32 *QT_FASTCALL fetchRGBToRGB32F(QRgbaFloat32 *buffer, const uchar *src, int index, int count, + const QList<QRgb> *, QDitherInfo *) +{ + for (int i = 0; i < count; ++i) + buffer[i] = convertPixelToRGB32F<Format>(fetchPixel<bitsPerPixel<Format>()>(src, index + i)); return buffer; } @@ -360,7 +436,7 @@ static const uint *QT_FASTCALL fetchARGBPMToARGB32PM(uint *buffer, const uchar * } #endif for (int i = 0; i < count; ++i) - buffer[i] = convertPixelToARGB32PM<Format>(qFetchPixel<BPP>(src, index + i)); + buffer[i] = convertPixelToARGB32PM<Format>(fetchPixel<BPP>(src, index + i)); return buffer; } @@ -385,7 +461,33 @@ static const QRgba64 *QT_FASTCALL fetchARGBPMToRGBA64PM(QRgba64 *buffer, const u { constexpr QPixelLayout::BPP bpp = bitsPerPixel<Format>(); for (int i = 0; i < count; ++i) - buffer[i] = convertPixelToRGBA64PM<Format>(qFetchPixel<bpp>(src, index + i)); + buffer[i] = convertPixelToRGBA64PM<Format>(fetchPixel<bpp>(src, index + i)); + return buffer; +} + +template<QImage::Format Format> +static Q_ALWAYS_INLINE QRgbaFloat32 convertPixelToRGBA32F(uint s) +{ + return QRgbaFloat32::fromArgb32(convertPixelToARGB32PM<Format>(s)); +} + +template<QImage::Format Format> +static const QRgbaFloat32 *QT_FASTCALL fetchARGBPMToRGBA32F(QRgbaFloat32 *buffer, const uchar *src, int index, int count, + const QList<QRgb> *, QDitherInfo *) +{ + constexpr QPixelLayout::BPP bpp = bitsPerPixel<Format>(); + for (int i = 0; i < count; ++i) + buffer[i] = convertPixelToRGBA32F<Format>(fetchPixel<bpp>(src, index + i)); + return buffer; +} + +template<QImage::Format Format> +static const QRgbaFloat32 *QT_FASTCALL fetchARGBToRGBA32F(QRgbaFloat32 *buffer, const uchar *src, int index, int count, + const QList<QRgb> *, QDitherInfo *) +{ + constexpr QPixelLayout::BPP bpp = bitsPerPixel<Format>(); + for (int i = 0; i < count; ++i) + buffer[i] = convertPixelToRGBA32F<Format>(fetchPixel<bpp>(src, index + i)).premultiplied(); return buffer; } @@ -518,7 +620,7 @@ static void QT_FASTCALL rbSwap(uchar *dst, const uchar *src, int count) constexpr QPixelLayout::BPP bpp = bitsPerPixel<Format>(); for (int i = 0; i < count; ++i) { - const uint c = qFetchPixel<bpp>(src, i); + const uint c = fetchPixel<bpp>(src, i); const uint r = (c >> rShift) & redBlueMask; const uint b = (c >> bShift) & redBlueMask; const uint t = (c & alphaGreenMask) @@ -589,6 +691,27 @@ static void QT_FASTCALL rbSwap_4x16(uchar *d, const uchar *s, int count) } } +static void QT_FASTCALL rbSwap_4x32(uchar *d, const uchar *s, int count) +{ + const uint *src = reinterpret_cast<const uint *>(s); + uint *dest = reinterpret_cast<uint *>(d); + if (src != dest) { + for (int i = 0; i < count; ++i) { + dest[i * 4 + 0] = src[i * 4 + 2]; + dest[i * 4 + 1] = src[i * 4 + 1]; + dest[i * 4 + 2] = src[i * 4 + 0]; + dest[i * 4 + 3] = src[i * 4 + 3]; + } + } else { + for (int i = 0; i < count; ++i) { + const uint r = src[i * 4 + 0]; + const uint b = src[i * 4 + 2]; + dest[i * 4 + 0] = b; + dest[i * 4 + 2] = r; + } + } +} + template<QImage::Format Format> constexpr static inline QPixelLayout pixelLayoutRGB() { return QPixelLayout{ @@ -632,7 +755,7 @@ static const uint *QT_FASTCALL fetchIndexedToARGB32PM(uint *buffer, const uchar const QList<QRgb> *clut, QDitherInfo *) { for (int i = 0; i < count; ++i) { - const uint s = qFetchPixel<BPP>(src, index + i); + const uint s = fetchPixel<BPP>(src, index + i); buffer[i] = qPremultiply(clut->at(s)); } return buffer; @@ -643,17 +766,29 @@ static const QRgba64 *QT_FASTCALL fetchIndexedToRGBA64PM(QRgba64 *buffer, const const QList<QRgb> *clut, QDitherInfo *) { for (int i = 0; i < count; ++i) { - const uint s = qFetchPixel<BPP>(src, index + i); + const uint s = fetchPixel<BPP>(src, index + i); buffer[i] = QRgba64::fromArgb32(clut->at(s)).premultiplied(); } return buffer; } -static const QRgba64 *QT_FASTCALL convertIndexedToRGBA64PM(QRgba64 *buffer, const uint *src, int count, - const QList<QRgb> *clut, QDitherInfo *) +template<QPixelLayout::BPP BPP> +static const QRgbaFloat32 *QT_FASTCALL fetchIndexedToRGBA32F(QRgbaFloat32 *buffer, const uchar *src, int index, int count, + const QList<QRgb> *clut, QDitherInfo *) +{ + for (int i = 0; i < count; ++i) { + const uint s = fetchPixel<BPP>(src, index + i); + buffer[i] = QRgbaFloat32::fromArgb32(clut->at(s)).premultiplied(); + } + return buffer; +} + +template<typename QRgba> +static const QRgba *QT_FASTCALL convertIndexedTo(QRgba *buffer, const uint *src, int count, + const QList<QRgb> *clut, QDitherInfo *) { for (int i = 0; i < count; ++i) - buffer[i] = QRgba64::fromArgb32(clut->at(src[i])).premultiplied(); + buffer[i] = QRgba::fromArgb32(clut->at(src[i])).premultiplied(); return buffer; } @@ -731,18 +866,21 @@ static const uint *QT_FASTCALL fetchAlpha8ToRGB32(uint *buffer, const uchar *src return buffer; } -static const QRgba64 *QT_FASTCALL convertAlpha8ToRGB64(QRgba64 *buffer, const uint *src, int count, - const QList<QRgb> *, QDitherInfo *) +template<typename QRgba> +static const QRgba *QT_FASTCALL convertAlpha8To(QRgba *buffer, const uint *src, int count, + const QList<QRgb> *, QDitherInfo *) { for (int i = 0; i < count; ++i) - buffer[i] = QRgba64::fromRgba(0, 0, 0, src[i]); + buffer[i] = QRgba::fromRgba(0, 0, 0, src[i]); return buffer; } -static const QRgba64 *QT_FASTCALL fetchAlpha8ToRGB64(QRgba64 *buffer, const uchar *src, int index, int count, - const QList<QRgb> *, QDitherInfo *) + +template<typename QRgba> +static const QRgba *QT_FASTCALL fetchAlpha8To(QRgba *buffer, const uchar *src, int index, int count, + const QList<QRgb> *, QDitherInfo *) { for (int i = 0; i < count; ++i) - buffer[i] = QRgba64::fromRgba(0, 0, 0, src[index + i]); + buffer[i] = QRgba::fromRgba(0, 0, 0, src[index + i]); return buffer; } @@ -764,20 +902,22 @@ static const uint *QT_FASTCALL fetchGrayscale8ToRGB32(uint *buffer, const uchar return buffer; } -static const QRgba64 *QT_FASTCALL convertGrayscale8ToRGB64(QRgba64 *buffer, const uint *src, int count, - const QList<QRgb> *, QDitherInfo *) +template<typename QRgba> +static const QRgba *QT_FASTCALL convertGrayscale8To(QRgba *buffer, const uint *src, int count, + const QList<QRgb> *, QDitherInfo *) { for (int i = 0; i < count; ++i) - buffer[i] = QRgba64::fromRgba(src[i], src[i], src[i], 255); + buffer[i] = QRgba::fromRgba(src[i], src[i], src[i], 255); return buffer; } -static const QRgba64 *QT_FASTCALL fetchGrayscale8ToRGB64(QRgba64 *buffer, const uchar *src, int index, int count, - const QList<QRgb> *, QDitherInfo *) +template<typename QRgba> +static const QRgba *QT_FASTCALL fetchGrayscale8To(QRgba *buffer, const uchar *src, int index, int count, + const QList<QRgb> *, QDitherInfo *) { for (int i = 0; i < count; ++i) { const uint s = src[index + i]; - buffer[i] = QRgba64::fromRgba(s, s, s, 255); + buffer[i] = QRgba::fromRgba(s, s, s, 255); } return buffer; } @@ -789,7 +929,6 @@ static void QT_FASTCALL convertGrayscale16ToRGB32(uint *buffer, int count, const buffer[i] = qRgb(x, x, x); } } - static const uint *QT_FASTCALL fetchGrayscale16ToRGB32(uint *buffer, const uchar *src, int index, int count, const QList<QRgb> *, QDitherInfo *) { @@ -801,20 +940,22 @@ static const uint *QT_FASTCALL fetchGrayscale16ToRGB32(uint *buffer, const uchar return buffer; } -static const QRgba64 *QT_FASTCALL convertGrayscale16ToRGBA64(QRgba64 *buffer, const uint *src, int count, - const QList<QRgb> *, QDitherInfo *) +template<typename QRgba> +static const QRgba *QT_FASTCALL convertGrayscale16To(QRgba *buffer, const uint *src, int count, + const QList<QRgb> *, QDitherInfo *) { for (int i = 0; i < count; ++i) - buffer[i] = QRgba64::fromRgba64(src[i], src[i], src[i], 65535); + buffer[i] = QRgba::fromRgba64(src[i], src[i], src[i], 65535); return buffer; } -static const QRgba64 *QT_FASTCALL fetchGrayscale16ToRGBA64(QRgba64 *buffer, const uchar *src, int index, int count, - const QList<QRgb> *, QDitherInfo *) +template<typename QRgba> +static const QRgba *QT_FASTCALL fetchGrayscale16To(QRgba *buffer, const uchar *src, int index, int count, + const QList<QRgb> *, QDitherInfo *) { const unsigned short *s = reinterpret_cast<const unsigned short *>(src) + index; for (int i = 0; i < count; ++i) { - buffer[i] = QRgba64::fromRgba64(s[i], s[i], s[i], 65535); + buffer[i] = QRgba::fromRgba64(s[i], s[i], s[i], 65535); } return buffer; } @@ -1047,10 +1188,12 @@ static const QRgba64 *QT_FASTCALL fetchRGBA64ToRGBA64PM(QRgba64 *buffer, const u const QRgba64 *s = reinterpret_cast<const QRgba64 *>(src) + index; #ifdef __SSE2__ for (int i = 0; i < count; ++i) { + const auto a = s[i].alpha(); __m128i vs = _mm_loadl_epi64((const __m128i *)(s + i)); __m128i va = _mm_shufflelo_epi16(vs, _MM_SHUFFLE(3, 3, 3, 3)); vs = multiplyAlpha65535(vs, va); _mm_storel_epi64((__m128i *)(buffer + i), vs); + buffer[i].setAlpha(a); } #else for (int i = 0; i < count; ++i) @@ -1212,6 +1355,44 @@ static const QRgba64 *QT_FASTCALL fetchA2RGB30PMToRGBA64PM(QRgba64 *buffer, cons return convertA2RGB30PMToRGBA64PM<PixelOrder>(buffer, reinterpret_cast<const uint *>(src) + index, count, nullptr, nullptr); } +template<enum QtPixelOrder> inline QRgbaFloat32 qConvertA2rgb30ToRgbaFP(uint rgb); + +template<> +inline QRgbaFloat32 qConvertA2rgb30ToRgbaFP<PixelOrderBGR>(uint rgb) +{ + float alpha = (rgb >> 30) * (1.f/3.f); + float blue = ((rgb >> 20) & 0x3ff) * (1.f/1023.f); + float green = ((rgb >> 10) & 0x3ff) * (1.f/1023.f); + float red = (rgb & 0x3ff) * (1.f/1023.f); + return QRgbaFloat32{ red, green, blue, alpha }; +} + +template<> +inline QRgbaFloat32 qConvertA2rgb30ToRgbaFP<PixelOrderRGB>(uint rgb) +{ + float alpha = (rgb >> 30) * (1.f/3.f); + float red = ((rgb >> 20) & 0x3ff) * (1.f/1023.f); + float green = ((rgb >> 10) & 0x3ff) * (1.f/1023.f); + float blue = (rgb & 0x3ff) * (1.f/1023.f); + return QRgbaFloat32{ red, green, blue, alpha }; +} + +template<QtPixelOrder PixelOrder> +static const QRgbaFloat32 *QT_FASTCALL convertA2RGB30PMToRGBA32F(QRgbaFloat32 *buffer, const uint *src, int count, + const QList<QRgb> *, QDitherInfo *) +{ + for (int i = 0; i < count; ++i) + buffer[i] = qConvertA2rgb30ToRgbaFP<PixelOrder>(src[i]); + return buffer; +} + +template<QtPixelOrder PixelOrder> +static const QRgbaFloat32 *QT_FASTCALL fetchRGB30ToRGBA32F(QRgbaFloat32 *buffer, const uchar *src, int index, int count, + const QList<QRgb> *, QDitherInfo *) +{ + return convertA2RGB30PMToRGBA32F<PixelOrder>(buffer, reinterpret_cast<const uint *>(src) + index, count, nullptr, nullptr); +} + template<QtPixelOrder PixelOrder> static void QT_FASTCALL storeA2RGB30PMFromARGB32PM(uchar *dest, const uint *src, int index, int count, const QList<QRgb> *, QDitherInfo *) @@ -1365,22 +1546,194 @@ static void QT_FASTCALL storeRGBA64FromARGB32(uchar *dest, const uint *src, int d[i] = QRgba64::fromArgb32(src[i]); } +static const uint *QT_FASTCALL fetchRGB16FToRGB32(uint *buffer, const uchar *src, int index, int count, + const QList<QRgb> *, QDitherInfo *) +{ + const QRgbaFloat16 *s = reinterpret_cast<const QRgbaFloat16 *>(src) + index; + for (int i = 0; i < count; ++i) + buffer[i] = s[i].toArgb32(); + return buffer; +} + +static void QT_FASTCALL storeRGB16FFromRGB32(uchar *dest, const uint *src, int index, int count, + const QList<QRgb> *, QDitherInfo *) +{ + QRgbaFloat16 *d = reinterpret_cast<QRgbaFloat16 *>(dest) + index; + for (int i = 0; i < count; ++i) + d[i] = QRgbaFloat16::fromArgb32(src[i]); +} + +static const uint *QT_FASTCALL fetchRGBA16FToARGB32PM(uint *buffer, const uchar *src, int index, int count, + const QList<QRgb> *, QDitherInfo *) +{ + const QRgbaFloat16 *s = reinterpret_cast<const QRgbaFloat16 *>(src) + index; + for (int i = 0; i < count; ++i) + buffer[i] = s[i].premultiplied().toArgb32(); + return buffer; +} + +static const QRgba64 *QT_FASTCALL fetchRGBA16FToRGBA64PM(QRgba64 *buffer, const uchar *src, int index, int count, + const QList<QRgb> *, QDitherInfo *) +{ + const QRgbaFloat16 *s = reinterpret_cast<const QRgbaFloat16 *>(src) + index; + for (int i = 0; i < count; ++i) { + QRgbaFloat16 c = s[i].premultiplied(); + buffer[i] = QRgba64::fromRgba64(c.red16(), c.green16(), c.blue16(), c.alpha16()); + } + return buffer; +} + +static void QT_FASTCALL storeRGBA16FFromARGB32PM(uchar *dest, const uint *src, int index, int count, + const QList<QRgb> *, QDitherInfo *) +{ + QRgbaFloat16 *d = reinterpret_cast<QRgbaFloat16 *>(dest) + index; + for (int i = 0; i < count; ++i) + d[i] = QRgbaFloat16::fromArgb32(src[i]).unpremultiplied(); +} + +static const QRgba64 *QT_FASTCALL fetchRGBA16FPMToRGBA64PM(QRgba64 *buffer, const uchar *src, int index, int count, + const QList<QRgb> *, QDitherInfo *) +{ + const QRgbaFloat16 *s = reinterpret_cast<const QRgbaFloat16 *>(src) + index; + for (int i = 0; i < count; ++i) { + QRgbaFloat16 c = s[i]; + buffer[i] = QRgba64::fromRgba64(c.red16(), c.green16(), c.blue16(), c.alpha16()); + } + return buffer; +} + +static const uint *QT_FASTCALL fetchRGB32FToRGB32(uint *buffer, const uchar *src, int index, int count, + const QList<QRgb> *, QDitherInfo *) +{ + const QRgbaFloat32 *s = reinterpret_cast<const QRgbaFloat32 *>(src) + index; + for (int i = 0; i < count; ++i) + buffer[i] = s[i].toArgb32(); + return buffer; +} + +static void QT_FASTCALL storeRGB32FFromRGB32(uchar *dest, const uint *src, int index, int count, + const QList<QRgb> *, QDitherInfo *) +{ + QRgbaFloat32 *d = reinterpret_cast<QRgbaFloat32 *>(dest) + index; + for (int i = 0; i < count; ++i) + d[i] = QRgbaFloat32::fromArgb32(src[i]); +} + +static const uint *QT_FASTCALL fetchRGBA32FToARGB32PM(uint *buffer, const uchar *src, int index, int count, + const QList<QRgb> *, QDitherInfo *) +{ + const QRgbaFloat32 *s = reinterpret_cast<const QRgbaFloat32 *>(src) + index; + for (int i = 0; i < count; ++i) + buffer[i] = s[i].premultiplied().toArgb32(); + return buffer; +} + +static const QRgba64 *QT_FASTCALL fetchRGBA32FToRGBA64PM(QRgba64 *buffer, const uchar *src, int index, int count, + const QList<QRgb> *, QDitherInfo *) +{ + const QRgbaFloat32 *s = reinterpret_cast<const QRgbaFloat32 *>(src) + index; + for (int i = 0; i < count; ++i) { + QRgbaFloat32 c = s[i].premultiplied(); + buffer[i] = QRgba64::fromRgba64(c.red16(), c.green16(), c.blue16(), c.alpha16()); + } + return buffer; +} + +static void QT_FASTCALL storeRGBA32FFromARGB32PM(uchar *dest, const uint *src, int index, int count, + const QList<QRgb> *, QDitherInfo *) +{ + QRgbaFloat32 *d = reinterpret_cast<QRgbaFloat32 *>(dest) + index; + for (int i = 0; i < count; ++i) + d[i] = QRgbaFloat32::fromArgb32(src[i]).unpremultiplied(); +} + +static const QRgba64 *QT_FASTCALL fetchRGBA32FPMToRGBA64PM(QRgba64 *buffer, const uchar *src, int index, int count, + const QList<QRgb> *, QDitherInfo *) +{ + const QRgbaFloat32 *s = reinterpret_cast<const QRgbaFloat32 *>(src) + index; + for (int i = 0; i < count; ++i) { + QRgbaFloat32 c = s[i]; + buffer[i] = QRgba64::fromRgba64(c.red16(), c.green16(), c.blue16(), c.alpha16()); + } + return buffer; +} + +inline const uint *qt_convertCMYK8888ToARGB32PM(uint *buffer, const uint *src, int count) +{ + UNALIASED_CONVERSION_LOOP(buffer, src, count, [](uint s) { + const QColor color = QCmyk32::fromCmyk32(s).toColor(); + return color.rgba(); + }); + return buffer; +} + +static void QT_FASTCALL convertCMYK8888ToARGB32PM(uint *buffer, int count, const QList<QRgb> *) +{ + qt_convertCMYK8888ToARGB32PM(buffer, buffer, count); +} + +static const QRgba64 *QT_FASTCALL convertCMYK8888ToToRGBA64PM(QRgba64 *buffer, const uint *src, int count, + const QList<QRgb> *, QDitherInfo *) +{ + for (int i = 0; i < count; ++i) + buffer[i] = QCmyk32::fromCmyk32(src[i]).toColor().rgba64(); + return buffer; +} + +static const uint *QT_FASTCALL fetchCMYK8888ToARGB32PM(uint *buffer, const uchar *src, int index, int count, + const QList<QRgb> *, QDitherInfo *) +{ + const uint *s = reinterpret_cast<const uint *>(src) + index; + for (int i = 0; i < count; ++i) + buffer[i] = QCmyk32::fromCmyk32(s[i]).toColor().rgba(); + return buffer; +} + +static const QRgba64 *QT_FASTCALL fetchCMYK8888ToRGBA64PM(QRgba64 *buffer, const uchar *src, int index, int count, + const QList<QRgb> *, QDitherInfo *) +{ + const uint *s = reinterpret_cast<const uint *>(src) + index; + for (int i = 0; i < count; ++i) + buffer[i] = QCmyk32::fromCmyk32(s[i]).toColor().rgba64(); + return buffer; +} + +static void QT_FASTCALL storeCMYK8888FromARGB32PM(uchar *dest, const uint *src, int index, int count, + const QList<QRgb> *, QDitherInfo *) +{ + uint *d = reinterpret_cast<uint *>(dest) + index; + for (int i = 0; i < count; ++i) { + QColor c = qUnpremultiply(src[i]); + d[i] = QCmyk32::fromColor(c).toUint(); + } +} + +static void QT_FASTCALL storeCMYK8888FromRGB32(uchar *dest, const uint *src, int index, int count, + const QList<QRgb> *, QDitherInfo *) +{ + uint *d = reinterpret_cast<uint *>(dest) + index; + for (int i = 0; i < count; ++i) { + QColor c = src[i]; + d[i] = QCmyk32::fromColor(c).toUint(); + } +} + // Note: // convertToArgb32() assumes that no color channel is less than 4 bits. // storeRGBFromARGB32PM() assumes that no color channel is more than 8 bits. // QImage::rgbSwapped() assumes that the red and blue color channels have the same number of bits. -QPixelLayout qPixelLayouts[QImage::NImageFormats] = { +QPixelLayout qPixelLayouts[] = { { false, false, QPixelLayout::BPPNone, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr }, // Format_Invalid { false, false, QPixelLayout::BPP1MSB, nullptr, - convertIndexedToARGB32PM, convertIndexedToRGBA64PM, + convertIndexedToARGB32PM, convertIndexedTo<QRgba64>, fetchIndexedToARGB32PM<QPixelLayout::BPP1MSB>, fetchIndexedToRGBA64PM<QPixelLayout::BPP1MSB>, nullptr, nullptr }, // Format_Mono { false, false, QPixelLayout::BPP1LSB, nullptr, - convertIndexedToARGB32PM, convertIndexedToRGBA64PM, + convertIndexedToARGB32PM, convertIndexedTo<QRgba64>, fetchIndexedToARGB32PM<QPixelLayout::BPP1LSB>, fetchIndexedToRGBA64PM<QPixelLayout::BPP1LSB>, nullptr, nullptr }, // Format_MonoLSB { false, false, QPixelLayout::BPP8, nullptr, - convertIndexedToARGB32PM, convertIndexedToRGBA64PM, + convertIndexedToARGB32PM, convertIndexedTo<QRgba64>, fetchIndexedToARGB32PM<QPixelLayout::BPP8>, fetchIndexedToRGBA64PM<QPixelLayout::BPP8>, nullptr, nullptr }, // Format_Indexed8 // Technically using convertPassThrough to convert from ARGB32PM to RGB32 is wrong, @@ -1439,12 +1792,12 @@ QPixelLayout qPixelLayouts[QImage::NImageFormats] = { storeRGB30FromRGB32<PixelOrderRGB> }, // Format_A2RGB30_Premultiplied { true, true, QPixelLayout::BPP8, nullptr, - convertAlpha8ToRGB32, convertAlpha8ToRGB64, - fetchAlpha8ToRGB32, fetchAlpha8ToRGB64, + convertAlpha8ToRGB32, convertAlpha8To<QRgba64>, + fetchAlpha8ToRGB32, fetchAlpha8To<QRgba64>, storeAlpha8FromARGB32PM, nullptr }, // Format_Alpha8 { false, false, QPixelLayout::BPP8, nullptr, - convertGrayscale8ToRGB32, convertGrayscale8ToRGB64, - fetchGrayscale8ToRGB32, fetchGrayscale8ToRGB64, + convertGrayscale8ToRGB32, convertGrayscale8To<QRgba64>, + fetchGrayscale8ToRGB32, fetchGrayscale8To<QRgba64>, storeGrayscale8FromARGB32PM, storeGrayscale8FromRGB32 }, // Format_Grayscale8 { false, false, QPixelLayout::BPP64, rbSwap_4x16, convertPassThrough, nullptr, @@ -1459,13 +1812,41 @@ QPixelLayout qPixelLayouts[QImage::NImageFormats] = { fetchRGB64ToRGB32, fetchPassThrough64, storeRGBA64FromARGB32, storeRGB64FromRGB32 }, // Format_RGBA64_Premultiplied { false, false, QPixelLayout::BPP16, nullptr, - convertGrayscale16ToRGB32, convertGrayscale16ToRGBA64, - fetchGrayscale16ToRGB32, fetchGrayscale16ToRGBA64, + convertGrayscale16ToRGB32, convertGrayscale16To<QRgba64>, + fetchGrayscale16ToRGB32, fetchGrayscale16To<QRgba64>, storeGrayscale16FromARGB32PM, storeGrayscale16FromRGB32 }, // Format_Grayscale16 pixelLayoutRGB<QImage::Format_BGR888>(), + { false, false, QPixelLayout::BPP16FPx4, rbSwap_4x16, + convertPassThrough, nullptr, + fetchRGB16FToRGB32, fetchRGBA16FPMToRGBA64PM, + storeRGB16FFromRGB32, storeRGB16FFromRGB32 }, // Format_RGBX16FPx4 + { true, false, QPixelLayout::BPP16FPx4, rbSwap_4x16, + convertARGB32ToARGB32PM, nullptr, + fetchRGBA16FToARGB32PM, fetchRGBA16FToRGBA64PM, + storeRGBA16FFromARGB32PM, storeRGB16FFromRGB32 }, // Format_RGBA16FPx4 + { true, true, QPixelLayout::BPP16FPx4, rbSwap_4x16, + convertPassThrough, nullptr, + fetchRGB16FToRGB32, fetchRGBA16FPMToRGBA64PM, + storeRGB16FFromRGB32, storeRGB16FFromRGB32 }, // Format_RGBA16FPx4_Premultiplied + { false, false, QPixelLayout::BPP32FPx4, rbSwap_4x32, + convertPassThrough, nullptr, + fetchRGB32FToRGB32, fetchRGBA32FPMToRGBA64PM, + storeRGB32FFromRGB32, storeRGB32FFromRGB32 }, // Format_RGBX32FPx4 + { true, false, QPixelLayout::BPP32FPx4, rbSwap_4x32, + convertARGB32ToARGB32PM, nullptr, + fetchRGBA32FToARGB32PM, fetchRGBA32FToRGBA64PM, + storeRGBA32FFromARGB32PM, storeRGB32FFromRGB32 }, // Format_RGBA32FPx4 + { true, true, QPixelLayout::BPP32FPx4, rbSwap_4x32, + convertPassThrough, nullptr, + fetchRGB32FToRGB32, fetchRGBA32FPMToRGBA64PM, + storeRGB32FFromRGB32, storeRGB32FFromRGB32 }, // Format_RGBA32FPx4_Premultiplied + { false, false, QPixelLayout::BPP32, nullptr, + convertCMYK8888ToARGB32PM, convertCMYK8888ToToRGBA64PM, + fetchCMYK8888ToARGB32PM, fetchCMYK8888ToRGBA64PM, + storeCMYK8888FromARGB32PM, storeCMYK8888FromRGB32 }, // Format_CMYK8888 }; -static_assert(sizeof(qPixelLayouts) / sizeof(*qPixelLayouts) == QImage::NImageFormats); +static_assert(std::size(qPixelLayouts) == QImage::NImageFormats); static void QT_FASTCALL convertFromRgb64(uint *dest, const QRgba64 *src, int length) { @@ -1548,7 +1929,67 @@ static void QT_FASTCALL storeGray16FromRGBA64PM(uchar *dest, const QRgba64 *src, } } -ConvertAndStorePixelsFunc64 qStoreFromRGBA64PM[QImage::NImageFormats] = { +static void QT_FASTCALL storeRGBX16FFromRGBA64PM(uchar *dest, const QRgba64 *src, int index, int count, + const QList<QRgb> *, QDitherInfo *) +{ + QRgbaFloat16 *d = reinterpret_cast<QRgbaFloat16 *>(dest) + index; + for (int i = 0; i < count; ++i) { + d[i] = qConvertRgb64ToRgbaF16(src[i]).unpremultiplied(); + d[i].setAlpha(1.0); + } +} + +static void QT_FASTCALL storeRGBA16FFromRGBA64PM(uchar *dest, const QRgba64 *src, int index, int count, + const QList<QRgb> *, QDitherInfo *) +{ + QRgbaFloat16 *d = reinterpret_cast<QRgbaFloat16 *>(dest) + index; + for (int i = 0; i < count; ++i) + d[i] = qConvertRgb64ToRgbaF16(src[i]).unpremultiplied(); +} + +static void QT_FASTCALL storeRGBA16FPMFromRGBA64PM(uchar *dest, const QRgba64 *src, int index, int count, + const QList<QRgb> *, QDitherInfo *) +{ + QRgbaFloat16 *d = reinterpret_cast<QRgbaFloat16 *>(dest) + index; + for (int i = 0; i < count; ++i) + d[i] = qConvertRgb64ToRgbaF16(src[i]); +} + +static void QT_FASTCALL storeRGBX32FFromRGBA64PM(uchar *dest, const QRgba64 *src, int index, int count, + const QList<QRgb> *, QDitherInfo *) +{ + QRgbaFloat32 *d = reinterpret_cast<QRgbaFloat32 *>(dest) + index; + for (int i = 0; i < count; ++i) { + d[i] = qConvertRgb64ToRgbaF32(src[i]).unpremultiplied(); + d[i].setAlpha(1.0); + } +} + +static void QT_FASTCALL storeRGBA32FFromRGBA64PM(uchar *dest, const QRgba64 *src, int index, int count, + const QList<QRgb> *, QDitherInfo *) +{ + QRgbaFloat32 *d = reinterpret_cast<QRgbaFloat32 *>(dest) + index; + for (int i = 0; i < count; ++i) + d[i] = qConvertRgb64ToRgbaF32(src[i]).unpremultiplied(); +} + +static void QT_FASTCALL storeRGBA32FPMFromRGBA64PM(uchar *dest, const QRgba64 *src, int index, int count, + const QList<QRgb> *, QDitherInfo *) +{ + QRgbaFloat32 *d = reinterpret_cast<QRgbaFloat32 *>(dest) + index; + for (int i = 0; i < count; ++i) + d[i] = qConvertRgb64ToRgbaF32(src[i]); +} + +static void QT_FASTCALL storeCMYKFromRGBA64PM(uchar *dest, const QRgba64 *src, int index, int count, + const QList<QRgb> *, QDitherInfo *) +{ + uint *d = reinterpret_cast<uint *>(dest) + index; + for (int i = 0; i < count; ++i) + d[i] = QCmyk32::fromColor(QColor(src[i])).toUint(); +} + +ConvertAndStorePixelsFunc64 qStoreFromRGBA64PM[] = { nullptr, nullptr, nullptr, @@ -1579,6 +2020,417 @@ ConvertAndStorePixelsFunc64 qStoreFromRGBA64PM[QImage::NImageFormats] = { storeRGBA64PMFromRGBA64PM, storeGray16FromRGBA64PM, storeGenericFromRGBA64PM<QImage::Format_BGR888>, + storeRGBX16FFromRGBA64PM, + storeRGBA16FFromRGBA64PM, + storeRGBA16FPMFromRGBA64PM, + storeRGBX32FFromRGBA64PM, + storeRGBA32FFromRGBA64PM, + storeRGBA32FPMFromRGBA64PM, + storeCMYKFromRGBA64PM, }; +static_assert(std::size(qStoreFromRGBA64PM) == QImage::NImageFormats); + +#if QT_CONFIG(raster_fp) +static void QT_FASTCALL convertToRgbaF32(QRgbaFloat32 *dest, const uint *src, int length) +{ + for (int i = 0; i < length; ++i) + dest[i] = QRgbaFloat32::fromArgb32(src[i]); +} + +template<QImage::Format format> +static const QRgbaFloat32 * QT_FASTCALL convertGenericToRGBA32F(QRgbaFloat32 *buffer, const uint *src, int count, + const QList<QRgb> *clut, QDitherInfo *) +{ + uint buffer32[BufferSize]; + memcpy(buffer32, src, count * sizeof(uint)); + qPixelLayouts[format].convertToARGB32PM(buffer32, count, clut); + convertToRgbaF32(buffer, buffer32, count); + return buffer; +} + +static const QRgbaFloat32 * QT_FASTCALL convertARGB32ToRGBA32F(QRgbaFloat32 *buffer, const uint *src, int count, + const QList<QRgb> *, QDitherInfo *) +{ + for (int i = 0; i < count; ++i) + buffer[i] = QRgbaFloat32::fromArgb32(src[i]).premultiplied(); + return buffer; +} + +static const QRgbaFloat32 * QT_FASTCALL convertRGBA8888ToRGBA32F(QRgbaFloat32 *buffer, const uint *src, int count, + const QList<QRgb> *, QDitherInfo *) +{ + for (int i = 0; i < count; ++i) + buffer[i] = QRgbaFloat32::fromArgb32(RGBA2ARGB(src[i])).premultiplied(); + return buffer; +} + +template<QtPixelOrder PixelOrder> +static const QRgbaFloat32 * QT_FASTCALL convertRGB30ToRGBA32F(QRgbaFloat32 *buffer, const uint *src, int count, + const QList<QRgb> *, QDitherInfo *) +{ + for (int i = 0; i < count; ++i) { + QRgba64 s = qConvertA2rgb30ToRgb64<PixelOrder>(src[i]); + buffer[i] = QRgbaFloat32::fromRgba64(s.red(), s.green(), s.blue(), s.alpha()); + } + return buffer; +} + +static const QRgbaFloat32 * QT_FASTCALL convertCMYKToRGBA32F(QRgbaFloat32 *buffer, const uint *src, int count, + const QList<QRgb> *, QDitherInfo *) +{ + for (int i = 0; i < count; ++i) + buffer[i] = QRgbaFloat32::fromArgb32(QCmyk32::fromCmyk32(src[i]).toColor().rgba()); + + return buffer; +} + +ConvertToFPFunc qConvertToRGBA32F[] = { + nullptr, + convertIndexedTo<QRgbaFloat32>, + convertIndexedTo<QRgbaFloat32>, + convertIndexedTo<QRgbaFloat32>, + convertGenericToRGBA32F<QImage::Format_RGB32>, + convertARGB32ToRGBA32F, + convertGenericToRGBA32F<QImage::Format_ARGB32_Premultiplied>, + convertGenericToRGBA32F<QImage::Format_RGB16>, + convertGenericToRGBA32F<QImage::Format_ARGB8565_Premultiplied>, + convertGenericToRGBA32F<QImage::Format_RGB666>, + convertGenericToRGBA32F<QImage::Format_ARGB6666_Premultiplied>, + convertGenericToRGBA32F<QImage::Format_RGB555>, + convertGenericToRGBA32F<QImage::Format_ARGB8555_Premultiplied>, + convertGenericToRGBA32F<QImage::Format_RGB888>, + convertGenericToRGBA32F<QImage::Format_RGB444>, + convertGenericToRGBA32F<QImage::Format_ARGB4444_Premultiplied>, + convertGenericToRGBA32F<QImage::Format_RGBX8888>, + convertRGBA8888ToRGBA32F, + convertGenericToRGBA32F<QImage::Format_RGBA8888_Premultiplied>, + convertRGB30ToRGBA32F<PixelOrderBGR>, + convertRGB30ToRGBA32F<PixelOrderBGR>, + convertRGB30ToRGBA32F<PixelOrderRGB>, + convertRGB30ToRGBA32F<PixelOrderRGB>, + convertAlpha8To<QRgbaFloat32>, + convertGrayscale8To<QRgbaFloat32>, + nullptr, + nullptr, + nullptr, + convertGrayscale16To<QRgbaFloat32>, + convertGenericToRGBA32F<QImage::Format_BGR888>, + nullptr, + nullptr, + nullptr, + nullptr, + nullptr, + nullptr, + convertCMYKToRGBA32F, +}; + +static_assert(std::size(qConvertToRGBA32F) == QImage::NImageFormats); + +static const QRgbaFloat32 *QT_FASTCALL fetchRGBX64ToRGBA32F(QRgbaFloat32 *buffer, const uchar *src, int index, int count, + const QList<QRgb> *, QDitherInfo *) +{ + const QRgba64 *s = reinterpret_cast<const QRgba64 *>(src) + index; + for (int i = 0; i < count; ++i) { + QRgba64 c = s[i]; + buffer[i] = QRgbaFloat32::fromRgba64(c.red(), c.green(), c.blue(), 65535); + } + return buffer; +} + +static const QRgbaFloat32 *QT_FASTCALL fetchRGBA64ToRGBA32F(QRgbaFloat32 *buffer, const uchar *src, int index, int count, + const QList<QRgb> *, QDitherInfo *) +{ + const QRgba64 *s = reinterpret_cast<const QRgba64 *>(src) + index; + for (int i = 0; i < count; ++i) + buffer[i] = qConvertRgb64ToRgbaF32(s[i]).premultiplied(); + return buffer; +} + +static const QRgbaFloat32 *QT_FASTCALL fetchRGBA64PMToRGBA32F(QRgbaFloat32 *buffer, const uchar *src, int index, int count, + const QList<QRgb> *, QDitherInfo *) +{ + const QRgba64 *s = reinterpret_cast<const QRgba64 *>(src) + index; + for (int i = 0; i < count; ++i) + buffer[i] = qConvertRgb64ToRgbaF32(s[i]); + return buffer; +} + +static const QRgbaFloat32 *QT_FASTCALL fetchRGBA16FToRGBA32F(QRgbaFloat32 *buffer, const uchar *src, int index, int count, + const QList<QRgb> *, QDitherInfo *) +{ + const QRgbaFloat16 *s = reinterpret_cast<const QRgbaFloat16 *>(src) + index; + for (int i = 0; i < count; ++i) { + auto c = s[i].premultiplied(); + buffer[i] = QRgbaFloat32 { c.r, c.g, c.b, c.a}; + } + return buffer; +} + +static const QRgbaFloat32 *QT_FASTCALL fetchRGBA16F(QRgbaFloat32 *buffer, const uchar *src, int index, int count, + const QList<QRgb> *, QDitherInfo *) +{ + const QRgbaFloat16 *s = reinterpret_cast<const QRgbaFloat16 *>(src) + index; + qFloatFromFloat16((float *)buffer, (const qfloat16 *)s, count * 4); + return buffer; +} + +static const QRgbaFloat32 *QT_FASTCALL fetchRGBA32FToRGBA32F(QRgbaFloat32 *buffer, const uchar *src, int index, int count, + const QList<QRgb> *, QDitherInfo *) +{ + const QRgbaFloat32 *s = reinterpret_cast<const QRgbaFloat32 *>(src) + index; + for (int i = 0; i < count; ++i) + buffer[i] = s[i].premultiplied(); + return buffer; +} + +static const QRgbaFloat32 *QT_FASTCALL fetchRGBA32F(QRgbaFloat32 *, const uchar *src, int index, int, + const QList<QRgb> *, QDitherInfo *) +{ + const QRgbaFloat32 *s = reinterpret_cast<const QRgbaFloat32 *>(src) + index; + return s; +} + +static const QRgbaFloat32 *QT_FASTCALL fetchCMYKToRGBA32F(QRgbaFloat32 *buffer, const uchar *src, int index, int count, + const QList<QRgb> *, QDitherInfo *) +{ + const uint *s = reinterpret_cast<const uint *>(src) + index; + for (int i = 0; i < count; ++i) + buffer[i] = QRgbaFloat32::fromArgb32(QCmyk32::fromCmyk32(s[i]).toColor().rgba()); + + return buffer; +} + +FetchAndConvertPixelsFuncFP qFetchToRGBA32F[] = { + nullptr, + fetchIndexedToRGBA32F<QPixelLayout::BPP1MSB>, + fetchIndexedToRGBA32F<QPixelLayout::BPP1LSB>, + fetchIndexedToRGBA32F<QPixelLayout::BPP8>, + fetchRGBToRGB32F<QImage::Format_RGB32>, + fetchARGBToRGBA32F<QImage::Format_ARGB32>, + fetchARGBPMToRGBA32F<QImage::Format_ARGB32_Premultiplied>, + fetchRGBToRGB32F<QImage::Format_RGB16>, + fetchARGBToRGBA32F<QImage::Format_ARGB8565_Premultiplied>, + fetchRGBToRGB32F<QImage::Format_RGB666>, + fetchARGBToRGBA32F<QImage::Format_ARGB6666_Premultiplied>, + fetchRGBToRGB32F<QImage::Format_RGB555>, + fetchARGBToRGBA32F<QImage::Format_ARGB8555_Premultiplied>, + fetchRGBToRGB32F<QImage::Format_RGB888>, + fetchRGBToRGB32F<QImage::Format_RGB444>, + fetchARGBToRGBA32F<QImage::Format_ARGB4444_Premultiplied>, + fetchRGBToRGB32F<QImage::Format_RGBX8888>, + fetchARGBToRGBA32F<QImage::Format_RGBA8888>, + fetchARGBPMToRGBA32F<QImage::Format_RGBA8888_Premultiplied>, + fetchRGB30ToRGBA32F<PixelOrderBGR>, + fetchRGB30ToRGBA32F<PixelOrderBGR>, + fetchRGB30ToRGBA32F<PixelOrderRGB>, + fetchRGB30ToRGBA32F<PixelOrderRGB>, + fetchAlpha8To<QRgbaFloat32>, + fetchGrayscale8To<QRgbaFloat32>, + fetchRGBX64ToRGBA32F, + fetchRGBA64ToRGBA32F, + fetchRGBA64PMToRGBA32F, + fetchGrayscale16To<QRgbaFloat32>, + fetchRGBToRGB32F<QImage::Format_BGR888>, + fetchRGBA16F, + fetchRGBA16FToRGBA32F, + fetchRGBA16F, + fetchRGBA32F, + fetchRGBA32FToRGBA32F, + fetchRGBA32F, + fetchCMYKToRGBA32F, +}; + +static_assert(std::size(qFetchToRGBA32F) == QImage::NImageFormats); + +static void QT_FASTCALL convertFromRgba32f(uint *dest, const QRgbaFloat32 *src, int length) +{ + for (int i = 0; i < length; ++i) + dest[i] = src[i].toArgb32(); +} + +template<QImage::Format format> +static void QT_FASTCALL storeGenericFromRGBA32F(uchar *dest, const QRgbaFloat32 *src, int index, int count, + const QList<QRgb> *clut, QDitherInfo *dither) +{ + uint buffer[BufferSize]; + convertFromRgba32f(buffer, src, count); + qPixelLayouts[format].storeFromARGB32PM(dest, buffer, index, count, clut, dither); +} + +static void QT_FASTCALL storeARGB32FromRGBA32F(uchar *dest, const QRgbaFloat32 *src, int index, int count, + const QList<QRgb> *, QDitherInfo *) +{ + uint *d = (uint*)dest + index; + for (int i = 0; i < count; ++i) + d[i] = src[i].unpremultiplied().toArgb32(); +} + +static void QT_FASTCALL storeRGBA8888FromRGBA32F(uchar *dest, const QRgbaFloat32 *src, int index, int count, + const QList<QRgb> *, QDitherInfo *) +{ + uint *d = (uint*)dest + index; + for (int i = 0; i < count; ++i) + d[i] = ARGB2RGBA(src[i].unpremultiplied().toArgb32()); +} + +template<QtPixelOrder PixelOrder> +static void QT_FASTCALL storeRGB30FromRGBA32F(uchar *dest, const QRgbaFloat32 *src, int index, int count, + const QList<QRgb> *, QDitherInfo *) +{ + uint *d = (uint*)dest + index; + for (int i = 0; i < count; ++i) { + const auto s = src[i]; + d[i] = qConvertRgb64ToRgb30<PixelOrder>(QRgba64::fromRgba64(s.red16(), s.green16(), s.blue16(), s.alpha16())); + } +} + +static void QT_FASTCALL storeRGBX64FromRGBA32F(uchar *dest, const QRgbaFloat32 *src, int index, int count, + const QList<QRgb> *, QDitherInfo *) +{ + QRgba64 *d = reinterpret_cast<QRgba64 *>(dest) + index; + for (int i = 0; i < count; ++i) { + const auto s = src[i].unpremultiplied(); + d[i] = QRgba64::fromRgba64(s.red16(), s.green16(), s.blue16(), 65535); + } +} + +static void QT_FASTCALL storeRGBA64FromRGBA32F(uchar *dest, const QRgbaFloat32 *src, int index, int count, + const QList<QRgb> *, QDitherInfo *) +{ + QRgba64 *d = reinterpret_cast<QRgba64 *>(dest) + index; + for (int i = 0; i < count; ++i) { + const auto s = src[i].unpremultiplied(); + d[i] = QRgba64::fromRgba64(s.red16(), s.green16(), s.blue16(), s.alpha16()); + } +} + +static void QT_FASTCALL storeRGBA64PMFromRGBA32F(uchar *dest, const QRgbaFloat32 *src, int index, int count, + const QList<QRgb> *, QDitherInfo *) +{ + QRgba64 *d = reinterpret_cast<QRgba64 *>(dest) + index; + for (int i = 0; i < count; ++i) + d[i] = QRgba64::fromRgba64(src[i].red16(), src[i].green16(), src[i].blue16(), src[i].alpha16()); +} + +static void QT_FASTCALL storeGray16FromRGBA32F(uchar *dest, const QRgbaFloat32 *src, int index, int count, + const QList<QRgb> *, QDitherInfo *) +{ + quint16 *d = reinterpret_cast<quint16 *>(dest) + index; + for (int i = 0; i < count; ++i) { + auto s = src[i].unpremultiplied(); + d[i] = qGray(s.red16(), s.green16(), s.blue16()); + } +} + +static void QT_FASTCALL storeRGBX16FFromRGBA32F(uchar *dest, const QRgbaFloat32 *src, int index, int count, + const QList<QRgb> *, QDitherInfo *) +{ + QRgbaFloat16 *d = reinterpret_cast<QRgbaFloat16 *>(dest) + index; + for (int i = 0; i < count; ++i) { + auto s = src[i].unpremultiplied(); + d[i] = QRgbaFloat16{ qfloat16(s.r), qfloat16(s.g), qfloat16(s.b), qfloat16(1.0f) }; + } +} + +static void QT_FASTCALL storeRGBA16FFromRGBA32F(uchar *dest, const QRgbaFloat32 *src, int index, int count, + const QList<QRgb> *, QDitherInfo *) +{ + QRgbaFloat16 *d = reinterpret_cast<QRgbaFloat16 *>(dest) + index; + for (int i = 0; i < count; ++i) { + auto s = src[i].unpremultiplied(); + d[i] = QRgbaFloat16{ qfloat16(s.r), qfloat16(s.g), qfloat16(s.b), qfloat16(s.a) }; + } +} + +static void QT_FASTCALL storeRGBA16FPMFromRGBA32F(uchar *dest, const QRgbaFloat32 *src, int index, int count, + const QList<QRgb> *, QDitherInfo *) +{ + QRgbaFloat16 *d = reinterpret_cast<QRgbaFloat16 *>(dest) + index; + qFloatToFloat16((qfloat16 *)d, (const float *)src, count * 4); +} + +static void QT_FASTCALL storeRGBX32FFromRGBA32F(uchar *dest, const QRgbaFloat32 *src, int index, int count, + const QList<QRgb> *, QDitherInfo *) +{ + QRgbaFloat32 *d = reinterpret_cast<QRgbaFloat32 *>(dest) + index; + for (int i = 0; i < count; ++i) { + auto s = src[i].unpremultiplied(); + s.a = 1.0f; + d[i] = s; + } +} + +static void QT_FASTCALL storeRGBA32FFromRGBA32F(uchar *dest, const QRgbaFloat32 *src, int index, int count, + const QList<QRgb> *, QDitherInfo *) +{ + QRgbaFloat32 *d = reinterpret_cast<QRgbaFloat32 *>(dest) + index; + for (int i = 0; i < count; ++i) + d[i] = src[i].unpremultiplied(); +} + +static void QT_FASTCALL storeRGBA32FPMFromRGBA32F(uchar *dest, const QRgbaFloat32 *src, int index, int count, + const QList<QRgb> *, QDitherInfo *) +{ + QRgbaFloat32 *d = reinterpret_cast<QRgbaFloat32 *>(dest) + index; + if (d != src) { + for (int i = 0; i < count; ++i) + d[i] = src[i]; + } +} + +static void QT_FASTCALL storeCMYKFromRGBA32F(uchar *dest, const QRgbaFloat32 *src, int index, int count, + const QList<QRgb> *, QDitherInfo *) +{ + uint *d = reinterpret_cast<uint *>(dest) + index; + for (int i = 0; i < count; ++i) { + // Yikes, this really needs enablers in QColor and friends + d[i] = QCmyk32::fromColor(QColor(src[i].toArgb32())).toUint(); + } +} + +ConvertAndStorePixelsFuncFP qStoreFromRGBA32F[] = { + nullptr, + nullptr, + nullptr, + nullptr, + storeGenericFromRGBA32F<QImage::Format_RGB32>, + storeARGB32FromRGBA32F, + storeGenericFromRGBA32F<QImage::Format_ARGB32_Premultiplied>, + storeGenericFromRGBA32F<QImage::Format_RGB16>, + storeGenericFromRGBA32F<QImage::Format_ARGB8565_Premultiplied>, + storeGenericFromRGBA32F<QImage::Format_RGB666>, + storeGenericFromRGBA32F<QImage::Format_ARGB6666_Premultiplied>, + storeGenericFromRGBA32F<QImage::Format_RGB555>, + storeGenericFromRGBA32F<QImage::Format_ARGB8555_Premultiplied>, + storeGenericFromRGBA32F<QImage::Format_RGB888>, + storeGenericFromRGBA32F<QImage::Format_RGB444>, + storeGenericFromRGBA32F<QImage::Format_ARGB4444_Premultiplied>, + storeGenericFromRGBA32F<QImage::Format_RGBX8888>, + storeRGBA8888FromRGBA32F, + storeGenericFromRGBA32F<QImage::Format_RGBA8888_Premultiplied>, + storeRGB30FromRGBA32F<PixelOrderBGR>, + storeRGB30FromRGBA32F<PixelOrderBGR>, + storeRGB30FromRGBA32F<PixelOrderRGB>, + storeRGB30FromRGBA32F<PixelOrderRGB>, + storeGenericFromRGBA32F<QImage::Format_Alpha8>, + storeGenericFromRGBA32F<QImage::Format_Grayscale8>, + storeRGBX64FromRGBA32F, + storeRGBA64FromRGBA32F, + storeRGBA64PMFromRGBA32F, + storeGray16FromRGBA32F, + storeGenericFromRGBA32F<QImage::Format_BGR888>, + storeRGBX16FFromRGBA32F, + storeRGBA16FFromRGBA32F, + storeRGBA16FPMFromRGBA32F, + storeRGBX32FFromRGBA32F, + storeRGBA32FFromRGBA32F, + storeRGBA32FPMFromRGBA32F, + storeCMYKFromRGBA32F, +}; + +static_assert(std::size(qStoreFromRGBA32F) == QImage::NImageFormats); + +#endif // QT_CONFIG(raster_fp) + QT_END_NAMESPACE |