12#include <QReadWriteLock>
14#include <QGlobalStatic>
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());
235 QReadLocker l(&
d->registrylock);
236 auto connectionProfileRequests =
d->colorConversionSystem->requiredConnectionProfilesFor(item);
241 for (
auto it = connectionProfileRequests.begin(); it != connectionProfileRequests.end(); ++it) {
247 QWriteLocker l(&
d->registrylock);
248 d->colorSpaceFactoryRegistry.add(item);
249 d->colorConversionSystem->insertColorSpace(item);
254 QWriteLocker l(&
d->registrylock);
258 if (cs->
id() == item->
id()) {
259 toremove.push_back(
d->idsToCacheName(cs->
id(), cs->
profile()->
name()));
264 Q_FOREACH (
const QString&
id, toremove) {
268 d->colorSpaceFactoryRegistry.remove(item->
id());
273 d->profileStorage.addProfileAlias(name, to);
278 d->profileStorage.removeProfileAlias(name);
283 return d->profileStorage.profileAlias(name);
288 return d->profileStorage.profileByName(name);
293 return d->profileStorage.profileByUniqueId(
id);
298 QReadLocker l(&
d->registrylock);
299 return d->profileStorage.profilesFor(
d->colorSpaceFactoryRegistry.value(csID));
304 return d->colorSpace1(
colorSpaceId(colorModelId, colorDepthId), profile);
309 return d->colorSpace1(
colorSpaceId(colorModelId, colorDepthId), profileName);
314 return d->colorSpace1(
colorSpaceId(colorModelId, colorDepthId));
319 QReadLocker l(&
d->registrylock);
327 d->profileStorage.addProfile(
p);
332 if (!
p->valid())
return;
335 QReadLocker l(&
d->registrylock);
336 auto connectionProfileRequests =
d->colorConversionSystem->requiredConnectionProfilesFor(
p);
341 for (
auto it = connectionProfileRequests.begin(); it != connectionProfileRequests.end(); ++it) {
348 QWriteLocker locker(&
d->registrylock);
351 d->colorConversionSystem->insertColorProfile(
p);
362 d->profileStorage.removeProfile(profile);
366const KoColorSpace* KoColorSpaceRegistry::Private::getCachedColorSpaceImpl(
const QString & csID,
const QString & profileName)
const
368 auto it = csMap.find(idsToCacheName(csID, profileName));
370 if (it != csMap.end()) {
377QString KoColorSpaceRegistry::Private::idsToCacheName(
const QString & csID,
const QString & profileName)
const
379 return csID +
"<comb>" + profileName;
384 QReadLocker l(&
d->registrylock);
390 QWriteLocker l(&
d->registrylock);
391 return d->colorConversionSystem->createColorConverter(srcColorSpace, dstColorSpace, renderingIntent, conversionFlags);
396 QWriteLocker l(&
d->registrylock);
397 d->colorConversionSystem->createColorConverters(
colorSpace, possibilities, fromCS, toCS);
400QString KoColorSpaceRegistry::Private::defaultProfileForCsIdImpl(
const QString &csID)
402 QString defaultProfileName;
411 return defaultProfileName;
414const KoColorProfile *KoColorSpaceRegistry::Private::profileForCsIdWithFallbackImpl(
const QString &csID,
const QString &profileName)
424 profile = profileStorage.
profileByName(defaultProfileForCsIdImpl(csID));
429 if (profiles.isEmpty() || !profiles.first()) {
431 qWarning() <<
"profileForCsIdWithFallbackImpl couldn't fetch a fallback profile for " << qUtf8Printable(profileName);
435 profile = profiles.first();
442const KoColorSpace *KoColorSpaceRegistry::Private::lazyCreateColorSpaceImpl(
const QString &csID,
const KoColorProfile *profile)
455 cs = getCachedColorSpaceImpl(csID, profile->
name());
459 qWarning() <<
"Unable to create color space factory for" << csID;
465 qWarning() <<
"lazyCreateColorSpaceImpl was unable to create a color space for " << csID;
470 <<
", adding name: " << idsToCacheName(cs->
id(), cs->
profile()->
name())
471 <<
"\n\tcsID" << csID
472 <<
"\n\tcs->id()" << cs->
id()
473 <<
"\n\tcs->profile()->name()" << cs->
profile()->
name()
474 <<
"\n\tprofile->name()" << profile->
name();
475 Q_ASSERT(cs->
id() == csID);
484template<
class LockPolicy>
485const KoColorSpace * KoColorSpaceRegistry::Private::colorSpace1(
const QString &csID,
const QString &pName)
487 QString profileName = pName;
492 typename LockPolicy::ReadLocker l(®istrylock);
494 if (profileName.isEmpty()) {
495 profileName = defaultProfileForCsIdImpl(csID);
498 if (!profileName.isEmpty()) {
500 cs = getCachedColorSpaceImpl(csID, profileName);
506 typename LockPolicy::WriteLocker l(®istrylock);
509 profileForCsIdWithFallbackImpl(csID, profileName);
511 if (!profile)
return 0;
513 cs = lazyCreateColorSpaceImpl(csID, profile);
526 if (csID.isEmpty()) {
528 }
else if (!profile) {
529 return colorSpace1(csID);
535 QReadLocker l(®istrylock);
536 cs = getCachedColorSpaceImpl(csID, profile->
name());
542 q->addProfile(profile);
547 QWriteLocker l(®istrylock);
560 cs = lazyCreateColorSpaceImpl(csID, profile);
571 Q_ASSERT(
d->alphaCs);
577 if (!
d->alphaU16Cs) {
580 Q_ASSERT(
d->alphaU16Cs);
581 return d->alphaU16Cs;
587 if (!
d->alphaF16Cs) {
588 d->alphaF16Cs =
d->colorSpace1(KoAlphaF16ColorSpace::colorSpaceId());
590 Q_ASSERT(
d->alphaF16Cs);
591 return d->alphaF16Cs;
597 if (!
d->alphaF32Cs) {
600 Q_ASSERT(
d->alphaF32Cs);
601 return d->alphaF32Cs;
607 if (profile.isEmpty()) {
630 if (profile.isEmpty()) {
653 if (profileName.isEmpty()) {
657 Q_ASSERT(
d->rgbU8sRGB);
669 Q_ASSERT(
d->rgbU8sRGB);
687 if (profileName.isEmpty()) {
702 Q_ASSERT(
d->lab16sLAB);
715 return profileByName(
"Krita Rec. 2100 Perceptual Quantizer (203cd/m²)");
763 if (engine && generate) {
775#if QT_VERSION >= QT_VERSION_CHECK(6, 8, 0)
782 {QColorSpace::TransferFunction::Linear,
TRC_LINEAR},
784 {QColorSpace::TransferFunction::ProPhotoRgb,
TRC_PROPHOTO},
785#if QT_VERSION >= QT_VERSION_CHECK(6, 8, 0)
797#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
802 QByteArray profileData = space.iccProfile();
811 if (space.colorModel() == QColorSpace::ColorModel::Rgb) {
812 if (space.transferFunction() == QColorSpace::TransferFunction::Gamma) {
814 QByteArray profileData = space.iccProfile();
823 }
else if (space.colorModel() == QColorSpace::ColorModel::Gray) {
825 if (space.transferFunction() == QColorSpace::TransferFunction::Gamma) {
826 QByteArray profileData = space.iccProfile();
832 query.
whitePoint = {space.whitePoint().
x(), space.whitePoint().y()};
833 if (!profile && query.
isValid()) {
842 QByteArray profileData = space.iccProfile();
863 if (!profile)
return QColorSpace(QColorSpace::SRgb);
865 return QColorSpace(QColorSpace::SRgb);
867#if QT_VERSION >= QT_VERSION_CHECK(6, 8, 0)
871 return QColorSpace(QColorSpace::Bt2100Pq);
876 return QColorSpace::fromIccProfile(profile->
rawData());
881 QReadLocker l(&
d->registrylock);
901 QReadLocker l(&
d->registrylock);
923QString KoColorSpaceRegistry::Private::colorSpaceIdImpl(
const QString & colorModelId,
const QString & colorDepthId)
const
925 for (
auto it = colorSpaceFactoryRegistry.
constBegin(); it != colorSpaceFactoryRegistry.
constEnd(); ++it) {
926 if (it.value()->colorModelId().id() == colorModelId && it.value()->colorDepthId().id() == colorDepthId) {
927 return it.value()->id();
935 QReadLocker l(&
d->registrylock);
936 return d->colorSpaceIdImpl(colorModelId, colorDepthId);
946 QReadLocker l(&
d->registrylock);
958 QReadLocker l(&
d->registrylock);
970 return d->colorConversionSystem;
975 return d->colorConversionCache;
982 }
else if (*_colorSpace == *
d->alphaCs) {
987 Q_ASSERT(*cs == *_colorSpace);
994 QReadLocker l(&
d->registrylock);
996 Q_FOREACH (
const QString& key,
d->colorSpaceFactoryRegistry.keys()) {
997 answer.append(
KoID(key,
d->colorSpaceFactoryRegistry.get(key)->name()));
1010 QReadLocker l(&
d->registrylock);
1012 KoColorSpaceFactory* factory_ =
d->colorSpaceFactoryRegistry.get(
d->colorSpaceIdImpl(colorModelId, colorDepthId));
1017 if (profile && profile->valid()) {
1018 const QString effectiveProfileName = customProfileNameAlias.value(profile->name(), profile->name());
1020 return existingProfile;
1026 return constProfile;
1039 d->registrylock.lockForRead();
1041 d->registrylock.unlock();
1050 colorSpaces.append(cs);
1053 warnPigment <<
"Could not create colorspace for id" << factory->
id() <<
"since there is no working default profile";
1060 colorSpaces.append(cs);
1063 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
Used for PQ profiles.
KoColorimetryUtils::xy whitePoint
std::optional< double > hdrReferenceWhite
CICP-compatible enum value representing the transfer function.
virtual QByteArray rawData() const
virtual ColorPrimaries getColorPrimaries() const
getColorPrimaries
virtual QByteArray uniqueId() const =0
virtual KoColorProfile * clone() const =0
virtual TransferCharacteristics getTransferCharacteristics() const
getTransferCharacteristics This function should be subclassed at some point so we can get the value f...
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 KoColorProfile * createColorProfile(const QByteArray &rawData) const =0
virtual bool userVisible() const =0
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)
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 KoColorProfile * profileForInternal(const KoColorProfileQuery &query, const bool generate) const
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.