"Fossies" - the Fresh Open Source Software Archive  

Source code changes of the file "plugins/color/lcms2engine/colorprofiles/LcmsColorProfileContainer.cpp" between
krita-5.1.3.tar.xz and krita-5.1.4.tar.xz

About: Krita is a painting program offering art tools for everyone (concept art, texture and matte painters, illustrations and comics).

LcmsColorProfileContainer.cpp  (krita-5.1.3.tar.xz):LcmsColorProfileContainer.cpp  (krita-5.1.4.tar.xz)
skipping to change at line 14 skipping to change at line 14
* SPDX-FileCopyrightText: 2001 John Califf * SPDX-FileCopyrightText: 2001 John Califf
* SPDX-FileCopyrightText: 2004 Boudewijn Rempt <boud@valdyas.org> * SPDX-FileCopyrightText: 2004 Boudewijn Rempt <boud@valdyas.org>
* SPDX-FileCopyrightText: 2007 Thomas Zander <zander@kde.org> * SPDX-FileCopyrightText: 2007 Thomas Zander <zander@kde.org>
* SPDX-FileCopyrightText: 2007 Adrian Page <adrian@pagenet.plus.com> * SPDX-FileCopyrightText: 2007 Adrian Page <adrian@pagenet.plus.com>
* *
* SPDX-License-Identifier: LGPL-2.0-or-later * SPDX-License-Identifier: LGPL-2.0-or-later
*/ */
#include "LcmsColorProfileContainer.h" #include "LcmsColorProfileContainer.h"
#include <QGenericMatrix>
#include <QTransform>
#include <array>
#include <cfloat> #include <cfloat>
#include <cmath> #include <cmath>
#include <QTransform>
#include <QGenericMatrix>
#include <QDebug> #include <QDebug>
#include "kis_debug.h" #include "kis_debug.h"
class LcmsColorProfileContainer::Private class LcmsColorProfileContainer::Private
{ {
public: public:
cmsHPROFILE profile; cmsHPROFILE profile;
skipping to change at line 149 skipping to change at line 150
cmsProfileClassSignature profile_class; cmsProfileClassSignature profile_class;
profile_class = cmsGetDeviceClass(d->profile); profile_class = cmsGetDeviceClass(d->profile);
d->valid = ( profile_class != cmsSigNamedColorClass d->valid = ( profile_class != cmsSigNamedColorClass
&& profile_class != cmsSigLinkClass); && profile_class != cmsSigLinkClass);
//This is where obtain the whitepoint, and convert it to the actual whit e point of the profile in the case a Chromatic adaption tag is //This is where obtain the whitepoint, and convert it to the actual whit e point of the profile in the case a Chromatic adaption tag is
//present. This is necessary for profiles following the v4 spec. //present. This is necessary for profiles following the v4 spec.
cmsCIEXYZ baseMediaWhitePoint;//dummy to hold copy of mediawhitepoint if this is modified by chromatic adaption. cmsCIEXYZ baseMediaWhitePoint;//dummy to hold copy of mediawhitepoint if this is modified by chromatic adaption.
cmsCIEXYZ *mediaWhitePointPtr; cmsCIEXYZ *mediaWhitePointPtr;
bool whiteComp[3];
bool whiteIsD50;
// Possible bug in profiles: there are in fact some that says they conta in that tag // Possible bug in profiles: there are in fact some that says they conta in that tag
// but in fact the pointer is null. // but in fact the pointer is null.
// Let's not crash on it anyway, and assume there is no white point i nstead. // Let's not crash on it anyway, and assume there is no white point i nstead.
// BUG:423685 // BUG:423685
if (cmsIsTag(d->profile, cmsSigMediaWhitePointTag) if (cmsIsTag(d->profile, cmsSigMediaWhitePointTag)
&& (mediaWhitePointPtr = (cmsCIEXYZ *)cmsReadTag(d->profile, cms SigMediaWhitePointTag))) { && (mediaWhitePointPtr = (cmsCIEXYZ *)cmsReadTag(d->profile, cms SigMediaWhitePointTag))) {
d->mediaWhitePoint = *(mediaWhitePointPtr); d->mediaWhitePoint = *(mediaWhitePointPtr);
baseMediaWhitePoint = d->mediaWhitePoint; baseMediaWhitePoint = d->mediaWhitePoint;
whiteComp[0] = std::fabs(baseMediaWhitePoint.X - cmsD50_XYZ()->X) <
0.00001;
whiteComp[1] = std::fabs(baseMediaWhitePoint.Y - cmsD50_XYZ()->Y) <
0.00001;
whiteComp[2] = std::fabs(baseMediaWhitePoint.Z - cmsD50_XYZ()->Z) <
0.00001;
whiteIsD50 = std::all_of(std::begin(whiteComp), std::end(whiteComp),
[](bool b) {return b;});
cmsXYZ2xyY(&d->whitePoint, &d->mediaWhitePoint); cmsXYZ2xyY(&d->whitePoint, &d->mediaWhitePoint);
cmsCIEXYZ *CAM1; cmsCIEXYZ *CAM1;
if (cmsIsTag(d->profile, cmsSigChromaticAdaptationTag) if (cmsIsTag(d->profile, cmsSigChromaticAdaptationTag)
&& (CAM1 = (cmsCIEXYZ *)cmsReadTag(d->profile, cmsSigChromat && (CAM1 = (cmsCIEXYZ *)cmsReadTag(d->profile, cmsSigChromat
icAdaptationTag))) { icAdaptationTag))
&& whiteIsD50) {
//the chromatic adaption tag represent a matrix from the actual white point of the profile to D50. //the chromatic adaption tag represent a matrix from the actual white point of the profile to D50.
//We first put all our data into structures we can manipulate. //We first put all our data into structures we can manipulate.
double d3dummy [3] = {d->mediaWhitePoint.X, d->mediaWhitePoint.Y , d->mediaWhitePoint.Z}; double d3dummy [3] = {d->mediaWhitePoint.X, d->mediaWhitePoint.Y , d->mediaWhitePoint.Z};
QGenericMatrix<1, 3, double> whitePointMatrix(d3dummy); QGenericMatrix<1, 3, double> whitePointMatrix(d3dummy);
QTransform invertDummy(CAM1[0].X, CAM1[0].Y, CAM1[0].Z, CAM1[1]. X, CAM1[1].Y, CAM1[1].Z, CAM1[2].X, CAM1[2].Y, CAM1[2].Z); QTransform invertDummy(CAM1[0].X, CAM1[0].Y, CAM1[0].Z, CAM1[1]. X, CAM1[1].Y, CAM1[1].Z, CAM1[2].X, CAM1[2].Y, CAM1[2].Z);
//we then abuse QTransform's invert function because it probably does matrix inversion 20 times better than I can program. //we then abuse QTransform's invert function because it probably does matrix inversion 20 times better than I can program.
//if the matrix is uninvertable, invertedDummy will be an identi ty matrix, which for us means that it won't give any noticeble //if the matrix is uninvertable, invertedDummy will be an identi ty matrix, which for us means that it won't give any noticeble
//effect when we start multiplying. //effect when we start multiplying.
QTransform invertedDummy = invertDummy.inverted(); QTransform invertedDummy = invertDummy.inverted();
skipping to change at line 201 skipping to change at line 211
// BUG:423685 // BUG:423685
if (cmsIsTag(d->profile, cmsSigRedColorantTag) && cmsIsTag(d->profile, c msSigRedColorantTag) && cmsIsTag(d->profile, cmsSigRedColorantTag) if (cmsIsTag(d->profile, cmsSigRedColorantTag) && cmsIsTag(d->profile, c msSigRedColorantTag) && cmsIsTag(d->profile, cmsSigRedColorantTag)
&& (tempColorantsRed = (cmsCIEXYZ *)cmsReadTag(d->profile, cmsSi gRedColorantTag)) && (tempColorantsRed = (cmsCIEXYZ *)cmsReadTag(d->profile, cmsSi gRedColorantTag))
&& (tempColorantsGreen = (cmsCIEXYZ *)cmsReadTag(d->profile, cms SigGreenColorantTag)) && (tempColorantsGreen = (cmsCIEXYZ *)cmsReadTag(d->profile, cms SigGreenColorantTag))
&& (tempColorantsBlue = (cmsCIEXYZ *)cmsReadTag(d->profile, cmsS igBlueColorantTag))) { && (tempColorantsBlue = (cmsCIEXYZ *)cmsReadTag(d->profile, cmsS igBlueColorantTag))) {
cmsCIEXYZTRIPLE tempColorants; cmsCIEXYZTRIPLE tempColorants;
tempColorants.Red = *tempColorantsRed; tempColorants.Red = *tempColorantsRed;
tempColorants.Green = *tempColorantsGreen; tempColorants.Green = *tempColorantsGreen;
tempColorants.Blue = *tempColorantsBlue; tempColorants.Blue = *tempColorantsBlue;
//convert to d65, this is useless. //convert to d65, this is useless.
cmsAdaptToIlluminant(&d->colorants.Red, &baseMediaWhitePoint, &d->me cmsAdaptToIlluminant(&d->colorants.Red, cmsD50_XYZ(), &d->mediaWhite
diaWhitePoint, &tempColorants.Red); Point, &tempColorants.Red);
cmsAdaptToIlluminant(&d->colorants.Green, &baseMediaWhitePoint, &d-> cmsAdaptToIlluminant(&d->colorants.Green, cmsD50_XYZ(), &d->mediaWhi
mediaWhitePoint, &tempColorants.Green); tePoint, &tempColorants.Green);
cmsAdaptToIlluminant(&d->colorants.Blue, &baseMediaWhitePoint, &d->m cmsAdaptToIlluminant(&d->colorants.Blue, cmsD50_XYZ(), &d->mediaWhit
ediaWhitePoint, &tempColorants.Blue); ePoint, &tempColorants.Blue);
//d->colorants = tempColorants; //d->colorants = tempColorants;
d->hasColorants = true; d->hasColorants = true;
} else { } else {
//qDebug()<<d->name<<": has no colorants"; //qDebug()<<d->name<<": has no colorants";
d->hasColorants = false; d->hasColorants = false;
} }
//retrieve TRC. //retrieve TRC.
if (cmsIsTag(d->profile, cmsSigRedTRCTag) && cmsIsTag(d->profile, cmsSig BlueTRCTag) && cmsIsTag(d->profile, cmsSigGreenTRCTag)) { if (cmsIsTag(d->profile, cmsSigRedTRCTag) && cmsIsTag(d->profile, cmsSig BlueTRCTag) && cmsIsTag(d->profile, cmsSigGreenTRCTag)) {
d->redTRC = ((cmsToneCurve *)cmsReadTag (d->profile, cmsSigRedTRCTag )); d->redTRC = ((cmsToneCurve *)cmsReadTag (d->profile, cmsSigRedTRCTag ));
skipping to change at line 564 skipping to change at line 574
} }
if (!isNull) { if (!isNull) {
d->uniqueId = id; d->uniqueId = id;
} }
} }
return d->uniqueId; return d->uniqueId;
} }
bool LcmsColorProfileContainer::compareTRC(TransferCharacteristics characteristi
cs, float error) const
{
if (!d->hasTRC) {
return false;
}
std::array<cmsFloat32Number, 2> calcValues{};
cmsToneCurve *mainCurve = [&]() {
if (d->hasColorants) {
return d->redTRC;
}
return d->grayTRC;
}();
cmsToneCurve *compareCurve = transferFunction(characteristics);
// Number of sweep samples across the curve
for (uint32_t i = 0; i < 32; i++) {
const float step = float(i) / 31.0f;
calcValues[0] = cmsEvalToneCurveFloat(mainCurve, step);
calcValues[1] = cmsEvalToneCurveFloat(compareCurve, step);
if (std::fabs(calcValues[0] - calcValues[1]) >= error) {
return false;
}
}
return true;
}
cmsToneCurve *LcmsColorProfileContainer::transferFunction(TransferCharacteristic s transferFunction) cmsToneCurve *LcmsColorProfileContainer::transferFunction(TransferCharacteristic s transferFunction)
{ {
cmsToneCurve *mainCurve; cmsToneCurve *mainCurve;
// Values courtesey of Elle Stone // Values courtesey of Elle Stone
cmsFloat64Number srgb_parameters[5] = cmsFloat64Number srgb_parameters[5] =
{ 2.4, 1.0 / 1.055, 0.055 / 1.055, 1.0 / 12.92, 0.04045 }; { 2.4, 1.0 / 1.055, 0.055 / 1.055, 1.0 / 12.92, 0.04045 };
cmsFloat64Number rec709_parameters[5] = cmsFloat64Number rec709_parameters[5] =
{ 1.0 / 0.45, 1.0 / 1.099, 0.099 / 1.099, 1.0 / 4.5, 0.081 }; { 1.0 / 0.45, 1.0 / 1.099, 0.099 / 1.099, 1.0 / 4.5, 0.081 };
skipping to change at line 587 skipping to change at line 627
cmsFloat64Number SMPTE_240M_parameters[5] = cmsFloat64Number SMPTE_240M_parameters[5] =
{ 1.0 / 0.45, 1.0 / 1.1115, 0.1115 / 1.1115, 1.0 / 4.0, 0.0913 }; { 1.0 / 0.45, 1.0 / 1.1115, 0.1115 / 1.1115, 1.0 / 4.0, 0.0913 };
cmsFloat64Number prophoto_parameters[5] = cmsFloat64Number prophoto_parameters[5] =
{ 1.8, 1.0, 0, 1.0 / 16, (16.0/512) }; { 1.8, 1.0, 0, 1.0 / 16, (16.0/512) };
cmsFloat64Number log_100[5] = {1.0, 10, 2.0, -2.0, 0.0}; cmsFloat64Number log_100[5] = {1.0, 10, 2.0, -2.0, 0.0};
cmsFloat64Number log_100_sqrt[5] = {1.0, 10, 2.5, -2.5, 0.0}; cmsFloat64Number log_100_sqrt[5] = {1.0, 10, 2.5, -2.5, 0.0};
cmsFloat64Number labl_parameters[5] = {3.0, 0.862076, 0.137924, 0.110703, 0.
080002};
switch (transferFunction) { switch (transferFunction) {
case TRC_IEC_61966_2_4: case TRC_IEC_61966_2_4:
// Not possible in ICC due to lack of a*pow(bX+c,y) construct. // Not possible in ICC due to lack of a*pow(bX+c,y) construct.
case TRC_ITU_R_BT_1361: case TRC_ITU_R_BT_1361:
// This is not possible in ICC due to lack of a*pow(bX+c,y) construct. // This is not possible in ICC due to lack of a*pow(bX+c,y) construct.
qWarning() << "Neither IEC 61966 2-4 nor Bt. 1361 are supported, returni ng a rec 709 curve."; qWarning() << "Neither IEC 61966 2-4 nor Bt. 1361 are supported, returni ng a rec 709 curve.";
Q_FALLTHROUGH(); Q_FALLTHROUGH();
case TRC_ITU_R_BT_709_5: case TRC_ITU_R_BT_709_5:
case TRC_ITU_R_BT_601_6: case TRC_ITU_R_BT_601_6:
case TRC_ITU_R_BT_2020_2_10bit: case TRC_ITU_R_BT_2020_2_10bit:
skipping to change at line 621 skipping to change at line 663
case TRC_IEC_61966_2_1: case TRC_IEC_61966_2_1:
mainCurve = cmsBuildParametricToneCurve(NULL, 4, srgb_parameters); mainCurve = cmsBuildParametricToneCurve(NULL, 4, srgb_parameters);
break; break;
case TRC_LOGARITHMIC_100: case TRC_LOGARITHMIC_100:
mainCurve = cmsBuildParametricToneCurve(NULL, 8, log_100); mainCurve = cmsBuildParametricToneCurve(NULL, 8, log_100);
break; break;
case TRC_LOGARITHMIC_100_sqrt10: case TRC_LOGARITHMIC_100_sqrt10:
mainCurve = cmsBuildParametricToneCurve(NULL, 8, log_100_sqrt); mainCurve = cmsBuildParametricToneCurve(NULL, 8, log_100_sqrt);
break; break;
case TRC_A98: case TRC_A98:
//gamma 256/563 // gamma 563/256
mainCurve = cmsBuildGamma(NULL, 256.0/563); mainCurve = cmsBuildGamma(NULL, 563.0 / 256.0);
break; break;
case TRC_PROPHOTO: case TRC_PROPHOTO:
mainCurve = cmsBuildParametricToneCurve(NULL, 4, prophoto_parameters); mainCurve = cmsBuildParametricToneCurve(NULL, 4, prophoto_parameters);
break; break;
case TRC_GAMMA_1_8: case TRC_GAMMA_1_8:
mainCurve = cmsBuildGamma(NULL, 1.8); mainCurve = cmsBuildGamma(NULL, 1.8);
break; break;
case TRC_GAMMA_2_4: case TRC_GAMMA_2_4:
mainCurve = cmsBuildGamma(NULL, 2.4); mainCurve = cmsBuildGamma(NULL, 2.4);
break; break;
case TRC_LAB_L:
mainCurve = cmsBuildParametricToneCurve(NULL, 4, labl_parameters);
break;
case TRC_SMPTE_ST_428_1: case TRC_SMPTE_ST_428_1:
// Requires an a*X^y construction, not possible. // Requires an a*X^y construction, not possible.
case TRC_ITU_R_BT_2100_0_PQ: case TRC_ITU_R_BT_2100_0_PQ:
// Perceptual Quantizer // Perceptual Quantizer
case TRC_ITU_R_BT_2100_0_HLG: case TRC_ITU_R_BT_2100_0_HLG:
// Hybrid log gamma. // Hybrid log gamma.
qWarning() << "Cannot generate an icc profile with this transfer functio n, will generate a linear profile"; qWarning() << "Cannot generate an icc profile with this transfer functio n, will generate a linear profile";
Q_FALLTHROUGH(); Q_FALLTHROUGH();
case TRC_LINEAR: case TRC_LINEAR:
default: default:
 End of changes. 10 change blocks. 
12 lines changed or deleted 63 lines changed or added

Home  |  About  |  Features  |  All  |  Newest  |  Dox  |  Diffs  |  RSS Feeds  |  Screenshots  |  Comments  |  Imprint  |  Privacy  |  HTTP(S)