22 : d(new
Private(registryInterface))
29 qDeleteAll(
d->vertexes);
50 d->graph.insert(key, n);
63 if (profiles.isEmpty()) {
69 dbgPigment <<
"Cannot add node for " << csf->
name() <<
", since there are no profiles available";
82 QHash<NodeKey, Node*>::ConstIterator it =
d->graph.constFind(engineKey);
83 if (it !=
d->graph.constEnd()) {
84 engineNode = it.value();
110 v->setFactoryFromDst(cctf);
113 v->setFactoryFromSrc(cctf);
131 Q_ASSERT(engineNode);
144 if (srcNode == n || dstNode == n) {
153 v->setFactoryFromDst(cctf);
156 v->setFactoryFromSrc(cctf);
174 d->graph.insert(
NodeKey(_modelId, _depthId, _profileName), n);
182 profile ? profile->
name() :
"default");
187 dbgPigmentCCS <<
"Look for node: " << _colorModelId <<
" " << _colorDepthId <<
" " << _profileName;
188 return nodeFor(
NodeKey(_colorModelId, _colorDepthId, _profileName));
194 return d->graph.value(key);
199 return nodeFor(
NodeKey(_colorModelId, _colorDepthId, _profileName));
204 QHash<NodeKey, Node*>::ConstIterator it =
d->graph.constFind(key);
205 if (it !=
d->graph.constEnd()) {
215 Q_FOREACH (
Node* node,
d->graph) {
225 Q_ASSERT(srcColorSpace);
226 Q_ASSERT(dstColorSpace);
227 if (*srcColorSpace == *dstColorSpace) {
235 Q_ASSERT(path.length() > 0);
252 typedef QPair<KoID, KoID> KoID2KoID;
253 Q_FOREACH (
const KoID2KoID & possibility, possibilities) {
254 const KoColorSpaceFactory* csf =
d->registryInterface->colorSpaceFactory(possibility.first.id(), possibility.second.id());
257 Q_ASSERT(path.length() > 0);
271 Q_ASSERT(!returnPath.
isEmpty());
279 Q_ASSERT(srcColorSpace->
colorModelId().
id() == path.startNode()->modelId);
280 Q_ASSERT(srcColorSpace->
colorDepthId().
id() == path.startNode()->depthId);
281 Q_ASSERT(dstColorSpace->
colorModelId().
id() == path.endNode()->modelId);
282 Q_ASSERT(dstColorSpace->
colorDepthId().
id() == path.endNode()->depthId);
288 if (pathOfNode.size() == 2) {
289 transfo = pathOfNode[1].second->createColorTransformation(srcColorSpace, dstColorSpace, renderingIntent, conversionFlags);
295 transfo = mccTransfo;
298 dbgPigmentCCS << pathOfNode[ 0 ].first->id() <<
" to " << pathOfNode[ 1 ].first->id();
303 mccTransfo->
appendTransfo(pathOfNode[1].second->createColorTransformation(srcColorSpace, intermCS, renderingIntent, conversionFlags));
305 for (
int i = 2; i < pathOfNode.size() - 1; i++) {
306 dbgPigmentCCS << pathOfNode[ i - 1 ].first->id() <<
" to " << pathOfNode[ i ].first->id();
309 mccTransfo->
appendTransfo(pathOfNode[i].second->createColorTransformation(intermCS, intermCS2, renderingIntent, conversionFlags));
310 intermCS = intermCS2;
313 dbgPigmentCCS << pathOfNode[ pathOfNode.size() - 2 ].first->id() <<
" to " << pathOfNode[ pathOfNode.size() - 1 ].first->id();
314 mccTransfo->
appendTransfo(pathOfNode.last().second->createColorTransformation(intermCS, dstColorSpace, renderingIntent, conversionFlags));
334 d->vertexes.append(
v);
342 return QString(
" \"%1\" -> \"%2\" %3\n").arg(
v->srcNode->id()).arg(
v->dstNode->id()).arg(options);
347 QString dot =
"digraph CCS {\n";
348 Q_FOREACH (
Vertex* oV,
d->vertexes) {
355bool KoColorConversionSystem::existsPath(
const QString& srcModelId,
const QString& srcDepthId,
const QString& srcProfileName,
const QString& dstModelId,
const QString& dstDepthId,
const QString& dstProfileName)
const
357 dbgPigmentCCS <<
"srcModelId = " << srcModelId <<
" srcDepthId = " << srcDepthId <<
" srcProfileName = " << srcProfileName <<
" dstModelId = " << dstModelId <<
" dstDepthId = " << dstDepthId <<
" dstProfileName = " << dstProfileName;
358 const Node* srcNode =
nodeFor(srcModelId, srcDepthId, srcProfileName);
359 const Node* dstNode =
nodeFor(dstModelId, dstDepthId, dstProfileName);
360 if (srcNode == dstNode)
return true;
361 if (!srcNode)
return false;
362 if (!dstNode)
return false;
364 bool exist = !path.isEmpty();
368bool KoColorConversionSystem::existsGoodPath(
const QString& srcModelId,
const QString& srcDepthId,
const QString& srcProfileName,
const QString& dstModelId,
const QString& dstDepthId,
const QString& dstProfileName)
const
370 const Node* srcNode =
nodeFor(srcModelId, srcDepthId, srcProfileName);
371 const Node* dstNode =
nodeFor(dstModelId, dstDepthId, dstProfileName);
372 if (srcNode == dstNode)
return true;
373 if (!srcNode)
return false;
374 if (!dstNode)
return false;
376 bool existAndGood = path.isGood;
382 const Node *srcNode =
nodeFor(srcModelId, srcDepthId, srcProfileName);
383 const Node *dstNode =
nodeFor(dstModelId, dstDepthId, dstProfileName);
405 const Node* srcNode = 0;
406 const Node* dstNode = 0;
407 Q_FOREACH (
Node* node,
d->graph) {
408 if (node->
id() == srcKey) {
411 if (node->
id() == dstKey) {
416 Q_ASSERT(!
p.isEmpty());
417 QString dot =
"digraph CCS {\n" +
418 QString(
" \"%1\" [color=red]\n").arg(srcNode->
id()) +
419 QString(
" \"%1\" [color=red]\n").arg(dstNode->
id());
420 Q_FOREACH (
Vertex* oV,
d->vertexes) {
422 if (
p.vertexes.contains(oV)) {
423 options =
"[color=red]";
436 dbgPigmentCCS <<
"Find best path between " << srcNode->
id() <<
" and " << dstNode->
id();
443 if (
v->dstNode->isInitialized) {
446 Node* endNode =
v->dstNode;
447 if (endNode == dstNode) {
453 node2path.insert(endNode,
p);
454 possiblePaths.append(
p);
459 Path currentBestPath;
461 while (possiblePaths.size() > 0) {
465 for (
const Path &
p : currentPaths) {
466 const Node* endNode =
p.endNode();
468 if (
v->dstNode->isInitialized && !
p.contains(
v->dstNode)) {
471 Node* newEndNode =
v->dstNode;
472 if (newEndNode == dstNode) {
482 currentBestPath = newP;
487 Node2PathHash::Iterator it = node2path.find(newEndNode);
488 if (it != node2path.end()) {
492 possiblePaths.append(newP);
495 node2path.insert(newEndNode, newP);
496 possiblePaths.append(newP);
501 possiblePaths.removeAll(
p);
505 if (!currentBestPath.
isEmpty()) {
506 warnPigment <<
"No good path from " << srcNode->
id() <<
" to " << dstNode->
id() <<
" found : length = " << currentBestPath.
length() <<
" cost = " << currentBestPath.
cost <<
" referenceDepth = " << currentBestPath.
referenceDepth <<
" respectColorCorrectness = " <<
" isGood = " << currentBestPath.
isGood ;
507 return currentBestPath;
509 errorPigment <<
"No path from " << srcNode->
id() <<
" to " << dstNode->
id() <<
" found not ";
510 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 QList< KoColorConversionTransformationFactory * > colorConversionLinksFromProfile(const KoColorProfile *profile) const
colorConversionLinksFromProfile Sometimes, we need to generate special color conversion links based o...
virtual QString colorSpaceEngine() const =0
bool lessWorseThan(const KoColorConversionSystem::Path &path1, const KoColorConversionSystem::Path &path2) const
bool isGoodPath(const KoColorConversionSystem::Path &path) const