18#include <QSharedPointer>
77 QScopedPointer<IccColorProfile::Data>
data;
115 cmsCIExyY whitePoint;
124 if (modifiedColorants.size()>=2) {
134 if (modifiedColorants.size()>0 && modifiedColorants.size() <= 3) {
135 primaries = {{modifiedColorants[0].x, modifiedColorants[0].y, 1.0},
136 {modifiedColorants[1].x, modifiedColorants[1].y, 1.0},
137 {modifiedColorants[2].x, modifiedColorants[2].y, 1.0}};
140 cmsHPROFILE iccProfile =
nullptr;
143 iccProfile = cmsCreateGrayProfile(&whitePoint, mainCurve);
145 cmsFreeToneCurve(mainCurve);
148 cmsToneCurve *curve[3];
149 curve[0] = curve[1] = curve[2] = mainCurve;
150 iccProfile = cmsCreateRGBProfile(&whitePoint, &
primaries, curve);
151 cmsFreeToneCurve(mainCurve);
155 qWarning() <<
"WARNING: LCMS failed to create a profile for the requested parameters";
158 qWarning() <<
" requested colorants:" << query.
rgbColorants;
164 name.append(
"Krita");
167 name.append(QStringLiteral(
"Rec. 2100"));
173 cmsCIEXYZ media_blackpoint = {0.0, 0.0, 0.0};
174 cmsWriteTag (iccProfile, cmsSigMediaBlackPointTag, &media_blackpoint);
182 cmsWriteTag(iccProfile, cmsSigRedColorantTag,
nullptr);
183 cmsWriteTag(iccProfile, cmsSigGreenColorantTag,
nullptr);
184 cmsWriteTag(iccProfile, cmsSigBlueColorantTag,
nullptr);
185 cmsWriteTag(iccProfile, cmsSigRedTRCTag,
nullptr);
186 cmsWriteTag(iccProfile, cmsSigGreenTRCTag,
nullptr);
187 cmsWriteTag(iccProfile, cmsSigBlueTRCTag,
nullptr);
195 cmsVideoSignalType cicpValues;
196 cicpValues.ColourPrimaries = quint8(query.
primaries);
197 cicpValues.TransferCharacteristics = quint8(query.
transfer);
198 cicpValues.MatrixCoefficients = 0;
199 cicpValues.VideoFullRangeFlag = 0;
200 cmsWriteTag (iccProfile, cmsSigcicpTag, &cicpValues);
205 mlu = cmsMLUalloc (NULL, 1);
206 cmsMLUsetWide(mlu,
"en",
"US",
name.join(
" ").toStdWString().data());
207 cmsWriteTag (iccProfile, cmsSigProfileDescriptionTag, mlu);
209 mlu = cmsMLUalloc (NULL, 1);
210 cmsMLUsetASCII (mlu,
"en",
"US", QString(
"Profile generated by Krita, Public domain.").toLatin1());
211 cmsWriteTag(iccProfile, cmsSigCopyrightTag, mlu);
220 cmsCloseProfile(iccProfile);
222 setFileName(
name.join(
" ").remove(
"(").remove(
")").replace(
"cd/m²",
"nits").split(
" ").join(
"-")+
".icc");
245 return d->shared->data->rawData();
250 d->shared->data->setRawData(
rawData);
255 if (
d->shared->lcmsProfile) {
256 return d->shared->lcmsProfile->valid();
262 if (
d->shared->lcmsProfile) {
263 return d->shared->lcmsProfile->version();
272 switch (
d->shared->lcmsProfile->colorSpaceSignature()) {
288 case cmsSigYCbCrData:
300 if (
d->shared->lcmsProfile) {
301 return d->shared->lcmsProfile->isSuitableForOutput() &&
d->shared->profileInfo->value.canCreateCyclicTransform;
307 if (
d->shared->lcmsProfile) {
308 return d->shared->lcmsProfile->isSuitableForInput() &&
d->shared->profileInfo->value.canCreateCyclicTransform;
314 if (
d->shared->lcmsProfile) {
315 return d->shared->lcmsProfile->isSuitableForWorkspace() &&
d->shared->profileInfo->value.canCreateCyclicTransform;
323 if (
d->shared->lcmsProfile) {
324 return d->shared->lcmsProfile->isSuitableForPrinting();
331 if (
d->shared->lcmsProfile) {
332 return d->shared->lcmsProfile->isSuitableForDisplay();
339 if (
d->shared->lcmsProfile) {
340 return d->shared->lcmsProfile->supportsPerceptual();
346 if (
d->shared->lcmsProfile) {
347 return d->shared->lcmsProfile->supportsSaturation();
353 if (
d->shared->lcmsProfile) {
354 return d->shared->lcmsProfile->supportsAbsolute();
360 if (
d->shared->lcmsProfile) {
361 return d->shared->lcmsProfile->supportsRelative();
367 if (
d->shared->lcmsProfile) {
368 return d->shared->lcmsProfile->hasColorants();
374 if (
d->shared->lcmsProfile)
375 return d->shared->lcmsProfile->hasTRC();
380 if (
d->shared->lcmsProfile)
381 return d->shared->lcmsProfile->isLinear();
386 if (
d->shared->lcmsProfile) {
387 return d->shared->lcmsProfile->getColorantsXYZ();
393 if (
d->shared->lcmsProfile) {
394 return d->shared->lcmsProfile->getColorantsxyY();
401 if (
d->shared->lcmsProfile) {
402 return d->shared->lcmsProfile->getWhitePointXYZ();
408 if (
d->shared->lcmsProfile) {
409 return d->shared->lcmsProfile->getWhitePointxyY();
415 QVector <qreal> dummy(3);
417 if (
d->shared->lcmsProfile) {
418 return d->shared->lcmsProfile->getEstimatedTRC();
425 if (
d->shared->lcmsProfile) {
433 if (
d->shared->lcmsProfile)
434 d->shared->lcmsProfile->LinearizeFloatValue(
Value);
438 if (
d->shared->lcmsProfile)
439 d->shared->lcmsProfile->DelinearizeFloatValue(
Value);
443 if (
d->shared->lcmsProfile)
444 d->shared->lcmsProfile->LinearizeFloatValueFast(
Value);
448 if (
d->shared->lcmsProfile)
449 d->shared->lcmsProfile->DelinearizeFloatValueFast(
Value);
455 if (
d->shared->lcmsProfile) {
456 dummy =
d->shared->lcmsProfile->getProfileUniqueId();
464 if (file.open(QIODevice::ReadOnly)) {
465 QByteArray
rawData = file.readAll();
472 qWarning() <<
"Failed to load profile from " <<
fileName();
483 if (!
d->shared->lcmsProfile) {
486 if (
d->shared->lcmsProfile->init()) {
487 setName(
d->shared->lcmsProfile->name());
488 setInfo(
d->shared->lcmsProfile->info());
491 if (
d->shared->lcmsProfile->hasCicpValues()) {
492 setCharacteristics(
d->shared->lcmsProfile->cicpPrimaries(),
d->shared->lcmsProfile->cicpTransfer());
494 if (
d->shared->lcmsProfile->valid()) {
496 return d->calculateFloatUIMinMax();
507 Q_ASSERT(
d->shared->lcmsProfile);
508 return d->shared->lcmsProfile.data();
515 return d->shared == rhsIcc->
d->shared;
522 Q_ASSERT(!
d->shared->profileInfo->value.uiMinMaxes.isEmpty());
523 return d->shared->profileInfo->value.uiMinMaxes;
532 cmsHPROFILE cprofile =
shared->lcmsProfile->lcmsProfile();
535 cmsColorSpaceSignature color_space_sig = cmsGetColorSpace(cprofile);
536 unsigned int num_channels = cmsChannelsOf(color_space_sig);
537 unsigned int color_space_mask = _cmsLCMScolorSpace(color_space_sig);
539 Q_ASSERT(num_channels >= 1 && num_channels <= 4);
540 Q_ASSERT(color_space_mask);
546 uint16_t in_min_pixel[4] = {0, 0, 0, 0};
547 uint16_t in_max_pixel[4] = {0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF};
548 qreal out_min_pixel[4] = {0, 0, 0, 0};
549 qreal out_max_pixel[4] = {0, 0, 0, 0};
551 cmsHTRANSFORM trans = cmsCreateTransform(
553 (COLORSPACE_SH(color_space_mask) | CHANNELS_SH(num_channels) | BYTES_SH(2)),
555 (COLORSPACE_SH(color_space_mask) | FLOAT_SH(1) | CHANNELS_SH(num_channels) | BYTES_SH(0)),
560 cmsDoTransform(trans, in_min_pixel, out_min_pixel, 1);
561 cmsDoTransform(trans, in_max_pixel, out_max_pixel, 1);
562 cmsDeleteTransform(trans);
576 info.canCreateCyclicTransform = bool(trans);
578 ret.resize(num_channels);
579 for (
unsigned int i = 0; i < num_channels; ++i) {
580 if (color_space_sig == cmsSigYCbCrData) {
589 }
else if (out_min_pixel[i] < out_max_pixel[i]) {
590 ret[i].minVal = out_min_pixel[i];
591 ret[i].maxVal = out_max_pixel[i];
@ PRIMARIES_ITU_R_BT_2020_2_AND_2100_0
TransferCharacteristics
The transferCharacteristics enum Enum of transfer characteristics, follows ITU H.273 for values 0 to ...
@ TRC_ITU_R_BT_2100_0_HLG
QScopedPointer< Private > const d
void setRawData(const QByteArray &)
bool isSuitableForDisplay() const override
bool isSuitableForInput() const override
void linearizeFloatValueFast(QVector< qreal > &Value) const override
KoColorimetryUtils::xyY getWhitePointxyY() const override
void setRawData(const QByteArray &rawData)
bool operator==(const KoColorProfile &) const override
QVector< KoColorimetryUtils::XYZ > getColorantsXYZ() const override
~IccColorProfile() override
LcmsColorProfileContainer * asLcms() const
bool supportsRelative() const override
bool hasColorants() const override
bool isSuitableForWorkspace() const override
bool supportsPerceptual() const override
bool isSuitableForPrinting() const override
bool isLinear() const override
void delinearizeFloatValue(QVector< qreal > &Value) const override
QString colorModelID() const override
QByteArray rawData() const override
void linearizeFloatValue(QVector< qreal > &Value) const override
const QVector< KoChannelInfo::DoubleRange > & getFloatUIMinMax(void) const
bool isSuitableForOutput() const override
bool supportsSaturation() const override
bool valid() const override
bool hasTRC() const override
IccColorProfile(const QString &fileName=QString())
float version() const override
QByteArray uniqueId() const override
void delinearizeFloatValueFast(QVector< qreal > &Value) const override
KoColorProfile * clone() const override
QScopedPointer< Private > d
KoColorimetryUtils::XYZ getWhitePointXYZ() const override
bool compareTRC(TransferCharacteristics characteristics, float error) const override
QVector< KoColorimetryUtils::xyY > getColorantsxyY() const override
bool supportsAbsolute() const override
QVector< qreal > getEstimatedTRC() const override
static cmsToneCurve * transferFunction(TransferCharacteristics transferFunction)
static QByteArray lcmsProfileToByteArray(const cmsHPROFILE profile)
static bool setPerceptualQuantizerAToBDummyPipeline(cmsHPROFILE iccProfile, cmsTagSignature tag, ColorPrimaries primaries, double diffuseWhiteNits=80.0)
static bool setDiffuseWhitePerceptualQuantizer(cmsHPROFILE iccProfile, double diffuseWhiteNits=80.0)
setDiffuseWhitePerceptualQuantizer This adds a dictionary with an CRWL entry to the profile.
static bool setPerceptualQuantizerBToADummyPipeline(cmsHPROFILE iccProfile, cmsTagSignature tag, ColorPrimaries primaries, double diffuseWhiteNits=80.0)
#define KIS_SAFE_ASSERT_RECOVER_RETURN(cond)
#define INTENT_ABSOLUTE_COLORIMETRIC
QString toString(const QString &value)
QVector< KoChannelInfo::DoubleRange > uiMinMaxes
bool canCreateCyclicTransform
QScopedPointer< LcmsColorProfileContainer > lcmsProfile
QScopedPointer< IccColorProfile::Data > data
LazyProfileInfo profileInfo
ProfileInfo calculateFloatUIMinMax() const
QSharedPointer< Shared > shared
KisLazyStorage< KisLazyValueWrapper< ProfileInfo >, std::function< ProfileInfo()> > LazyProfileInfo
The KoColorProfileQuery struct.
TransferCharacteristics transfer
CICP-compatible enum value representing the white point and primaries.
ColorPrimaries primaries
Rgb Primaries of the profile. When empty, this is a query for a greyscale profile.
bool isValid() const
CICP-compatible enum value representing the transfer function.
QList< KoColorimetryUtils::xy > rgbColorants
The desired white point of the profile.
KoColorimetryUtils::xy whitePoint
void setFileName(const QString &filename)
TransferCharacteristics characteristics
void setCopyright(const QString ©right)
static QString getTransferCharacteristicName(TransferCharacteristics curve)
getTransferCharacteristicName
static QString getColorPrimariesName(ColorPrimaries primaries)
getColorPrimariesName
void setName(const QString &name)
static void colorantsForType(ColorPrimaries primaries, KoColorimetryUtils::xy &whitePoint, QList< KoColorimetryUtils::xy > &colorants, const bool prequantized=false)
colorantsForPrimaries fills a QVector<float> with the xy values of the whitepoint and red,...
void setManufacturer(const QString &manufacturer)
void setCharacteristics(ColorPrimaries primaries, TransferCharacteristics curve)
setCharacteristics ideally, we'd read this from the icc profile curve, but that can be tricky,...
void setInfo(const QString &info)