1 /*
2  *  Copyright (c) 2007-2008 Cyrille Berger <cberger@cberger.net>
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Lesser General Public
6  * License as published by the Free Software Foundation; either
7  * version 2.1 of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * Lesser General Public License for more details.
13  *
14  * You should have received a copy of the GNU Lesser General Public License
15  * along with this library; see the file COPYING.LIB.  If not, write to
16  * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
17  * Boston, MA 02110-1301, USA.
18 */
19 
20 #ifndef _KO_COLOR_CONVERSION_SYSTEM_H_
21 #define _KO_COLOR_CONVERSION_SYSTEM_H_
22 
23 class KoColorProfile;
24 class KoColorSpace;
25 class KoColorSpaceFactory;
26 class KoColorSpaceEngine;
27 class KoID;
28 
29 #include "KoColorConversionTransformation.h"
30 
31 #include <QList>
32 #include <QPair>
33 
34 #include "kritapigment_export.h"
35 
36 /**
37  * This class hold the logic related to pigment's Color Conversion System. It's
38  * basically a graph containing all the possible color transformation between
39  * the color spaces. The most useful functions are createColorConverter to create
40  * a color conversion between two color spaces, and insertColorSpace which is called
41  * by KoColorSpaceRegistry each time a new color space is added to the registry.
42  *
43  * This class is not part of public API, and can be changed without notice.
44  */
45 class KRITAPIGMENT_EXPORT KoColorConversionSystem
46 {
47 public:
48     struct RegistryInterface {
~RegistryInterfaceRegistryInterface49         virtual ~RegistryInterface() {}
50 
51         virtual const KoColorSpace * colorSpace(const QString & colorModelId, const QString & colorDepthId, const QString &profileName) = 0;
52         virtual const KoColorSpaceFactory* colorSpaceFactory(const QString &colorModelId, const QString &colorDepthId) const = 0;
53         virtual QList<const KoColorProfile *>  profilesFor(const KoColorSpaceFactory * csf) const = 0;
54         virtual QList<const KoColorSpaceFactory*> colorSpacesFor(const KoColorProfile* profile) const = 0;
55     };
56 
57 public:
58     struct Node;
59     struct Vertex;
60     struct NodeKey;
61     friend uint qHash(const KoColorConversionSystem::NodeKey &key);
62     struct Path;
63     /**
64      * Construct a Color Conversion System, leave to the KoColorSpaceRegistry to
65      * create it.
66      */
67     KoColorConversionSystem(RegistryInterface *registryInterface);
68     ~KoColorConversionSystem();
69     /**
70      * This function is called by the KoColorSpaceRegistry to add a new color space
71      * to the graph of transformation.
72      */
73     void insertColorSpace(const KoColorSpaceFactory*);
74 
75     void insertColorProfile(const KoColorProfile*);
76     /**
77      * This function is called by the color space to create a color conversion
78      * between two color space. This function search in the graph of transformations
79      * the best possible path between the two color space.
80      */
81     KoColorConversionTransformation* createColorConverter(const KoColorSpace * srcColorSpace, const KoColorSpace * dstColorSpace, KoColorConversionTransformation::Intent renderingIntent, KoColorConversionTransformation::ConversionFlags conversionFlags) const;
82 
83     /**
84      * This function creates two transformations, one from the color space and one to the
85      * color space. The destination color space is picked from a list of color space, such
86      * as the conversion between the two color space is of the best quality.
87      *
88      * The typical use case of this function is for KoColorTransformationFactory which
89      * doesn't support all color spaces, so unsupported color space have to find an
90      * acceptable conversion in order to use that KoColorTransformationFactory.
91      *
92      * @param colorSpace the source color space
93      * @param possibilities a list of color space among which we need to find the best
94      *                      conversion
95      * @param fromCS the conversion from the source color space will be affected to this
96      *               variable
97      * @param toCS the revert conversion to the source color space will be affected to this
98      *             variable
99      */
100     void createColorConverters(const KoColorSpace* colorSpace, const QList< QPair<KoID, KoID> >& possibilities, KoColorConversionTransformation*& fromCS, KoColorConversionTransformation*& toCS) const;
101 public:
102     /**
103      * This function return a text that can be compiled using dot to display
104      * the graph of color conversion connection.
105      */
106     QString toDot() const;
107     /**
108      * This function return a text that can be compiled using dot to display
109      * the graph of color conversion connection, with a red link to show the
110      * path of the best color conversion.
111      */
112     QString bestPathToDot(const QString& srcKey, const QString& dstKey) const;
113 public:
114     /**
115      * @return true if there is a path between two color spaces
116      */
117     bool existsPath(const QString& srcModelId, const QString& srcDepthId, const QString& srcProfileName, const QString& dstModelId, const QString& dstDepthId, const QString& dstProfileName) const;
118     /**
119      * @return true if there is a good path between two color spaces
120      */
121     bool existsGoodPath(const QString& srcModelId, const QString& srcDepthId, const QString& srcProfileName, const QString& dstModelId, const QString& dstDepthId, const QString& dstProfileName) const;
122 private:
123     QString vertexToDot(Vertex* v, const QString &options) const;
124 private:
125     /**
126      * Insert an engine.
127      */
128     Node* insertEngine(const KoColorSpaceEngine* engine);
129     KoColorConversionTransformation* createTransformationFromPath(const KoColorConversionSystem::Path& path, const KoColorSpace* srcColorSpace, const KoColorSpace* dstColorSpace, KoColorConversionTransformation::Intent renderingIntent, KoColorConversionTransformation::ConversionFlags conversionFlags) const;
130     /**
131      * Query the registry to get the color space associated with this
132      * node. (default profile)
133      */
134     const KoColorSpace* defaultColorSpaceForNode(const Node* node) const;
135     /**
136      * Create a new node
137      */
138     Node* createNode(const QString& _modelId, const QString& _depthId, const QString& _profileName);
139     /**
140      * Initialise a node for ICC color spaces
141      */
142     void connectToEngine(Node* _node, Node* _engine);
143     const Node* nodeFor(const KoColorSpace*) const;
144     /**
145      * @return the node corresponding to that key, or create it if needed
146      */
147     Node* nodeFor(const NodeKey& key);
148     const Node* nodeFor(const NodeKey& key) const;
149     /**
150      * @return the list of nodes that correspond to a given model and depth.
151      */
152     QList<Node*> nodesFor(const QString& _modelId, const QString& _depthId);
153     /**
154      * @return the node associated with that key, and create it if needed
155      */
156     Node* nodeFor(const QString& colorModelId, const QString& colorDepthId, const QString& _profileName);
157     const Node* nodeFor(const QString& colorModelId, const QString& colorDepthId, const QString& _profileName) const;
158     /**
159      * @return the vertex between two nodes, or null if the vertex doesn't exist
160      */
161     Vertex* vertexBetween(Node* srcNode, Node* dstNode);
162     /**
163      * create a vertex between two nodes and return it.
164      */
165     Vertex* createVertex(Node* srcNode, Node* dstNode);
166     /**
167      * looks for the best path between two nodes
168      */
169     Path findBestPath(const Node* srcNode, const Node* dstNode) const;
170     /**
171      * Delete all the paths of the list given in argument.
172      */
173     void deletePaths(QList<KoColorConversionSystem::Path*> paths) const;
174     /**
175      * Don't call that function, but raher findBestPath
176      * @internal
177      */
178     inline Path findBestPathImpl2(const Node* srcNode, const Node* dstNode, bool ignoreHdr, bool ignoreColorCorrectness) const;
179     /**
180      * Don't call that function, but raher findBestPath
181      * @internal
182      */
183     inline Path findBestPathImpl(const Node* srcNode, const Node* dstNode, bool ignoreHdr) const;
184 
185 private:
186     struct Private;
187     Private* const d;
188 };
189 
190 #endif
191