22 : d(new
Private(registryInterface))
29 qDeleteAll(
d->vertexes);
50 d->graph.insert(key, n);
62 if (profiles.isEmpty()) {
68 dbgPigment <<
"Cannot add node for " << csf->
name() <<
", since there are no profiles available";
80 QHash<NodeKey, Node*>::ConstIterator it =
d->graph.constFind(engineKey);
81 if (it !=
d->graph.constEnd()) {
82 engineNode = it.value();
108 v->setFactoryFromDst(cctf);
111 v->setFactoryFromSrc(cctf);
129 Q_ASSERT(engineNode);
141 if (srcNode == n || dstNode == n) {
150 v->setFactoryFromDst(cctf);
153 v->setFactoryFromSrc(cctf);
171 d->graph.insert(
NodeKey(_modelId, _depthId, _profileName), n);
179 profile ? profile->
name() :
"default");
184 dbgPigmentCCS <<
"Look for node: " << _colorModelId <<
" " << _colorDepthId <<
" " << _profileName;
185 return nodeFor(
NodeKey(_colorModelId, _colorDepthId, _profileName));
191 return d->graph.value(key);
196 return nodeFor(
NodeKey(_colorModelId, _colorDepthId, _profileName));
201 QHash<NodeKey, Node*>::ConstIterator it =
d->graph.constFind(key);
202 if (it !=
d->graph.constEnd()) {
212 Q_FOREACH (
Node* node,
d->graph) {
222 Q_ASSERT(srcColorSpace);
223 Q_ASSERT(dstColorSpace);
224 if (*srcColorSpace == *dstColorSpace) {
232 Q_ASSERT(path.length() > 0);
249 typedef QPair<KoID, KoID> KoID2KoID;
250 Q_FOREACH (
const KoID2KoID & possibility, possibilities) {
251 const KoColorSpaceFactory* csf =
d->registryInterface->colorSpaceFactory(possibility.first.id(), possibility.second.id());
254 Q_ASSERT(path.length() > 0);
268 Q_ASSERT(!returnPath.
isEmpty());
276 Q_ASSERT(srcColorSpace->
colorModelId().
id() == path.startNode()->modelId);
277 Q_ASSERT(srcColorSpace->
colorDepthId().
id() == path.startNode()->depthId);
278 Q_ASSERT(dstColorSpace->
colorModelId().
id() == path.endNode()->modelId);
279 Q_ASSERT(dstColorSpace->
colorDepthId().
id() == path.endNode()->depthId);
285 if (pathOfNode.size() == 2) {
286 transfo = pathOfNode[1].second->createColorTransformation(srcColorSpace, dstColorSpace, renderingIntent, conversionFlags);
292 transfo = mccTransfo;
295 dbgPigmentCCS << pathOfNode[ 0 ].first->id() <<
" to " << pathOfNode[ 1 ].first->id();
300 mccTransfo->
appendTransfo(pathOfNode[1].second->createColorTransformation(srcColorSpace, intermCS, renderingIntent, conversionFlags));
302 for (
int i = 2; i < pathOfNode.size() - 1; i++) {
303 dbgPigmentCCS << pathOfNode[ i - 1 ].first->id() <<
" to " << pathOfNode[ i ].first->id();
306 mccTransfo->
appendTransfo(pathOfNode[i].second->createColorTransformation(intermCS, intermCS2, renderingIntent, conversionFlags));
307 intermCS = intermCS2;
310 dbgPigmentCCS << pathOfNode[ pathOfNode.size() - 2 ].first->id() <<
" to " << pathOfNode[ pathOfNode.size() - 1 ].first->id();
311 mccTransfo->
appendTransfo(pathOfNode.last().second->createColorTransformation(intermCS, dstColorSpace, renderingIntent, conversionFlags));
331 d->vertexes.append(
v);
339 return QString(
" \"%1\" -> \"%2\" %3\n").arg(
v->srcNode->id()).arg(
v->dstNode->id()).arg(options);
344 QString dot =
"digraph CCS {\n";
345 Q_FOREACH (
Vertex* oV,
d->vertexes) {
352bool KoColorConversionSystem::existsPath(
const QString& srcModelId,
const QString& srcDepthId,
const QString& srcProfileName,
const QString& dstModelId,
const QString& dstDepthId,
const QString& dstProfileName)
const
354 dbgPigmentCCS <<
"srcModelId = " << srcModelId <<
" srcDepthId = " << srcDepthId <<
" srcProfileName = " << srcProfileName <<
" dstModelId = " << dstModelId <<
" dstDepthId = " << dstDepthId <<
" dstProfileName = " << dstProfileName;
355 const Node* srcNode =
nodeFor(srcModelId, srcDepthId, srcProfileName);
356 const Node* dstNode =
nodeFor(dstModelId, dstDepthId, dstProfileName);
357 if (srcNode == dstNode)
return true;
358 if (!srcNode)
return false;
359 if (!dstNode)
return false;
361 bool exist = !path.isEmpty();
365bool KoColorConversionSystem::existsGoodPath(
const QString& srcModelId,
const QString& srcDepthId,
const QString& srcProfileName,
const QString& dstModelId,
const QString& dstDepthId,
const QString& dstProfileName)
const
367 const Node* srcNode =
nodeFor(srcModelId, srcDepthId, srcProfileName);
368 const Node* dstNode =
nodeFor(dstModelId, dstDepthId, dstProfileName);
369 if (srcNode == dstNode)
return true;
370 if (!srcNode)
return false;
371 if (!dstNode)
return false;
373 bool existAndGood = path.isGood;
379 const Node *srcNode =
nodeFor(srcModelId, srcDepthId, srcProfileName);
380 const Node *dstNode =
nodeFor(dstModelId, dstDepthId, dstProfileName);
402 const Node* srcNode = 0;
403 const Node* dstNode = 0;
404 Q_FOREACH (
Node* node,
d->graph) {
405 if (node->
id() == srcKey) {
408 if (node->
id() == dstKey) {
413 Q_ASSERT(!
p.isEmpty());
414 QString dot =
"digraph CCS {\n" +
415 QString(
" \"%1\" [color=red]\n").arg(srcNode->
id()) +
416 QString(
" \"%1\" [color=red]\n").arg(dstNode->
id());
417 Q_FOREACH (
Vertex* oV,
d->vertexes) {
419 if (
p.vertexes.contains(oV)) {
420 options =
"[color=red]";
433 dbgPigmentCCS <<
"Find best path between " << srcNode->
id() <<
" and " << dstNode->
id();
440 if (
v->dstNode->isInitialized) {
443 Node* endNode =
v->dstNode;
444 if (endNode == dstNode) {
450 node2path.insert(endNode,
p);
451 possiblePaths.append(
p);
456 Path currentBestPath;
458 while (possiblePaths.size() > 0) {
462 for (
const Path &
p : currentPaths) {
463 const Node* endNode =
p.endNode();
465 if (
v->dstNode->isInitialized && !
p.contains(
v->dstNode)) {
468 Node* newEndNode =
v->dstNode;
469 if (newEndNode == dstNode) {
479 currentBestPath = newP;
484 Node2PathHash::Iterator it = node2path.find(newEndNode);
485 if (it != node2path.end()) {
489 possiblePaths.append(newP);
492 node2path.insert(newEndNode, newP);
493 possiblePaths.append(newP);
498 possiblePaths.removeAll(
p);
502 if (!currentBestPath.
isEmpty()) {
503 warnPigment <<
"No good path from " << srcNode->
id() <<
" to " << dstNode->
id() <<
" found : length = " << currentBestPath.
length() <<
" cost = " << currentBestPath.
cost <<
" referenceDepth = " << currentBestPath.
referenceDepth <<
" respectColorCorrectness = " <<
" isGood = " << currentBestPath.
isGood ;
504 return currentBestPath;
506 errorPigment <<
"No path from " << srcNode->
id() <<
" to " << dstNode->
id() <<
" found not ";
507 return currentBestPath;
QHash< KoColorConversionSystem::Node *, KoColorConversionSystem::Path > Node2PathHash
KoColorConversionTransformation * createTransformationFromPath(const KoColorConversionSystem::Path &path, const KoColorSpace *srcColorSpace, const KoColorSpace *dstColorSpace, KoColorConversionTransformation::Intent renderingIntent, KoColorConversionTransformation::ConversionFlags conversionFlags) const
Vertex * createVertex(Node *srcNode, Node *dstNode)
Node * insertEngine(const KoColorSpaceEngine *engine)
QList< Node * > nodesFor(const QString &_modelId, const QString &_depthId)
void connectToEngine(Node *_node, Node *_engine)
bool existsGoodPath(const QString &srcModelId, const QString &srcDepthId, const QString &srcProfileName, const QString &dstModelId, const QString &dstDepthId, const QString &dstProfileName) const
KoColorConversionTransformation * createColorConverter(const KoColorSpace *srcColorSpace, const KoColorSpace *dstColorSpace, KoColorConversionTransformation::Intent renderingIntent, KoColorConversionTransformation::ConversionFlags conversionFlags) const
KoColorConversionSystem(RegistryInterface *registryInterface)
Path findBestPath(const QString &srcModelId, const QString &srcDepthId, const QString &srcProfileName, const QString &dstModelId, const QString &dstDepthId, const QString &dstProfileName) const
const KoColorSpace * defaultColorSpaceForNode(const Node *node) const
Vertex * vertexBetween(Node *srcNode, Node *dstNode)
void insertColorSpace(const KoColorSpaceFactory *)
Node * createNode(const QString &_modelId, const QString &_depthId, const QString &_profileName)
bool existsPath(const QString &srcModelId, const QString &srcDepthId, const QString &srcProfileName, const QString &dstModelId, const QString &dstDepthId, const QString &dstProfileName) const
void insertColorProfile(const KoColorProfile *)
const Node * nodeFor(const KoColorSpace *) const
~KoColorConversionSystem()
QString bestPathToDot(const QString &srcKey, const QString &dstKey) const
QString vertexToDot(Vertex *v, const QString &options) const
void createColorConverters(const KoColorSpace *colorSpace, const QList< QPair< KoID, KoID > > &possibilities, KoColorConversionTransformation *&fromCS, KoColorConversionTransformation *&toCS) const
static KoColorSpaceEngineRegistry * instance()
virtual KoID colorModelId() const =0
virtual KoID colorDepthId() const =0
virtual const KoColorProfile * profile() const =0
T get(const QString &id) const
void init(const KoColorSpaceFactory *_colorSpaceFactory)
QList< Vertex * > outputVertexes
void appendVertex(Vertex *v)
virtual bool supportsColorSpace(const QString &colorModelId, const QString &colorDepthId, const KoColorProfile *profile) const
virtual KoID colorDepthId() const =0
virtual QString name() const =0
virtual QString defaultProfile() const =0
virtual KoID colorModelId() const =0
virtual QString id() const =0
virtual QList< KoColorConversionTransformationFactory * > colorConversionLinks() const =0
virtual QString colorSpaceEngine() const =0
bool lessWorseThan(const KoColorConversionSystem::Path &path1, const KoColorConversionSystem::Path &path2) const
bool isGoodPath(const KoColorConversionSystem::Path &path) const