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

#include <LcmsColorProfileContainer.h>

+ Inheritance diagram for LcmsColorProfileContainer:

Classes

class  Private
 

Public Member Functions

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< double > getColorantsxyY () const override
 
QVector< double > getColorantsXYZ () const override
 
QVector< double > getEstimatedTRC () const override
 
QByteArray getProfileUniqueId () const override
 
QVector< double > getWhitePointxyY () const override
 
QVector< double > getWhitePointXYZ () const override
 
bool hasColorants () const override
 
virtual bool hasTRC () const
 
QString info () const override
 
bool isLinear () const
 
bool isSuitableForDisplay () const override
 
bool isSuitableForOutput () const override
 
bool isSuitableForPrinting () 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 23 of file LcmsColorProfileContainer.h.

Constructor & Destructor Documentation

◆ LcmsColorProfileContainer() [1/2]

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

◆ ~LcmsColorProfileContainer()

LcmsColorProfileContainer::~LcmsColorProfileContainer ( )
override

Definition at line 144 of file LcmsColorProfileContainer.cpp.

145{
146 cmsCloseProfile(d->profile);
147 delete d;
148}

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

◆ LcmsColorProfileContainer() [2/2]

LcmsColorProfileContainer::LcmsColorProfileContainer ( )
protected

Definition at line 107 of file LcmsColorProfileContainer.cpp.

108 : d(new Private())
109{
110 d->profile = 0;
111}

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

Member Function Documentation

◆ colorSpaceSignature()

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

Definition at line 323 of file LcmsColorProfileContainer.cpp.

324{
325 return d->colorSpaceSignature;
326}

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

◆ compareTRC()

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

Implements IccColorProfile::Container.

Definition at line 630 of file LcmsColorProfileContainer.cpp.

631{
632 if (!*d->hasTRC) {
633 return false;
634 }
635
636 std::array<cmsFloat32Number, 2> calcValues{};
637
638 cmsToneCurve *mainCurve = [&]() {
639 if (d->hasColorants) {
640 return d->redTRC;
641 }
642 return d->grayTRC;
643 }();
644
645 cmsToneCurve *compareCurve = transferFunction(characteristics);
646
647 // Number of sweep samples across the curve
648 for (uint32_t i = 0; i < 32; i++) {
649 const float step = float(i) / 31.0f;
650 calcValues[0] = cmsEvalToneCurveFloat(mainCurve, step);
651 calcValues[1] = cmsEvalToneCurveFloat(compareCurve, step);
652 if (std::fabs(calcValues[0] - calcValues[1]) >= error) {
653 return false;
654 }
655 }
656
657 return true;
658}
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 338 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 137 of file LcmsColorProfileContainer.cpp.

138{
139 IccColorProfile *iccprofile = new IccColorProfile(lcmsProfileToByteArray(profile));
140 cmsCloseProfile(profile);
141 return iccprofile;
142}
static QByteArray lcmsProfileToByteArray(const cmsHPROFILE profile)

References IccColorProfile, and lcmsProfileToByteArray().

◆ DelinearizeFloatValue()

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

Definition at line 521 of file LcmsColorProfileContainer.cpp.

522{
523 if (d->hasColorants) {
524 if (!cmsIsToneCurveLinear(d->redTRC)) {
525 Value[0] = cmsEvalToneCurveFloat(*d->redTRCReverse, Value[0]);
526 }
527 if (!cmsIsToneCurveLinear(d->greenTRC)) {
528 Value[1] = cmsEvalToneCurveFloat(*d->greenTRCReverse, Value[1]);
529 }
530 if (!cmsIsToneCurveLinear(d->blueTRC)) {
531 Value[2] = cmsEvalToneCurveFloat(*d->blueTRCReverse, Value[2]);
532 }
533
534 } else {
535 if (cmsIsTag(d->profile, cmsSigGrayTRCTag)) {
536 Value[0] = cmsEvalToneCurveFloat(*d->grayTRCReverse, Value[0]);
537 }
538 }
539}

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

◆ DelinearizeFloatValueFast()

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

Definition at line 568 of file LcmsColorProfileContainer.cpp.

569{
570 const qreal scale = 65535.0;
571 const qreal invScale = 1.0 / scale;
572
573 if (d->hasColorants) {
574 //we can only reliably delinearise in the 0-1.0 range, outside of that leave the value alone.
575
576 if (!cmsIsToneCurveLinear(d->redTRC) && Value[0]<1.0) {
577 quint16 newValue = cmsEvalToneCurve16(*d->redTRCReverse, Value[0] * scale);
578 Value[0] = newValue * invScale;
579 }
580 if (!cmsIsToneCurveLinear(d->greenTRC) && Value[1]<1.0) {
581 quint16 newValue = cmsEvalToneCurve16(*d->greenTRCReverse, Value[1] * scale);
582 Value[1] = newValue * invScale;
583 }
584 if (!cmsIsToneCurveLinear(d->blueTRC) && Value[2]<1.0) {
585 quint16 newValue = cmsEvalToneCurve16(*d->blueTRCReverse, Value[2] * scale);
586 Value[2] = newValue * invScale;
587 }
588 } else {
589 if (cmsIsTag(d->profile, cmsSigGrayTRCTag) && Value[0]<1.0) {
590 quint16 newValue = cmsEvalToneCurve16(*d->grayTRCReverse, Value[0] * scale);
591 Value[0] = newValue * invScale;
592 }
593 }
594}

References LcmsColorProfileContainer::Private::blueTRC, LcmsColorProfileContainer::Private::blueTRCReverse, d, LcmsColorProfileContainer::Private::grayTRCReverse, LcmsColorProfileContainer::Private::greenTRC, LcmsColorProfileContainer::Private::greenTRCReverse, LcmsColorProfileContainer::Private::hasColorants, 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 328 of file LcmsColorProfileContainer.cpp.

329{
330 return d->deviceClass;
331}

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

◆ getColorantsxyY()

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

Implements IccColorProfile::Container.

Definition at line 414 of file LcmsColorProfileContainer.cpp.

415{
416 cmsCIEXYZ temp1;
417 cmsCIExyY temp2;
418 QVector <double> colorants(9);
419
420 temp1.X = d->colorants.Red.X;
421 temp1.Y = d->colorants.Red.Y;
422 temp1.Z = d->colorants.Red.Z;
423 cmsXYZ2xyY(&temp2, &temp1);
424 colorants[0] = temp2.x;
425 colorants[1] = temp2.y;
426 colorants[2] = temp2.Y;
427
428 temp1.X = d->colorants.Green.X;
429 temp1.Y = d->colorants.Green.Y;
430 temp1.Z = d->colorants.Green.Z;
431 cmsXYZ2xyY(&temp2, &temp1);
432 colorants[3] = temp2.x;
433 colorants[4] = temp2.y;
434 colorants[5] = temp2.Y;
435
436 temp1.X = d->colorants.Blue.X;
437 temp1.Y = d->colorants.Blue.Y;
438 temp1.Z = d->colorants.Blue.Z;
439 cmsXYZ2xyY(&temp2, &temp1);
440 colorants[6] = temp2.x;
441 colorants[7] = temp2.y;
442 colorants[8] = temp2.Y;
443
444 return colorants;
445}

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

◆ getColorantsXYZ()

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

Implements IccColorProfile::Container.

Definition at line 399 of file LcmsColorProfileContainer.cpp.

400{
401 QVector <double> colorants(9);
402 colorants[0] = d->colorants.Red.X;
403 colorants[1] = d->colorants.Red.Y;
404 colorants[2] = d->colorants.Red.Z;
405 colorants[3] = d->colorants.Green.X;
406 colorants[4] = d->colorants.Green.Y;
407 colorants[5] = d->colorants.Green.Z;
408 colorants[6] = d->colorants.Blue.X;
409 colorants[7] = d->colorants.Blue.Y;
410 colorants[8] = d->colorants.Blue.Z;
411 return colorants;
412}

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

◆ getEstimatedTRC()

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

Implements IccColorProfile::Container.

Definition at line 467 of file LcmsColorProfileContainer.cpp.

468{
469 QVector <double> TRCtriplet(3);
470 if (d->hasColorants) {
471 if (cmsIsToneCurveLinear(d->redTRC)) {
472 TRCtriplet[0] = 1.0;
473 } else {
474 TRCtriplet[0] = cmsEstimateGamma(d->redTRC, 0.01);
475 }
476 if (cmsIsToneCurveLinear(d->greenTRC)) {
477 TRCtriplet[1] = 1.0;
478 } else {
479 TRCtriplet[1] = cmsEstimateGamma(d->greenTRC, 0.01);
480 }
481 if (cmsIsToneCurveLinear(d->blueTRC)) {
482 TRCtriplet[2] = 1.0;
483 } else {
484 TRCtriplet[2] = cmsEstimateGamma(d->blueTRC, 0.01);
485 }
486
487 } else {
488 if (cmsIsTag(d->profile, cmsSigGrayTRCTag)) {
489 if (cmsIsToneCurveLinear(d->grayTRC)) {
490 TRCtriplet.fill(1.0);
491 } else {
492 TRCtriplet.fill(cmsEstimateGamma(d->grayTRC, 0.01));
493 }
494 } else {
495 TRCtriplet.fill(1.0);
496 }
497 }
498 return TRCtriplet;
499}

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

◆ getProfileUniqueId()

QByteArray LcmsColorProfileContainer::getProfileUniqueId ( ) const
overridevirtual

Implements IccColorProfile::Container.

Definition at line 606 of file LcmsColorProfileContainer.cpp.

607{
608 if (d->uniqueId.isEmpty() && d->profile) {
609 QByteArray id(sizeof(cmsProfileID), 0);
610 cmsGetHeaderProfileID(d->profile, (quint8*)id.data());
611
612 bool isNull = std::all_of(id.constBegin(),
613 id.constEnd(),
614 [](char c) {return c == 0;});
615 if (isNull) {
616 if (cmsMD5computeID(d->profile)) {
617 cmsGetHeaderProfileID(d->profile, (quint8*)id.data());
618 isNull = false;
619 }
620 }
621
622 if (!isNull) {
623 d->uniqueId = id;
624 }
625 }
626
627 return d->uniqueId;
628}

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

◆ getWhitePointxyY()

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

Implements IccColorProfile::Container.

Definition at line 458 of file LcmsColorProfileContainer.cpp.

459{
460 QVector <double> tempWhitePoint(3);
461 tempWhitePoint[0] = d->whitePoint.x;
462 tempWhitePoint[1] = d->whitePoint.y;
463 tempWhitePoint[2] = d->whitePoint.Y;
464 return tempWhitePoint;
465}

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

◆ getWhitePointXYZ()

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

Implements IccColorProfile::Container.

Definition at line 447 of file LcmsColorProfileContainer.cpp.

448{
449 QVector <double> tempWhitePoint(3);
450
451 tempWhitePoint[0] = d->mediaWhitePoint.X;
452 tempWhitePoint[1] = d->mediaWhitePoint.Y;
453 tempWhitePoint[2] = d->mediaWhitePoint.Z;
454
455 return tempWhitePoint;
456}

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

◆ hasColorants()

bool LcmsColorProfileContainer::hasColorants ( ) const
overridevirtual

Implements IccColorProfile::Container.

Definition at line 387 of file LcmsColorProfileContainer.cpp.

388{
389 return d->hasColorants;
390}

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

◆ hasTRC()

bool LcmsColorProfileContainer::hasTRC ( ) const
virtual

Definition at line 391 of file LcmsColorProfileContainer.cpp.

392{
393 return *d->hasTRC;
394}

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

◆ info()

QString LcmsColorProfileContainer::info ( ) const
overridevirtual

◆ init()

bool LcmsColorProfileContainer::init ( )
private

Definition at line 152 of file LcmsColorProfileContainer.cpp.

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

◆ isLinear()

bool LcmsColorProfileContainer::isLinear ( ) const

Definition at line 395 of file LcmsColorProfileContainer.cpp.

396{
397 return *d->isLinear;
398}

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

◆ isSuitableForDisplay()

bool LcmsColorProfileContainer::isSuitableForDisplay ( ) const
overridevirtual

Implements IccColorProfile::Container.

Definition at line 363 of file LcmsColorProfileContainer.cpp.

364{
365 return deviceClass() == cmsSigDisplayClass;
366}
cmsProfileClassSignature deviceClass() const

References deviceClass().

◆ isSuitableForOutput()

bool LcmsColorProfileContainer::isSuitableForOutput ( ) const
overridevirtual

Implements IccColorProfile::Container.

Definition at line 353 of file LcmsColorProfileContainer.cpp.

354{
355 return d->suitableForOutput;
356}

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

◆ isSuitableForPrinting()

bool LcmsColorProfileContainer::isSuitableForPrinting ( ) const
overridevirtual

Implements IccColorProfile::Container.

Definition at line 358 of file LcmsColorProfileContainer.cpp.

359{
360 return deviceClass() == cmsSigOutputClass;
361}

References deviceClass().

◆ lcmsProfile()

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

Definition at line 318 of file LcmsColorProfileContainer.cpp.

319{
320 return d->profile;
321}

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 121 of file LcmsColorProfileContainer.cpp.

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

◆ LinearizeFloatValue()

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

Definition at line 501 of file LcmsColorProfileContainer.cpp.

502{
503 if (d->hasColorants) {
504 if (!cmsIsToneCurveLinear(d->redTRC)) {
505 Value[0] = cmsEvalToneCurveFloat(d->redTRC, Value[0]);
506 }
507 if (!cmsIsToneCurveLinear(d->greenTRC)) {
508 Value[1] = cmsEvalToneCurveFloat(d->greenTRC, Value[1]);
509 }
510 if (!cmsIsToneCurveLinear(d->blueTRC)) {
511 Value[2] = cmsEvalToneCurveFloat(d->blueTRC, Value[2]);
512 }
513
514 } else {
515 if (cmsIsTag(d->profile, cmsSigGrayTRCTag)) {
516 Value[0] = cmsEvalToneCurveFloat(d->grayTRC, Value[0]);
517 }
518 }
519}

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

◆ LinearizeFloatValueFast()

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

Definition at line 541 of file LcmsColorProfileContainer.cpp.

542{
543 const qreal scale = 65535.0;
544 const qreal invScale = 1.0 / scale;
545
546 if (d->hasColorants) {
547 //we can only reliably delinearise in the 0-1.0 range, outside of that leave the value alone.
548
549 if (!cmsIsToneCurveLinear(d->redTRC) && Value[0]<1.0) {
550 quint16 newValue = cmsEvalToneCurve16(d->redTRC, Value[0] * scale);
551 Value[0] = newValue * invScale;
552 }
553 if (!cmsIsToneCurveLinear(d->greenTRC) && Value[1]<1.0) {
554 quint16 newValue = cmsEvalToneCurve16(d->greenTRC, Value[1] * scale);
555 Value[1] = newValue * invScale;
556 }
557 if (!cmsIsToneCurveLinear(d->blueTRC) && Value[2]<1.0) {
558 quint16 newValue = cmsEvalToneCurve16(d->blueTRC, Value[2] * scale);
559 Value[2] = newValue * invScale;
560 }
561 } else {
562 if (cmsIsTag(d->profile, cmsSigGrayTRCTag) && Value[0]<1.0) {
563 quint16 newValue = cmsEvalToneCurve16(d->grayTRC, Value[0] * scale);
564 Value[0] = newValue * invScale;
565 }
566 }
567}

References LcmsColorProfileContainer::Private::blueTRC, d, LcmsColorProfileContainer::Private::grayTRC, LcmsColorProfileContainer::Private::greenTRC, LcmsColorProfileContainer::Private::hasColorants, 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 333 of file LcmsColorProfileContainer.cpp.

334{
335 return d->manufacturer;
336}

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

◆ name()

QString LcmsColorProfileContainer::name ( ) const
overridevirtual

Implements IccColorProfile::Container.

Definition at line 596 of file LcmsColorProfileContainer.cpp.

597{
598 return d->name;
599}

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

◆ supportsAbsolute()

bool LcmsColorProfileContainer::supportsAbsolute ( ) const
virtual

Definition at line 376 of file LcmsColorProfileContainer.cpp.

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

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

◆ supportsPerceptual()

bool LcmsColorProfileContainer::supportsPerceptual ( ) const
virtual

Definition at line 368 of file LcmsColorProfileContainer.cpp.

369{
370 return d->isPerceptualCLUT;
371}

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

◆ supportsRelative()

bool LcmsColorProfileContainer::supportsRelative ( ) const
virtual

Definition at line 380 of file LcmsColorProfileContainer.cpp.

381{
383 return true;
384 }
385 return false;
386}

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

◆ supportsSaturation()

bool LcmsColorProfileContainer::supportsSaturation ( ) const
virtual

Definition at line 372 of file LcmsColorProfileContainer.cpp.

373{
374 return d->isSaturationCLUT;
375}

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

◆ transferFunction()

cmsToneCurve * LcmsColorProfileContainer::transferFunction ( TransferCharacteristics transferFunction)
static

Definition at line 660 of file LcmsColorProfileContainer.cpp.

661{
662 cmsToneCurve *mainCurve;
663
664 // Values courtesy of Elle Stone
665 cmsFloat64Number srgb_parameters[5] =
666 { 2.4, 1.0 / 1.055, 0.055 / 1.055, 1.0 / 12.92, 0.04045 };
667 cmsFloat64Number rec709_parameters[5] =
668 { 1.0 / 0.45, 1.0 / 1.099, 0.099 / 1.099, 1.0 / 4.5, 0.081 };
669
670 // The following is basically a precise version of rec709.
671 cmsFloat64Number rec202012bit_parameters[5] =
672 { 1.0 / 0.45, 1.0 / 1.0993, 0.0993 / 1.0993, 1.0 / 4.5, 0.0812 };
673
674 cmsFloat64Number SMPTE_240M_parameters[5] =
675 { 1.0 / 0.45, 1.0 / 1.1115, 0.1115 / 1.1115, 1.0 / 4.0, 0.0913 };
676
677 cmsFloat64Number prophoto_parameters[5] =
678 { 1.8, 1.0, 0, 1.0 / 16, (16.0/512) };
679
680 cmsFloat64Number log_100[5] = {1.0, 10, 2.0, -2.0, 0.0};
681 cmsFloat64Number log_100_sqrt[5] = {1.0, 10, 2.5, -2.5, 0.0};
682
683 cmsFloat64Number labl_parameters[5] = {3.0, 0.862076, 0.137924, 0.110703, 0.080002};
684
685 switch (transferFunction) {
687 // Not possible in ICC due to lack of a*pow(bX+c,y) construct.
689 // This is not possible in ICC due to lack of a*pow(bX+c,y) construct.
690 qWarning() << "Neither IEC 61966 2-4 nor Bt. 1361 are supported, returning a rec 709 curve.";
691 Q_FALLTHROUGH();
695 mainCurve = cmsBuildParametricToneCurve(NULL, 4, rec709_parameters);
696 break;
698 mainCurve = cmsBuildParametricToneCurve(NULL, 4, rec202012bit_parameters);
699 break;
701 mainCurve = cmsBuildGamma(NULL, 2.2);
702 break;
704 mainCurve = cmsBuildGamma(NULL, 2.8);
705 break;
706 case TRC_SMPTE_240M:
707 mainCurve = cmsBuildParametricToneCurve(NULL, 4, SMPTE_240M_parameters);
708 break;
710 mainCurve = cmsBuildParametricToneCurve(NULL, 4, srgb_parameters);
711 break;
713 mainCurve = cmsBuildParametricToneCurve(NULL, 8, log_100);
714 break;
716 mainCurve = cmsBuildParametricToneCurve(NULL, 8, log_100_sqrt);
717 break;
718 case TRC_A98:
719 // gamma 563/256
720 mainCurve = cmsBuildGamma(NULL, 563.0 / 256.0);
721 break;
722 case TRC_PROPHOTO:
723 mainCurve = cmsBuildParametricToneCurve(NULL, 4, prophoto_parameters);
724 break;
725 case TRC_GAMMA_1_8:
726 mainCurve = cmsBuildGamma(NULL, 1.8);
727 break;
728 case TRC_GAMMA_2_4:
729 mainCurve = cmsBuildGamma(NULL, 2.4);
730 break;
731 case TRC_LAB_L:
732 mainCurve = cmsBuildParametricToneCurve(NULL, 4, labl_parameters);
733 break;
735 // Requires an a*X^y construction, not possible.
737 // Perceptual Quantizer
739 // Hybrid log gamma.
740 qWarning() << "Cannot generate an icc profile with this transfer function, will generate a linear profile";
741 Q_FALLTHROUGH();
742 case TRC_LINEAR:
743 default:
744 mainCurve = cmsBuildGamma(NULL, 1.0);
745 break;
746 }
747
748 return mainCurve;
749}
@ 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

References 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 343 of file LcmsColorProfileContainer.cpp.

344{
345 return d->valid;
346}

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

◆ version()

float LcmsColorProfileContainer::version ( ) const
virtual

Definition at line 348 of file LcmsColorProfileContainer.cpp.

349{
350 return d->version;
351}

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

Friends And Related Symbol Documentation

◆ IccColorProfile

friend class IccColorProfile
friend

Definition at line 25 of file LcmsColorProfileContainer.h.

Member Data Documentation

◆ d

Private* const LcmsColorProfileContainer::d
private

Definition at line 107 of file LcmsColorProfileContainer.h.


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