12#include <QReadWriteLock>
14#include <QGlobalStatic>
45 struct ProfileRegistrationInterface;
47 struct ConversionSystemInterface;
56 QHash<QString, const KoColorSpace *>
csMap;
81 QString
idsToCacheName(
const QString & csId,
const QString & profileName)
const;
84 QString
colorSpaceIdImpl(
const QString & colorModelId,
const QString & colorDepthId)
const;
93 template<
class LockPolicy = NormalLockPolicy>
112 const KoColorSpace *
colorSpace(
const QString & colorModelId,
const QString & colorDepthId,
const QString &profileName)
override {
113 return q->
d->colorSpace1<
NoLockPolicy>(
q->
d->colorSpaceIdImpl(colorModelId, colorDepthId), profileName);
117 return q->
d->colorSpaceFactoryRegistry.get(
q->
d->colorSpaceIdImpl(colorModelId, colorDepthId));
121 return q->
d->profileStorage.profilesFor(csf);
140 if (!s_instance.exists()) {
158 d->conversionSystemInterface.reset(
new Private::ConversionSystemInterface(
this));
172 <<
new KoAlphaF16ColorSpaceFactory()
184 config.
blacklist =
"ColorSpacePluginsDisabled";
185 config.
group =
"krita";
189 configExtensions.
blacklist =
"ColorSpaceExtensionsPluginsDisabled";
190 configExtensions.
group =
"krita";
194 dbgPigment <<
"Loaded the following colorspaces:";
196 dbgPigment <<
"\t" <<
id.id() <<
"," <<
id.name();
202 d->colorConversionSystem =
nullptr;
203 d->colorConversionCache =
nullptr;
208 delete d->colorConversionSystem;
209 d->colorConversionSystem =
nullptr;
218 delete d->colorConversionCache;
219 d->colorConversionCache =
nullptr;
223 d->colorSpaceFactoryRegistry.remove(f->id());
235 QWriteLocker l(&
d->registrylock);
236 d->colorSpaceFactoryRegistry.add(item);
237 d->colorConversionSystem->insertColorSpace(item);
242 QWriteLocker l(&
d->registrylock);
246 if (cs->
id() == item->
id()) {
247 toremove.push_back(
d->idsToCacheName(cs->
id(), cs->
profile()->
name()));
252 Q_FOREACH (
const QString&
id, toremove) {
256 d->colorSpaceFactoryRegistry.remove(item->
id());
261 d->profileStorage.addProfileAlias(name, to);
266 return d->profileStorage.profileAlias(name);
271 return d->profileStorage.profileByName(name);
276 return d->profileStorage.profileByUniqueId(
id);
281 QReadLocker l(&
d->registrylock);
282 return d->profileStorage.profilesFor(
d->colorSpaceFactoryRegistry.value(csID));
287 return d->colorSpace1(
colorSpaceId(colorModelId, colorDepthId), profile);
292 return d->colorSpace1(
colorSpaceId(colorModelId, colorDepthId), profileName);
297 return d->colorSpace1(
colorSpaceId(colorModelId, colorDepthId));
302 QReadLocker l(&
d->registrylock);
310 d->profileStorage.addProfile(
p);
315 if (!
p->valid())
return;
317 QWriteLocker locker(&
d->registrylock);
320 d->colorConversionSystem->insertColorProfile(
p);
331 d->profileStorage.removeProfile(profile);
335const KoColorSpace* KoColorSpaceRegistry::Private::getCachedColorSpaceImpl(
const QString & csID,
const QString & profileName)
const
337 auto it = csMap.find(idsToCacheName(csID, profileName));
339 if (it != csMap.end()) {
346QString KoColorSpaceRegistry::Private::idsToCacheName(
const QString & csID,
const QString & profileName)
const
348 return csID +
"<comb>" + profileName;
353 QReadLocker l(&
d->registrylock);
359 QWriteLocker l(&
d->registrylock);
360 return d->colorConversionSystem->createColorConverter(srcColorSpace, dstColorSpace, renderingIntent, conversionFlags);
365 QWriteLocker l(&
d->registrylock);
366 d->colorConversionSystem->createColorConverters(
colorSpace, possibilities, fromCS, toCS);
369QString KoColorSpaceRegistry::Private::defaultProfileForCsIdImpl(
const QString &csID)
371 QString defaultProfileName;
380 return defaultProfileName;
383const KoColorProfile *KoColorSpaceRegistry::Private::profileForCsIdWithFallbackImpl(
const QString &csID,
const QString &profileName)
393 profile = profileStorage.
profileByName(defaultProfileForCsIdImpl(csID));
398 if (profiles.isEmpty() || !profiles.first()) {
400 qWarning() <<
"profileForCsIdWithFallbackImpl couldn't fetch a fallback profile for " << qUtf8Printable(profileName);
404 profile = profiles.first();
411const KoColorSpace *KoColorSpaceRegistry::Private::lazyCreateColorSpaceImpl(
const QString &csID,
const KoColorProfile *profile)
424 cs = getCachedColorSpaceImpl(csID, profile->
name());
428 qWarning() <<
"Unable to create color space factory for" << csID;
434 qWarning() <<
"lazyCreateColorSpaceImpl was unable to create a color space for " << csID;
439 <<
", adding name: " << idsToCacheName(cs->
id(), cs->
profile()->
name())
440 <<
"\n\tcsID" << csID
441 <<
"\n\tcs->id()" << cs->
id()
442 <<
"\n\tcs->profile()->name()" << cs->
profile()->
name()
443 <<
"\n\tprofile->name()" << profile->
name();
444 Q_ASSERT(cs->
id() == csID);
453template<
class LockPolicy>
454const KoColorSpace * KoColorSpaceRegistry::Private::colorSpace1(
const QString &csID,
const QString &pName)
456 QString profileName = pName;
461 typename LockPolicy::ReadLocker l(®istrylock);
463 if (profileName.isEmpty()) {
464 profileName = defaultProfileForCsIdImpl(csID);
467 if (!profileName.isEmpty()) {
469 cs = getCachedColorSpaceImpl(csID, profileName);
475 typename LockPolicy::WriteLocker l(®istrylock);
478 profileForCsIdWithFallbackImpl(csID, profileName);
480 if (!profile)
return 0;
482 cs = lazyCreateColorSpaceImpl(csID, profile);
495 if (csID.isEmpty()) {
497 }
else if (!profile) {
498 return colorSpace1(csID);
504 QReadLocker l(®istrylock);
505 cs = getCachedColorSpaceImpl(csID, profile->
name());
511 q->addProfile(profile);
516 QWriteLocker l(®istrylock);
529 cs = lazyCreateColorSpaceImpl(csID, profile);
540 Q_ASSERT(
d->alphaCs);
546 if (!
d->alphaU16Cs) {
549 Q_ASSERT(
d->alphaU16Cs);
550 return d->alphaU16Cs;
556 if (!
d->alphaF16Cs) {
557 d->alphaF16Cs =
d->colorSpace1(KoAlphaF16ColorSpace::colorSpaceId());
559 Q_ASSERT(
d->alphaF16Cs);
560 return d->alphaF16Cs;
566 if (!
d->alphaF32Cs) {
569 Q_ASSERT(
d->alphaF32Cs);
570 return d->alphaF32Cs;
576 if (profile.isEmpty()) {
599 if (profile.isEmpty()) {
622 if (profileName.isEmpty()) {
626 Q_ASSERT(
d->rgbU8sRGB);
638 Q_ASSERT(
d->rgbU8sRGB);
656 if (profileName.isEmpty()) {
671 Q_ASSERT(
d->lab16sLAB);
684 return profileByName(
"High Dynamic Range UHDTV Wide Color Gamut Display (Rec. 2020) - SMPTE ST 2084 PQ EOTF");
722 return engine->
getProfile(colorants, colorPrimaries, transferFunction);
733#if QT_VERSION >= QT_VERSION_CHECK(6, 8, 0)
740 {QColorSpace::TransferFunction::Linear,
TRC_LINEAR},
742 {QColorSpace::TransferFunction::ProPhotoRgb,
TRC_PROPHOTO},
743#if QT_VERSION >= QT_VERSION_CHECK(6, 8, 0)
754#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
759 QByteArray profileData = space.iccProfile();
763 profile =
profileFor(colorants, primaries, transfer);
768 if (space.colorModel() == QColorSpace::ColorModel::Rgb) {
769 if (space.transferFunction() == QColorSpace::TransferFunction::Gamma) {
771 QByteArray profileData = space.iccProfile();
779 profile =
profileFor(colorants, primaries, transfer);
781 }
else if (space.colorModel() == QColorSpace::ColorModel::Gray) {
783 if (space.transferFunction() == QColorSpace::TransferFunction::Gamma) {
784 QByteArray profileData = space.iccProfile();
789 colorants << space.whitePoint().x() << space.whitePoint().y();
799 QByteArray profileData = space.iccProfile();
820 if (!profile)
return QColorSpace(QColorSpace::SRgb);
822 return QColorSpace(QColorSpace::SRgb);
824#if QT_VERSION >= QT_VERSION_CHECK(6, 8, 0)
826 return QColorSpace(QColorSpace::Bt2100Pq);
829 return QColorSpace::fromIccProfile(profile->
rawData());
834 QReadLocker l(&
d->registrylock);
854 QReadLocker l(&
d->registrylock);
876QString KoColorSpaceRegistry::Private::colorSpaceIdImpl(
const QString & colorModelId,
const QString & colorDepthId)
const
878 for (
auto it = colorSpaceFactoryRegistry.
constBegin(); it != colorSpaceFactoryRegistry.
constEnd(); ++it) {
879 if (it.value()->colorModelId().id() == colorModelId && it.value()->colorDepthId().id() == colorDepthId) {
880 return it.value()->id();
888 QReadLocker l(&
d->registrylock);
889 return d->colorSpaceIdImpl(colorModelId, colorDepthId);
899 QReadLocker l(&
d->registrylock);
911 QReadLocker l(&
d->registrylock);
923 return d->colorConversionSystem;
928 return d->colorConversionCache;
935 }
else if (*_colorSpace == *
d->alphaCs) {
940 Q_ASSERT(*cs == *_colorSpace);
947 QReadLocker l(&
d->registrylock);
949 Q_FOREACH (
const QString& key,
d->colorSpaceFactoryRegistry.keys()) {
950 answer.append(
KoID(key,
d->colorSpaceFactoryRegistry.get(key)->name()));
961 return d->profileStorage.profileByName(profileName);
965 d->profileStorage.addProfile(profile);
966 d->colorConversionSystem->insertColorProfile(profile);
974 QWriteLocker l(&
d->registrylock);
975 KoColorSpaceFactory* factory_ =
d->colorSpaceFactoryRegistry.get(
d->colorSpaceIdImpl(colorModelId, colorDepthId));
977 Private::ProfileRegistrationInterface interface(
d);
988 d->registrylock.lockForRead();
990 d->registrylock.unlock();
999 colorSpaces.append(cs);
1002 warnPigment <<
"Could not create colorspace for id" << factory->
id() <<
"since there is no working default profile";
1009 colorSpaces.append(cs);
1012 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)
virtual QByteArray rawData() const
virtual QByteArray uniqueId() const =0
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 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
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())
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
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.