File indexing completed on 2024-05-12 15:59:35

0001 /*
0002  *  SPDX-FileCopyrightText: 2003 Patrick Julien <freak@codepimps.org>
0003  *  SPDX-FileCopyrightText: 2004, 2010 Cyrille Berger <cberger@cberger.net>
0004  *
0005  * SPDX-License-Identifier: LGPL-2.1-or-later
0006 */
0007 
0008 #ifndef KOCOLORSPACEREGISTRY_H
0009 #define KOCOLORSPACEREGISTRY_H
0010 
0011 #include <QObject>
0012 #include <QList>
0013 #include <QString>
0014 #include "kritapigment_export.h"
0015 
0016 #include <KoGenericRegistry.h>
0017 #include <KoColorSpace.h>
0018 #include <KoColorSpaceFactory.h>
0019 #include <KoConfig.h>
0020 #include <KoColorProfileConstants.h>
0021 
0022 class KoColorProfile;
0023 class KoColorConversionSystem;
0024 class KoColorConversionCache;
0025 class KoColorConversionTransformation;
0026 
0027 /**
0028  * The registry for colorspaces and profiles.
0029  * This class contains:
0030  *      - a registry of colorspace instantiated with specific profiles.
0031  *      - a registry of singleton colorspace factories.
0032  *      - a registry of icc profiles
0033  *
0034  * Locking policy details:
0035  *
0036  * Basically, we have two levels of locks in the registry:
0037  * 1) (outer level) is Private::registrylock, which controls the structures
0038  *     of the color space registry itself
0039  * 2) (inner level) is KoColorProfileStorage::Private::lock controls
0040  *    the structures related to profiles.
0041  *
0042  * The locks can be taken individually, but if you are going to take both
0043  * of them, you should always follow the order 1) registry; 2) profiles.
0044  * Otherwise you'll get a deadlock.
0045  *
0046  * To avoid recursive deadlocks, all the dependent classes
0047  * (KoColorConversionSystem and KoColorSpaceFactory) now do not use the direct
0048  * links to the registry. Instead, they use special private interfaces that
0049  * skip recursive locking and ensure we take a lock twice.
0050  */
0051 class KRITAPIGMENT_EXPORT KoColorSpaceRegistry
0052 {
0053 public:
0054     KoColorSpaceRegistry();
0055 
0056     enum ColorSpaceListVisibility {
0057         OnlyUserVisible = 1, ///< Only user visible color space
0058         AllColorSpaces = 4 ///< All color space even those not visible to the user
0059     };
0060     enum ColorSpaceListProfilesSelection {
0061         OnlyDefaultProfile = 1, ///< Only add the default profile
0062         AllProfiles = 4 ///< Add all profiles
0063     };
0064 
0065     /**
0066      * Return an instance of the KoColorSpaceRegistry
0067      * Creates an instance if that has never happened before and returns the singleton instance.
0068      */
0069     static KoColorSpaceRegistry * instance();
0070 
0071     virtual ~KoColorSpaceRegistry();
0072 
0073 public:
0074     /**
0075       * add a color space to the registry
0076       * @param item the color space factory to add
0077       */
0078     void add(KoColorSpaceFactory* item);
0079 
0080     /**
0081      * Remove a color space factory from the registry. Note that it is the
0082      * responsibility of the caller to ensure that the colorspaces are not
0083      * used anymore.
0084      */
0085     void remove(KoColorSpaceFactory* item);
0086 
0087     /**
0088      * Add a profile to the profile map but do not add it to the
0089      * color conversion system yet.
0090      * @param profile the new profile to be registered.
0091      */
0092     void addProfileToMap(KoColorProfile *p);
0093 
0094     /**
0095      * register the profile with the color space registry
0096      * @param profile the new profile to be registered so it can be combined with
0097      *  colorspaces.
0098      */
0099     void addProfile(KoColorProfile* profile);
0100     void addProfile(const KoColorProfile* profile); // TODO why ?
0101     void removeProfile(KoColorProfile* profile);
0102 
0103     /**
0104      * Create an alias to a profile with a different name. Then @ref profileByName
0105      * will return the profile @p to when passed @p name as a parameter.
0106      */
0107     void addProfileAlias(const QString& name, const QString& to);
0108 
0109     /**
0110      * @return the profile alias, or name if not aliased
0111      */
0112     QString profileAlias(const QString& name) const;
0113 
0114     /**
0115      * create a profile of the specified type.
0116      */
0117     const KoColorProfile *createColorProfile(const QString & colorModelId, const QString & colorDepthId, const QByteArray& rawData);
0118 
0119     /**
0120      * Return a profile by its given name, or 0 if none registered.
0121      * @return a profile by its given name, or 0 if none registered.
0122      * @param name the product name as set on the profile.
0123      * @see addProfile()
0124      * @see KoColorProfile::productName()
0125      */
0126     const KoColorProfile * profileByName(const QString & name) const ;
0127 
0128 
0129     /**
0130      * Returns a profile by its unique id stored/calculated in the header.
0131      * The first call to this function might take long, because the map is
0132      * created on the first use only (atm used by SVG only)
0133      * @param id unique ProfileID of the profile (MD5 sum of its header)
0134      * @return the profile or 0 if not found
0135      */
0136     const KoColorProfile *profileByUniqueId(const QByteArray &id) const;
0137 
0138     bool profileIsCompatible(const KoColorProfile* profile, const QString &colorSpaceId);
0139 
0140     /**
0141      * Return the list of profiles for a colorspace with the argument id.
0142      * Profiles will not work with any color space, you can query which profiles
0143      * that are registered with this registry can be used in combination with the
0144      * argument factory.
0145      * @param colorSpaceId the colorspace-id with which all the returned profiles will work.
0146      * @return a list of profiles for the factory
0147      */
0148     QList<const KoColorProfile *>  profilesFor(const QString& csID) const;
0149     QString defaultProfileForColorSpace(const QString &colorSpaceId) const;
0150 
0151     /**
0152      * This function is called by the color space to create a color conversion
0153      * between two color space. This function search in the graph of transformations
0154      * the best possible path between the two color space.
0155      */
0156     KoColorConversionTransformation* createColorConverter(const KoColorSpace * srcColorSpace, const KoColorSpace * dstColorSpace, KoColorConversionTransformation::Intent renderingIntent, KoColorConversionTransformation::ConversionFlags conversionFlags) const;
0157 
0158     /**
0159      * This function creates two transformations, one from the color space and one to the
0160      * color space. The destination color space is picked from a list of color space, such
0161      * as the conversion between the two color space is of the best quality.
0162      *
0163      * The typical use case of this function is for KoColorTransformationFactory which
0164      * doesn't support all color spaces, so unsupported color space have to find an
0165      * acceptable conversion in order to use that KoColorTransformationFactory.
0166      *
0167      * @param colorSpace the source color space
0168      * @param possibilities a list of color space among which we need to find the best
0169      *                      conversion
0170      * @param fromCS the conversion from the source color space will be affected to this
0171      *               variable
0172      * @param toCS the revert conversion to the source color space will be affected to this
0173      *             variable
0174      */
0175     void createColorConverters(const KoColorSpace* colorSpace, const QList< QPair<KoID, KoID> >& possibilities, KoColorConversionTransformation*& fromCS, KoColorConversionTransformation*& toCS) const;
0176 
0177     /**
0178      * Return a colorspace that works with the parameter profile.
0179      * @param colorSpaceId the ID string of the colorspace that you want to have returned
0180      * @param profile the profile be combined with the colorspace
0181      * @return the wanted colorspace, or 0 when the cs and profile can not be combined.
0182      */
0183     const KoColorSpace * colorSpace(const QString & colorModelId, const QString & colorDepthId, const KoColorProfile *profile);
0184 
0185     /**
0186      * Return a colorspace that works with the parameter profile.
0187      * @param profileName the name of the KoColorProfile to be combined with the colorspace
0188      * @return the wanted colorspace, or 0 when the cs and profile can not be combined.
0189      */
0190     const KoColorSpace * colorSpace(const QString & colorModelId, const QString & colorDepthId, const QString &profileName);
0191 
0192     const KoColorSpace * colorSpace(const QString & colorModelId, const QString & colorDepthId);
0193 
0194     /**
0195      * Return the id of the colorspace that have the defined colorModelId with colorDepthId.
0196      * @param colorModelId id of the color model
0197      * @param colorDepthId id of the color depth
0198      * @return the id of the wanted colorspace, or "" if no colorspace correspond to those ids
0199      */
0200     QString colorSpaceId(const QString & colorModelId, const QString & colorDepthId) const;
0201     /**
0202      * It's a convenient function that behave like the above.
0203      * Return the id of the colorspace that have the defined colorModelId with colorDepthId.
0204      * @param colorModelId id of the color model
0205      * @param colorDepthId id of the color depth
0206      * @return the id of the wanted colorspace, or "" if no colorspace correspond to those ids
0207      */
0208     QString colorSpaceId(const KoID& colorModelId, const KoID& colorDepthId) const;
0209 
0210     /**
0211      * @return the identifier of the color model for the given color space id.
0212      *
0213      * This function is a compatibility function used to get the color space from
0214      * all kra files.
0215      */
0216     KoID colorSpaceColorModelId(const QString & _colorSpaceId) const;
0217 
0218     /**
0219      * @return the identifier of the color depth for the given color space id.
0220      *
0221      * This function is a compatibility function used to get the color space from
0222      * all kra files.
0223      */
0224     KoID colorSpaceColorDepthId(const QString & _colorSpaceId) const;
0225 
0226     /**
0227      * Convenience methods to get the often used alpha colorspaces
0228      */
0229     const KoColorSpace *alpha8();
0230     const KoColorSpace *alpha16();
0231 #ifdef HAVE_OPENEXR
0232     const KoColorSpace *alpha16f();
0233 #endif
0234     const KoColorSpace *alpha32f();
0235 
0236     /**
0237      * Convenience method to get a GRAYA 8 bit colorspace. If a profile is not specified,
0238      * the default profile defined in the GRAY colorspace will be used
0239      * @param profile the profile name
0240      * @return an 8 bit graya colorspace with the default profile or 0.
0241      */
0242     const KoColorSpace *graya8(const QString &profile = QString());
0243 
0244     /**
0245      * Convenience method to get a GRAYA 8 bit colorspace. If a profile is not specified,
0246      * the default profile defined in the GRAY colorspace will be used
0247      * @param profile the profile
0248      * @return an 8 bit graya colorspace with the default profile or 0.
0249      */
0250     const KoColorSpace *graya8(const KoColorProfile *profile);
0251 
0252     /**
0253      * Convenience method to get a GRAYA 16 bit colorspace. If a profile is not specified,
0254      * the default profile defined in the GRAY colorspace will be used
0255      * @param the profile
0256      * @return an 8 bit graya colorspace with the default profile or 0.
0257      */
0258     const KoColorSpace *graya16(const QString &profile = QString());
0259 
0260     /**
0261      * Convenience method to get a GRAYA 16 bit colorspace. If a profile is not specified,
0262      * the default profile defined in the GRAY colorspace will be used
0263      * @param the profile
0264      * @return an 8 bit graya colorspace with the default profile or 0.
0265      */
0266     const KoColorSpace *graya16(const KoColorProfile *profile);
0267 
0268 
0269     /**
0270      * Convenience method to get an RGBA 8bit colorspace. If a profile is not specified,
0271      * an sRGB profile will be used.
0272      * @param profileName the name of an RGB color profile
0273      * @return the wanted colorspace, or 0 if the color space and profile can not be combined.
0274      */
0275     const KoColorSpace * rgb8(const QString &profileName = QString());
0276 
0277     /**
0278      * Convenience method to get an RGBA 8bit colorspace with the given profile.
0279      * @param profile an RGB profile
0280      * @return the wanted colorspace, or 0 if the color space and profile can not be combined.
0281      */
0282     const KoColorSpace * rgb8(const KoColorProfile * profile);
0283 
0284     /**
0285      * Convenience method to get an RGBA 16bit colorspace. If a profile is not specified,
0286      * an sRGB profile will be used.
0287      * @param profileName the name of an RGB color profile
0288      * @return the wanted colorspace, or 0 if the color space and profile can not be combined.
0289      */
0290     const KoColorSpace * rgb16(const QString &profileName = QString());
0291 
0292     /**
0293      * Convenience method to get an RGBA 16bit colorspace with the given profile.
0294      * @param profile an RGB profile
0295      * @return the wanted colorspace, or 0 if the color space and profile can not be combined.
0296      */
0297     const KoColorSpace * rgb16(const KoColorProfile * profile);
0298 
0299     /**
0300      * Convenience method to get an Lab 16bit colorspace. If a profile is not specified,
0301      * an Lab profile with a D50 whitepoint will be used.
0302      * @param profileName the name of an Lab color profile
0303      * @return the wanted colorspace, or 0 if the color space and profile can not be combined.
0304      */
0305     const KoColorSpace * lab16(const QString &profileName = QString());
0306 
0307     /**
0308      * Convenience method to get an Lab 16bit colorspace with the given profile.
0309      * @param profile an Lab profile
0310      * @return the wanted colorspace, or 0 if the color space and profile can not be combined.
0311      */
0312     const KoColorSpace * lab16(const KoColorProfile * profile);
0313 
0314     /**
0315      * Convenience method to get a standard profile for Rec.2020 linear light
0316      * color space
0317      */
0318     const KoColorProfile *p2020G10Profile() const;
0319 
0320     /**
0321      * Convenience method to get a standard profile for Rec.2020 PQ color space
0322      */
0323     const KoColorProfile *p2020PQProfile() const;
0324 
0325     /**
0326      * Convenience method to get a standard profile for Rec. 709 linear light
0327      * color space
0328      */
0329     const KoColorProfile *p709G10Profile() const;
0330 
0331     /**
0332      * Convenience method to get a standard profile for Rec. 709 sRGB-tone-
0333      * response-curve profile
0334      */
0335     const KoColorProfile *p709SRGBProfile() const;
0336 
0337     /**
0338      * @brief profileFor tries to find the profile that matches these characteristics, if no
0339      * such profile is found, it attempts to generate one.
0340      * @param colorants a double of xy (for xyY) values, this expects the first two as the white point,
0341      * then the red, green and blue. If there's only a whitepoint and primaries type is undefined,
0342      * a grayscale profile will be returned.
0343      * @param colorPrimaries the color primaries type as defined in KoColorProfile.
0344      * @param transferFunction the transfer function, as defined in KoColorProfile.
0345      * @return a profile that matches these characteristics.
0346      */
0347     const KoColorProfile *profileFor(const QVector<double> &colorants, ColorPrimaries colorPrimaries, TransferCharacteristics transferFunction) const;
0348 
0349     /**
0350      * @return the list of available color models
0351      */
0352     QList<KoID> colorModelsList(ColorSpaceListVisibility option) const;
0353 
0354     /**
0355      * @return the list of available color models for the given colorModelId
0356      */
0357     QList<KoID> colorDepthList(const KoID& colorModelId, ColorSpaceListVisibility option) const;
0358 
0359     /**
0360      * @return the list of available color models for the given colorModelId
0361      */
0362     QList<KoID> colorDepthList(const QString & colorModelId, ColorSpaceListVisibility option) const;
0363 
0364     /**
0365      * @return the cache of color conversion transformation to be use by KoColorSpace
0366      */
0367     KoColorConversionCache* colorConversionCache() const;
0368 
0369     /**
0370      * @return a permanent colorspace owned by the registry, of the same type and profile
0371      *         as the one given in argument
0372      */
0373     const KoColorSpace* permanentColorspace(const KoColorSpace* _colorSpace);
0374 
0375     /**
0376      * This function return a list of all the keys in KoID format by using the name() method
0377      * on the objects stored in the registry.
0378      */
0379     QList<KoID> listKeys() const;
0380 
0381 private:
0382 
0383     friend class KisCsConversionTest;
0384     friend class KisIteratorTest;
0385     friend class KisIteratorNGTest;
0386     friend class KisPainterTest;
0387     friend class KisCrashFilterTest;
0388     friend class KoColorSpacesBenchmark;
0389     friend class TestKoColorSpaceSanity;
0390     friend class TestColorConversionSystem;
0391     friend struct FriendOfColorSpaceRegistry;
0392 
0393     /**
0394      * @return a list with an instance of all color space with their default profile.
0395      */
0396     QList<const KoColorSpace*> allColorSpaces(ColorSpaceListVisibility visibility, ColorSpaceListProfilesSelection pSelection);
0397 
0398     /**
0399      * @return the color conversion system use by the registry and the color
0400      * spaces to create color conversion transformation.
0401      *
0402      * WARNING: conversion system is guarded by the registry locks, don't
0403      *          use it anywhere other than unittests!
0404      */
0405     const KoColorConversionSystem* colorConversionSystem() const;
0406 
0407 private:
0408     KoColorSpaceRegistry(const KoColorSpaceRegistry&);
0409     KoColorSpaceRegistry operator=(const KoColorSpaceRegistry&);
0410     void init();
0411 
0412 private:
0413     struct Private;
0414     Private * const d;
0415 };
0416 
0417 #endif // KOCOLORSPACEREGISTRY_H