18#include <QSharedPointer>
74 QScopedPointer<IccColorProfile::Data>
data;
114 cmsCIExyY whitePoint;
120 if (modifiedColorants.size()>=2) {
121 whitePoint.x = modifiedColorants[0];
122 whitePoint.y = modifiedColorants[1];
130 if (modifiedColorants.size()>2 && modifiedColorants.size() <= 8) {
131 primaries = {{modifiedColorants[2], modifiedColorants[3], 1.0},
132 {modifiedColorants[4], modifiedColorants[5], 1.0},
133 {modifiedColorants[6], modifiedColorants[7], 1.0}};
136 cmsHPROFILE iccProfile =
nullptr;
138 if (colorants.size() == 2) {
139 iccProfile = cmsCreateGrayProfile(&whitePoint, mainCurve);
142 cmsToneCurve *curve[3];
143 curve[0] = curve[1] = curve[2] = mainCurve;
144 iccProfile = cmsCreateRGBProfile(&whitePoint, &
primaries, curve);
150 name.append(
"Krita");
154 cmsCIEXYZ media_blackpoint = {0.0, 0.0, 0.0};
155 cmsWriteTag (iccProfile, cmsSigMediaBlackPointTag, &media_blackpoint);
159 mlu = cmsMLUalloc (NULL, 1);
160 cmsMLUsetASCII (mlu,
"en",
"US",
name.join(
" ").toLatin1());
161 cmsWriteTag (iccProfile, cmsSigProfileDescriptionTag, mlu);
163 mlu = cmsMLUalloc (NULL, 1);
164 cmsMLUsetASCII (mlu,
"en",
"US", QString(
"Profile generated by Krita, Public domain.").toLatin1());
165 cmsWriteTag(iccProfile, cmsSigCopyrightTag, mlu);
173 cmsCloseProfile(iccProfile);
197 return d->shared->data->rawData();
202 d->shared->data->setRawData(
rawData);
207 if (
d->shared->lcmsProfile) {
208 return d->shared->lcmsProfile->valid();
214 if (
d->shared->lcmsProfile) {
215 return d->shared->lcmsProfile->version();
224 switch (
d->shared->lcmsProfile->colorSpaceSignature()) {
240 case cmsSigYCbCrData:
252 if (
d->shared->lcmsProfile) {
253 return d->shared->lcmsProfile->isSuitableForOutput() &&
d->shared->profileInfo->value.canCreateCyclicTransform;
259 if (
d->shared->lcmsProfile) {
260 return d->shared->lcmsProfile->isSuitableForInput() &&
d->shared->profileInfo->value.canCreateCyclicTransform;
266 if (
d->shared->lcmsProfile) {
267 return d->shared->lcmsProfile->isSuitableForWorkspace() &&
d->shared->profileInfo->value.canCreateCyclicTransform;
275 if (
d->shared->lcmsProfile) {
276 return d->shared->lcmsProfile->isSuitableForPrinting();
283 if (
d->shared->lcmsProfile) {
284 return d->shared->lcmsProfile->isSuitableForDisplay();
291 if (
d->shared->lcmsProfile) {
292 return d->shared->lcmsProfile->supportsPerceptual();
298 if (
d->shared->lcmsProfile) {
299 return d->shared->lcmsProfile->supportsSaturation();
305 if (
d->shared->lcmsProfile) {
306 return d->shared->lcmsProfile->supportsAbsolute();
312 if (
d->shared->lcmsProfile) {
313 return d->shared->lcmsProfile->supportsRelative();
319 if (
d->shared->lcmsProfile) {
320 return d->shared->lcmsProfile->hasColorants();
326 if (
d->shared->lcmsProfile)
327 return d->shared->lcmsProfile->hasTRC();
332 if (
d->shared->lcmsProfile)
333 return d->shared->lcmsProfile->isLinear();
338 if (
d->shared->lcmsProfile) {
339 return d->shared->lcmsProfile->getColorantsXYZ();
345 if (
d->shared->lcmsProfile) {
346 return d->shared->lcmsProfile->getColorantsxyY();
352 QVector <qreal> d50Dummy(3);
353 d50Dummy << 0.9642 << 1.0000 << 0.8249;
354 if (
d->shared->lcmsProfile) {
355 return d->shared->lcmsProfile->getWhitePointXYZ();
361 QVector <qreal> d50Dummy(3);
362 d50Dummy << 0.34773 << 0.35952 << 1.0;
363 if (
d->shared->lcmsProfile) {
364 return d->shared->lcmsProfile->getWhitePointxyY();
370 QVector <qreal> dummy(3);
372 if (
d->shared->lcmsProfile) {
373 return d->shared->lcmsProfile->getEstimatedTRC();
380 if (
d->shared->lcmsProfile) {
388 if (
d->shared->lcmsProfile)
389 d->shared->lcmsProfile->LinearizeFloatValue(
Value);
393 if (
d->shared->lcmsProfile)
394 d->shared->lcmsProfile->DelinearizeFloatValue(
Value);
398 if (
d->shared->lcmsProfile)
399 d->shared->lcmsProfile->LinearizeFloatValueFast(
Value);
403 if (
d->shared->lcmsProfile)
404 d->shared->lcmsProfile->DelinearizeFloatValueFast(
Value);
410 if (
d->shared->lcmsProfile) {
411 dummy =
d->shared->lcmsProfile->getProfileUniqueId();
419 file.open(QIODevice::ReadOnly);
420 QByteArray
rawData = file.readAll();
426 qWarning() <<
"Failed to load profile from " <<
fileName();
437 if (!
d->shared->lcmsProfile) {
440 if (
d->shared->lcmsProfile->init()) {
441 setName(
d->shared->lcmsProfile->name());
442 setInfo(
d->shared->lcmsProfile->info());
445 if (
d->shared->lcmsProfile->valid()) {
447 return d->calculateFloatUIMinMax();
458 Q_ASSERT(
d->shared->lcmsProfile);
459 return d->shared->lcmsProfile.data();
466 return d->shared == rhsIcc->
d->shared;
473 Q_ASSERT(!
d->shared->profileInfo->value.uiMinMaxes.isEmpty());
474 return d->shared->profileInfo->value.uiMinMaxes;
483 cmsHPROFILE cprofile =
shared->lcmsProfile->lcmsProfile();
486 cmsColorSpaceSignature color_space_sig = cmsGetColorSpace(cprofile);
487 unsigned int num_channels = cmsChannelsOf(color_space_sig);
488 unsigned int color_space_mask = _cmsLCMScolorSpace(color_space_sig);
490 Q_ASSERT(num_channels >= 1 && num_channels <= 4);
491 Q_ASSERT(color_space_mask);
497 uint16_t in_min_pixel[4] = {0, 0, 0, 0};
498 uint16_t in_max_pixel[4] = {0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF};
499 qreal out_min_pixel[4] = {0, 0, 0, 0};
500 qreal out_max_pixel[4] = {0, 0, 0, 0};
502 cmsHTRANSFORM trans = cmsCreateTransform(
504 (COLORSPACE_SH(color_space_mask) | CHANNELS_SH(num_channels) | BYTES_SH(2)),
506 (COLORSPACE_SH(color_space_mask) | FLOAT_SH(1) | CHANNELS_SH(num_channels) | BYTES_SH(0)),
511 cmsDoTransform(trans, in_min_pixel, out_min_pixel, 1);
512 cmsDoTransform(trans, in_max_pixel, out_max_pixel, 1);
513 cmsDeleteTransform(trans);
527 info.canCreateCyclicTransform = bool(trans);
529 ret.resize(num_channels);
530 for (
unsigned int i = 0; i < num_channels; ++i) {
531 if (color_space_sig == cmsSigYCbCrData) {
540 }
else if (out_min_pixel[i] < out_max_pixel[i]) {
541 ret[i].minVal = out_min_pixel[i];
542 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 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)