diff --git a/src/gui/painting/qcolorspace.cpp b/src/gui/painting/qcolorspace.cpp index 7a1d34a408..f21e6ec738 100644 --- a/src/gui/painting/qcolorspace.cpp +++ b/src/gui/painting/qcolorspace.cpp @@ -448,11 +448,15 @@ QColorTransform QColorSpacePrivate::transformationToXYZ() const transform.d = ptr; ptr->colorSpaceIn = this; ptr->colorSpaceOut = this; - // Convert to XYZ relative to our white point, not the regular D50 white point. if (isThreeComponentMatrix()) - ptr->colorMatrix = QColorMatrix::chromaticAdaptation(whitePoint).inverted() * toXyz; + ptr->colorMatrix = toXyz; else ptr->colorMatrix = QColorMatrix::identity(); + // Convert to XYZ relative to our white point, not the regular D50 white point. + if (!chad.isNull()) + ptr->colorMatrix = chad.inverted() * ptr->colorMatrix; + else if (!whitePoint.isNull()) + ptr->colorMatrix = QColorMatrix::chromaticAdaptation(whitePoint).inverted() * ptr->colorMatrix; return transform; } diff --git a/src/gui/painting/qcolortransform.cpp b/src/gui/painting/qcolortransform.cpp index aac07bdc09..33b1dcdeb0 100644 --- a/src/gui/painting/qcolortransform.cpp +++ b/src/gui/painting/qcolortransform.cpp @@ -1640,7 +1640,7 @@ void QColorTransformPrivate::applyConvertIn(const S *src, QColorVector *buffer, loadUnpremultiplied(buffer, src, len, this); if (!colorSpaceOut->isThreeComponentMatrix()) - applyMatrix(buffer, len, colorMatrix); // colorMatrix should have the first half only. + applyMatrix(buffer, len, colorSpaceIn->toXyz); return; } } @@ -1666,7 +1666,7 @@ void QColorTransformPrivate::applyConvertOut(D *dst, const S *src, QColorVector // Avoid compiling this part for D=QCmyk32: if constexpr (!std::is_same_v) { if (colorSpaceOut->isThreeComponentMatrix()) { - applyMatrix(buffer, len, colorMatrix); // colorMatrix should have the latter half only. + applyMatrix(buffer, len, colorMatrix); if constexpr (std::is_same_v) { storeOpaque(dst, buffer, len, this); @@ -1695,77 +1695,19 @@ void QColorTransformPrivate::applyConvertOut(D *dst, const S *src, QColorVector storeUnpremultipliedLUT(dst, src, buffer, len); } -template -void QColorTransformPrivate::applyElementListTransform(D *dst, const S *src, qsizetype count, TransformFlags flags) const +/*! + \internal + Adapt Profile Connecting Color spaces. +*/ +void QColorTransformPrivate::pcsAdapt(QColorVector *buffer, qsizetype count) const { - Q_ASSERT(!colorSpaceIn->isThreeComponentMatrix() || !colorSpaceOut->isThreeComponentMatrix()); - - if (!colorMatrix.isValid()) - return; - - if (colorSpaceIn->isThreeComponentMatrix()) - updateLutsIn(); - if (colorSpaceOut->isThreeComponentMatrix()) - updateLutsOut(); - - QUninitialized buffer; - qsizetype i = 0; - while (i < count) { - const qsizetype len = qMin(count - i, WorkBlockSize); - - applyConvertIn(src + i, buffer, len, flags); - - // Match Profile Connection Spaces (PCS): - if (colorSpaceOut->isPcsLab && !colorSpaceIn->isPcsLab) { - for (qsizetype j = 0; j < len; ++j) - buffer[j] = buffer[j].xyzToLab(); - } else if (colorSpaceIn->isPcsLab && !colorSpaceOut->isPcsLab) { - for (qsizetype j = 0; j < len; ++j) - buffer[j] = buffer[j].labToXyz(); - } - - applyConvertOut(dst + i, src + i, buffer, len, flags); - - i += len; - } -} - -template -void QColorTransformPrivate::applyThreeComponentMatrix(D *dst, const S *src, qsizetype count, TransformFlags flags) const -{ - Q_ASSERT(colorSpaceIn->isThreeComponentMatrix() && colorSpaceOut->isThreeComponentMatrix()); - - if (!colorMatrix.isValid()) - return; - - updateLutsIn(); - updateLutsOut(); - - bool doApplyMatrix = !colorMatrix.isIdentity(); - constexpr ApplyMatrixForm doClamp = (std::is_same_v || std::is_same_v) ? DoNotClamp : DoClamp; - - QUninitialized buffer; - qsizetype i = 0; - while (i < count) { - const qsizetype len = qMin(count - i, WorkBlockSize); - if (flags & InputPremultiplied) - loadPremultiplied(buffer, src + i, len, this); - else - loadUnpremultiplied(buffer, src + i, len, this); - - if (doApplyMatrix) - applyMatrix(buffer, len, colorMatrix); - else - clampIfNeeded(buffer, len); - - if (flags & InputOpaque) - storeOpaque(dst + i, buffer, len, this); - else if (flags & OutputPremultiplied) - storePremultiplied(dst + i, src + i, buffer, len, this); - else - storeUnpremultiplied(dst + i, src + i, buffer, len, this); - - i += len; + // Match Profile Connection Spaces (PCS): + if (colorSpaceOut->isPcsLab && !colorSpaceIn->isPcsLab) { + for (qsizetype j = 0; j < count; ++j) + buffer[j] = buffer[j].xyzToLab(); + } else if (colorSpaceIn->isPcsLab && !colorSpaceOut->isPcsLab) { + for (qsizetype j = 0; j < count; ++j) + buffer[j] = buffer[j].labToXyz(); } } @@ -1781,11 +1723,24 @@ void QColorTransformPrivate::applyThreeComponentMatrix(D *dst, const S *src, qsi template void QColorTransformPrivate::apply(D *dst, const S *src, qsizetype count, TransformFlags flags) const { - if constexpr (!std::is_same_v && !std::is_same_v) { - if (isThreeComponentMatrix()) - return applyThreeComponentMatrix(dst, src, count, flags); + if (colorSpaceIn->isThreeComponentMatrix()) + updateLutsIn(); + if (colorSpaceOut->isThreeComponentMatrix()) + updateLutsOut(); + + QUninitialized buffer; + qsizetype i = 0; + while (i < count) { + const qsizetype len = qMin(count - i, WorkBlockSize); + + applyConvertIn(src + i, buffer, len, flags); + + pcsAdapt(buffer, len); + + applyConvertOut(dst + i, src + i, buffer, len, flags); + + i += len; } - applyElementListTransform(dst, src, count, flags); } /*! @@ -1970,15 +1925,6 @@ template void QColorTransformPrivate::apply(QRgbaFloat32 template void QColorTransformPrivate::apply(QRgbaFloat32 *dst, const QRgba64 *src, qsizetype count, TransformFlags flags) const; template void QColorTransformPrivate::apply(QRgbaFloat32 *dst, const QRgbaFloat32 *src, qsizetype count, TransformFlags flags) const; -bool QColorTransformPrivate::isThreeComponentMatrix() const -{ - if (colorSpaceIn && !colorSpaceIn->isThreeComponentMatrix()) - return false; - if (colorSpaceOut && !colorSpaceOut->isThreeComponentMatrix()) - return false; - return true; -} - /*! \internal */ @@ -1991,7 +1937,7 @@ bool QColorTransformPrivate::isIdentity() const if (colorSpaceIn && colorSpaceOut) { if (colorSpaceIn->equals(colorSpaceOut.constData())) return true; - if (!isThreeComponentMatrix()) + if (!colorSpaceIn->isThreeComponentMatrix() || !colorSpaceOut->isThreeComponentMatrix()) return false; if (colorSpaceIn->transferFunction != colorSpaceOut->transferFunction) return false; @@ -2001,7 +1947,9 @@ bool QColorTransformPrivate::isIdentity() const && colorSpaceIn->trc[2] == colorSpaceOut->trc[2]; } } else { - if (!isThreeComponentMatrix()) + if (colorSpaceIn && !colorSpaceIn->isThreeComponentMatrix()) + return false; + if (colorSpaceOut && !colorSpaceOut->isThreeComponentMatrix()) return false; if (colorSpaceIn && colorSpaceIn->transferFunction != QColorSpace::TransferFunction::Linear) return false; diff --git a/src/gui/painting/qcolortransform_p.h b/src/gui/painting/qcolortransform_p.h index 59ea6a2405..c74fe100eb 100644 --- a/src/gui/painting/qcolortransform_p.h +++ b/src/gui/painting/qcolortransform_p.h @@ -37,7 +37,6 @@ public: void updateLutsIn() const; void updateLutsOut() const; bool isIdentity() const; - bool isThreeComponentMatrix() const; Q_GUI_EXPORT void prepare(); enum TransformFlag { @@ -60,14 +59,11 @@ public: void applyReturnGray(D *dst, const S *src, qsizetype count, TransformFlags flags) const; private: + void pcsAdapt(QColorVector *buffer, qsizetype len) const; template void applyConvertIn(const S *src, QColorVector *buffer, qsizetype len, TransformFlags flags) const; template void applyConvertOut(D *dst, const S *src, QColorVector *buffer, qsizetype len, TransformFlags flags) const; - template - void applyElementListTransform(D *dst, const S *src, qsizetype count, TransformFlags flags) const; - template - void applyThreeComponentMatrix(D *dst, const S *src, qsizetype count, TransformFlags flags) const; }; QT_END_NAMESPACE