Warning, file /office/calligra/libs/pigment/KoColorSpaceRegistry.cpp was not indexed or was modified since last indexation (in which case cross-reference links may be missing, inaccurate or erroneous).

0001 /*
0002  *  Copyright (c) 2003 Patrick Julien  <freak@codepimps.org>
0003  *  Copyright (c) 2004,2010 Cyrille Berger <cberger@cberger.net>
0004  *
0005  * This library is free software; you can redistribute it and/or
0006  * modify it under the terms of the GNU Lesser General Public
0007  * License as published by the Free Software Foundation; either
0008  * version 2.1 of the License, or (at your option) any later version.
0009  *
0010  * This library is distributed in the hope that it will be useful,
0011  * but WITHOUT ANY WARRANTY; without even the implied warranty of
0012  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
0013  * Lesser General Public License for more details.
0014  *
0015  * You should have received a copy of the GNU Lesser General Public License
0016  * along with this library; see the file COPYING.LIB.  If not, write to
0017  * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
0018  * Boston, MA 02110-1301, USA.
0019 */
0020 
0021 #include "KoColorSpaceRegistry.h"
0022 
0023 #include <QHash>
0024 
0025 #include <QReadWriteLock>
0026 #include <QStringList>
0027 #include <QDir>
0028 #include <QGlobalStatic>
0029 
0030 #include "KoPluginLoader.h"
0031 #include "KoGenericRegistry.h"
0032 #include "DebugPigment.h"
0033 #include "KoBasicHistogramProducers.h"
0034 #include "KoColorSpace.h"
0035 #include "KoColorProfile.h"
0036 #include "KoColorConversionCache.h"
0037 #include "KoColorConversionSystem.h"
0038 
0039 #include "colorspaces/KoAlphaColorSpace.h"
0040 #include "colorspaces/KoLabColorSpace.h"
0041 #include "colorspaces/KoRgbU16ColorSpace.h"
0042 #include "colorspaces/KoRgbU8ColorSpace.h"
0043 #include "colorspaces/KoSimpleColorSpaceEngine.h"
0044 #include "KoColorSpace_p.h"
0045 
0046 Q_GLOBAL_STATIC(KoColorSpaceRegistry, s_instance)
0047 
0048 
0049 struct Q_DECL_HIDDEN KoColorSpaceRegistry::Private {
0050     KoGenericRegistry<KoColorSpaceFactory *> colorSpaceFactoryRegistry;
0051     QList<KoColorSpaceFactory *> localFactories;
0052     QHash<QString, KoColorProfile * > profileMap;
0053     QHash<QString, QString> profileAlias;
0054     QHash<QString, const KoColorSpace * > csMap;
0055     KoColorConversionSystem *colorConversionSystem;
0056     KoColorConversionCache* colorConversionCache;
0057     KoColorSpaceFactory* alphaCSF;
0058     const KoColorSpace *rgbU8sRGB;
0059     const KoColorSpace *lab16sLAB;
0060     const KoColorSpace *alphaCs;
0061     QReadWriteLock registrylock;
0062 };
0063 
0064 KoColorSpaceRegistry* KoColorSpaceRegistry::instance()
0065 {
0066     if (!s_instance.exists()) {
0067         s_instance->init();
0068     }
0069     return s_instance;
0070 }
0071 
0072 
0073 void KoColorSpaceRegistry::init()
0074 {
0075     d->rgbU8sRGB = 0;
0076     d->lab16sLAB = 0;
0077     d->alphaCs = 0;
0078 
0079     d->colorConversionSystem = new KoColorConversionSystem;
0080     d->colorConversionCache = new KoColorConversionCache;
0081 
0082     KoColorSpaceEngineRegistry::instance()->add(new KoSimpleColorSpaceEngine());
0083 
0084     addProfile(new KoDummyColorProfile);
0085 
0086     // Create the built-in colorspaces
0087     d->localFactories << new KoLabColorSpaceFactory()
0088             << new KoRgbU8ColorSpaceFactory()
0089             << new KoRgbU16ColorSpaceFactory();
0090     foreach(KoColorSpaceFactory *factory, d->localFactories) {
0091         add(factory);
0092     }
0093 
0094     d->alphaCs = new KoAlphaColorSpace();
0095     d->alphaCs->d->deletability = OwnedByRegistryRegistryDeletes;
0096 
0097     KoPluginLoader::PluginsConfig config;
0098     config.whiteList = "ColorSpacePlugins";
0099     config.blacklist = "ColorSpacePluginsDisabled";
0100     config.group = "calligra";
0101     KoPluginLoader::load(QStringLiteral("calligra/colorspaces"), config);
0102 
0103     KoPluginLoader::PluginsConfig configExtensions;
0104     configExtensions.whiteList = "ColorSpaceExtensionsPlugins";
0105     configExtensions.blacklist = "ColorSpaceExtensionsPluginsDisabled";
0106     configExtensions.group = "calligra";
0107     KoPluginLoader::load(QStringLiteral("calligra/colorspaceextensions"), configExtensions);
0108 
0109 
0110     dbgPigment << "Loaded the following colorspaces:";
0111     foreach(const KoID& id, listKeys()) {
0112         dbgPigment << "\t" << id.id() << "," << id.name();
0113     }
0114 }
0115 
0116 KoColorSpaceRegistry::KoColorSpaceRegistry() : d(new Private())
0117 {
0118     d->colorConversionSystem = 0;
0119     d->colorConversionCache = 0;
0120 }
0121 
0122 KoColorSpaceRegistry::~KoColorSpaceRegistry()
0123 {
0124     // Just leak on exit... It's faster.
0125 //    delete d->colorConversionSystem;
0126 //    foreach(KoColorProfile* profile, d->profileMap) {
0127 //        delete profile;
0128 //    }
0129 //    d->profileMap.clear();
0130 
0131 //    foreach(const KoColorSpace * cs, d->csMap) {
0132 //        cs->d->deletability = OwnedByRegistryRegistryDeletes;
0133 //    }
0134 //    d->csMap.clear();
0135 
0136 //    // deleting colorspaces calls a function in the cache
0137 //    delete d->colorConversionCache;
0138 //    d->colorConversionCache = 0;
0139 
0140 //    // Delete the colorspace factories
0141 //    qDeleteAll(d->localFactories);
0142 
0143 //    delete d->alphaCSF;
0144 
0145     delete d;
0146 }
0147 
0148 void KoColorSpaceRegistry::add(KoColorSpaceFactory* item)
0149 {
0150     {
0151         QWriteLocker l(&d->registrylock);
0152         d->colorSpaceFactoryRegistry.add(item);
0153     }
0154     d->colorConversionSystem->insertColorSpace(item);
0155 }
0156 
0157 void KoColorSpaceRegistry::remove(KoColorSpaceFactory* item)
0158 {
0159     d->registrylock.lockForRead();
0160     QList<QString> toremove;
0161     foreach(const KoColorSpace * cs, d->csMap) {
0162         if (cs->id() == item->id()) {
0163             toremove.push_back(idsToCacheName(cs->id(), cs->profile()->name()));
0164             cs->d->deletability = OwnedByRegistryRegistryDeletes;
0165         }
0166     }
0167     d->registrylock.unlock();
0168     d->registrylock.lockForWrite();
0169     foreach(const QString& id, toremove) {
0170         d->csMap.remove(id);
0171         // TODO: should not it delete the color space when removing it from the map ?
0172     }
0173     d->colorSpaceFactoryRegistry.remove(item->id());
0174     d->registrylock.unlock();
0175 }
0176 
0177 void KoColorSpaceRegistry::addProfileAlias(const QString& name, const QString& to)
0178 {
0179     QWriteLocker l(&d->registrylock);
0180     d->profileAlias[name] = to;
0181 }
0182 
0183 QString KoColorSpaceRegistry::profileAlias(const QString& _name) const
0184 {
0185     QReadLocker l(&d->registrylock);
0186     return d->profileAlias.value(_name, _name);
0187 }
0188 
0189 const KoColorProfile *  KoColorSpaceRegistry::profileByName(const QString & _name) const
0190 {
0191     QReadLocker l(&d->registrylock);
0192     return d->profileMap.value( profileAlias(_name), 0);
0193 }
0194 
0195 QList<const KoColorProfile *>  KoColorSpaceRegistry::profilesFor(const QString &id) const
0196 {
0197     return profilesFor(d->colorSpaceFactoryRegistry.value(id));
0198 }
0199 
0200 const KoColorSpace *  KoColorSpaceRegistry::colorSpace(const KoID &csID, const QString & profileName)
0201 {
0202     return colorSpace(csID.id(), profileName);
0203 }
0204 
0205 const KoColorSpace * KoColorSpaceRegistry::colorSpace(const QString & colorModelId, const QString & colorDepthId, const KoColorProfile *profile)
0206 {
0207     return colorSpace(colorSpaceId(colorModelId, colorDepthId), profile);
0208 }
0209 
0210 const KoColorSpace * KoColorSpaceRegistry::colorSpace(const QString & colorModelId, const QString & colorDepthId, const QString &profileName)
0211 {
0212     return colorSpace(colorSpaceId(colorModelId, colorDepthId), profileName);
0213 }
0214 
0215 QList<const KoColorProfile *>  KoColorSpaceRegistry::profilesFor(const KoColorSpaceFactory * csf) const
0216 {
0217     QReadLocker l(&d->registrylock);
0218     QList<const KoColorProfile *>  profiles;
0219     if (csf == 0)
0220         return profiles;
0221 
0222     QHash<QString, KoColorProfile * >::Iterator it;
0223     for (it = d->profileMap.begin(); it != d->profileMap.end(); ++it) {
0224         KoColorProfile *  profile = it.value();
0225         if (csf->profileIsCompatible(profile)) {
0226             Q_ASSERT(profile);
0227             //         if (profile->colorSpaceSignature() == csf->colorSpaceSignature()) {
0228             profiles.push_back(profile);
0229         }
0230     }
0231     return profiles;
0232 }
0233 
0234 QList<const KoColorSpaceFactory*> KoColorSpaceRegistry::colorSpacesFor(const KoColorProfile* _profile) const
0235 {
0236     QReadLocker l(&d->registrylock);
0237     QList<const KoColorSpaceFactory*> csfs;
0238     foreach(KoColorSpaceFactory* csf, d->colorSpaceFactoryRegistry.values()) {
0239         if (csf->profileIsCompatible(_profile)) {
0240             csfs.push_back(csf);
0241         }
0242     }
0243     return csfs;
0244 }
0245 
0246 QList<const KoColorProfile *>  KoColorSpaceRegistry::profilesFor(const KoID& id) const
0247 {
0248     return profilesFor(id.id());
0249 }
0250 
0251 void KoColorSpaceRegistry::addProfileToMap(KoColorProfile *p)
0252 {
0253     Q_ASSERT(p);
0254     if (p->valid()) {
0255         d->profileMap[p->name()] = p;
0256     }
0257 }
0258 
0259 void KoColorSpaceRegistry::addProfile(KoColorProfile *p)
0260 {
0261     Q_ASSERT(p);
0262     if (p->valid()) {
0263         d->profileMap[p->name()] = p;
0264         d->colorConversionSystem->insertColorProfile(p);
0265     }
0266 }
0267 
0268 void KoColorSpaceRegistry::addProfile(const KoColorProfile* profile)
0269 {
0270     addProfile(profile->clone());
0271 }
0272 
0273 void KoColorSpaceRegistry::removeProfile(KoColorProfile* profile)
0274 {
0275     d->profileMap.remove(profile->name());
0276 }
0277 
0278 const KoColorSpace* KoColorSpaceRegistry::getCachedColorSpace(const QString & csID, const QString & profileName) const
0279 {
0280     auto it = d->csMap.find(idsToCacheName(csID, profileName));
0281 
0282     if (it != d->csMap.end()) {
0283             return it.value();
0284     }
0285 
0286     return 0;
0287 }
0288 
0289 QString KoColorSpaceRegistry::idsToCacheName(const QString & csID, const QString & profileName) const
0290 {
0291     return csID + "<comb>" + profileName;
0292 }
0293 
0294 const KoColorSpaceFactory* KoColorSpaceRegistry::colorSpaceFactory(const QString &colorSpaceId) const
0295 {
0296     QReadLocker l(&d->registrylock);
0297     return d->colorSpaceFactoryRegistry.get(colorSpaceId);
0298 }
0299 
0300 const KoColorSpace * KoColorSpaceRegistry::colorSpace(const QString &csID, const QString &pName)
0301 {
0302     QString profileName = pName;
0303 
0304     if (profileName.isEmpty()) {
0305         QReadLocker l(&d->registrylock);
0306         KoColorSpaceFactory *csf = d->colorSpaceFactoryRegistry.value(csID);
0307 
0308         if (!csf) {
0309             dbgPigmentCSRegistry << "Unknown color space type : " << csID;
0310             return 0;
0311         }
0312 
0313         profileName = csf->defaultProfile();
0314     }
0315 
0316     if (profileName.isEmpty()) {
0317         return 0;
0318     }
0319 
0320     const KoColorSpace *cs = 0;
0321     {
0322         QReadLocker l(&d->registrylock);
0323         cs = getCachedColorSpace(csID, profileName);
0324     }
0325 
0326     if (!cs) {
0327         KoColorSpaceFactory *csf = d->colorSpaceFactoryRegistry.value(csID);
0328 
0329         if (!csf) {
0330             dbgPigmentCSRegistry << "Unknown color space type :" << csf;
0331             return 0;
0332         }
0333 
0334         // last attempt at getting a profile, sometimes the default profile, like adobe cmyk isn't available.
0335         const KoColorProfile *p = profileByName(profileName);
0336         if (!p) {
0337             dbgPigmentCSRegistry << "Profile not found :" << profileName;
0338 
0339             /**
0340              * If the requested profile is not available, try fetching the
0341              * default one
0342              */
0343             profileName = csf->defaultProfile();
0344             p = profileByName(profileName);
0345 
0346             /**
0347              * If there is no luck, try to fetch the first one
0348              */
0349             if (!p) {
0350                 QList<const KoColorProfile *> profiles = profilesFor(csID);
0351                 if (!profiles.isEmpty()) {
0352                     p = profiles[0];
0353                     Q_ASSERT(p);
0354                 }
0355             }
0356         }
0357 
0358         // We did our best, but still have no profile: and since csf->grabColorSpace
0359         // needs the profile to find the colorspace, we have to give up.
0360         if (!p) {
0361             return 0;
0362         }
0363         profileName = p->name();
0364 
0365         QWriteLocker l(&d->registrylock);
0366         /*
0367          * We need to check again here, a thread requesting the same colorspace could've added it
0368          * already, in between the read unlock and write lock.
0369          * TODO: We also potentially changed profileName content, which means we maybe are going to
0370          * create a colorspace that's actually in the space registry cache, but currently this might
0371          * not be an issue because the colorspace should be cached also by the factory, so it won't
0372          * create a new instance. That being said, having two caches with the same stuff doesn't make
0373          * much sense.
0374          */
0375         cs = getCachedColorSpace(csID, profileName);
0376         if (!cs) {
0377             cs = csf->grabColorSpace(p);
0378             if (!cs) {
0379                 dbgPigmentCSRegistry << "Unable to create color space";
0380                 return 0;
0381             }
0382 
0383             dbgPigmentCSRegistry << "colorspace count: " << d->csMap.count()
0384                                  << ", adding name: " << idsToCacheName(cs->id(), cs->profile()->name())
0385                                  << "\n\tcsID" << csID
0386                                  << "\n\tprofileName" << profileName
0387                                  << "\n\tcs->id()" << cs->id()
0388                                  << "\n\tcs->profile()->name()" << cs->profile()->name()
0389                                  << "\n\tpName" << pName;
0390             Q_ASSERT(cs->id() == csID);
0391             Q_ASSERT(cs->profile()->name() == profileName);
0392             d->csMap[idsToCacheName(cs->id(), cs->profile()->name())] = cs;
0393             cs->d->deletability = OwnedByRegistryDoNotDelete;
0394         }
0395     }
0396     else {
0397         Q_ASSERT(cs->id() == csID);
0398         Q_ASSERT(cs->profile()->name() == profileName);
0399     }
0400 
0401     return cs;
0402 }
0403 
0404 
0405 const KoColorSpace * KoColorSpaceRegistry::colorSpace(const QString &csID, const KoColorProfile *profile)
0406 {
0407     if (csID.isEmpty()) {
0408         return 0;
0409     }
0410     if (profile) {
0411         d->registrylock.lockForRead();
0412         const KoColorSpace *cs = getCachedColorSpace(csID, profile->name());
0413         d->registrylock.unlock();
0414 
0415         if (!d->profileMap.contains(profile->name())) {
0416             addProfile(profile);
0417         }
0418 
0419         if (!cs) {
0420             // The profile was not stored and thus not the combination either
0421             d->registrylock.lockForRead();
0422             KoColorSpaceFactory *csf = d->colorSpaceFactoryRegistry.value(csID);
0423             d->registrylock.unlock();
0424             if (!csf) {
0425                 dbgPigmentCSRegistry << "Unknown color space type :" << csf;
0426                 return 0;
0427             }
0428             if (!csf->profileIsCompatible(profile ) ) {
0429                 return 0;
0430             }
0431 
0432             QWriteLocker l(&d->registrylock);
0433             // Check again, anything could've happened between the unlock and the write lock
0434             cs = getCachedColorSpace(csID, profile->name());
0435             if (!cs) {
0436                 cs = csf->grabColorSpace(profile);
0437                 if (!cs)
0438                     return 0;
0439 
0440                 QString name = idsToCacheName(csID, profile->name());
0441                 d->csMap[name] = cs;
0442                 cs->d->deletability = OwnedByRegistryDoNotDelete;
0443                 dbgPigmentCSRegistry << "colorspace count: " << d->csMap.count() << ", adding name: " << name;
0444             }
0445         }
0446 
0447         return cs;
0448     } else {
0449         return colorSpace(csID);
0450     }
0451 }
0452 
0453 const KoColorSpace * KoColorSpaceRegistry::alpha8()
0454 {
0455     if (!d->alphaCs) {
0456         d->alphaCs = colorSpace(KoAlphaColorSpace::colorSpaceId());
0457     }
0458     Q_ASSERT(d->alphaCs);
0459     return d->alphaCs;
0460 }
0461 
0462 const KoColorSpace * KoColorSpaceRegistry::rgb8(const QString &profileName)
0463 {
0464     if (profileName.isEmpty()) {
0465         if (!d->rgbU8sRGB) {
0466             d->rgbU8sRGB = colorSpace(KoRgbU8ColorSpace::colorSpaceId());
0467         }
0468         Q_ASSERT(d->rgbU8sRGB);
0469         return d->rgbU8sRGB;
0470     }
0471     return colorSpace(KoRgbU8ColorSpace::colorSpaceId(), profileName);
0472 }
0473 
0474 const KoColorSpace * KoColorSpaceRegistry::rgb8(const KoColorProfile * profile)
0475 {
0476     if (profile == 0) {
0477         if (!d->rgbU8sRGB) {
0478             d->rgbU8sRGB = colorSpace(KoRgbU8ColorSpace::colorSpaceId());
0479         }
0480         Q_ASSERT(d->rgbU8sRGB);
0481         return d->rgbU8sRGB;
0482     }
0483     return colorSpace(KoRgbU8ColorSpace::colorSpaceId(), profile);
0484 }
0485 
0486 const KoColorSpace * KoColorSpaceRegistry::rgb16(const QString &profileName)
0487 {
0488     return colorSpace(KoRgbU16ColorSpace::colorSpaceId(), profileName);
0489 }
0490 
0491 const KoColorSpace * KoColorSpaceRegistry::rgb16(const KoColorProfile * profile)
0492 {
0493     return colorSpace(KoRgbU16ColorSpace::colorSpaceId(), profile);
0494 }
0495 
0496 const KoColorSpace * KoColorSpaceRegistry::lab16(const QString &profileName)
0497 {
0498     if (profileName.isEmpty()) {
0499         if (!d->lab16sLAB) {
0500             d->lab16sLAB = colorSpace(KoLabColorSpace::colorSpaceId(), profileName);
0501         }
0502         return d->lab16sLAB;
0503     }
0504     return colorSpace(KoLabColorSpace::colorSpaceId(), profileName);
0505 }
0506 
0507 const KoColorSpace * KoColorSpaceRegistry::lab16(const KoColorProfile * profile)
0508 {
0509     if (profile == 0) {
0510         if (!d->lab16sLAB) {
0511             d->lab16sLAB = colorSpace(KoLabColorSpace::colorSpaceId(), profile);
0512         }
0513         Q_ASSERT(d->lab16sLAB);
0514         return d->lab16sLAB;
0515     }
0516     return colorSpace(KoLabColorSpace::colorSpaceId(), profile);
0517 }
0518 
0519 QList<KoID> KoColorSpaceRegistry::colorModelsList(ColorSpaceListVisibility option) const
0520 {
0521     QReadLocker l(&d->registrylock);
0522     QList<KoID> ids;
0523     QList<KoColorSpaceFactory*> factories = d->colorSpaceFactoryRegistry.values();
0524     foreach(KoColorSpaceFactory* factory, factories) {
0525         if (!ids.contains(factory->colorModelId())
0526                 && (option == AllColorSpaces || factory->userVisible())) {
0527             ids << factory->colorModelId();
0528         }
0529     }
0530     return ids;
0531 }
0532 QList<KoID> KoColorSpaceRegistry::colorDepthList(const KoID& colorModelId, ColorSpaceListVisibility option) const
0533 {
0534     return colorDepthList(colorModelId.id(), option);
0535 }
0536 
0537 
0538 QList<KoID> KoColorSpaceRegistry::colorDepthList(const QString & colorModelId, ColorSpaceListVisibility option) const
0539 {
0540     QReadLocker l(&d->registrylock);
0541     QList<KoID> ids;
0542     QList<KoColorSpaceFactory*> factories = d->colorSpaceFactoryRegistry.values();
0543     foreach(KoColorSpaceFactory* factory, factories) {
0544         if (!ids.contains(KoID(factory->colorDepthId()))
0545                 && factory->colorModelId().id() == colorModelId
0546                 && (option == AllColorSpaces || factory->userVisible())) {
0547             ids << factory->colorDepthId();
0548         }
0549     }
0550     return ids;
0551 }
0552 
0553 QString KoColorSpaceRegistry::colorSpaceId(const QString & colorModelId, const QString & colorDepthId) const
0554 {
0555     QReadLocker l(&d->registrylock);
0556     QList<KoColorSpaceFactory*> factories = d->colorSpaceFactoryRegistry.values();
0557     foreach(KoColorSpaceFactory* factory, factories) {
0558         if (factory->colorModelId().id() == colorModelId && factory->colorDepthId().id() == colorDepthId) {
0559             return factory->id();
0560         }
0561     }
0562     return "";
0563 }
0564 
0565 QString KoColorSpaceRegistry::colorSpaceId(const KoID& colorModelId, const KoID& colorDepthId) const
0566 {
0567     return colorSpaceId(colorModelId.id(), colorDepthId.id());
0568 }
0569 
0570 KoID KoColorSpaceRegistry::colorSpaceColorModelId(const QString & _colorSpaceId) const
0571 {
0572     QReadLocker l(&d->registrylock);
0573     KoColorSpaceFactory* factory = d->colorSpaceFactoryRegistry.get(_colorSpaceId);
0574     if (factory) {
0575         return factory->colorModelId();
0576     } else {
0577         return KoID();
0578     }
0579 }
0580 
0581 KoID KoColorSpaceRegistry::colorSpaceColorDepthId(const QString & _colorSpaceId) const
0582 {
0583     QReadLocker l(&d->registrylock);
0584     KoColorSpaceFactory* factory = d->colorSpaceFactoryRegistry.get(_colorSpaceId);
0585     if (factory) {
0586         return factory->colorDepthId();
0587     } else {
0588         return KoID();
0589     }
0590 }
0591 
0592 const KoColorConversionSystem* KoColorSpaceRegistry::colorConversionSystem() const
0593 {
0594     return d->colorConversionSystem;
0595 }
0596 
0597 KoColorConversionCache* KoColorSpaceRegistry::colorConversionCache() const
0598 {
0599     return d->colorConversionCache;
0600 }
0601 
0602 const KoColorSpace* KoColorSpaceRegistry::permanentColorspace(const KoColorSpace* _colorSpace)
0603 {
0604     if (_colorSpace->d->deletability != NotOwnedByRegistry) {
0605         return _colorSpace;
0606     } else if (*_colorSpace == *d->alphaCs) {
0607         return d->alphaCs;
0608     } else {
0609         const KoColorSpace* cs = colorSpace(_colorSpace->id(), _colorSpace->profile());
0610         Q_ASSERT(cs);
0611         Q_ASSERT(*cs == *_colorSpace);
0612         return cs;
0613     }
0614 }
0615 
0616 QList<KoID> KoColorSpaceRegistry::listKeys() const
0617 {
0618     QReadLocker l(&d->registrylock);
0619     QList<KoID> answer;
0620     foreach(const QString& key, d->colorSpaceFactoryRegistry.keys()) {
0621         answer.append(KoID(key, d->colorSpaceFactoryRegistry.get(key)->name()));
0622     }
0623 
0624     return answer;
0625 }
0626 
0627 const KoColorProfile* KoColorSpaceRegistry::createColorProfile(const QString& colorModelId, const QString& colorDepthId, const QByteArray& rawData)
0628 {
0629     QReadLocker l(&d->registrylock);
0630     KoColorSpaceFactory* factory_ = d->colorSpaceFactoryRegistry.get(colorSpaceId(colorModelId, colorDepthId));
0631     return factory_->colorProfile(rawData);
0632 }
0633 
0634 QList<const KoColorSpace*> KoColorSpaceRegistry::allColorSpaces(ColorSpaceListVisibility visibility, ColorSpaceListProfilesSelection pSelection)
0635 {
0636     QList<const KoColorSpace*> colorSpaces;
0637 
0638     d->registrylock.lockForRead();
0639     QList<KoColorSpaceFactory*> factories = d->colorSpaceFactoryRegistry.values();
0640     d->registrylock.unlock();
0641 
0642     foreach(KoColorSpaceFactory* factory, factories) {
0643         // Don't test with ycbcr for now, since we don't have a default profile for it.
0644         if (factory->colorModelId().id().startsWith("Y")) continue;
0645         if (visibility == AllColorSpaces || factory->userVisible()) {
0646             if (pSelection == OnlyDefaultProfile) {
0647                 const KoColorSpace *cs = colorSpace(factory->id());
0648                 if (cs) {
0649                     colorSpaces.append(cs);
0650                 }
0651                 else {
0652                     warnPigment << "Could not create colorspace for id" << factory->id() << "since there is no working default profile";
0653                 }
0654             } else {
0655                 QList<const KoColorProfile*> profiles = KoColorSpaceRegistry::instance()->profilesFor(factory->id());
0656                 foreach(const KoColorProfile * profile, profiles) {
0657                     const KoColorSpace *cs = colorSpace(factory->id(), profile);
0658                     if (cs) {
0659                         colorSpaces.append(cs);
0660                     }
0661                     else {
0662                         warnPigment << "Could not create colorspace for id" << factory->id() << "and profile" << profile->name();
0663                     }
0664                 }
0665             }
0666         }
0667     }
0668 
0669     return colorSpaces;
0670 }