Krita Source Code Documentation
Loading...
Searching...
No Matches
KoColorConversionSystem Struct Reference

#include <KoColorConversionSystem.h>

+ Inheritance diagram for KoColorConversionSystem:

Classes

struct  Node
 
struct  NodeKey
 
struct  Path
 
struct  RegistryInterface
 
struct  Vertex
 

Public Member Functions

QString bestPathToDot (const QString &srcKey, const QString &dstKey) const
 
KoColorConversionTransformationcreateColorConverter (const KoColorSpace *srcColorSpace, const KoColorSpace *dstColorSpace, KoColorConversionTransformation::Intent renderingIntent, KoColorConversionTransformation::ConversionFlags conversionFlags) const
 
void createColorConverters (const KoColorSpace *colorSpace, const QList< QPair< KoID, KoID > > &possibilities, KoColorConversionTransformation *&fromCS, KoColorConversionTransformation *&toCS) const
 
bool existsGoodPath (const QString &srcModelId, const QString &srcDepthId, const QString &srcProfileName, const QString &dstModelId, const QString &dstDepthId, const QString &dstProfileName) const
 
bool existsPath (const QString &srcModelId, const QString &srcDepthId, const QString &srcProfileName, const QString &dstModelId, const QString &dstDepthId, const QString &dstProfileName) const
 
Path findBestPath (const NodeKey &src, const NodeKey &dst) const
 
Path findBestPath (const QString &srcModelId, const QString &srcDepthId, const QString &srcProfileName, const QString &dstModelId, const QString &dstDepthId, const QString &dstProfileName) const
 
void insertColorProfile (const KoColorProfile *profile)
 
void insertColorSpace (const KoColorSpaceFactory *csf)
 
 KoColorConversionSystem (RegistryInterface *registryInterface)
 
 Private (RegistryInterface *_registryInterface)
 
QList< KoColorProfileQueryrequiredConnectionProfilesFor (const KoColorProfile *profile)
 
QList< KoColorProfileQueryrequiredConnectionProfilesFor (const KoColorSpaceFactory *csf)
 
QString toDot () const
 
 ~KoColorConversionSystem ()
 
- Public Member Functions inherited from Private
 Private (KisCanvas2 *c)
 

Public Attributes

QHash< NodeKey, Node * > graph
 
RegistryInterfaceregistryInterface
 
QList< Vertex * > vertexes
 
- Public Attributes inherited from Private
KisCanvas2canvas
 
int displayedFrame
 
int intendedFrame
 

Private Member Functions

void connectToEngine (Node *_node, Node *_engine)
 
NodecreateNode (const QString &_modelId, const QString &_depthId, const QString &_profileName)
 
KoColorConversionTransformationcreateTransformationFromPath (const KoColorConversionSystem::Path &path, const KoColorSpace *srcColorSpace, const KoColorSpace *dstColorSpace, KoColorConversionTransformation::Intent renderingIntent, KoColorConversionTransformation::ConversionFlags conversionFlags) const
 
VertexcreateVertex (Node *srcNode, Node *dstNode)
 
const KoColorSpacedefaultColorSpaceForNode (const Node *node) const
 
void deletePaths (QList< KoColorConversionSystem::Path * > paths) const
 
Path findBestPath (const Node *srcNode, const Node *dstNode) const
 
NodeinsertEngine (const KoColorSpaceEngine *engine)
 
const NodenodeFor (const KoColorSpace *) const
 
NodenodeFor (const NodeKey &key)
 
const NodenodeFor (const NodeKey &key) const
 
NodenodeFor (const QString &colorModelId, const QString &colorDepthId, const QString &_profileName)
 
const NodenodeFor (const QString &colorModelId, const QString &colorDepthId, const QString &_profileName) const
 
QList< Node * > nodesFor (const QString &_modelId, const QString &_depthId)
 
VertexvertexBetween (Node *srcNode, Node *dstNode)
 
QString vertexToDot (Vertex *v, const QString &options) const
 

Private Attributes

Private *const d
 

Friends

uint qHash (const KoColorConversionSystem::NodeKey &key)
 

Detailed Description

This class hold the logic related to pigment's Color Conversion System. It's basically a graph containing all the possible color transformation between the color spaces. The most useful functions are createColorConverter to create a color conversion between two color spaces, and insertColorSpace which is called by KoColorSpaceRegistry each time a new color space is added to the registry.

This class is not part of public API, and can be changed without notice.

Definition at line 33 of file KoColorConversionSystem.h.

Constructor & Destructor Documentation

◆ KoColorConversionSystem()

KoColorConversionSystem::KoColorConversionSystem ( RegistryInterface * registryInterface)

Construct a Color Conversion System, leave to the KoColorSpaceRegistry to create it.

Definition at line 22 of file KoColorConversionSystem.cpp.

◆ ~KoColorConversionSystem()

KoColorConversionSystem::~KoColorConversionSystem ( )

Definition at line 27 of file KoColorConversionSystem.cpp.

28{
29 qDeleteAll(d->graph);
30 qDeleteAll(d->vertexes);
31 delete d;
32}

References d.

Member Function Documentation

◆ bestPathToDot()

QString KoColorConversionSystem::bestPathToDot ( const QString & srcKey,
const QString & dstKey ) const

This function return a text that can be compiled using dot to display the graph of color conversion connection, with a red link to show the path of the best color conversion.

Definition at line 445 of file KoColorConversionSystem.cpp.

446{
447 const Node* srcNode = 0;
448 const Node* dstNode = 0;
449 Q_FOREACH (Node* node, d->graph) {
450 if (node->id() == srcKey) {
451 srcNode = node;
452 }
453 if (node->id() == dstKey) {
454 dstNode = node;
455 }
456 }
457 Path p = findBestPath(srcNode, dstNode);
458 Q_ASSERT(!p.isEmpty());
459 QString dot = "digraph CCS {\n" +
460 QString(" \"%1\" [color=red]\n").arg(srcNode->id()) +
461 QString(" \"%1\" [color=red]\n").arg(dstNode->id());
462 Q_FOREACH (Vertex* oV, d->vertexes) {
463 QString options;
464 if (p.vertexes.contains(oV)) {
465 options = "[color=red]";
466 }
467 dot += vertexToDot(oV, options) ;
468 }
469 dot += "}\n";
470 return dot;
471}
const Params2D p
Path findBestPath(const QString &srcModelId, const QString &srcDepthId, const QString &srcProfileName, const QString &dstModelId, const QString &dstDepthId, const QString &dstProfileName) const
QString vertexToDot(Vertex *v, const QString &options) const
Definition Node.h:24

References d, findBestPath(), KoColorConversionSystem::Node::id(), p, and vertexToDot().

◆ connectToEngine()

void KoColorConversionSystem::connectToEngine ( Node * _node,
Node * _engine )
private

Initialise a node for ICC color spaces

Definition at line 34 of file KoColorConversionSystem.cpp.

35{
36 Vertex* v1 = createVertex(_node, _engine);
37 Vertex* v2 = createVertex(_engine, _node);
38
39 Q_UNUSED(v1);
40 Q_UNUSED(v2);
41}
Vertex * createVertex(Node *srcNode, Node *dstNode)

References createVertex().

◆ createColorConverter()

KoColorConversionTransformation * KoColorConversionSystem::createColorConverter ( const KoColorSpace * srcColorSpace,
const KoColorSpace * dstColorSpace,
KoColorConversionTransformation::Intent renderingIntent,
KoColorConversionTransformation::ConversionFlags conversionFlags ) const

This function is called by the color space to create a color conversion between two color space. This function search in the graph of transformations the best possible path between the two color space.

Definition at line 265 of file KoColorConversionSystem.cpp.

266{
267 Q_ASSERT(srcColorSpace);
268 Q_ASSERT(dstColorSpace);
269 if (*srcColorSpace == *dstColorSpace) {
270 return new KoCopyColorConversionTransformation(srcColorSpace);
271 }
272 dbgPigmentCCS << srcColorSpace->id() << (srcColorSpace->profile() ? srcColorSpace->profile()->name() : "default");
273 dbgPigmentCCS << dstColorSpace->id() << (dstColorSpace->profile() ? dstColorSpace->profile()->name() : "default");
274 Path path = findBestPath(
275 nodeFor(srcColorSpace),
276 nodeFor(dstColorSpace));
277 Q_ASSERT(path.length() > 0);
278 KoColorConversionTransformation* transfo = createTransformationFromPath(path, srcColorSpace, dstColorSpace, renderingIntent, conversionFlags);
279 Q_ASSERT(transfo);
280 Q_ASSERT(*transfo->srcColorSpace() == *srcColorSpace);
281 Q_ASSERT(*transfo->dstColorSpace() == *dstColorSpace);
282 return transfo;
283}
#define dbgPigmentCCS
KoColorConversionTransformation * createTransformationFromPath(const KoColorConversionSystem::Path &path, const KoColorSpace *srcColorSpace, const KoColorSpace *dstColorSpace, KoColorConversionTransformation::Intent renderingIntent, KoColorConversionTransformation::ConversionFlags conversionFlags) const
const Node * nodeFor(const KoColorSpace *) const
virtual const KoColorProfile * profile() const =0

References createTransformationFromPath(), dbgPigmentCCS, KoColorConversionTransformation::dstColorSpace, findBestPath(), KoColorSpace::id, KoColorProfile::name, nodeFor(), KoColorSpace::profile(), and KoColorConversionTransformation::srcColorSpace.

◆ createColorConverters()

void KoColorConversionSystem::createColorConverters ( const KoColorSpace * colorSpace,
const QList< QPair< KoID, KoID > > & possibilities,
KoColorConversionTransformation *& fromCS,
KoColorConversionTransformation *& toCS ) const

This function creates two transformations, one from the color space and one to the color space. The destination color space is picked from a list of color space, such as the conversion between the two color space is of the best quality.

The typical use case of this function is for KoColorTransformationFactory which doesn't support all color spaces, so unsupported color space have to find an acceptable conversion in order to use that KoColorTransformationFactory.

Parameters
colorSpacethe source color space
possibilitiesa list of color space among which we need to find the best conversion
fromCSthe conversion from the source color space will be affected to this variable
toCSthe revert conversion to the source color space will be affected to this variable

Definition at line 285 of file KoColorConversionSystem.cpp.

286{
287 // TODO This function currently only select the best conversion only based on the transformation
288 // from colorSpace to one of the color spaces in the list, but not the other way around
289 // it might be worth to look also the return path.
290 const Node* csNode = nodeFor(colorSpace);
291 PathQualityChecker pQC(csNode->referenceDepth);
292 // Look for a color conversion
293 Path bestPath;
294 typedef QPair<KoID, KoID> KoID2KoID;
295 Q_FOREACH (const KoID2KoID & possibility, possibilities) {
296 const KoColorSpaceFactory* csf = d->registryInterface->colorSpaceFactory(possibility.first.id(), possibility.second.id());
297 if (csf) {
298 Path path = findBestPath(csNode, nodeFor(csf->colorModelId().id(), csf->colorDepthId().id(), csf->defaultProfile()));
299 Q_ASSERT(path.length() > 0);
300 path.isGood = pQC.isGoodPath(path);
301
302 if (bestPath.isEmpty()) {
303 bestPath = path;
304 } else if ((!bestPath.isGood && path.isGood) || pQC.lessWorseThan(path, bestPath)) {
305 bestPath = path;
306 }
307 }
308 }
309 Q_ASSERT(!bestPath.isEmpty());
310 const KoColorSpace* endColorSpace = defaultColorSpaceForNode(bestPath.endNode());
312 Path returnPath = findBestPath(bestPath.endNode(), csNode);
313 Q_ASSERT(!returnPath.isEmpty());
315 Q_ASSERT(*toCS->dstColorSpace() == *fromCS->srcColorSpace());
316 Q_ASSERT(*fromCS->dstColorSpace() == *toCS->srcColorSpace());
317}
const KoColorSpace * defaultColorSpaceForNode(const Node *node) const
QString id() const
Definition KoID.cpp:63
virtual KoID colorDepthId() const =0
virtual QString defaultProfile() const =0
virtual KoID colorModelId() const =0

References KoColorSpaceFactory::colorDepthId(), KoColorSpaceFactory::colorModelId(), createTransformationFromPath(), d, defaultColorSpaceForNode(), KoColorSpaceFactory::defaultProfile(), KoColorConversionTransformation::dstColorSpace, KoColorConversionSystem::Path::endNode(), findBestPath(), KoID::id(), KoColorConversionTransformation::internalConversionFlags(), KoColorConversionTransformation::internalRenderingIntent(), KoColorConversionSystem::Path::isEmpty(), KoColorConversionSystem::Path::isGood, PathQualityChecker::isGoodPath(), PathQualityChecker::lessWorseThan(), nodeFor(), KoColorConversionSystem::Node::referenceDepth, and KoColorConversionTransformation::srcColorSpace.

◆ createNode()

KoColorConversionSystem::Node * KoColorConversionSystem::createNode ( const QString & _modelId,
const QString & _depthId,
const QString & _profileName )
private

Create a new node

Definition at line 210 of file KoColorConversionSystem.cpp.

211{
212 Node* n = new Node;
213 n->modelId = _modelId;
214 n->depthId = _depthId;
215 n->profileName = _profileName;
216 d->graph.insert(NodeKey(_modelId, _depthId, _profileName), n);
217 return n;
218}

References d, KoColorConversionSystem::Node::depthId, KoColorConversionSystem::Node::modelId, and KoColorConversionSystem::Node::profileName.

◆ createTransformationFromPath()

KoColorConversionTransformation * KoColorConversionSystem::createTransformationFromPath ( const KoColorConversionSystem::Path & path,
const KoColorSpace * srcColorSpace,
const KoColorSpace * dstColorSpace,
KoColorConversionTransformation::Intent renderingIntent,
KoColorConversionTransformation::ConversionFlags conversionFlags ) const
private

Definition at line 319 of file KoColorConversionSystem.cpp.

320{
321 Q_ASSERT(srcColorSpace->colorModelId().id() == path.startNode()->modelId);
322 Q_ASSERT(srcColorSpace->colorDepthId().id() == path.startNode()->depthId);
323 Q_ASSERT(dstColorSpace->colorModelId().id() == path.endNode()->modelId);
324 Q_ASSERT(dstColorSpace->colorDepthId().id() == path.endNode()->depthId);
325
327
328 const QList< Path::node2factory > pathOfNode = path.compressedPath();
329
330 if (pathOfNode.size() == 2) { // Direct connection
331 transfo = pathOfNode[1].second->createColorTransformation(srcColorSpace, dstColorSpace, renderingIntent, conversionFlags);
332 }
333 else {
334
335 KoMultipleColorConversionTransformation* mccTransfo = new KoMultipleColorConversionTransformation(srcColorSpace, dstColorSpace, renderingIntent, conversionFlags);
336
337 transfo = mccTransfo;
338
339 // Get the first intermediary color space
340 dbgPigmentCCS << pathOfNode[ 0 ].first->id() << " to " << pathOfNode[ 1 ].first->id();
341
342 const KoColorSpace* intermCS =
343 defaultColorSpaceForNode(pathOfNode[1].first);
344
345 mccTransfo->appendTransfo(pathOfNode[1].second->createColorTransformation(srcColorSpace, intermCS, renderingIntent, conversionFlags));
346
347 for (int i = 2; i < pathOfNode.size() - 1; i++) {
348 dbgPigmentCCS << pathOfNode[ i - 1 ].first->id() << " to " << pathOfNode[ i ].first->id();
349 const KoColorSpace* intermCS2 = defaultColorSpaceForNode(pathOfNode[i].first);
350 Q_ASSERT(intermCS2);
351 mccTransfo->appendTransfo(pathOfNode[i].second->createColorTransformation(intermCS, intermCS2, renderingIntent, conversionFlags));
352 intermCS = intermCS2;
353 }
354
355 dbgPigmentCCS << pathOfNode[ pathOfNode.size() - 2 ].first->id() << " to " << pathOfNode[ pathOfNode.size() - 1 ].first->id();
356 mccTransfo->appendTransfo(pathOfNode.last().second->createColorTransformation(intermCS, dstColorSpace, renderingIntent, conversionFlags));
357 }
358 return transfo;
359}
virtual KoID colorModelId() const =0
virtual KoID colorDepthId() const =0
void appendTransfo(KoColorConversionTransformation *transfo)

References KoMultipleColorConversionTransformation::appendTransfo(), KoColorSpace::colorDepthId(), KoColorSpace::colorModelId(), dbgPigmentCCS, defaultColorSpaceForNode(), and KoID::id().

◆ createVertex()

KoColorConversionSystem::Vertex * KoColorConversionSystem::createVertex ( Node * srcNode,
Node * dstNode )
private

create a vertex between two nodes and return it.

Definition at line 372 of file KoColorConversionSystem.cpp.

373{
374 Vertex* v = new Vertex(srcNode, dstNode);
375 srcNode->outputVertexes.append(v);
376 d->vertexes.append(v);
377 return v;
378}
qreal v

References d, KoColorConversionSystem::Node::outputVertexes, and v.

◆ defaultColorSpaceForNode()

const KoColorSpace * KoColorConversionSystem::defaultColorSpaceForNode ( const Node * node) const
private

Query the registry to get the color space associated with this node. (default profile)

Definition at line 205 of file KoColorConversionSystem.cpp.

206{
207 return d->registryInterface->colorSpace(node->modelId, node->depthId, node->profileName);
208}

References d, KoColorConversionSystem::Node::depthId, KoColorConversionSystem::Node::modelId, and KoColorConversionSystem::Node::profileName.

◆ deletePaths()

void KoColorConversionSystem::deletePaths ( QList< KoColorConversionSystem::Path * > paths) const
private

Delete all the paths of the list given in argument.

◆ existsGoodPath()

bool KoColorConversionSystem::existsGoodPath ( const QString & srcModelId,
const QString & srcDepthId,
const QString & srcProfileName,
const QString & dstModelId,
const QString & dstDepthId,
const QString & dstProfileName ) const
Returns
true if there is a good path between two color spaces

Definition at line 410 of file KoColorConversionSystem.cpp.

411{
412 const Node* srcNode = nodeFor(srcModelId, srcDepthId, srcProfileName);
413 const Node* dstNode = nodeFor(dstModelId, dstDepthId, dstProfileName);
414 if (srcNode == dstNode) return true;
415 if (!srcNode) return false;
416 if (!dstNode) return false;
417 Path path = findBestPath(srcNode, dstNode);
418 bool existAndGood = path.isGood;
419 return existAndGood;
420}

References findBestPath(), and nodeFor().

◆ existsPath()

bool KoColorConversionSystem::existsPath ( const QString & srcModelId,
const QString & srcDepthId,
const QString & srcProfileName,
const QString & dstModelId,
const QString & dstDepthId,
const QString & dstProfileName ) const
Returns
true if there is a path between two color spaces

Definition at line 397 of file KoColorConversionSystem.cpp.

398{
399 dbgPigmentCCS << "srcModelId = " << srcModelId << " srcDepthId = " << srcDepthId << " srcProfileName = " << srcProfileName << " dstModelId = " << dstModelId << " dstDepthId = " << dstDepthId << " dstProfileName = " << dstProfileName;
400 const Node* srcNode = nodeFor(srcModelId, srcDepthId, srcProfileName);
401 const Node* dstNode = nodeFor(dstModelId, dstDepthId, dstProfileName);
402 if (srcNode == dstNode) return true;
403 if (!srcNode) return false;
404 if (!dstNode) return false;
405 Path path = findBestPath(srcNode, dstNode);
406 bool exist = !path.isEmpty();
407 return exist;
408}

References dbgPigmentCCS, findBestPath(), and nodeFor().

◆ findBestPath() [1/3]

KoColorConversionSystem::Path KoColorConversionSystem::findBestPath ( const Node * srcNode,
const Node * dstNode ) const
private

looks for the best path between two nodes

Definition at line 473 of file KoColorConversionSystem.cpp.

474{
475 KIS_ASSERT(srcNode);
476 KIS_ASSERT(dstNode);
477
478 dbgPigmentCCS << "Find best path between " << srcNode->id() << " and " << dstNode->id();
479
480 PathQualityChecker pQC(qMin(srcNode->referenceDepth, dstNode->referenceDepth));
481 Node2PathHash node2path; // current best path to reach a given node
482 QList<Path> possiblePaths; // list of all paths
483 // Generate the initial list of paths
484 Q_FOREACH (Vertex* v, srcNode->outputVertexes) {
485 if (v->dstNode->isInitialized) {
486 Path p;
487 p.appendVertex(v);
488 Node* endNode = v->dstNode;
489 if (endNode == dstNode) {
490 Q_ASSERT(pQC.isGoodPath(p)); // <- it's a direct link, it has to be a good path
491 p.isGood = true;
492 return p;
493 } else {
494 //Q_ASSERT(!node2path.contains(endNode)); // That would be a total fuck up if there are two vertices between two nodes
495 node2path.insert(endNode, p);
496 possiblePaths.append(p);
497 }
498 }
499 }
500
501 Path currentBestPath;
502 // Continue while there are any possibilities remaining
503 while (possiblePaths.size() > 0) {
504
505 // Loop through all paths and explore one step further
506 const QList<Path> currentPaths = possiblePaths;
507 for (const Path &p : currentPaths) {
508 const Node* endNode = p.endNode();
509 for (Vertex* v : endNode->outputVertexes) {
510 if (v->dstNode->isInitialized && !p.contains(v->dstNode)) {
511 Path newP = p; // Candidate
512 newP.appendVertex(v);
513 Node* newEndNode = v->dstNode;
514 if (newEndNode == dstNode) {
515 if (pQC.isGoodPath(newP)) { // Victory
516 newP.isGood = true;
517 return newP;
518 } else if (pQC.lessWorseThan(newP, currentBestPath)) {
519 if (newP.startNode() && newP.endNode() && currentBestPath.startNode() && currentBestPath.endNode()) {
520 Q_ASSERT(newP.startNode()->id() == currentBestPath.startNode()->id());
521 Q_ASSERT(newP.endNode()->id() == currentBestPath.endNode()->id());
522 // Can we do better than dumping memory values???
523 // warnPigment << pQC.lessWorseThan(newP, currentBestPath) << " " << newP << " " << currentBestPath;
524 currentBestPath = newP;
525 }
526 }
527 } else {
528 // This is an incomplete path. Check if there's a better way to get to its endpoint.
529 Node2PathHash::Iterator it = node2path.find(newEndNode);
530 if (it != node2path.end()) {
531 Path &p2 = it.value();
532 if (pQC.lessWorseThan(newP, p2)) {
533 p2 = newP;
534 possiblePaths.append(newP);
535 }
536 } else {
537 node2path.insert(newEndNode, newP);
538 possiblePaths.append(newP);
539 }
540 }
541 }
542 }
543 possiblePaths.removeAll(p); // Remove from list of remaining paths
544 }
545 }
546
547 if (!currentBestPath.isEmpty()) {
548 warnPigment << "No good path from " << srcNode->id() << " to " << dstNode->id() << " found : length = " << currentBestPath.length() << " cost = " << currentBestPath.cost << " referenceDepth = " << currentBestPath.referenceDepth << " respectColorCorrectness = " << " isGood = " << currentBestPath.isGood ;
549 return currentBestPath;
550 }
551 errorPigment << "No path from " << srcNode->id() << " to " << dstNode->id() << " found not ";
552 return currentBestPath;
553}
#define warnPigment
#define errorPigment
QPointF p2
QHash< KoColorConversionSystem::Node *, KoColorConversionSystem::Path > Node2PathHash
#define KIS_ASSERT(cond)
Definition kis_assert.h:33

References KoColorConversionSystem::Path::appendVertex(), KoColorConversionSystem::Path::cost, dbgPigmentCCS, KoColorConversionSystem::Path::endNode(), errorPigment, KoColorConversionSystem::Node::id(), KoColorConversionSystem::Path::isEmpty(), KoColorConversionSystem::Path::isGood, PathQualityChecker::isGoodPath(), KIS_ASSERT, KoColorConversionSystem::Path::length(), PathQualityChecker::lessWorseThan(), KoColorConversionSystem::Node::outputVertexes, p, p2, KoColorConversionSystem::Node::referenceDepth, KoColorConversionSystem::Path::referenceDepth, KoColorConversionSystem::Path::startNode(), v, and warnPigment.

◆ findBestPath() [2/3]

KoColorConversionSystem::Path KoColorConversionSystem::findBestPath ( const NodeKey & src,
const NodeKey & dst ) const
Returns
the best path for the specified color spaces. Used for testing purposes only

Definition at line 433 of file KoColorConversionSystem.cpp.

434{
435 const Node *srcNode = nodeFor(src);
436 const Node *dstNode = nodeFor(dst);
437
438 KIS_ASSERT(srcNode);
439 KIS_ASSERT(dstNode);
440
441 return findBestPath(srcNode, dstNode);
442}

References findBestPath(), KIS_ASSERT, and nodeFor().

◆ findBestPath() [3/3]

KoColorConversionSystem::Path KoColorConversionSystem::findBestPath ( const QString & srcModelId,
const QString & srcDepthId,
const QString & srcProfileName,
const QString & dstModelId,
const QString & dstDepthId,
const QString & dstProfileName ) const
Returns
the best path for the specified color spaces. Used for testing purposes only

Definition at line 422 of file KoColorConversionSystem.cpp.

423{
424 const Node *srcNode = nodeFor(srcModelId, srcDepthId, srcProfileName);
425 const Node *dstNode = nodeFor(dstModelId, dstDepthId, dstProfileName);
426
427 KIS_ASSERT(srcNode);
428 KIS_ASSERT(dstNode);
429
430 return findBestPath(srcNode, dstNode);
431}

References findBestPath(), KIS_ASSERT, and nodeFor().

◆ insertColorProfile()

void KoColorConversionSystem::insertColorProfile ( const KoColorProfile * profile)

Add a profile to the graph of transformation. The new node will be added for each known color space compatible with this profile.

Make sure you call requiredConnectionProfilesFor(profile) and add all the required connection profiles into the registry before inserting the actual profile profile. Otherwise the created node will not be able to connect itself into the graph (due to a missing connection point).

See also
requiredConnectionProfilesFor()

Definition at line 160 of file KoColorConversionSystem.cpp.

161{
162 dbgPigmentCCS << _profile->name();
163 const QList< const KoColorSpaceFactory* >& factories = d->registryInterface->colorSpacesFor(_profile);
164 Q_FOREACH (const KoColorSpaceFactory* factory, factories) {
165 QString modelId = factory->colorModelId().id();
166 QString depthId = factory->colorDepthId().id();
167 Node* n = nodeFor(modelId, depthId, _profile->name());
168 n->init(factory);
169 if (!factory->colorSpaceEngine().isEmpty()) {
171 Q_ASSERT(engine);
172 Node* engineNode = d->graph[ NodeKey(engine->id(), engine->id(), engine->id())];
173 Q_ASSERT(engineNode);
174
175 if (engine->supportsColorSpace(modelId, depthId, _profile)) {
176 connectToEngine(n, engineNode);
177 }
178 }
180 cctfs.append(factory->colorConversionLinksFromProfile(_profile));
181 Q_FOREACH (KoColorConversionTransformationFactory* cctf, cctfs) {
182 Node* srcNode = nodeFor(cctf->srcColorModelId(), cctf->srcColorDepthId(), cctf->srcProfile());
183 Q_ASSERT(srcNode);
184 Node* dstNode = nodeFor(cctf->dstColorModelId(), cctf->dstColorDepthId(), cctf->dstProfile());
185 Q_ASSERT(dstNode);
186 if (srcNode == n || dstNode == n) {
187 // Check if the two nodes are already connected
188 Vertex* v = vertexBetween(srcNode, dstNode);
189 // If the vertex doesn't already exist, then create it
190 if (!v) {
191 v = createVertex(srcNode, dstNode);
192 }
193 Q_ASSERT(v); // we should have one now
194 if (dstNode->modelId == modelId && dstNode->depthId == depthId) {
195 v->setFactoryFromDst(cctf);
196 }
197 if (srcNode->modelId == modelId && srcNode->depthId == depthId) {
198 v->setFactoryFromSrc(cctf);
199 }
200 }
201 }
202 }
203}
void connectToEngine(Node *_node, Node *_engine)
Vertex * vertexBetween(Node *srcNode, Node *dstNode)
static KoColorSpaceEngineRegistry * instance()
T get(const QString &id) const
virtual bool supportsColorSpace(const QString &colorModelId, const QString &colorDepthId, const KoColorProfile *profile) const
virtual QList< KoColorConversionTransformationFactory * > colorConversionLinks() const =0
virtual QList< KoColorConversionTransformationFactory * > colorConversionLinksFromProfile(const KoColorProfile *profile) const
colorConversionLinksFromProfile Sometimes, we need to generate special color conversion links based o...
virtual QString colorSpaceEngine() const =0

References KoColorSpaceFactory::colorConversionLinks(), KoColorSpaceFactory::colorConversionLinksFromProfile(), KoColorSpaceFactory::colorDepthId(), KoColorSpaceFactory::colorModelId(), KoColorSpaceFactory::colorSpaceEngine(), connectToEngine(), createVertex(), d, dbgPigmentCCS, KoColorConversionSystem::Node::depthId, KoColorConversionTransformationFactory::dstColorDepthId(), KoColorConversionTransformationFactory::dstColorModelId(), KoColorConversionTransformationFactory::dstProfile, KoGenericRegistry< T >::get(), KoID::id(), KoColorSpaceEngine::id, KoColorConversionSystem::Node::init(), KoColorSpaceEngineRegistry::instance(), KoColorConversionSystem::Node::modelId, KoColorProfile::name, nodeFor(), KoColorConversionTransformationFactory::srcColorDepthId(), KoColorConversionTransformationFactory::srcColorModelId(), KoColorConversionTransformationFactory::srcProfile, KoColorSpaceEngine::supportsColorSpace(), v, and vertexBetween().

◆ insertColorSpace()

void KoColorConversionSystem::insertColorSpace ( const KoColorSpaceFactory * csf)

Add a color space to a graph of transformation. The new node will be added for each known compatible profile.

Make sure you call requiredConnectionProfilesFor(csf) and add all the required connection profiles into the registry before inserting the actual color space csf. Otherwise the created node will not be able to connect itself into the graph (due to a missing connection point).

See also
requiredConnectionProfilesFor()

Definition at line 77 of file KoColorConversionSystem.cpp.

78{
79 dbgPigment << "Inserting color space " << csf->name() << " (" << csf->id() << ") Model: " << csf->colorModelId() << " Depth: " << csf->colorDepthId() << " into the CCS";
80 const QList<const KoColorProfile*> profiles = d->registryInterface->profilesFor(csf);
81 QString modelId = csf->colorModelId().id();
82 QString depthId = csf->colorDepthId().id();
84 if (profiles.isEmpty()) { // There is no profile for this CS, create a node without profile name if the color engine isn't icc-based
85 if (csf->colorSpaceEngine() != "icc") {
86 Node* n = nodeFor(modelId, depthId, "default");
87 n->init(csf);
88 }
89 else {
90 dbgPigment << "Cannot add node for " << csf->name() << ", since there are no profiles available";
91 }
92 } else {
93 // Initialise the nodes
94 Q_FOREACH (const KoColorProfile* profile, profiles) {
95 Node* n = nodeFor(modelId, depthId, profile->name());
96 cctfs.append(csf->colorConversionLinksFromProfile(profile));
97 n->init(csf);
98 if (!csf->colorSpaceEngine().isEmpty()) {
100 Q_ASSERT(engine);
101 NodeKey engineKey(engine->id(), engine->id(), engine->id());
102 Node* engineNode = 0;
103 QHash<NodeKey, Node*>::ConstIterator it = d->graph.constFind(engineKey);
104 if (it != d->graph.constEnd()) {
105 engineNode = it.value();
106 } else {
107 engineNode = insertEngine(engine);
108 }
109
110 if (engine->supportsColorSpace(modelId, depthId, profile)) {
111 connectToEngine(n, engineNode);
112 }
113 }
114 }
115 }
116 // Construct a link for "custom" transformation
117 cctfs.append(csf->colorConversionLinks());
118 Q_FOREACH (KoColorConversionTransformationFactory* cctf, cctfs) {
119 Node* srcNode = nodeFor(cctf->srcColorModelId(), cctf->srcColorDepthId(), cctf->srcProfile());
120 Q_ASSERT(srcNode);
121 Node* dstNode = nodeFor(cctf->dstColorModelId(), cctf->dstColorDepthId(), cctf->dstProfile());
122 Q_ASSERT(dstNode);
123 // Check if the two nodes are already connected
124 Vertex* v = vertexBetween(srcNode, dstNode);
125 // If the vertex doesn't already exist, then create it
126 if (!v) {
127 v = createVertex(srcNode, dstNode);
128 }
129 Q_ASSERT(v); // we should have one now
130 if (dstNode->modelId == modelId && dstNode->depthId == depthId) {
131 v->setFactoryFromDst(cctf);
132 }
133 if (srcNode->modelId == modelId && srcNode->depthId == depthId) {
134 v->setFactoryFromSrc(cctf);
135 }
136 }
137}
#define dbgPigment
Node * insertEngine(const KoColorSpaceEngine *engine)
virtual QString name() const =0
virtual QString id() const =0

References KoColorSpaceFactory::colorConversionLinks(), KoColorSpaceFactory::colorConversionLinksFromProfile(), KoColorSpaceFactory::colorDepthId(), KoColorSpaceFactory::colorModelId(), KoColorSpaceFactory::colorSpaceEngine(), connectToEngine(), createVertex(), d, dbgPigment, KoColorConversionSystem::Node::depthId, KoColorConversionTransformationFactory::dstColorDepthId(), KoColorConversionTransformationFactory::dstColorModelId(), KoColorConversionTransformationFactory::dstProfile, KoGenericRegistry< T >::get(), KoID::id(), KoColorSpaceEngine::id, KoColorSpaceFactory::id(), KoColorConversionSystem::Node::init(), insertEngine(), KoColorSpaceEngineRegistry::instance(), KoColorConversionSystem::Node::modelId, KoColorProfile::name, KoColorSpaceFactory::name(), nodeFor(), KoColorConversionTransformationFactory::srcColorDepthId(), KoColorConversionTransformationFactory::srcColorModelId(), KoColorConversionTransformationFactory::srcProfile, KoColorSpaceEngine::supportsColorSpace(), v, and vertexBetween().

◆ insertEngine()

KoColorConversionSystem::Node * KoColorConversionSystem::insertEngine ( const KoColorSpaceEngine * engine)
private

Insert an engine.

Definition at line 43 of file KoColorConversionSystem.cpp.

44{
45 NodeKey key(engine->id(), engine->id(), engine->id());
46 Node* n = new Node;
47 n->modelId = engine->id();
48 n->depthId = engine->id();
49 n->profileName = engine->id();
50 n->referenceDepth = 64; // engine don't have reference depth,
51 d->graph.insert(key, n);
52 n->init(engine);
53 return n;
54}

References d, KoColorConversionSystem::Node::depthId, KoColorSpaceEngine::id, KoColorConversionSystem::Node::init(), KoColorConversionSystem::Node::modelId, KoColorConversionSystem::Node::profileName, and KoColorConversionSystem::Node::referenceDepth.

◆ nodeFor() [1/5]

const KoColorConversionSystem::Node * KoColorConversionSystem::nodeFor ( const KoColorSpace * _colorSpace) const
private

Definition at line 220 of file KoColorConversionSystem.cpp.

221{
222 const KoColorProfile* profile = _colorSpace->profile();
223 return nodeFor(_colorSpace->colorModelId().id(), _colorSpace->colorDepthId().id(),
224 profile ? profile->name() : "default");
225}

References KoColorSpace::colorDepthId(), KoColorSpace::colorModelId(), KoID::id(), KoColorProfile::name, nodeFor(), and KoColorSpace::profile().

◆ nodeFor() [2/5]

KoColorConversionSystem::Node * KoColorConversionSystem::nodeFor ( const NodeKey & key)
private
Returns
the node corresponding to that key, or create it if needed

Definition at line 244 of file KoColorConversionSystem.cpp.

245{
246 QHash<NodeKey, Node*>::ConstIterator it = d->graph.constFind(key);
247 if (it != d->graph.constEnd()) {
248 return it.value();
249 } else {
250 return createNode(key.modelId, key.depthId, key.profileName);
251 }
252}
Node * createNode(const QString &_modelId, const QString &_depthId, const QString &_profileName)

References createNode(), d, KoColorConversionSystem::NodeKey::depthId, KoColorConversionSystem::NodeKey::modelId, and KoColorConversionSystem::NodeKey::profileName.

◆ nodeFor() [3/5]

const KoColorConversionSystem::Node * KoColorConversionSystem::nodeFor ( const NodeKey & key) const
private

Definition at line 233 of file KoColorConversionSystem.cpp.

234{
235 dbgPigmentCCS << "Look for node: " << key.modelId << " " << key.depthId << " " << key.profileName << " " << d->graph.value(key);
236 return d->graph.value(key);
237}

References d, dbgPigmentCCS, KoColorConversionSystem::NodeKey::depthId, KoColorConversionSystem::NodeKey::modelId, and KoColorConversionSystem::NodeKey::profileName.

◆ nodeFor() [4/5]

KoColorConversionSystem::Node * KoColorConversionSystem::nodeFor ( const QString & colorModelId,
const QString & colorDepthId,
const QString & _profileName )
private
Returns
the node associated with that key, and create it if needed

Definition at line 239 of file KoColorConversionSystem.cpp.

240{
241 return nodeFor(NodeKey(_colorModelId, _colorDepthId, _profileName));
242}

References nodeFor().

◆ nodeFor() [5/5]

const KoColorConversionSystem::Node * KoColorConversionSystem::nodeFor ( const QString & colorModelId,
const QString & colorDepthId,
const QString & _profileName ) const
private

Definition at line 227 of file KoColorConversionSystem.cpp.

228{
229 dbgPigmentCCS << "Look for node: " << _colorModelId << " " << _colorDepthId << " " << _profileName;
230 return nodeFor(NodeKey(_colorModelId, _colorDepthId, _profileName));
231}

References dbgPigmentCCS, and nodeFor().

◆ nodesFor()

QList< KoColorConversionSystem::Node * > KoColorConversionSystem::nodesFor ( const QString & _modelId,
const QString & _depthId )
private
Returns
the list of nodes that correspond to a given model and depth.

Definition at line 254 of file KoColorConversionSystem.cpp.

255{
256 QList<Node*> nodes;
257 Q_FOREACH (Node* node, d->graph) {
258 if (node->modelId == _modelId && node->depthId == _depthId) {
259 nodes << node;
260 }
261 }
262 return nodes;
263}

References d, KoColorConversionSystem::Node::depthId, and KoColorConversionSystem::Node::modelId.

◆ Private()

KoColorConversionSystem::Private ( RegistryInterface * _registryInterface)
inline

Definition at line 326 of file KoColorConversionSystem_p.h.

326: registryInterface(_registryInterface) {}

◆ requiredConnectionProfilesFor() [1/2]

QList< KoColorProfileQuery > KoColorConversionSystem::requiredConnectionProfilesFor ( const KoColorProfile * profile)
Returns
a list of connection profiles required for this profile

Some color space nodes may require custom profiles to be connected to the color conversion system. I.e. Display P3 PQ space will require a Display P3 Linear profile to connect itself to the color conversion system through.

This function returns a list of such connection profiles.

Connection profiles should be requested and added to the registry before adding the profile profile into the color conversion system with insertColorProfile(csf).

Definition at line 139 of file KoColorConversionSystem.cpp.

140{
141 QList<KoColorProfileQuery> profileQueries;
142
143 const QList< const KoColorSpaceFactory* >& factories = d->registryInterface->colorSpacesFor(profile);
144 Q_FOREACH (const KoColorSpaceFactory* factory, factories) {
145 profileQueries.append(factory->requiredConnectionProfiles(profile));
146 }
147
148 // TODO: make a better 'unique' function without sorting
149 QList<KoColorProfileQuery> uniqueProfileQueries;
150 std::copy_if(profileQueries.begin(),
151 profileQueries.end(),
152 std::back_inserter(uniqueProfileQueries),
153 [&](const KoColorProfileQuery &query) {
154 return !uniqueProfileQueries.contains(query);
155 });
156
157 return uniqueProfileQueries;
158}
The KoColorProfileQuery struct.
virtual QList< KoColorProfileQuery > requiredConnectionProfiles(const KoColorProfile *profile) const

References d, and KoColorSpaceFactory::requiredConnectionProfiles().

◆ requiredConnectionProfilesFor() [2/2]

QList< KoColorProfileQuery > KoColorConversionSystem::requiredConnectionProfilesFor ( const KoColorSpaceFactory * csf)
Returns
a list of connection profiles required for this color space

Some color space nodes may require custom profiles to be connected to the color conversion system. I.e. Display P3 PQ space will require a Display P3 Linear profile to connect itself to the color conversion system through.

This function returns a list of such connection profiles.

Connection profiles should be requested and added to the registry before adding the color space csf into the color conversion system with insertColorSpace(csf).

Definition at line 56 of file KoColorConversionSystem.cpp.

57{
58 QList<KoColorProfileQuery> profileQueries;
59
60 const QList<const KoColorProfile*> existingProfiles = d->registryInterface->profilesFor(csf);
61 Q_FOREACH (const KoColorProfile* profile, existingProfiles) {
62 profileQueries.append(csf->requiredConnectionProfiles(profile));
63 }
64
65 // TODO: make a better 'unique' function without sorting
66 QList<KoColorProfileQuery> uniqueProfileQueries;
67 std::copy_if(profileQueries.begin(),
68 profileQueries.end(),
69 std::back_inserter(uniqueProfileQueries),
70 [&](const KoColorProfileQuery &query) {
71 return !uniqueProfileQueries.contains(query);
72 });
73
74 return uniqueProfileQueries;
75}

References d, and KoColorSpaceFactory::requiredConnectionProfiles().

◆ toDot()

QString KoColorConversionSystem::toDot ( ) const

This function return a text that can be compiled using dot to display the graph of color conversion connection.

Definition at line 387 of file KoColorConversionSystem.cpp.

388{
389 QString dot = "digraph CCS {\n";
390 Q_FOREACH (Vertex* oV, d->vertexes) {
391 dot += vertexToDot(oV, "default") ;
392 }
393 dot += "}\n";
394 return dot;
395}

References d, and vertexToDot().

◆ vertexBetween()

KoColorConversionSystem::Vertex * KoColorConversionSystem::vertexBetween ( KoColorConversionSystem::Node * srcNode,
KoColorConversionSystem::Node * dstNode )
private
Returns
the vertex between two nodes, or null if the vertex doesn't exist

Definition at line 362 of file KoColorConversionSystem.cpp.

363{
364 Q_FOREACH (Vertex* oV, srcNode->outputVertexes) {
365 if (oV->dstNode == dstNode) {
366 return oV;
367 }
368 }
369 return 0;
370}

References KoColorConversionSystem::Vertex::dstNode, and KoColorConversionSystem::Node::outputVertexes.

◆ vertexToDot()

QString KoColorConversionSystem::vertexToDot ( KoColorConversionSystem::Vertex * v,
const QString & options ) const
private

Definition at line 382 of file KoColorConversionSystem.cpp.

383{
384 return QString(" \"%1\" -> \"%2\" %3\n").arg(v->srcNode->id()).arg(v->dstNode->id()).arg(options);
385}

References v.

Friends And Related Symbol Documentation

◆ qHash

uint qHash ( const KoColorConversionSystem::NodeKey & key)
friend

Definition at line 319 of file KoColorConversionSystem_p.h.

320{
321 return qHash(key.modelId) + qHash(key.depthId);
322}
friend uint qHash(const KoColorConversionSystem::NodeKey &key)

Member Data Documentation

◆ d

Private* const KoColorConversionSystem::d
private

Definition at line 231 of file KoColorConversionSystem.h.

◆ graph

QHash<NodeKey, Node*> KoColorConversionSystem::graph

Definition at line 328 of file KoColorConversionSystem_p.h.

◆ registryInterface

RegistryInterface* KoColorConversionSystem::registryInterface

Definition at line 330 of file KoColorConversionSystem_p.h.

◆ vertexes

QList<Vertex*> KoColorConversionSystem::vertexes

Definition at line 329 of file KoColorConversionSystem_p.h.


The documentation for this struct was generated from the following files: