Krita Source Code Documentation
Loading...
Searching...
No Matches
LcmsColorProfileContainer Class Reference

#include <LcmsColorProfileContainer.h>

+ Inheritance diagram for LcmsColorProfileContainer:

Classes

class  Private
 

Public Member Functions

ColorPrimaries cicpPrimaries () const override
 
TransferCharacteristics cicpTransfer () const override
 
cmsColorSpaceSignature colorSpaceSignature () const
 
bool compareTRC (TransferCharacteristics characteristics, float error) const override
 
QString copyright () const override
 
virtual void DelinearizeFloatValue (QVector< double > &Value) const
 
virtual void DelinearizeFloatValueFast (QVector< double > &Value) const
 
cmsProfileClassSignature deviceClass () const
 
QVector< KoColorimetryUtils::xyYgetColorantsxyY () const override
 
QVector< KoColorimetryUtils::XYZgetColorantsXYZ () const override
 
QVector< double > getEstimatedTRC () const override
 
QByteArray getProfileUniqueId () const override
 
KoColorimetryUtils::xyY getWhitePointxyY () const override
 
KoColorimetryUtils::XYZ getWhitePointXYZ () const override
 
bool hasCicpValues () const override
 
bool hasColorants () const override
 
virtual bool hasTRC () const
 
QString info () const override
 
bool isLinear () const
 
bool isSuitableForDisplay () const override
 
bool isSuitableForInput () const override
 
bool isSuitableForOutput () const override
 
bool isSuitableForPrinting () const override
 
bool isSuitableForWorkspace () const override
 
cmsHPROFILE lcmsProfile () const
 
virtual void LinearizeFloatValue (QVector< double > &Value) const
 
virtual void LinearizeFloatValueFast (QVector< double > &Value) const
 
QString manufacturer () const override
 
QString name () const override
 
virtual bool supportsAbsolute () const
 
virtual bool supportsPerceptual () const
 
virtual bool supportsRelative () const
 
virtual bool supportsSaturation () const
 
bool valid () const override
 
virtual float version () const
 
 ~LcmsColorProfileContainer () override
 
- Public Member Functions inherited from IccColorProfile::Container
 Container ()
 
virtual ~Container ()
 

Static Public Member Functions

static IccColorProfilecreateFromLcmsProfile (const cmsHPROFILE profile)
 
static cmsToneCurve * transferFunction (TransferCharacteristics transferFunction)
 

Protected Member Functions

 LcmsColorProfileContainer ()
 
 LcmsColorProfileContainer (IccColorProfile::Data *)
 

Private Member Functions

bool init ()
 

Static Private Member Functions

static QByteArray lcmsProfileToByteArray (const cmsHPROFILE profile)
 

Private Attributes

Private *const d
 

Friends

class IccColorProfile
 

Detailed Description

This class contains an LCMS color profile. Don't use it outside LcmsColorSpace.

Definition at line 24 of file LcmsColorProfileContainer.h.

Constructor & Destructor Documentation

◆ LcmsColorProfileContainer() [1/2]

LcmsColorProfileContainer::LcmsColorProfileContainer ( IccColorProfile::Data * data)
protected

◆ ~LcmsColorProfileContainer()

LcmsColorProfileContainer::~LcmsColorProfileContainer ( )
override

Definition at line 149 of file LcmsColorProfileContainer.cpp.

150{
151 cmsCloseProfile(d->profile);
152 delete d;
153}

References d, and LcmsColorProfileContainer::Private::profile.

◆ LcmsColorProfileContainer() [2/2]

LcmsColorProfileContainer::LcmsColorProfileContainer ( )
protected

Definition at line 112 of file LcmsColorProfileContainer.cpp.

113 : d(new Private())
114{
115 d->profile = 0;
116}

References d, and LcmsColorProfileContainer::Private::profile.

Member Function Documentation

◆ cicpPrimaries()

ColorPrimaries LcmsColorProfileContainer::cicpPrimaries ( ) const
overridevirtual

Implements IccColorProfile::Container.

Definition at line 651 of file LcmsColorProfileContainer.cpp.

651 {
652 if (!d->cicpValues) return PRIMARIES_UNSPECIFIED;
653 return ColorPrimaries(d->cicpValues->ColourPrimaries);
654}
ColorPrimaries
The colorPrimaries enum Enum of colorants, follows ITU H.273 for values 0 to 255, and has extra known...
@ PRIMARIES_UNSPECIFIED

References LcmsColorProfileContainer::Private::cicpValues, d, and PRIMARIES_UNSPECIFIED.

◆ cicpTransfer()

TransferCharacteristics LcmsColorProfileContainer::cicpTransfer ( ) const
overridevirtual

Implements IccColorProfile::Container.

Definition at line 656 of file LcmsColorProfileContainer.cpp.

657{
658 if (!d->cicpValues) return TRC_UNSPECIFIED;
659 return TransferCharacteristics(d->cicpValues->TransferCharacteristics);
660}
TransferCharacteristics
The transferCharacteristics enum Enum of transfer characteristics, follows ITU H.273 for values 0 to ...

References LcmsColorProfileContainer::Private::cicpValues, d, and TRC_UNSPECIFIED.

◆ colorSpaceSignature()

cmsColorSpaceSignature LcmsColorProfileContainer::colorSpaceSignature ( ) const
Returns
the ICC color space signature

Definition at line 343 of file LcmsColorProfileContainer.cpp.

344{
345 return d->colorSpaceSignature;
346}

References LcmsColorProfileContainer::Private::colorSpaceSignature, and d.

◆ compareTRC()

bool LcmsColorProfileContainer::compareTRC ( TransferCharacteristics characteristics,
float error ) const
overridevirtual

Implements IccColorProfile::Container.

Definition at line 662 of file LcmsColorProfileContainer.cpp.

663{
664 if (!*d->hasTRC) {
665 return false;
666 }
667
668 std::array<cmsFloat32Number, 2> calcValues{};
669
670 cmsToneCurve *mainCurve = [&]() {
671 if (d->hasColorants) {
672 return d->redTRC;
673 }
674 return d->grayTRC;
675 }();
676
677 cmsToneCurve *compareCurve = transferFunction(characteristics);
678
679 // Number of sweep samples across the curve
680 for (uint32_t i = 0; i < 32; i++) {
681 const float step = float(i) / 31.0f;
682 calcValues[0] = cmsEvalToneCurveFloat(mainCurve, step);
683 calcValues[1] = cmsEvalToneCurveFloat(compareCurve, step);
684 if (std::fabs(calcValues[0] - calcValues[1]) >= error) {
685 return false;
686 }
687 }
688
689 return true;
690}
static cmsToneCurve * transferFunction(TransferCharacteristics transferFunction)

References d, LcmsColorProfileContainer::Private::grayTRC, LcmsColorProfileContainer::Private::hasColorants, LcmsColorProfileContainer::Private::hasTRC, LcmsColorProfileContainer::Private::redTRC, and transferFunction().

◆ copyright()

QString LcmsColorProfileContainer::copyright ( ) const
overridevirtual
Returns
the embedded copyright

Implements IccColorProfile::Container.

Definition at line 358 of file LcmsColorProfileContainer.cpp.

References LcmsColorProfileContainer::Private::copyright, and d.

◆ createFromLcmsProfile()

IccColorProfile * LcmsColorProfileContainer::createFromLcmsProfile ( const cmsHPROFILE profile)
static
Parameters
profilelcms memory structure with the profile, it is freed after the call to this function
Returns
an ICC profile created from an LCMS profile

Definition at line 142 of file LcmsColorProfileContainer.cpp.

143{
144 IccColorProfile *iccprofile = new IccColorProfile(lcmsProfileToByteArray(profile));
145 cmsCloseProfile(profile);
146 return iccprofile;
147}
static QByteArray lcmsProfileToByteArray(const cmsHPROFILE profile)

References IccColorProfile, and lcmsProfileToByteArray().

◆ DelinearizeFloatValue()

void LcmsColorProfileContainer::DelinearizeFloatValue ( QVector< double > & Value) const
virtual

Definition at line 537 of file LcmsColorProfileContainer.cpp.

538{
539 if (d->hasColorants && hasTRC()) {
540 if (!cmsIsToneCurveLinear(d->redTRC)) {
541 Value[0] = cmsEvalToneCurveFloat(*d->redTRCReverse, Value[0]);
542 }
543 if (!cmsIsToneCurveLinear(d->greenTRC)) {
544 Value[1] = cmsEvalToneCurveFloat(*d->greenTRCReverse, Value[1]);
545 }
546 if (!cmsIsToneCurveLinear(d->blueTRC)) {
547 Value[2] = cmsEvalToneCurveFloat(*d->blueTRCReverse, Value[2]);
548 }
549
550 } else {
551 if (cmsIsTag(d->profile, cmsSigGrayTRCTag)) {
552 Value[0] = cmsEvalToneCurveFloat(*d->grayTRCReverse, Value[0]);
553 }
554 }
555}

References LcmsColorProfileContainer::Private::blueTRC, LcmsColorProfileContainer::Private::blueTRCReverse, d, LcmsColorProfileContainer::Private::grayTRCReverse, LcmsColorProfileContainer::Private::greenTRC, LcmsColorProfileContainer::Private::greenTRCReverse, LcmsColorProfileContainer::Private::hasColorants, hasTRC(), LcmsColorProfileContainer::Private::profile, LcmsColorProfileContainer::Private::redTRC, and LcmsColorProfileContainer::Private::redTRCReverse.

◆ DelinearizeFloatValueFast()

void LcmsColorProfileContainer::DelinearizeFloatValueFast ( QVector< double > & Value) const
virtual

Definition at line 584 of file LcmsColorProfileContainer.cpp.

585{
586 const qreal scale = 65535.0;
587 const qreal invScale = 1.0 / scale;
588
589 if (d->hasColorants && hasTRC()) {
590 //we can only reliably delinearise in the 0-1.0 range, outside of that leave the value alone.
591
592 if (!cmsIsToneCurveLinear(d->redTRC) && Value[0]<1.0) {
593 quint16 newValue = cmsEvalToneCurve16(*d->redTRCReverse, Value[0] * scale);
594 Value[0] = newValue * invScale;
595 }
596 if (!cmsIsToneCurveLinear(d->greenTRC) && Value[1]<1.0) {
597 quint16 newValue = cmsEvalToneCurve16(*d->greenTRCReverse, Value[1] * scale);
598 Value[1] = newValue * invScale;
599 }
600 if (!cmsIsToneCurveLinear(d->blueTRC) && Value[2]<1.0) {
601 quint16 newValue = cmsEvalToneCurve16(*d->blueTRCReverse, Value[2] * scale);
602 Value[2] = newValue * invScale;
603 }
604 } else {
605 if (cmsIsTag(d->profile, cmsSigGrayTRCTag) && Value[0]<1.0) {
606 quint16 newValue = cmsEvalToneCurve16(*d->grayTRCReverse, Value[0] * scale);
607 Value[0] = newValue * invScale;
608 }
609 }
610}

References LcmsColorProfileContainer::Private::blueTRC, LcmsColorProfileContainer::Private::blueTRCReverse, d, LcmsColorProfileContainer::Private::grayTRCReverse, LcmsColorProfileContainer::Private::greenTRC, LcmsColorProfileContainer::Private::greenTRCReverse, LcmsColorProfileContainer::Private::hasColorants, hasTRC(), LcmsColorProfileContainer::Private::profile, LcmsColorProfileContainer::Private::redTRC, and LcmsColorProfileContainer::Private::redTRCReverse.

◆ deviceClass()

cmsProfileClassSignature LcmsColorProfileContainer::deviceClass ( ) const
Returns
the class of the color space signature

Definition at line 348 of file LcmsColorProfileContainer.cpp.

349{
350 return d->deviceClass;
351}

References d, and LcmsColorProfileContainer::Private::deviceClass.

◆ getColorantsxyY()

QVector< KoColorimetryUtils::xyY > LcmsColorProfileContainer::getColorantsxyY ( ) const
overridevirtual

Implements IccColorProfile::Container.

Definition at line 446 of file LcmsColorProfileContainer.cpp.

447{
448 cmsCIEXYZ temp1;
449 cmsCIExyY temp2;
451
452 temp1.X = d->colorants.Red.X;
453 temp1.Y = d->colorants.Red.Y;
454 temp1.Z = d->colorants.Red.Z;
455 cmsXYZ2xyY(&temp2, &temp1);
456 colorants.append(fromCIExyY(temp2));
457
458 temp1.X = d->colorants.Green.X;
459 temp1.Y = d->colorants.Green.Y;
460 temp1.Z = d->colorants.Green.Z;
461 cmsXYZ2xyY(&temp2, &temp1);
462 colorants.append(fromCIExyY(temp2));
463
464 temp1.X = d->colorants.Blue.X;
465 temp1.Y = d->colorants.Blue.Y;
466 temp1.Z = d->colorants.Blue.Z;
467 cmsXYZ2xyY(&temp2, &temp1);
468 colorants.append(fromCIExyY(temp2));
469
470 return colorants;
471}
KoColorimetryUtils::xyY fromCIExyY(const cmsCIExyY &xyY)

References LcmsColorProfileContainer::Private::colorants, d, and fromCIExyY().

◆ getColorantsXYZ()

QVector< KoColorimetryUtils::XYZ > LcmsColorProfileContainer::getColorantsXYZ ( ) const
overridevirtual

Implements IccColorProfile::Container.

Definition at line 436 of file LcmsColorProfileContainer.cpp.

437{
438 QVector <KoColorimetryUtils::XYZ> colorants(9);
439
440 colorants.append(fromCieXYZ(d->colorants.Red));
441 colorants.append(fromCieXYZ(d->colorants.Green));
442 colorants.append(fromCieXYZ(d->colorants.Blue));
443 return colorants;
444}
KoColorimetryUtils::XYZ fromCieXYZ(const cmsCIEXYZ &xyz)

References LcmsColorProfileContainer::Private::colorants, d, and fromCieXYZ().

◆ getEstimatedTRC()

QVector< double > LcmsColorProfileContainer::getEstimatedTRC ( ) const
overridevirtual

Implements IccColorProfile::Container.

Definition at line 483 of file LcmsColorProfileContainer.cpp.

484{
485 QVector <double> TRCtriplet(3);
486 if (d->hasColorants && hasTRC()) {
487 if (cmsIsToneCurveLinear(d->redTRC)) {
488 TRCtriplet[0] = 1.0;
489 } else {
490 TRCtriplet[0] = cmsEstimateGamma(d->redTRC, 0.01);
491 }
492 if (cmsIsToneCurveLinear(d->greenTRC)) {
493 TRCtriplet[1] = 1.0;
494 } else {
495 TRCtriplet[1] = cmsEstimateGamma(d->greenTRC, 0.01);
496 }
497 if (cmsIsToneCurveLinear(d->blueTRC)) {
498 TRCtriplet[2] = 1.0;
499 } else {
500 TRCtriplet[2] = cmsEstimateGamma(d->blueTRC, 0.01);
501 }
502
503 } else {
504 if (cmsIsTag(d->profile, cmsSigGrayTRCTag)) {
505 if (cmsIsToneCurveLinear(d->grayTRC)) {
506 TRCtriplet.fill(1.0);
507 } else {
508 TRCtriplet.fill(cmsEstimateGamma(d->grayTRC, 0.01));
509 }
510 } else {
511 TRCtriplet.fill(1.0);
512 }
513 }
514 return TRCtriplet;
515}

References LcmsColorProfileContainer::Private::blueTRC, d, LcmsColorProfileContainer::Private::grayTRC, LcmsColorProfileContainer::Private::greenTRC, LcmsColorProfileContainer::Private::hasColorants, hasTRC(), LcmsColorProfileContainer::Private::profile, and LcmsColorProfileContainer::Private::redTRC.

◆ getProfileUniqueId()

QByteArray LcmsColorProfileContainer::getProfileUniqueId ( ) const
overridevirtual

Implements IccColorProfile::Container.

Definition at line 622 of file LcmsColorProfileContainer.cpp.

623{
624 if (d->uniqueId.isEmpty() && d->profile) {
625 QByteArray id(sizeof(cmsProfileID), 0);
626 cmsGetHeaderProfileID(d->profile, (quint8*)id.data());
627
628 bool isNull = std::all_of(id.constBegin(),
629 id.constEnd(),
630 [](char c) {return c == 0;});
631 if (isNull) {
632 if (cmsMD5computeID(d->profile)) {
633 cmsGetHeaderProfileID(d->profile, (quint8*)id.data());
634 isNull = false;
635 }
636 }
637
638 if (!isNull) {
639 d->uniqueId = id;
640 }
641 }
642
643 return d->uniqueId;
644}

References d, LcmsColorProfileContainer::Private::profile, and LcmsColorProfileContainer::Private::uniqueId.

◆ getWhitePointxyY()

KoColorimetryUtils::xyY LcmsColorProfileContainer::getWhitePointxyY ( ) const
overridevirtual

◆ getWhitePointXYZ()

KoColorimetryUtils::XYZ LcmsColorProfileContainer::getWhitePointXYZ ( ) const
overridevirtual

◆ hasCicpValues()

bool LcmsColorProfileContainer::hasCicpValues ( ) const
overridevirtual

Implements IccColorProfile::Container.

Definition at line 646 of file LcmsColorProfileContainer.cpp.

647{
648 return (d->cicpValues);
649}

References LcmsColorProfileContainer::Private::cicpValues, and d.

◆ hasColorants()

bool LcmsColorProfileContainer::hasColorants ( ) const
overridevirtual

Implements IccColorProfile::Container.

Definition at line 415 of file LcmsColorProfileContainer.cpp.

416{
417 return d->hasColorants;
418}

References d, and LcmsColorProfileContainer::Private::hasColorants.

◆ hasTRC()

bool LcmsColorProfileContainer::hasTRC ( ) const
virtual

Definition at line 419 of file LcmsColorProfileContainer.cpp.

420{
421 return *d->hasTRC;
422}

References d, and LcmsColorProfileContainer::Private::hasTRC.

◆ info()

QString LcmsColorProfileContainer::info ( ) const
overridevirtual

◆ init()

bool LcmsColorProfileContainer::init ( )
private

Definition at line 157 of file LcmsColorProfileContainer.cpp.

158{
159 if (d->profile) {
160 cmsCloseProfile(d->profile);
161 }
162
163 d->profile = cmsOpenProfileFromMem((void *)d->data->rawData().constData(), d->data->rawData().size());
164
165
166#ifndef NDEBUG
167 if (d->data->rawData().size() == 4096) {
168 qWarning() << "Profile has a size of 4096, which is suspicious and indicates a possible misuse of QIODevice::read(int), check your code.";
169 }
170#endif
171
172 if (d->profile) {
173 wchar_t buffer[_BUFFER_SIZE_];
174 d->colorSpaceSignature = cmsGetColorSpace(d->profile);
175 d->deviceClass = cmsGetDeviceClass(d->profile);
176 cmsGetProfileInfo(d->profile, cmsInfoDescription, cmsNoLanguage, cmsNoCountry, buffer, _BUFFER_SIZE_);
177 d->name = QString::fromWCharArray(buffer);
178
179 //apparently this should give us a localised string??? Not sure about this.
180 cmsGetProfileInfo(d->profile, cmsInfoModel, cmsNoLanguage, cmsNoCountry, buffer, _BUFFER_SIZE_);
181 d->productDescription = QString::fromWCharArray(buffer);
182
183 cmsGetProfileInfo(d->profile, cmsInfoManufacturer, cmsNoLanguage, cmsNoCountry, buffer, _BUFFER_SIZE_);
184 d->manufacturer = QString::fromWCharArray(buffer);
185
186 cmsGetProfileInfo(d->profile, cmsInfoCopyright, cmsNoLanguage, cmsNoCountry, buffer, _BUFFER_SIZE_);
187 d->copyright = QString::fromWCharArray(buffer);
188
189 cmsProfileClassSignature profile_class;
190 profile_class = cmsGetDeviceClass(d->profile);
191 d->valid = ( profile_class != cmsSigNamedColorClass
192 && profile_class != cmsSigLinkClass);
193
194 //This is where obtain the whitepoint, and convert it to the actual white point of the profile in the case a Chromatic adaption tag is
195 //present. This is necessary for profiles following the v4 spec.
196 cmsCIEXYZ baseMediaWhitePoint;//dummy to hold copy of mediawhitepoint if this is modified by chromatic adaption.
197 cmsCIEXYZ *mediaWhitePointPtr;
198 bool whiteComp[3];
199 bool whiteIsD50;
200 // Possible bug in profiles: there are in fact some that says they contain that tag
201 // but in fact the pointer is null.
202 // Let's not crash on it anyway, and assume there is no white point instead.
203 // BUG:423685
204 if (cmsIsTag(d->profile, cmsSigMediaWhitePointTag)
205 && (mediaWhitePointPtr = (cmsCIEXYZ *)cmsReadTag(d->profile, cmsSigMediaWhitePointTag))) {
206
207 d->mediaWhitePoint = *(mediaWhitePointPtr);
208 baseMediaWhitePoint = d->mediaWhitePoint;
209
210 whiteComp[0] = std::fabs(baseMediaWhitePoint.X - cmsD50_XYZ()->X) < 0.00001;
211 whiteComp[1] = std::fabs(baseMediaWhitePoint.Y - cmsD50_XYZ()->Y) < 0.00001;
212 whiteComp[2] = std::fabs(baseMediaWhitePoint.Z - cmsD50_XYZ()->Z) < 0.00001;
213 whiteIsD50 = std::all_of(std::begin(whiteComp), std::end(whiteComp), [](bool b) {return b;});
214
215 cmsXYZ2xyY(&d->whitePoint, &d->mediaWhitePoint);
216 cmsCIEXYZ *CAM1;
217 if (cmsIsTag(d->profile, cmsSigChromaticAdaptationTag)
218 && (CAM1 = (cmsCIEXYZ *)cmsReadTag(d->profile, cmsSigChromaticAdaptationTag))
219 && whiteIsD50) {
220 //the chromatic adaption tag represent a matrix from the actual white point of the profile to D50.
221
222 //We first put all our data into structures we can manipulate.
223 double d3dummy [3] = {d->mediaWhitePoint.X, d->mediaWhitePoint.Y, d->mediaWhitePoint.Z};
224 QGenericMatrix<1, 3, double> whitePointMatrix(d3dummy);
225 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);
226 //we then abuse QTransform's invert function because it probably does matrix inversion 20 times better than I can program.
227 //if the matrix is uninvertable, invertedDummy will be an identity matrix, which for us means that it won't give any noticeable
228 //effect when we start multiplying.
229 QTransform invertedDummy = invertDummy.inverted();
230 //we then put the QTransform into a generic 3x3 matrix.
231 double d9dummy [9] = {invertedDummy.m11(), invertedDummy.m12(), invertedDummy.m13(),
232 invertedDummy.m21(), invertedDummy.m22(), invertedDummy.m23(),
233 invertedDummy.m31(), invertedDummy.m32(), invertedDummy.m33()
234 };
235 QGenericMatrix<3, 3, double> chromaticAdaptionMatrix(d9dummy);
236 //multiplying our inverted adaption matrix with the whitepoint gives us the right whitepoint.
237 QGenericMatrix<1, 3, double> result = chromaticAdaptionMatrix * whitePointMatrix;
238 //and then we pour the matrix into the whitepoint variable. Generic matrix does row/column for indices even though it
239 //uses column/row for initialising.
240 d->mediaWhitePoint.X = result(0, 0);
241 d->mediaWhitePoint.Y = result(1, 0);
242 d->mediaWhitePoint.Z = result(2, 0);
243 cmsXYZ2xyY(&d->whitePoint, &d->mediaWhitePoint);
244 }
245 }
246 //This is for RGB profiles, but it only works for matrix profiles. Need to design it to work with non-matrix profiles.
247 cmsCIEXYZ *tempColorantsRed, *tempColorantsGreen, *tempColorantsBlue;
248 // Note: don't assume that cmsIsTag is enough to check for errors; check the pointers, too
249 // BUG:423685
250 if (cmsIsTag(d->profile, cmsSigRedColorantTag) && cmsIsTag(d->profile, cmsSigRedColorantTag) && cmsIsTag(d->profile, cmsSigRedColorantTag)
251 && (tempColorantsRed = (cmsCIEXYZ *)cmsReadTag(d->profile, cmsSigRedColorantTag))
252 && (tempColorantsGreen = (cmsCIEXYZ *)cmsReadTag(d->profile, cmsSigGreenColorantTag))
253 && (tempColorantsBlue = (cmsCIEXYZ *)cmsReadTag(d->profile, cmsSigBlueColorantTag))) {
254 cmsCIEXYZTRIPLE tempColorants;
255 tempColorants.Red = *tempColorantsRed;
256 tempColorants.Green = *tempColorantsGreen;
257 tempColorants.Blue = *tempColorantsBlue;
258 //convert to d65, this is useless.
259 cmsAdaptToIlluminant(&d->colorants.Red, cmsD50_XYZ(), &d->mediaWhitePoint, &tempColorants.Red);
260 cmsAdaptToIlluminant(&d->colorants.Green, cmsD50_XYZ(), &d->mediaWhitePoint, &tempColorants.Green);
261 cmsAdaptToIlluminant(&d->colorants.Blue, cmsD50_XYZ(), &d->mediaWhitePoint, &tempColorants.Blue);
262 //d->colorants = tempColorants;
263 d->hasColorants = true;
264 } else {
265 //qDebug()<<d->name<<": has no colorants";
266 d->hasColorants = false;
267 }
268 //retrieve TRC.
269 if (cmsIsTag(d->profile, cmsSigRedTRCTag) && cmsIsTag(d->profile, cmsSigBlueTRCTag) && cmsIsTag(d->profile, cmsSigGreenTRCTag)) {
270
271 d->redTRC = ((cmsToneCurve *)cmsReadTag (d->profile, cmsSigRedTRCTag));
272 d->greenTRC = ((cmsToneCurve *)cmsReadTag (d->profile, cmsSigGreenTRCTag));
273 d->blueTRC = ((cmsToneCurve *)cmsReadTag (d->profile, cmsSigBlueTRCTag));
277
278 d->hasTRC = Private::LazyBool([d = d] () {
279 return d->redTRC && d->greenTRC && d->blueTRC && *d->redTRCReverse && *d->greenTRCReverse && *d->blueTRCReverse;
280 });
281
282 d->isLinear = Private::LazyBool([d = d] () {
283 return *d->hasTRC
284 && cmsIsToneCurveLinear(d->redTRC)
285 && cmsIsToneCurveLinear(d->greenTRC)
286 && cmsIsToneCurveLinear(d->blueTRC);
287 });
288
289 } else if (cmsIsTag(d->profile, cmsSigGrayTRCTag)) {
290 d->grayTRC = ((cmsToneCurve *)cmsReadTag (d->profile, cmsSigGrayTRCTag));
292
293 d->hasTRC = Private::LazyBool([d = d] () {
294 return d->grayTRC && *d->grayTRCReverse;
295 });
296
297 d->isLinear = Private::LazyBool([d = d] () {
298 return *d->hasTRC && cmsIsToneCurveLinear(d->grayTRC);
299 });
300 } else {
301 d->hasTRC = Private::LazyBool(Private::LazyBool::init_value_tag{}, {});
302 }
303
304 if (cmsIsTag(d->profile, cmsSigcicpTag)) {
305 d->cicpValues = ((cmsVideoSignalType *) cmsReadTag (d->profile, cmsSigcicpTag));
306 }
307
308 // Check if the profile can convert (something->this)
309 d->suitableForOutput = cmsIsIntentSupported(d->profile, INTENT_PERCEPTUAL, LCMS_USED_AS_OUTPUT);
310 d->suitableForInput = cmsIsIntentSupported(d->profile, INTENT_PERCEPTUAL, LCMS_USED_AS_INPUT);
311
312 d->version = cmsGetProfileVersion(d->profile);
313 d->defaultIntent = cmsGetHeaderRenderingIntent(d->profile);
314 d->isMatrixShaper = cmsIsMatrixShaper(d->profile);
315 d->isPerceptualCLUT = cmsIsCLUT(d->profile, INTENT_PERCEPTUAL, LCMS_USED_AS_INPUT);
316 d->isSaturationCLUT = cmsIsCLUT(d->profile, INTENT_SATURATION, LCMS_USED_AS_INPUT);
317 d->isAbsoluteCLUT = cmsIsCLUT(d->profile, INTENT_SATURATION, LCMS_USED_AS_INPUT);
318 d->isRelativeCLUT = cmsIsCLUT(d->profile, INTENT_RELATIVE_COLORIMETRIC, LCMS_USED_AS_INPUT);
319
320 if (cmsIsTag(d->profile, cmsSigMetaTag)) {
321 dbgPigment << "icc profile has dictionary entries";
322
323 cmsHANDLE dictionary = (cmsHANDLE) cmsReadTag(d->profile, cmsSigMetaTag);
324 const cmsDICTentry *entry = cmsDictGetEntryList(dictionary);
325 while (entry) {
326 dbgPigment << QString::fromWCharArray(entry->Name, -1) << QString::fromWCharArray(entry->Value, -1);;
327 dbgPigment << entry->DisplayName << entry->DisplayValue;
328 entry = cmsDictNextEntry(entry);
329 }
330 }
331
332 return true;
333 }
334
335 return false;
336}
#define dbgPigment
#define _BUFFER_SIZE_
KisLazyStorage< KisLazyValueWrapper< bool >, std::function< bool()> > LazyBool
KisLazyStorage< ReverseCurveWrapper, cmsToneCurve * > LazyReverseCurve
#define INTENT_PERCEPTUAL
Definition kis_global.h:103
#define INTENT_RELATIVE_COLORIMETRIC
Definition kis_global.h:104
#define INTENT_SATURATION
Definition kis_global.h:105

References _BUFFER_SIZE_, LcmsColorProfileContainer::Private::blueTRC, LcmsColorProfileContainer::Private::blueTRCReverse, LcmsColorProfileContainer::Private::cicpValues, LcmsColorProfileContainer::Private::colorants, LcmsColorProfileContainer::Private::colorSpaceSignature, LcmsColorProfileContainer::Private::copyright, d, LcmsColorProfileContainer::Private::data, dbgPigment, LcmsColorProfileContainer::Private::defaultIntent, LcmsColorProfileContainer::Private::deviceClass, LcmsColorProfileContainer::Private::grayTRC, LcmsColorProfileContainer::Private::grayTRCReverse, LcmsColorProfileContainer::Private::greenTRC, LcmsColorProfileContainer::Private::greenTRCReverse, LcmsColorProfileContainer::Private::hasColorants, LcmsColorProfileContainer::Private::hasTRC, INTENT_PERCEPTUAL, INTENT_RELATIVE_COLORIMETRIC, INTENT_SATURATION, LcmsColorProfileContainer::Private::isAbsoluteCLUT, LcmsColorProfileContainer::Private::isLinear, LcmsColorProfileContainer::Private::isMatrixShaper, LcmsColorProfileContainer::Private::isPerceptualCLUT, LcmsColorProfileContainer::Private::isRelativeCLUT, LcmsColorProfileContainer::Private::isSaturationCLUT, LcmsColorProfileContainer::Private::manufacturer, LcmsColorProfileContainer::Private::mediaWhitePoint, LcmsColorProfileContainer::Private::name, LcmsColorProfileContainer::Private::productDescription, LcmsColorProfileContainer::Private::profile, IccColorProfile::Data::rawData(), LcmsColorProfileContainer::Private::redTRC, LcmsColorProfileContainer::Private::redTRCReverse, LcmsColorProfileContainer::Private::suitableForInput, LcmsColorProfileContainer::Private::suitableForOutput, LcmsColorProfileContainer::Private::valid, LcmsColorProfileContainer::Private::version, and LcmsColorProfileContainer::Private::whitePoint.

◆ isLinear()

bool LcmsColorProfileContainer::isLinear ( ) const

Definition at line 423 of file LcmsColorProfileContainer.cpp.

424{
425 return *d->isLinear;
426}

References d, and LcmsColorProfileContainer::Private::isLinear.

◆ isSuitableForDisplay()

bool LcmsColorProfileContainer::isSuitableForDisplay ( ) const
overridevirtual

Implements IccColorProfile::Container.

Definition at line 391 of file LcmsColorProfileContainer.cpp.

392{
393 return deviceClass() == cmsSigDisplayClass;
394}
cmsProfileClassSignature deviceClass() const

References deviceClass().

◆ isSuitableForInput()

bool LcmsColorProfileContainer::isSuitableForInput ( ) const
overridevirtual

Implements IccColorProfile::Container.

Definition at line 377 of file LcmsColorProfileContainer.cpp.

378{
379 return d->suitableForInput;
380}

References d, and LcmsColorProfileContainer::Private::suitableForInput.

◆ isSuitableForOutput()

bool LcmsColorProfileContainer::isSuitableForOutput ( ) const
overridevirtual

Implements IccColorProfile::Container.

Definition at line 373 of file LcmsColorProfileContainer.cpp.

374{
375 return d->suitableForOutput;
376}

References d, and LcmsColorProfileContainer::Private::suitableForOutput.

◆ isSuitableForPrinting()

bool LcmsColorProfileContainer::isSuitableForPrinting ( ) const
overridevirtual

Implements IccColorProfile::Container.

Definition at line 386 of file LcmsColorProfileContainer.cpp.

387{
388 return deviceClass() == cmsSigOutputClass;
389}

References deviceClass().

◆ isSuitableForWorkspace()

bool LcmsColorProfileContainer::isSuitableForWorkspace ( ) const
overridevirtual

◆ lcmsProfile()

cmsHPROFILE LcmsColorProfileContainer::lcmsProfile ( ) const
Returns
the structure to use with LCMS functions

Definition at line 338 of file LcmsColorProfileContainer.cpp.

339{
340 return d->profile;
341}

References d, and LcmsColorProfileContainer::Private::profile.

◆ lcmsProfileToByteArray()

QByteArray LcmsColorProfileContainer::lcmsProfileToByteArray ( const cmsHPROFILE profile)
staticprivate

Create a byte array from a lcms profile.

Definition at line 126 of file LcmsColorProfileContainer.cpp.

127{
128 cmsUInt32Number bytesNeeded = 0;
129 // Make a raw data image ready for saving
130 cmsSaveProfileToMem(profile, 0, &bytesNeeded); // calc size
131 QByteArray rawData;
132 rawData.resize(bytesNeeded);
133 if (rawData.size() >= (int)bytesNeeded) {
134 cmsSaveProfileToMem(profile, rawData.data(), &bytesNeeded); // fill buffer
135 } else {
136 qWarning() << "Couldn't resize the profile buffer, system is probably running out of memory.";
137 rawData.resize(0);
138 }
139 return rawData;
140}

◆ LinearizeFloatValue()

void LcmsColorProfileContainer::LinearizeFloatValue ( QVector< double > & Value) const
virtual

Definition at line 517 of file LcmsColorProfileContainer.cpp.

518{
519 if (d->hasColorants && hasTRC()) {
520 if (!cmsIsToneCurveLinear(d->redTRC)) {
521 Value[0] = cmsEvalToneCurveFloat(d->redTRC, Value[0]);
522 }
523 if (!cmsIsToneCurveLinear(d->greenTRC)) {
524 Value[1] = cmsEvalToneCurveFloat(d->greenTRC, Value[1]);
525 }
526 if (!cmsIsToneCurveLinear(d->blueTRC)) {
527 Value[2] = cmsEvalToneCurveFloat(d->blueTRC, Value[2]);
528 }
529
530 } else {
531 if (cmsIsTag(d->profile, cmsSigGrayTRCTag)) {
532 Value[0] = cmsEvalToneCurveFloat(d->grayTRC, Value[0]);
533 }
534 }
535}

References LcmsColorProfileContainer::Private::blueTRC, d, LcmsColorProfileContainer::Private::grayTRC, LcmsColorProfileContainer::Private::greenTRC, LcmsColorProfileContainer::Private::hasColorants, hasTRC(), LcmsColorProfileContainer::Private::profile, and LcmsColorProfileContainer::Private::redTRC.

◆ LinearizeFloatValueFast()

void LcmsColorProfileContainer::LinearizeFloatValueFast ( QVector< double > & Value) const
virtual

Definition at line 557 of file LcmsColorProfileContainer.cpp.

558{
559 const qreal scale = 65535.0;
560 const qreal invScale = 1.0 / scale;
561
562 if (d->hasColorants && hasTRC()) {
563 //we can only reliably delinearise in the 0-1.0 range, outside of that leave the value alone.
564
565 if (!cmsIsToneCurveLinear(d->redTRC) && Value[0]<1.0) {
566 quint16 newValue = cmsEvalToneCurve16(d->redTRC, Value[0] * scale);
567 Value[0] = newValue * invScale;
568 }
569 if (!cmsIsToneCurveLinear(d->greenTRC) && Value[1]<1.0) {
570 quint16 newValue = cmsEvalToneCurve16(d->greenTRC, Value[1] * scale);
571 Value[1] = newValue * invScale;
572 }
573 if (!cmsIsToneCurveLinear(d->blueTRC) && Value[2]<1.0) {
574 quint16 newValue = cmsEvalToneCurve16(d->blueTRC, Value[2] * scale);
575 Value[2] = newValue * invScale;
576 }
577 } else {
578 if (cmsIsTag(d->profile, cmsSigGrayTRCTag) && Value[0]<1.0) {
579 quint16 newValue = cmsEvalToneCurve16(d->grayTRC, Value[0] * scale);
580 Value[0] = newValue * invScale;
581 }
582 }
583}

References LcmsColorProfileContainer::Private::blueTRC, d, LcmsColorProfileContainer::Private::grayTRC, LcmsColorProfileContainer::Private::greenTRC, LcmsColorProfileContainer::Private::hasColorants, hasTRC(), LcmsColorProfileContainer::Private::profile, and LcmsColorProfileContainer::Private::redTRC.

◆ manufacturer()

QString LcmsColorProfileContainer::manufacturer ( ) const
overridevirtual
Returns
the name of the manufacturer

Implements IccColorProfile::Container.

Definition at line 353 of file LcmsColorProfileContainer.cpp.

354{
355 return d->manufacturer;
356}

References d, and LcmsColorProfileContainer::Private::manufacturer.

◆ name()

QString LcmsColorProfileContainer::name ( ) const
overridevirtual

Implements IccColorProfile::Container.

Definition at line 612 of file LcmsColorProfileContainer.cpp.

613{
614 return d->name;
615}

References d, and LcmsColorProfileContainer::Private::name.

◆ supportsAbsolute()

bool LcmsColorProfileContainer::supportsAbsolute ( ) const
virtual

Definition at line 404 of file LcmsColorProfileContainer.cpp.

405{
406 return d->isAbsoluteCLUT;//LCMS2 doesn't convert matrix shapers via absolute intent, because of V4 workflow.
407}

References d, and LcmsColorProfileContainer::Private::isAbsoluteCLUT.

◆ supportsPerceptual()

bool LcmsColorProfileContainer::supportsPerceptual ( ) const
virtual

Definition at line 396 of file LcmsColorProfileContainer.cpp.

397{
398 return d->isPerceptualCLUT;
399}

References d, and LcmsColorProfileContainer::Private::isPerceptualCLUT.

◆ supportsRelative()

bool LcmsColorProfileContainer::supportsRelative ( ) const
virtual

Definition at line 408 of file LcmsColorProfileContainer.cpp.

409{
411 return true;
412 }
413 return false;
414}

References d, LcmsColorProfileContainer::Private::isMatrixShaper, and LcmsColorProfileContainer::Private::isRelativeCLUT.

◆ supportsSaturation()

bool LcmsColorProfileContainer::supportsSaturation ( ) const
virtual

Definition at line 400 of file LcmsColorProfileContainer.cpp.

401{
402 return d->isSaturationCLUT;
403}

References d, and LcmsColorProfileContainer::Private::isSaturationCLUT.

◆ transferFunction()

cmsToneCurve * LcmsColorProfileContainer::transferFunction ( TransferCharacteristics transferFunction)
static

Definition at line 703 of file LcmsColorProfileContainer.cpp.

704{
705 cmsToneCurve *mainCurve;
706
707 // Values courtesy of Elle Stone
708 cmsFloat64Number srgb_parameters[5] =
709 { 2.4, 1.0 / 1.055, 0.055 / 1.055, 1.0 / 12.92, 0.04045 };
710 cmsFloat64Number rec709_parameters[5] =
711 { 1.0 / 0.45, 1.0 / 1.099, 0.099 / 1.099, 1.0 / 4.5, 0.081 };
712
713 // The following is basically a precise version of rec709.
714 cmsFloat64Number rec202012bit_parameters[5] =
715 { 1.0 / 0.45, 1.0 / 1.0993, 0.0993 / 1.0993, 1.0 / 4.5, 0.0812 };
716
717 cmsFloat64Number SMPTE_240M_parameters[5] =
718 { 1.0 / 0.45, 1.0 / 1.1115, 0.1115 / 1.1115, 1.0 / 4.0, 0.0913 };
719
720 cmsFloat64Number prophoto_parameters[5] =
721 { 1.8, 1.0, 0, 1.0 / 16, (16.0/512) };
722
723 cmsFloat64Number log_100[5] = {1.0, 10, 2.0, -2.0, 0.0};
724 cmsFloat64Number log_100_sqrt[5] = {1.0, 10, 2.5, -2.5, 0.0};
725
726 cmsFloat64Number labl_parameters[5] = {3.0, 0.862076, 0.137924, 0.110703, 0.080002};
727
728 switch (transferFunction) {
730 // Not possible in ICC due to lack of a*pow(bX+c,y) construct.
732 // This is not possible in ICC due to lack of a*pow(bX+c,y) construct.
733 qWarning() << "Neither IEC 61966 2-4 nor Bt. 1361 are supported, returning a rec 709 curve.";
734 Q_FALLTHROUGH();
738 mainCurve = cmsBuildParametricToneCurve(NULL, 4, rec709_parameters);
739 break;
741 mainCurve = cmsBuildParametricToneCurve(NULL, 4, rec202012bit_parameters);
742 break;
744 mainCurve = cmsBuildGamma(NULL, 2.2);
745 break;
747 mainCurve = cmsBuildGamma(NULL, 2.8);
748 break;
749 case TRC_SMPTE_240M:
750 mainCurve = cmsBuildParametricToneCurve(NULL, 4, SMPTE_240M_parameters);
751 break;
753 mainCurve = cmsBuildParametricToneCurve(NULL, 4, srgb_parameters);
754 break;
756 mainCurve = cmsBuildParametricToneCurve(NULL, 8, log_100);
757 break;
759 mainCurve = cmsBuildParametricToneCurve(NULL, 8, log_100_sqrt);
760 break;
761 case TRC_A98:
762 // gamma 563/256
763 mainCurve = cmsBuildGamma(NULL, 563.0 / 256.0);
764 break;
765 case TRC_PROPHOTO:
766 mainCurve = cmsBuildParametricToneCurve(NULL, 4, prophoto_parameters);
767 break;
768 case TRC_GAMMA_1_8:
769 mainCurve = cmsBuildGamma(NULL, 1.8);
770 break;
771 case TRC_GAMMA_2_4:
772 mainCurve = cmsBuildGamma(NULL, 2.4);
773 break;
774 case TRC_LAB_L:
775 mainCurve = cmsBuildParametricToneCurve(NULL, 4, labl_parameters);
776 break;
779 break;
781 // Requires an a*X^y construction, not possible.
783 // Hybrid log gamma.
784 qWarning() << "Cannot generate an icc profile with this transfer function, will generate a linear profile";
785 Q_FALLTHROUGH();
786 case TRC_LINEAR:
787 default:
788 mainCurve = cmsBuildGamma(NULL, 1.0);
789 break;
790 }
791
792 return mainCurve;
793}
@ TRC_IEC_61966_2_4
@ TRC_ITU_R_BT_2020_2_10bit
@ TRC_LOGARITHMIC_100
@ TRC_ITU_R_BT_470_6_SYSTEM_M
@ TRC_ITU_R_BT_470_6_SYSTEM_B_G
@ TRC_ITU_R_BT_1361
@ TRC_ITU_R_BT_2100_0_HLG
@ TRC_ITU_R_BT_2100_0_PQ
@ TRC_ITU_R_BT_601_6
@ TRC_IEC_61966_2_1
@ TRC_ITU_R_BT_709_5
@ TRC_SMPTE_ST_428_1
@ TRC_LOGARITHMIC_100_sqrt10
@ TRC_ITU_R_BT_2020_2_12bit
cmsToneCurve * perceptualQuantizerDummy()

References perceptualQuantizerDummy(), transferFunction(), TRC_A98, TRC_GAMMA_1_8, TRC_GAMMA_2_4, TRC_IEC_61966_2_1, TRC_IEC_61966_2_4, TRC_ITU_R_BT_1361, TRC_ITU_R_BT_2020_2_10bit, TRC_ITU_R_BT_2020_2_12bit, TRC_ITU_R_BT_2100_0_HLG, TRC_ITU_R_BT_2100_0_PQ, TRC_ITU_R_BT_470_6_SYSTEM_B_G, TRC_ITU_R_BT_470_6_SYSTEM_M, TRC_ITU_R_BT_601_6, TRC_ITU_R_BT_709_5, TRC_LAB_L, TRC_LINEAR, TRC_LOGARITHMIC_100, TRC_LOGARITHMIC_100_sqrt10, TRC_PROPHOTO, TRC_SMPTE_240M, and TRC_SMPTE_ST_428_1.

◆ valid()

bool LcmsColorProfileContainer::valid ( ) const
overridevirtual

Implements IccColorProfile::Container.

Definition at line 363 of file LcmsColorProfileContainer.cpp.

364{
365 return d->valid;
366}

References d, and LcmsColorProfileContainer::Private::valid.

◆ version()

float LcmsColorProfileContainer::version ( ) const
virtual

Definition at line 368 of file LcmsColorProfileContainer.cpp.

369{
370 return d->version;
371}

References d, and LcmsColorProfileContainer::Private::version.

Friends And Related Symbol Documentation

◆ IccColorProfile

friend class IccColorProfile
friend

Definition at line 26 of file LcmsColorProfileContainer.h.

Member Data Documentation

◆ d

Private* const LcmsColorProfileContainer::d
private

Definition at line 114 of file LcmsColorProfileContainer.h.


The documentation for this class was generated from the following files: