Krita Source Code Documentation
Loading...
Searching...
No Matches
KoColorConversionSystem_p.h
Go to the documentation of this file.
1/*
2 * SPDX-FileCopyrightText: 2007-2008 Cyrille Berger <cberger@cberger.net>
3 *
4 * SPDX-License-Identifier: LGPL-2.1-or-later
5*/
6
7#ifndef KOCOLORCONVERSIONSYSTEM_P_H
8#define KOCOLORCONVERSIONSYSTEM_P_H
9
10#include "DebugPigment.h"
14#include "KoColorSpaceEngine.h"
16#include <boost/operators.hpp>
17
18#include <QList>
19
21 None = 0x0,
22 HasColor = 0x1,
23 HasAlpha = 0x2,
24 HasHdr = 0x4
25};
26
27Q_DECLARE_FLAGS(NodeCapabilities, NodeCapability)
28Q_DECLARE_OPERATORS_FOR_FLAGS(NodeCapabilities)
29
31{
32
34 : isInitialized(false)
35 , referenceDepth(0)
36 , crossingCost(1)
37 , colorSpaceFactory(0)
38 , isEngine(false)
39 , engine(0) {}
40
41 void init(const KoColorSpaceFactory* _colorSpaceFactory) {
42 dbgPigment << "Initialise " << modelId << " " << depthId << " " << profileName;
43
44 if (isInitialized) {
45 dbgPigment << "Re-initializing node. Old factory" << colorSpaceFactory << "new factory" << _colorSpaceFactory;
46 }
47 isInitialized = true;
48
49 if (_colorSpaceFactory) {
50 {
51 const bool isGray = modelId == GrayColorModelID.id() ||
52 modelId == GrayAColorModelID.id();
53
54 const bool isAlpha = modelId == AlphaColorModelID.id();
55
56 if (_colorSpaceFactory->isHdr()) {
57 m_capabilities |= HasHdr;
58 }
59
60 if (!isGray && !isAlpha) {
61 m_capabilities |= HasColor;
62 }
63
64 if (!isAlpha && modelId != GrayColorModelID.id()) {
65 m_capabilities |= HasAlpha;
66 }
67 }
68
69 colorSpaceFactory = _colorSpaceFactory;
70 referenceDepth = _colorSpaceFactory->referenceDepth();
71 crossingCost = _colorSpaceFactory->crossingCost();
72 }
73 }
74
75 void init(const KoColorSpaceEngine* _engine) {
76 Q_ASSERT(!isInitialized);
77 isEngine = true;
78 isInitialized = true;
79 engine = _engine;
80 m_capabilities = HasAlpha | HasColor | HasHdr;
81 }
82
83 QString id() const {
84 return modelId + " " + depthId + " " + profileName;
85 }
86
87 NodeKey key() const;
88
89 friend bool operator==(const Node &lhs, const Node &rhs) {
90 return lhs.modelId == rhs.modelId &&
91 lhs.depthId == rhs.depthId &&
92 lhs.profileName == rhs.profileName;
93 }
94
95 NodeCapabilities capabilities() const {
96 return m_capabilities;
97 }
98
99 QString modelId;
100 QString depthId;
101 QString profileName;
109 NodeCapabilities m_capabilities = None;
110};
111
113
114QDebug operator<<(QDebug dbg, const KoColorConversionSystem::Node &node)
115{
116 dbg.nospace() << "Node(" << node.modelId << ", " << node.depthId << ", " << node.profileName << ")";
117 return dbg.space();
118}
119
121
122 Vertex(Node* _srcNode, Node* _dstNode)
123 : srcNode(_srcNode)
124 , dstNode(_dstNode)
125 , factoryFromSrc(0)
126 , factoryFromDst(0) {
127 }
128
131 delete factoryFromSrc;
132 } else {
133 delete factoryFromSrc;
134 delete factoryFromDst;
135 }
136 }
137
141
145
150
153
154private:
155
156 KoColorConversionTransformationFactory* factoryFromSrc; // Factory provided by the destination node
157 KoColorConversionTransformationFactory* factoryFromDst; // Factory provided by the destination node
158
159};
160
162 : public boost::equality_comparable<NodeKey>
163{
164
165 NodeKey(const QString &_modelId, const QString &_depthId, const QString &_profileName)
166 : modelId(_modelId)
167 , depthId(_depthId)
168 , profileName(_profileName) {}
169
171 return modelId == rhs.modelId && depthId == rhs.depthId && profileName == rhs.profileName;
172 }
173
174 QString modelId;
175 QString depthId;
176 QString profileName;
177};
179
180QDebug operator<<(QDebug dbg, const KoColorConversionSystem::NodeKey &key)
181{
182 dbg.nospace() << "NodeKey(" << key.modelId << ", " << key.depthId << ", " << key.profileName << ")";
183 return dbg.space();
184}
185
186
191
193
195 : referenceDepth(0)
196 , isGood(false)
197 , cost(0) {}
198
200 return vertexes.size() > 0 ?
201 (vertexes.first())->srcNode
202 : 0;
203 }
204
205 bool operator==(const Path &other) const {
206 return other.vertexes == vertexes;
207 }
208
209
210 const Node* startNode() const {
211 return vertexes.size() > 0 ?
212 (vertexes.first())->srcNode
213 : 0;
214 }
215
217 return vertexes.size() > 0 ?
218 (vertexes.last())->dstNode
219 : 0;
220 }
221
222 const Node* endNode() const {
223 return vertexes.size() > 0 ?
224 (vertexes.last())->dstNode
225 : 0;
226 }
227
228 bool isEmpty() const {
229 return vertexes.isEmpty();
230 }
231
233 if (vertexes.empty()) {
234 referenceDepth = v->srcNode->referenceDepth;
235 commonNodeCapabilities = v->srcNode->capabilities();
236 }
237
238 commonNodeCapabilities &= v->dstNode->capabilities();
239
240 vertexes.append(v);
241
242 referenceDepth = qMin(referenceDepth, v->dstNode->referenceDepth);
243 cost += v->dstNode->crossingCost;
244 }
245
246 NodeCapabilities unsupportedCapabilities() const {
247 NodeCapabilities minimalCaps =
248 !vertexes.isEmpty() ?
249 vertexes.first()->srcNode->capabilities() &
250 vertexes.last()->dstNode->capabilities() :
251 None;
252
253 return (minimalCaps & commonNodeCapabilities) ^ minimalCaps;
254 }
255
256 // Compress path to hide the Engine node and correctly select the factory
257 typedef QPair<Node*, const KoColorConversionTransformationAbstractFactory* > node2factory;
260 nodes.push_back(node2factory(vertexes.first()->srcNode , vertexes.first()->factory()));
261 const KoColorConversionTransformationAbstractFactory* previousFactory = 0;
262 Q_FOREACH (Vertex* vertex, vertexes) { // Unless the node is the icc node, add it to the path
263 Node* n = vertex->dstNode;
264 if (n->isEngine) {
265 previousFactory = n->engine;
266 } else {
267 nodes.push_back(
268 node2factory(n,
269 previousFactory ? previousFactory : vertex->factory()));
270 previousFactory = 0;
271 }
272 }
273 return nodes;
274 }
275
276 int length() const {
277 return vertexes.size();
278 }
279
280 bool contains(Node* n) const {
281 Q_FOREACH (Vertex* v, vertexes) {
282 if (v->srcNode == n || v->dstNode == n) {
283 return true;
284 }
285 }
286 return false;
287 }
288
291 bool isGood;
292 int cost;
293 NodeCapabilities commonNodeCapabilities = None;
294
295};
297
298
299inline QDebug operator<<(QDebug dbg, const KoColorConversionSystem::Path &path)
300{
301 bool havePrintedFirst = false;
302
303 Q_FOREACH (const KoColorConversionSystem::Vertex *v, path.vertexes) {
304 if (!havePrintedFirst) {
305 dbg.nospace() << v->srcNode->id();
306 havePrintedFirst = true;
307 }
308
309 dbg.nospace() << "->" << v->dstNode->id();
310 }
311
312 return dbg.space();
313}
314
315
316typedef QHash<KoColorConversionSystem::Node*, KoColorConversionSystem::Path > Node2PathHash;
317
318
320{
321 return qHash(key.modelId) + qHash(key.depthId);
322}
323
324struct Q_DECL_HIDDEN KoColorConversionSystem::Private {
325
326 Private(RegistryInterface *_registryInterface) : registryInterface(_registryInterface) {}
327
328 QHash<NodeKey, Node*> graph;
331};
332
334
335 PathQualityChecker(int _referenceDepth)
336 : referenceDepth(_referenceDepth)
337 {}
338
340 inline bool isGoodPath(const KoColorConversionSystem::Path & path) const {
341 return path.unsupportedCapabilities() == None &&
342 path.referenceDepth >= referenceDepth;
343 }
344
348 inline bool lessWorseThan(const KoColorConversionSystem::Path &path1, const KoColorConversionSystem::Path &path2) const {
349 // There is no point in comparing two paths which doesn't start from the same node or doesn't end at the same node
350
351 NodeCapabilities unsupported1 = path1.unsupportedCapabilities();
352 NodeCapabilities unsupported2 = path2.unsupportedCapabilities();
353
354 if (!unsupported1.testFlag(HasHdr) && unsupported2.testFlag(HasHdr)) {
355 return true;
356 }
357
358 if (!unsupported1.testFlag(HasColor) && unsupported2.testFlag(HasColor)) {
359 return true;
360 }
361
362 if (!unsupported1.testFlag(HasAlpha) && unsupported2.testFlag(HasAlpha)) {
363 return true;
364 }
365
366 if (path1.referenceDepth == path2.referenceDepth) {
367 return path1.cost < path2.cost; // if they have the same cost, well anyway you have to choose one, and there is no point in keeping one and not the other
368 }
369 return path1.referenceDepth > path2.referenceDepth;
370 }
372};
373
374#undef CHECK_ONE_AND_NOT_THE_OTHER
375
376#endif
#define dbgPigment
qreal v
Q_DECLARE_FLAGS(KisUpdaterContextSnapshotEx, KisUpdaterContextSnapshotExTag)
QHash< KoColorConversionSystem::Node *, KoColorConversionSystem::Path > Node2PathHash
QDebug operator<<(QDebug dbg, const KoColorConversionSystem::Node &node)
Q_DECLARE_TYPEINFO(KoColorConversionSystem::Node, Q_MOVABLE_TYPE)
const KoID GrayAColorModelID("GRAYA", ki18n("Grayscale/Alpha"))
const KoID AlphaColorModelID("A", ki18n("Alpha mask"))
const KoID GrayColorModelID("GRAY", ki18n("Grayscale (without transparency)"))
unsigned int uint
Private(RegistryInterface *_registryInterface)
QHash< NodeKey, Node * > graph
friend uint qHash(const KoColorConversionSystem::NodeKey &key)
QString id() const
Definition KoID.cpp:63
Q_DECLARE_OPERATORS_FOR_FLAGS(KisBaseRectsWalker::SubtreeVisitFlags)
bool operator==(const KoColorConversionSystem::NodeKey &rhs) const
NodeKey(const QString &_modelId, const QString &_depthId, const QString &_profileName)
void init(const KoColorSpaceFactory *_colorSpaceFactory)
friend bool operator==(const Node &lhs, const Node &rhs)
void init(const KoColorSpaceEngine *_engine)
const KoColorSpaceFactory * colorSpaceFactory
NodeCapabilities unsupportedCapabilities() const
QPair< Node *, const KoColorConversionTransformationAbstractFactory * > node2factory
bool operator==(const Path &other) const
QList< node2factory > compressedPath() const
KoColorConversionTransformationFactory * factoryFromDst
KoColorConversionTransformationFactory * factory()
KoColorConversionTransformationFactory * factoryFromSrc
void setFactoryFromSrc(KoColorConversionTransformationFactory *factory)
void setFactoryFromDst(KoColorConversionTransformationFactory *factory)
Vertex(Node *_srcNode, Node *_dstNode)
virtual int referenceDepth() const =0
virtual int crossingCost() const =0
virtual bool isHdr() const =0
PathQualityChecker(int _referenceDepth)
bool lessWorseThan(const KoColorConversionSystem::Path &path1, const KoColorConversionSystem::Path &path2) const
bool isGoodPath(const KoColorConversionSystem::Path &path) const