12#include <QReadWriteLock>
14#include <QGlobalStatic>
46 struct ProfileRegistrationInterface;
48 struct ConversionSystemInterface;
57 QHash<QString, const KoColorSpace *>
csMap;
82 QString
idsToCacheName(
const QString & csId,
const QString & profileName)
const;
85 QString
colorSpaceIdImpl(
const QString & colorModelId,
const QString & colorDepthId)
const;
94 template<
class LockPolicy = NormalLockPolicy>
113 const KoColorSpace *
colorSpace(
const QString & colorModelId,
const QString & colorDepthId,
const QString &profileName)
override {
114 return q->
d->colorSpace1<
NoLockPolicy>(
q->
d->colorSpaceIdImpl(colorModelId, colorDepthId), profileName);
118 return q->
d->colorSpaceFactoryRegistry.get(
q->
d->colorSpaceIdImpl(colorModelId, colorDepthId));
122 return q->
d->profileStorage.profilesFor(csf);
141 if (!s_instance.exists()) {
159 d->conversionSystemInterface.reset(
new Private::ConversionSystemInterface(
this));
173 <<
new KoAlphaF16ColorSpaceFactory()
185 config.
blacklist =
"ColorSpacePluginsDisabled";
186 config.
group =
"krita";
190 configExtensions.
blacklist =
"ColorSpaceExtensionsPluginsDisabled";
191 configExtensions.
group =
"krita";
195 dbgPigment <<
"Loaded the following colorspaces:";
197 dbgPigment <<
"\t" <<
id.id() <<
"," <<
id.name();
203 d->colorConversionSystem =
nullptr;
204 d->colorConversionCache =
nullptr;
209 delete d->colorConversionSystem;
210 d->colorConversionSystem =
nullptr;
219 delete d->colorConversionCache;
220 d->colorConversionCache =
nullptr;
224 d->colorSpaceFactoryRegistry.remove(f->id());
236 QWriteLocker l(&
d->registrylock);
237 d->colorSpaceFactoryRegistry.add(item);
238 d->colorConversionSystem->insertColorSpace(item);
243 QWriteLocker l(&
d->registrylock);
247 if (cs->
id() == item->
id()) {
248 toremove.push_back(
d->idsToCacheName(cs->
id(), cs->
profile()->
name()));
253 Q_FOREACH (
const QString&
id, toremove) {
257 d->colorSpaceFactoryRegistry.remove(item->
id());
262 d->profileStorage.addProfileAlias(name, to);
267 d->profileStorage.removeProfileAlias(name);
272 return d->profileStorage.profileAlias(name);
277 return d->profileStorage.profileByName(name);
282 return d->profileStorage.profileByUniqueId(
id);
287 QReadLocker l(&
d->registrylock);
288 return d->profileStorage.profilesFor(
d->colorSpaceFactoryRegistry.value(csID));
293 return d->colorSpace1(
colorSpaceId(colorModelId, colorDepthId), profile);
298 return d->colorSpace1(
colorSpaceId(colorModelId, colorDepthId), profileName);
303 return d->colorSpace1(
colorSpaceId(colorModelId, colorDepthId));
308 QReadLocker l(&
d->registrylock);
316 d->profileStorage.addProfile(
p);
321 if (!
p->valid())
return;
323 QWriteLocker locker(&
d->registrylock);
326 d->colorConversionSystem->insertColorProfile(
p);
337 d->profileStorage.removeProfile(profile);
341const KoColorSpace* KoColorSpaceRegistry::Private::getCachedColorSpaceImpl(
const QString & csID,
const QString & profileName)
const
343 auto it = csMap.find(idsToCacheName(csID, profileName));
345 if (it != csMap.end()) {
352QString KoColorSpaceRegistry::Private::idsToCacheName(
const QString & csID,
const QString & profileName)
const
354 return csID +
"<comb>" + profileName;
359 QReadLocker l(&
d->registrylock);
365 QWriteLocker l(&
d->registrylock);
366 return d->colorConversionSystem->createColorConverter(srcColorSpace, dstColorSpace, renderingIntent, conversionFlags);
371 QWriteLocker l(&
d->registrylock);
372 d->colorConversionSystem->createColorConverters(
colorSpace, possibilities, fromCS, toCS);
375QString KoColorSpaceRegistry::Private::defaultProfileForCsIdImpl(
const QString &csID)
377 QString defaultProfileName;
386 return defaultProfileName;
389const KoColorProfile *KoColorSpaceRegistry::Private::profileForCsIdWithFallbackImpl(
const QString &csID,
const QString &profileName)
399 profile = profileStorage.
profileByName(defaultProfileForCsIdImpl(csID));
404 if (profiles.isEmpty() || !profiles.first()) {
406 qWarning() <<
"profileForCsIdWithFallbackImpl couldn't fetch a fallback profile for " << qUtf8Printable(profileName);
410 profile = profiles.first();
417const KoColorSpace *KoColorSpaceRegistry::Private::lazyCreateColorSpaceImpl(
const QString &csID,
const KoColorProfile *profile)
430 cs = getCachedColorSpaceImpl(csID, profile->
name());
434 qWarning() <<
"Unable to create color space factory for" << csID;
440 qWarning() <<
"lazyCreateColorSpaceImpl was unable to create a color space for " << csID;
445 <<
", adding name: " << idsToCacheName(cs->
id(), cs->
profile()->
name())
446 <<
"\n\tcsID" << csID
447 <<
"\n\tcs->id()" << cs->
id()
448 <<
"\n\tcs->profile()->name()" << cs->
profile()->
name()
449 <<
"\n\tprofile->name()" << profile->
name();
450 Q_ASSERT(cs->
id() == csID);
459template<
class LockPolicy>
460const KoColorSpace * KoColorSpaceRegistry::Private::colorSpace1(
const QString &csID,
const QString &pName)
462 QString profileName = pName;
467 typename LockPolicy::ReadLocker l(®istrylock);
469 if (profileName.isEmpty()) {
470 profileName = defaultProfileForCsIdImpl(csID);
473 if (!profileName.isEmpty()) {
475 cs = getCachedColorSpaceImpl(csID, profileName);
481 typename LockPolicy::WriteLocker l(®istrylock);
484 profileForCsIdWithFallbackImpl(csID, profileName);
486 if (!profile)
return 0;
488 cs = lazyCreateColorSpaceImpl(csID, profile);
501 if (csID.isEmpty()) {
503 }
else if (!profile) {
504 return colorSpace1(csID);
510 QReadLocker l(®istrylock);
511 cs = getCachedColorSpaceImpl(csID, profile->
name());
517 q->addProfile(profile);
522 QWriteLocker l(®istrylock);
535 cs = lazyCreateColorSpaceImpl(csID, profile);
546 Q_ASSERT(
d->alphaCs);
552 if (!
d->alphaU16Cs) {
555 Q_ASSERT(
d->alphaU16Cs);
556 return d->alphaU16Cs;
562 if (!
d->alphaF16Cs) {
563 d->alphaF16Cs =
d->colorSpace1(KoAlphaF16ColorSpace::colorSpaceId());
565 Q_ASSERT(
d->alphaF16Cs);
566 return d->alphaF16Cs;
572 if (!
d->alphaF32Cs) {
575 Q_ASSERT(
d->alphaF32Cs);
576 return d->alphaF32Cs;
582 if (profile.isEmpty()) {
605 if (profile.isEmpty()) {
628 if (profileName.isEmpty()) {
632 Q_ASSERT(
d->rgbU8sRGB);
644 Q_ASSERT(
d->rgbU8sRGB);
662 if (profileName.isEmpty()) {
677 Q_ASSERT(
d->lab16sLAB);
690 return profileByName(
"Krita Rec. 2100 Perceptual Quantizer (80cd/m²)");
727 if (engine && generate) {
739#if QT_VERSION >= QT_VERSION_CHECK(6, 8, 0)
746 {QColorSpace::TransferFunction::Linear,
TRC_LINEAR},
748 {QColorSpace::TransferFunction::ProPhotoRgb,
TRC_PROPHOTO},
749#if QT_VERSION >= QT_VERSION_CHECK(6, 8, 0)
761#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
766 QByteArray profileData = space.iccProfile();
775 if (space.colorModel() == QColorSpace::ColorModel::Rgb) {
776 if (space.transferFunction() == QColorSpace::TransferFunction::Gamma) {
778 QByteArray profileData = space.iccProfile();
787 }
else if (space.colorModel() == QColorSpace::ColorModel::Gray) {
789 if (space.transferFunction() == QColorSpace::TransferFunction::Gamma) {
790 QByteArray profileData = space.iccProfile();
796 query.
whitePoint = {space.whitePoint().
x(), space.whitePoint().y()};
797 if (!profile && query.
isValid()) {
806 QByteArray profileData = space.iccProfile();
827 if (!profile)
return QColorSpace(QColorSpace::SRgb);
829 return QColorSpace(QColorSpace::SRgb);
831#if QT_VERSION >= QT_VERSION_CHECK(6, 8, 0)
833 return QColorSpace(QColorSpace::Bt2100Pq);
836 return QColorSpace::fromIccProfile(profile->
rawData());
841 QReadLocker l(&
d->registrylock);
861 QReadLocker l(&
d->registrylock);
883QString KoColorSpaceRegistry::Private::colorSpaceIdImpl(
const QString & colorModelId,
const QString & colorDepthId)
const
885 for (
auto it = colorSpaceFactoryRegistry.
constBegin(); it != colorSpaceFactoryRegistry.
constEnd(); ++it) {
886 if (it.value()->colorModelId().id() == colorModelId && it.value()->colorDepthId().id() == colorDepthId) {
887 return it.value()->id();
895 QReadLocker l(&
d->registrylock);
896 return d->colorSpaceIdImpl(colorModelId, colorDepthId);
906 QReadLocker l(&
d->registrylock);
918 QReadLocker l(&
d->registrylock);
930 return d->colorConversionSystem;
935 return d->colorConversionCache;
942 }
else if (*_colorSpace == *
d->alphaCs) {
947 Q_ASSERT(*cs == *_colorSpace);
954 QReadLocker l(&
d->registrylock);
956 Q_FOREACH (
const QString& key,
d->colorSpaceFactoryRegistry.keys()) {
957 answer.append(
KoID(key,
d->colorSpaceFactoryRegistry.get(key)->name()));
968 return d->profileStorage.profileByName(profileName);
972 d->profileStorage.addProfile(profile);
973 d->colorConversionSystem->insertColorProfile(profile);
986 QWriteLocker l(&
d->registrylock);
987 KoColorSpaceFactory* factory_ =
d->colorSpaceFactoryRegistry.get(
d->colorSpaceIdImpl(colorModelId, colorDepthId));
989 Private::ProfileRegistrationInterface interface(
d);
990 return factory_->
colorProfile(rawData, &interface, customProfileNameAlias);
1000 d->registrylock.lockForRead();
1002 d->registrylock.unlock();
1011 colorSpaces.append(cs);
1014 warnPigment <<
"Could not create colorspace for id" << factory->
id() <<
"since there is no working default profile";
1021 colorSpaces.append(cs);
1024 warnPigment <<
"Could not create colorspace for id" << factory->
id() <<
"and profile" << profile->
name();
#define dbgPigmentCSRegistry
Q_GLOBAL_STATIC(KisStoragePluginRegistry, s_instance)
KoAlphaColorSpaceFactoryImpl< AlphaU16Traits > KoAlphaU16ColorSpaceFactory
KoAlphaColorSpaceFactoryImpl< AlphaU8Traits > KoAlphaColorSpaceFactory
KoAlphaColorSpaceFactoryImpl< AlphaF32Traits > KoAlphaF32ColorSpaceFactory
const KoID Float32BitsColorDepthID("F32", ki18n("32-bit float/channel"))
const KoID Float64BitsColorDepthID("F64", ki18n("64-bit float/channel"))
const KoID GrayAColorModelID("GRAYA", ki18n("Grayscale/Alpha"))
const KoID Float16BitsColorDepthID("F16", ki18n("16-bit float/channel"))
const KoID Integer8BitsColorDepthID("U8", ki18n("8-bit integer/channel"))
const KoID Integer16BitsColorDepthID("U16", ki18n("16-bit integer/channel"))
const KoID RGBAColorModelID("RGBA", ki18n("RGB/Alpha"))
ColorPrimaries
The colorPrimaries enum Enum of colorants, follows ITU H.273 for values 0 to 255, and has extra known...
@ PRIMARIES_ITU_R_BT_2020_2_AND_2100_0
@ PRIMARIES_ADOBE_RGB_1998
@ PRIMARIES_SMPTE_EG_432_1
@ PRIMARIES_ITU_R_BT_709_5
TransferCharacteristics
The transferCharacteristics enum Enum of transfer characteristics, follows ITU H.273 for values 0 to ...
@ TRC_ITU_R_BT_2100_0_HLG
@ TRC_ITU_R_BT_2020_2_12bit
static QMap< QColorSpace::Primaries, ColorPrimaries > mapQColorSpaceColorPrimaries
static QMap< QColorSpace::TransferFunction, TransferCharacteristics > mapQColorSpaceColorTransfer
@ OwnedByRegistryDoNotDelete
@ OwnedByRegistryRegistryDeletes
static QString colorSpaceId()
The KoColorProfileStorage class is a "composite subclass" of KoColorSpaceRegistry that ensures that t...
const KoColorProfile * profileByName(const QString &name) const
QList< const KoColorProfile * > profilesFor(const KoColorSpaceFactory *csf) const
bool containsProfile(const KoColorProfile *profile)
containsProfile shows if a profile is registered in the storage
static KoColorSpaceEngineRegistry * instance()
virtual const KoColorProfile * profile() const =0
const T value(const QString &id) const
T get(const QString &id) const
QHash< QString, T >::const_iterator constBegin() const
QHash< QString, T >::const_iterator constEnd() const
static QString colorSpaceId()
void load(const QString &serviceType, const PluginsConfig &config=PluginsConfig(), QObject *owner=0, bool cache=true)
static KoPluginLoader * instance()
static QString colorSpaceId()
static QString colorSpaceId()
#define KIS_SAFE_ASSERT_RECOVER(cond)
#define KIS_SAFE_ASSERT_RECOVER_NOOP(cond)
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.
KoColorimetryUtils::xy whitePoint
virtual QByteArray rawData() const
virtual QByteArray uniqueId() const =0
virtual KoColorProfile * clone() const =0
virtual const KoColorProfile * getProfile(const KoColorProfileQuery &query)=0
getProfile This tries to generate a profile with the given characteristics and add it to the registry...
virtual const KoColorProfile * addProfile(const QString &filename)=0
virtual KoID colorDepthId() const =0
virtual QString defaultProfile() const =0
virtual KoID colorModelId() const =0
virtual QString id() const =0
virtual bool userVisible() const =0
virtual bool profileIsCompatible(const KoColorProfile *profile) const =0
const KoColorSpace * grabColorSpace(const KoColorProfile *profile)
const KoColorProfile * colorProfile(const QByteArray &rawData, ProfileRegistrationInterface *registrationInterface, const CustomProfileNameAlias &customProfileNameAlias) const
QList< const KoColorProfile * > profilesFor(const KoColorSpaceFactory *csf) const override
const KoColorSpace * colorSpace(const QString &colorModelId, const QString &colorDepthId, const QString &profileName) override
const KoColorSpaceFactory * colorSpaceFactory(const QString &colorModelId, const QString &colorDepthId) const override
QList< const KoColorSpaceFactory * > colorSpacesFor(const KoColorProfile *profile) const override
ConversionSystemInterface(KoColorSpaceRegistry *parentRegistry)
ProfileRegistrationInterface(KoColorSpaceRegistry::Private *_d)
void registerNewProfile(KoColorProfile *profile) override
KoColorSpaceRegistry::Private * d
const KoColorProfile * profileByName(const QString &profileName) const override
const KoColorProfile * profileByName(const QString &name) const
const KoColorSpace * colorSpace1(const QString &colorSpaceId, const QString &pName=QString())
QString colorSpaceId(const QString &colorModelId, const QString &colorDepthId) const
const KoColorSpace * lab16(const QString &profileName=QString())
const KoColorSpace * alpha32f()
KoColorConversionCache * colorConversionCache
const KoColorSpace * lazyCreateColorSpaceImpl(const QString &csID, const KoColorProfile *profile)
QList< KoID > colorDepthList(const KoID &colorModelId, ColorSpaceListVisibility option) const
void addProfileAlias(const QString &name, const QString &to)
const KoColorSpace * permanentColorspace(const KoColorSpace *_colorSpace)
ColorSpaceListProfilesSelection
@ OnlyDefaultProfile
Only add the default profile.
QString idsToCacheName(const QString &csId, const QString &profileName) const
QString colorSpaceIdImpl(const QString &colorModelId, const QString &colorDepthId) const
QString defaultProfileForCsIdImpl(const QString &csID)
QList< const KoColorSpace * > allColorSpaces(ColorSpaceListVisibility visibility, ColorSpaceListProfilesSelection pSelection)
const KoColorSpace * colorSpace(const QString &colorModelId, const QString &colorDepthId, const KoColorProfile *profile)
const KoColorSpace * colorSpace1(const QString &colorSpaceId, const KoColorProfile *profile)
KoColorConversionTransformation * createColorConverter(const KoColorSpace *srcColorSpace, const KoColorSpace *dstColorSpace, KoColorConversionTransformation::Intent renderingIntent, KoColorConversionTransformation::ConversionFlags conversionFlags) const
static KoColorSpaceRegistry * instance()
Private(KoColorSpaceRegistry *_q)
const KoColorSpace * graya8(const QString &profile=QString())
QHash< QString, QString > CustomProfileNameAlias
const KoColorProfile * profileFor(const KoColorProfileQuery &query, const bool generate=true) const
profileFor tries to find the profile that matches these characteristics, if no such profile is found,...
const KoColorSpace * graya16(const QString &profile=QString())
KoID colorSpaceColorDepthId(const QString &_colorSpaceId) const
const KoColorProfile * p709G10Profile() const
const KoColorProfile * p709SRGBProfile() const
void remove(KoColorSpaceFactory *item)
KoGenericRegistry< KoColorSpaceFactory * > colorSpaceFactoryRegistry
const KoColorSpace * rgb8(const QString &profileName=QString())
const KoColorProfile * profileForQColorSpace(const QColorSpace &space)
profileForQColorSpace Find a KoColorProfile that matches a given QColorSpace. This will use the QColo...
bool profileIsCompatible(const KoColorProfile *profile, const QString &colorSpaceId)
QString defaultProfileForColorSpace(const QString &colorSpaceId) const
void removeProfileAlias(const QString &name)
const KoColorProfile * profileByUniqueId(const QByteArray &id) const
const KoColorProfile * p2020PQProfile() const
const KoColorSpace * getCachedColorSpaceImpl(const QString &csId, const QString &profileName) const
const KoColorSpace * rgb16(const QString &profileName=QString())
const KoColorSpace * alpha8()
const KoColorProfile * profileForCsIdWithFallbackImpl(const QString &csID, const QString &profileName)
QList< KoID > colorModelsList(ColorSpaceListVisibility option) const
KoID colorSpaceColorModelId(const QString &_colorSpaceId) const
void add(KoColorSpaceFactory *item)
QList< const KoColorProfile * > profilesFor(const QString &csID) const
QColorSpace QColorSpaceForProfile(const KoColorProfile *profile) const
QColorSpaceForProfile Generate a QColorSpace for the given KoColorProfile. Will return sRGB when the ...
void addProfileToMap(KoColorProfile *p)
QString profileAlias(const QString &name) const
const KoColorSpace * alpha16()
void createColorConverters(const KoColorSpace *colorSpace, const QList< QPair< KoID, KoID > > &possibilities, KoColorConversionTransformation *&fromCS, KoColorConversionTransformation *&toCS) const
const KoColorProfile * p2020G10Profile() const
KoColorConversionSystem * colorConversionSystem
void removeProfile(KoColorProfile *profile)
@ AllColorSpaces
All color space even those not visible to the user.
QReadWriteLock registrylock
const KoColorProfile * createColorProfile(const QString &colorModelId, const QString &colorDepthId, const QByteArray &rawData)
QScopedPointer< ConversionSystemInterface > conversionSystemInterface
void addProfile(KoColorProfile *profile)
QHash< QString, const KoColorSpace * > csMap
KoColorProfileStorage profileStorage
QList< KoID > listKeys() const
virtual ~KoColorSpaceRegistry()
const char * blacklist
This contains the variable name for the list of plugins (by library name) that will not be loaded.