12#include <QReadWriteLock>
14#include <QGlobalStatic>
44 struct ProfileRegistrationInterface;
46 struct ConversionSystemInterface;
55 QHash<QString, const KoColorSpace *>
csMap;
80 QString
idsToCacheName(
const QString & csId,
const QString & profileName)
const;
83 QString
colorSpaceIdImpl(
const QString & colorModelId,
const QString & colorDepthId)
const;
92 template<
class LockPolicy = NormalLockPolicy>
111 const KoColorSpace *
colorSpace(
const QString & colorModelId,
const QString & colorDepthId,
const QString &profileName)
override {
112 return q->
d->colorSpace1<
NoLockPolicy>(
q->
d->colorSpaceIdImpl(colorModelId, colorDepthId), profileName);
116 return q->
d->colorSpaceFactoryRegistry.get(
q->
d->colorSpaceIdImpl(colorModelId, colorDepthId));
120 return q->
d->profileStorage.profilesFor(csf);
139 if (!s_instance.exists()) {
157 d->conversionSystemInterface.reset(
new Private::ConversionSystemInterface(
this));
171 <<
new KoAlphaF16ColorSpaceFactory()
183 config.
blacklist =
"ColorSpacePluginsDisabled";
184 config.
group =
"krita";
188 configExtensions.
blacklist =
"ColorSpaceExtensionsPluginsDisabled";
189 configExtensions.
group =
"krita";
193 dbgPigment <<
"Loaded the following colorspaces:";
195 dbgPigment <<
"\t" <<
id.id() <<
"," <<
id.name();
201 d->colorConversionSystem =
nullptr;
202 d->colorConversionCache =
nullptr;
207 delete d->colorConversionSystem;
208 d->colorConversionSystem =
nullptr;
217 delete d->colorConversionCache;
218 d->colorConversionCache =
nullptr;
222 d->colorSpaceFactoryRegistry.remove(f->id());
234 QWriteLocker l(&
d->registrylock);
235 d->colorSpaceFactoryRegistry.add(item);
236 d->colorConversionSystem->insertColorSpace(item);
241 QWriteLocker l(&
d->registrylock);
245 if (cs->
id() == item->
id()) {
246 toremove.push_back(
d->idsToCacheName(cs->
id(), cs->
profile()->
name()));
251 Q_FOREACH (
const QString&
id, toremove) {
255 d->colorSpaceFactoryRegistry.remove(item->
id());
260 d->profileStorage.addProfileAlias(name, to);
265 return d->profileStorage.profileAlias(name);
270 return d->profileStorage.profileByName(name);
275 return d->profileStorage.profileByUniqueId(
id);
280 QReadLocker l(&
d->registrylock);
281 return d->profileStorage.profilesFor(
d->colorSpaceFactoryRegistry.value(csID));
286 return d->colorSpace1(
colorSpaceId(colorModelId, colorDepthId), profile);
291 return d->colorSpace1(
colorSpaceId(colorModelId, colorDepthId), profileName);
296 return d->colorSpace1(
colorSpaceId(colorModelId, colorDepthId));
301 QReadLocker l(&
d->registrylock);
309 d->profileStorage.addProfile(
p);
314 if (!
p->valid())
return;
316 QWriteLocker locker(&
d->registrylock);
319 d->colorConversionSystem->insertColorProfile(
p);
330 d->profileStorage.removeProfile(profile);
334const KoColorSpace* KoColorSpaceRegistry::Private::getCachedColorSpaceImpl(
const QString & csID,
const QString & profileName)
const
336 auto it = csMap.find(idsToCacheName(csID, profileName));
338 if (it != csMap.end()) {
345QString KoColorSpaceRegistry::Private::idsToCacheName(
const QString & csID,
const QString & profileName)
const
347 return csID +
"<comb>" + profileName;
352 QReadLocker l(&
d->registrylock);
358 QWriteLocker l(&
d->registrylock);
359 return d->colorConversionSystem->createColorConverter(srcColorSpace, dstColorSpace, renderingIntent, conversionFlags);
364 QWriteLocker l(&
d->registrylock);
365 d->colorConversionSystem->createColorConverters(
colorSpace, possibilities, fromCS, toCS);
368QString KoColorSpaceRegistry::Private::defaultProfileForCsIdImpl(
const QString &csID)
370 QString defaultProfileName;
379 return defaultProfileName;
382const KoColorProfile *KoColorSpaceRegistry::Private::profileForCsIdWithFallbackImpl(
const QString &csID,
const QString &profileName)
392 profile = profileStorage.
profileByName(defaultProfileForCsIdImpl(csID));
397 if (profiles.isEmpty() || !profiles.first()) {
399 qWarning() <<
"profileForCsIdWithFallbackImpl couldn't fetch a fallback profile for " << qUtf8Printable(profileName);
403 profile = profiles.first();
410const KoColorSpace *KoColorSpaceRegistry::Private::lazyCreateColorSpaceImpl(
const QString &csID,
const KoColorProfile *profile)
423 cs = getCachedColorSpaceImpl(csID, profile->
name());
427 qWarning() <<
"Unable to create color space factory for" << csID;
433 qWarning() <<
"lazyCreateColorSpaceImpl was unable to create a color space for " << csID;
438 <<
", adding name: " << idsToCacheName(cs->
id(), cs->
profile()->
name())
439 <<
"\n\tcsID" << csID
440 <<
"\n\tcs->id()" << cs->
id()
441 <<
"\n\tcs->profile()->name()" << cs->
profile()->
name()
442 <<
"\n\tprofile->name()" << profile->
name();
443 Q_ASSERT(cs->
id() == csID);
452template<
class LockPolicy>
453const KoColorSpace * KoColorSpaceRegistry::Private::colorSpace1(
const QString &csID,
const QString &pName)
455 QString profileName = pName;
460 typename LockPolicy::ReadLocker l(®istrylock);
462 if (profileName.isEmpty()) {
463 profileName = defaultProfileForCsIdImpl(csID);
466 if (!profileName.isEmpty()) {
468 cs = getCachedColorSpaceImpl(csID, profileName);
474 typename LockPolicy::WriteLocker l(®istrylock);
477 profileForCsIdWithFallbackImpl(csID, profileName);
479 if (!profile)
return 0;
481 cs = lazyCreateColorSpaceImpl(csID, profile);
494 if (csID.isEmpty()) {
496 }
else if (!profile) {
497 return colorSpace1(csID);
503 QReadLocker l(®istrylock);
504 cs = getCachedColorSpaceImpl(csID, profile->
name());
510 q->addProfile(profile);
515 QWriteLocker l(®istrylock);
528 cs = lazyCreateColorSpaceImpl(csID, profile);
539 Q_ASSERT(
d->alphaCs);
545 if (!
d->alphaU16Cs) {
548 Q_ASSERT(
d->alphaU16Cs);
549 return d->alphaU16Cs;
555 if (!
d->alphaF16Cs) {
556 d->alphaF16Cs =
d->colorSpace1(KoAlphaF16ColorSpace::colorSpaceId());
558 Q_ASSERT(
d->alphaF16Cs);
559 return d->alphaF16Cs;
565 if (!
d->alphaF32Cs) {
568 Q_ASSERT(
d->alphaF32Cs);
569 return d->alphaF32Cs;
575 if (profile.isEmpty()) {
598 if (profile.isEmpty()) {
621 if (profileName.isEmpty()) {
625 Q_ASSERT(
d->rgbU8sRGB);
637 Q_ASSERT(
d->rgbU8sRGB);
655 if (profileName.isEmpty()) {
670 Q_ASSERT(
d->lab16sLAB);
683 return profileByName(
"High Dynamic Range UHDTV Wide Color Gamut Display (Rec. 2020) - SMPTE ST 2084 PQ EOTF");
721 return engine->
getProfile(colorants, colorPrimaries, transferFunction);
729 QReadLocker l(&
d->registrylock);
749 QReadLocker l(&
d->registrylock);
771QString KoColorSpaceRegistry::Private::colorSpaceIdImpl(
const QString & colorModelId,
const QString & colorDepthId)
const
773 for (
auto it = colorSpaceFactoryRegistry.
constBegin(); it != colorSpaceFactoryRegistry.
constEnd(); ++it) {
774 if (it.value()->colorModelId().id() == colorModelId && it.value()->colorDepthId().id() == colorDepthId) {
775 return it.value()->id();
783 QReadLocker l(&
d->registrylock);
784 return d->colorSpaceIdImpl(colorModelId, colorDepthId);
794 QReadLocker l(&
d->registrylock);
806 QReadLocker l(&
d->registrylock);
818 return d->colorConversionSystem;
823 return d->colorConversionCache;
830 }
else if (*_colorSpace == *
d->alphaCs) {
835 Q_ASSERT(*cs == *_colorSpace);
842 QReadLocker l(&
d->registrylock);
844 Q_FOREACH (
const QString& key,
d->colorSpaceFactoryRegistry.keys()) {
845 answer.append(
KoID(key,
d->colorSpaceFactoryRegistry.get(key)->name()));
856 return d->profileStorage.profileByName(profileName);
860 d->profileStorage.addProfile(profile);
861 d->colorConversionSystem->insertColorProfile(profile);
869 QWriteLocker l(&
d->registrylock);
870 KoColorSpaceFactory* factory_ =
d->colorSpaceFactoryRegistry.get(
d->colorSpaceIdImpl(colorModelId, colorDepthId));
872 Private::ProfileRegistrationInterface interface(
d);
883 d->registrylock.lockForRead();
885 d->registrylock.unlock();
894 colorSpaces.append(cs);
897 warnPigment <<
"Could not create colorspace for id" << factory->
id() <<
"since there is no working default profile";
904 colorSpaces.append(cs);
907 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"))
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_ITU_R_BT_709_5
TransferCharacteristics
The transferCharacteristics enum Enum of transfer characteristics, follows ITU H.273 for values 0 to ...
@ 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)
virtual KoColorProfile * clone() const =0
virtual const KoColorProfile * getProfile(const QVector< double > &colorants, ColorPrimaries colorPrimaries, TransferCharacteristics transferFunction)=0
getProfile This tries to generate a profile with the given characteristics and add it to the registry...
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
const KoColorProfile * colorProfile(const QByteArray &rawData, ProfileRegistrationInterface *registrationInterface) const
virtual bool profileIsCompatible(const KoColorProfile *profile) const =0
const KoColorSpace * grabColorSpace(const KoColorProfile *profile)
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
const KoColorProfile * profileFor(const QVector< double > &colorants, ColorPrimaries colorPrimaries, TransferCharacteristics transferFunction) const
profileFor tries to find the profile that matches these characteristics, if no such profile is found,...
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())
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())
bool profileIsCompatible(const KoColorProfile *profile, const QString &colorSpaceId)
QString defaultProfileForColorSpace(const QString &colorSpaceId) const
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
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.