18#include <QSharedPointer>
74 QScopedPointer<IccColorProfile::Data>
data;
116 cmsCIExyY whitePoint;
122 if (modifiedColorants.size()>=2) {
123 whitePoint.x = modifiedColorants[0];
124 whitePoint.y = modifiedColorants[1];
132 if (modifiedColorants.size()>2 && modifiedColorants.size() <= 8) {
133 primaries = {{modifiedColorants[2], modifiedColorants[3], 1.0},
134 {modifiedColorants[4], modifiedColorants[5], 1.0},
135 {modifiedColorants[6], modifiedColorants[7], 1.0}};
138 cmsHPROFILE iccProfile =
nullptr;
140 if (colorants.size() == 2) {
141 iccProfile = cmsCreateGrayProfile(&whitePoint, mainCurve);
144 cmsToneCurve *curve[3];
145 curve[0] = curve[1] = curve[2] = mainCurve;
146 iccProfile = cmsCreateRGBProfile(&whitePoint, &
primaries, curve);
150 qWarning() <<
"WARNING: LCMS failed to create a profile for the requested parameters";
152 qWarning().nospace() <<
" named primaries:" <<
getColorPrimariesName(colorPrimariesType) <<
" (" << colorPrimariesType <<
")";
153 qWarning() <<
" requested colorants:" << colorants;
159 name.append(
"Krita");
163 cmsCIEXYZ media_blackpoint = {0.0, 0.0, 0.0};
164 cmsWriteTag (iccProfile, cmsSigMediaBlackPointTag, &media_blackpoint);
168 mlu = cmsMLUalloc (NULL, 1);
169 cmsMLUsetASCII (mlu,
"en",
"US",
name.join(
" ").toLatin1());
170 cmsWriteTag (iccProfile, cmsSigProfileDescriptionTag, mlu);
172 mlu = cmsMLUalloc (NULL, 1);
173 cmsMLUsetASCII (mlu,
"en",
"US", QString(
"Profile generated by Krita, Public domain.").toLatin1());
174 cmsWriteTag(iccProfile, cmsSigCopyrightTag, mlu);
180 cmsCloseProfile(iccProfile);
204 return d->shared->data->rawData();
209 d->shared->data->setRawData(
rawData);
214 if (
d->shared->lcmsProfile) {
215 return d->shared->lcmsProfile->valid();
221 if (
d->shared->lcmsProfile) {
222 return d->shared->lcmsProfile->version();
231 switch (
d->shared->lcmsProfile->colorSpaceSignature()) {
247 case cmsSigYCbCrData:
259 if (
d->shared->lcmsProfile) {
260 return d->shared->lcmsProfile->isSuitableForOutput() &&
d->shared->profileInfo->value.canCreateCyclicTransform;
266 if (
d->shared->lcmsProfile) {
267 return d->shared->lcmsProfile->isSuitableForInput() &&
d->shared->profileInfo->value.canCreateCyclicTransform;
273 if (
d->shared->lcmsProfile) {
274 return d->shared->lcmsProfile->isSuitableForWorkspace() &&
d->shared->profileInfo->value.canCreateCyclicTransform;
282 if (
d->shared->lcmsProfile) {
283 return d->shared->lcmsProfile->isSuitableForPrinting();
290 if (
d->shared->lcmsProfile) {
291 return d->shared->lcmsProfile->isSuitableForDisplay();
298 if (
d->shared->lcmsProfile) {
299 return d->shared->lcmsProfile->supportsPerceptual();
305 if (
d->shared->lcmsProfile) {
306 return d->shared->lcmsProfile->supportsSaturation();
312 if (
d->shared->lcmsProfile) {
313 return d->shared->lcmsProfile->supportsAbsolute();
319 if (
d->shared->lcmsProfile) {
320 return d->shared->lcmsProfile->supportsRelative();
326 if (
d->shared->lcmsProfile) {
327 return d->shared->lcmsProfile->hasColorants();
333 if (
d->shared->lcmsProfile)
334 return d->shared->lcmsProfile->hasTRC();
339 if (
d->shared->lcmsProfile)
340 return d->shared->lcmsProfile->isLinear();
345 if (
d->shared->lcmsProfile) {
346 return d->shared->lcmsProfile->getColorantsXYZ();
352 if (
d->shared->lcmsProfile) {
353 return d->shared->lcmsProfile->getColorantsxyY();
359 QVector <qreal> d50Dummy(3);
360 d50Dummy << 0.9642 << 1.0000 << 0.8249;
361 if (
d->shared->lcmsProfile) {
362 return d->shared->lcmsProfile->getWhitePointXYZ();
368 QVector <qreal> d50Dummy(3);
369 d50Dummy << 0.34773 << 0.35952 << 1.0;
370 if (
d->shared->lcmsProfile) {
371 return d->shared->lcmsProfile->getWhitePointxyY();
377 QVector <qreal> dummy(3);
379 if (
d->shared->lcmsProfile) {
380 return d->shared->lcmsProfile->getEstimatedTRC();
387 if (
d->shared->lcmsProfile) {
395 if (
d->shared->lcmsProfile)
396 d->shared->lcmsProfile->LinearizeFloatValue(
Value);
400 if (
d->shared->lcmsProfile)
401 d->shared->lcmsProfile->DelinearizeFloatValue(
Value);
405 if (
d->shared->lcmsProfile)
406 d->shared->lcmsProfile->LinearizeFloatValueFast(
Value);
410 if (
d->shared->lcmsProfile)
411 d->shared->lcmsProfile->DelinearizeFloatValueFast(
Value);
417 if (
d->shared->lcmsProfile) {
418 dummy =
d->shared->lcmsProfile->getProfileUniqueId();
426 file.open(QIODevice::ReadOnly);
427 QByteArray
rawData = file.readAll();
433 qWarning() <<
"Failed to load profile from " <<
fileName();
444 if (!
d->shared->lcmsProfile) {
447 if (
d->shared->lcmsProfile->init()) {
448 setName(
d->shared->lcmsProfile->name());
449 setInfo(
d->shared->lcmsProfile->info());
452 if (
d->shared->lcmsProfile->valid()) {
454 return d->calculateFloatUIMinMax();
465 Q_ASSERT(
d->shared->lcmsProfile);
466 return d->shared->lcmsProfile.data();
473 return d->shared == rhsIcc->
d->shared;
480 Q_ASSERT(!
d->shared->profileInfo->value.uiMinMaxes.isEmpty());
481 return d->shared->profileInfo->value.uiMinMaxes;
490 cmsHPROFILE cprofile =
shared->lcmsProfile->lcmsProfile();
493 cmsColorSpaceSignature color_space_sig = cmsGetColorSpace(cprofile);
494 unsigned int num_channels = cmsChannelsOf(color_space_sig);
495 unsigned int color_space_mask = _cmsLCMScolorSpace(color_space_sig);
497 Q_ASSERT(num_channels >= 1 && num_channels <= 4);
498 Q_ASSERT(color_space_mask);
504 uint16_t in_min_pixel[4] = {0, 0, 0, 0};
505 uint16_t in_max_pixel[4] = {0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF};
506 qreal out_min_pixel[4] = {0, 0, 0, 0};
507 qreal out_max_pixel[4] = {0, 0, 0, 0};
509 cmsHTRANSFORM trans = cmsCreateTransform(
511 (COLORSPACE_SH(color_space_mask) | CHANNELS_SH(num_channels) | BYTES_SH(2)),
513 (COLORSPACE_SH(color_space_mask) | FLOAT_SH(1) | CHANNELS_SH(num_channels) | BYTES_SH(0)),
518 cmsDoTransform(trans, in_min_pixel, out_min_pixel, 1);
519 cmsDoTransform(trans, in_max_pixel, out_max_pixel, 1);
520 cmsDeleteTransform(trans);
534 info.canCreateCyclicTransform = bool(trans);
536 ret.resize(num_channels);
537 for (
unsigned int i = 0; i < num_channels; ++i) {
538 if (color_space_sig == cmsSigYCbCrData) {
547 }
else if (out_min_pixel[i] < out_max_pixel[i]) {
548 ret[i].minVal = out_min_pixel[i];
549 ret[i].maxVal = out_max_pixel[i];
ColorPrimaries
The colorPrimaries enum Enum of colorants, follows ITU H.273 for values 0 to 255, and has extra known...
TransferCharacteristics
The transferCharacteristics enum Enum of transfer characteristics, follows ITU H.273 for values 0 to ...
QScopedPointer< Private > const d
void setRawData(const QByteArray &)
bool isSuitableForDisplay() const override
bool isSuitableForInput() const override
void linearizeFloatValueFast(QVector< qreal > &Value) const override
QVector< qreal > getColorantsxyY() const override
void setRawData(const QByteArray &rawData)
bool operator==(const KoColorProfile &) const override
~IccColorProfile() override
LcmsColorProfileContainer * asLcms() const
QVector< qreal > getColorantsXYZ() const override
bool supportsRelative() const override
bool hasColorants() const override
bool isSuitableForWorkspace() const override
bool supportsPerceptual() const override
bool isSuitableForPrinting() const override
QVector< qreal > getWhitePointXYZ() 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
QVector< qreal > getWhitePointxyY() const override
bool compareTRC(TransferCharacteristics characteristics, float error) const override
bool supportsAbsolute() const override
QVector< qreal > getEstimatedTRC() const override
static cmsToneCurve * transferFunction(TransferCharacteristics transferFunction)
static QByteArray lcmsProfileToByteArray(const cmsHPROFILE profile)
#define KIS_SAFE_ASSERT_RECOVER_RETURN(cond)
#define INTENT_ABSOLUTE_COLORIMETRIC
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
static void colorantsForType(ColorPrimaries primaries, QVector< double > &colorants)
colorantsForPrimaries fills a QVector<float> with the xy values of the whitepoint and red,...
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)
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)