Commit 7de02569 authored by Boudewijn Rempt's avatar Boudewijn Rempt

Create the proofing transform

This doesn't use the caching graph stuff, which is too complex
to refactor for now.
parent 00efd627
......@@ -25,7 +25,6 @@
#include "KoColorConversionAlphaTransformation.h"
#include "KoColorConversionTransformation.h"
#include "KoColorProofingConversionTransformation.h"
#include "KoColorProfile.h"
#include "KoColorSpace.h"
#include "KoCopyColorConversionTransformation.h"
......@@ -262,28 +261,6 @@ KoColorConversionTransformation* KoColorConversionSystem::createColorConverter(c
return transfo;
}
KoColorProofingConversionTransformation* KoColorConversionSystem::createColorProofingConverter(const KoColorSpace * srcColorSpace, const KoColorSpace * dstColorSpace, const KoColorSpace *proofingSpace, KoColorProofingConversionTransformation::Intent renderingIntent, KoColorProofingConversionTransformation::ConversionFlags conversionFlags) const
{
/*if (*srcColorSpace == *dstColorSpace && *srcColorSpace == *proofingSpace) {
return new KoCopyColorConversionTransformation(srcColorSpace);
}*/
Q_ASSERT(srcColorSpace);
Q_ASSERT(dstColorSpace);
dbgPigmentCCS << srcColorSpace->id() << (srcColorSpace->profile() ? srcColorSpace->profile()->name() : "default");
dbgPigmentCCS << dstColorSpace->id() << (dstColorSpace->profile() ? dstColorSpace->profile()->name() : "default");
Path path = findBestPath(
nodeFor(srcColorSpace),
nodeFor(dstColorSpace));
Q_ASSERT(path.length() > 0);
const QList< Path::node2factory > pathOfNode = path.compressedPath();
//Let's hack our way around tis for now.
KoColorProofingConversionTransformation* transfo = pathOfNode[0].second->createColorProofingTransformation(srcColorSpace, dstColorSpace, proofingSpace, renderingIntent, conversionFlags);
Q_ASSERT(*transfo->srcColorSpace() == *srcColorSpace);
Q_ASSERT(*transfo->dstColorSpace() == *dstColorSpace);
Q_ASSERT(transfo);
return transfo;
}
void KoColorConversionSystem::createColorConverters(const KoColorSpace* colorSpace, const QList< QPair<KoID, KoID> >& possibilities, KoColorConversionTransformation*& fromCS, KoColorConversionTransformation*& toCS) const
{
// TODO This function currently only select the best conversion only based on the transformation
......
......@@ -27,7 +27,6 @@ class KoColorSpaceEngine;
class KoID;
#include "KoColorConversionTransformation.h"
#include "KoColorProofingConversionTransformation.h"
#include <QList>
#include <QPair>
......@@ -70,7 +69,6 @@ public:
* the best possible path between the two color space.
*/
KoColorConversionTransformation* createColorConverter(const KoColorSpace * srcColorSpace, const KoColorSpace * dstColorSpace, KoColorConversionTransformation::Intent renderingIntent, KoColorConversionTransformation::ConversionFlags conversionFlags) const;
KoColorProofingConversionTransformation* createColorProofingConverter(const KoColorSpace * srcColorSpace, const KoColorSpace * dstColorSpace, const KoColorSpace *proofingSpace, KoColorProofingConversionTransformation::Intent renderingIntent, KoColorProofingConversionTransformation::ConversionFlags conversionFlags) const;
/**
* This function creates two transformations, one from the color space and one to the
......
......@@ -30,6 +30,7 @@ class KRITAPIGMENT_EXPORT KoColorConversionTransformationAbstractFactory
public:
KoColorConversionTransformationAbstractFactory() {}
virtual ~KoColorConversionTransformationAbstractFactory() {}
/**
* Creates a color transformation between the source color space and the destination
* color space.
......
......@@ -21,85 +21,23 @@
#include "KoColorSpace.h"
struct Q_DECL_HIDDEN KoColorProofingConversionTransformation::Private {
const KoColorSpace* srcColorSpace;
const KoColorSpace* dstColorSpace;
const KoColorSpace* proofingSpace;
Intent renderingIntent;
ConversionFlags conversionFlags;
};
KoColorProofingConversionTransformation::KoColorProofingConversionTransformation(const KoColorSpace* srcCs,
const KoColorSpace* dstCs,
const KoColorSpace* proofingSpace,
Intent renderingIntent,
ConversionFlags conversionFlags)
: d(new Private)
: KoColorConversionTransformation(srcCs, dstCs, renderingIntent, conversionFlags)
{
Q_ASSERT(srcCs);
Q_ASSERT(dstCs);
Q_ASSERT(proofingSpace);
d->srcColorSpace = srcCs;
d->dstColorSpace = dstCs;
d->proofingSpace = proofingSpace;
d->renderingIntent = renderingIntent;
d->conversionFlags = conversionFlags;
m_proofingSpace = proofingSpace;
}
KoColorProofingConversionTransformation::~KoColorProofingConversionTransformation()
{
delete d;
}
const KoColorSpace* KoColorProofingConversionTransformation::srcColorSpace() const
{
return d->srcColorSpace;
}
const KoColorSpace* KoColorProofingConversionTransformation::dstColorSpace() const
{
return d->dstColorSpace;
}
const KoColorSpace* KoColorProofingConversionTransformation::proofingSpace() const
{
return d->proofingSpace;
}
KoColorProofingConversionTransformation::Intent KoColorProofingConversionTransformation::renderingIntent() const
{
return d->renderingIntent;
}
KoColorProofingConversionTransformation::ConversionFlags KoColorProofingConversionTransformation::conversionFlags() const
{
return d->conversionFlags;
}
void KoColorProofingConversionTransformation::setSrcColorSpace(const KoColorSpace* cs) const
{
Q_ASSERT(*d->srcColorSpace == *cs);
d->srcColorSpace = cs;
}
void KoColorProofingConversionTransformation::setDstColorSpace(const KoColorSpace* cs) const
{
Q_ASSERT(*d->dstColorSpace == *cs);
d->dstColorSpace = cs;
}
void KoColorProofingConversionTransformation::setProofingSpace(const KoColorSpace* cs) const
{
Q_ASSERT(*d->proofingSpace == *cs);
d->proofingSpace = cs;
}
void KoColorProofingConversionTransformation::setIntent(Intent renderingIntent) const
{
d->renderingIntent = renderingIntent;
}
void KoColorProofingConversionTransformation::setConversionFlags(ConversionFlags conversionFlags) const
{
d->conversionFlags = conversionFlags;
return m_proofingSpace;
}
......@@ -20,7 +20,7 @@
#ifndef _KO_COLOR_PROOFING_CONVERSION_TRANSFORMATION_H_
#define _KO_COLOR_PROOFING_CONVERSION_TRANSFORMATION_H_
#include "KoColorTransformation.h"
#include "KoColorConversionTransformation.h"
#include "kritapigment_export.h"
......@@ -30,120 +30,28 @@ class KoColorConversionCache;
/**
* This is the base class of all color transform that convert the color of a pixel
*/
class KRITAPIGMENT_EXPORT KoColorProofingConversionTransformation : public KoColorTransformation
class KRITAPIGMENT_EXPORT KoColorProofingConversionTransformation : public KoColorConversionTransformation
{
friend class KoColorConversionCache;
struct Private;
public:
/**
* Possible value for the intent of a color conversion (useful only for ICC
* transformations)
*/
enum Intent {
IntentPerceptual = 0,
IntentRelativeColorimetric = 1,
IntentSaturation = 2,
IntentAbsoluteColorimetric = 3
};
/**
* Flags for the color conversion, see lcms2 documentation for more information
*/
enum ConversionFlag {
Empty = 0x0,
NoOptimization = 0x0100,
GamutCheck = 0x1000, // Out of Gamut alarm
SoftProofing = 0x4000, // Do softproofing
BlackpointCompensation = 0x2000,
NoWhiteOnWhiteFixup = 0x0004, // Don't fix scum dot
HighQuality = 0x0400, // Use more memory to give better accurancy
LowQuality = 0x0800 // Use less memory to minimize resouces
};
Q_DECLARE_FLAGS(ConversionFlags, ConversionFlag)
/**
* We have numerous places where we need to convert color spaces.
*
* In several cases the user asks us about the conversion
* explicitly, e.g. when changing the image type or converting
* pixel data to the monitor profile. Doing this explicitly the
* user can choose what rendering intent and conversion flags to
* use.
*
* But there are also cases when we have to do a conversion
* internally (transparently for the user), for example, when
* merging heterogeneous images, creating thumbnails, converting
* data to/from QImage or while doing some adjustments. We cannot
* ask the user about parameters for every single
* conversion. That's why in all these non-critical cases the
* following default values should be used.
*/
static Intent internalRenderingIntent() { return IntentPerceptual; }
static ConversionFlags internalConversionFlags() { return BlackpointCompensation; }
static Intent adjustmentRenderingIntent() { return IntentPerceptual; }
static ConversionFlags adjustmentConversionFlags() { return ConversionFlags(BlackpointCompensation | NoWhiteOnWhiteFixup); }
public:
KoColorProofingConversionTransformation(const KoColorSpace* srcCs,
const KoColorSpace* dstCs,
const KoColorSpace* proofingSpace,
Intent renderingIntent,
ConversionFlags conversionFlags);
~KoColorProofingConversionTransformation();
public:
KoColorProofingConversionTransformation(const KoColorSpace *srcCs,
const KoColorSpace *dstCs,
const KoColorSpace *proofingSpace,
Intent renderingIntent,
ConversionFlags conversionFlags);
virtual ~KoColorProofingConversionTransformation();
/**
* @return the source color space for this transformation.
*/
const KoColorSpace* srcColorSpace() const;
/**
* @return the destination color space for this transformation.
*/
const KoColorSpace* dstColorSpace() const;
public:
/**
* @brief proofingSpace
* @return the space that is used to proof the color transform
*/
const KoColorSpace* proofingSpace() const;
/**
* @return the rendering intent of this transformation (this is only useful
* for ICC transformations)
*/
Intent renderingIntent() const;
/**
* @return the conversion flags
*/
ConversionFlags conversionFlags() const;
/**
* perform the color conversion between two buffers.
* @param nPixels the number of pixels in the buffers.
*/
virtual void transform(const quint8 *src, quint8 *dst, qint32 nPixels) const = 0;
/**
* @return false if the transformation is not valid
*/
virtual bool isValid() const { return true; }
const KoColorSpace *proofingSpace() const;
private:
void setSrcColorSpace(const KoColorSpace*) const;
void setDstColorSpace(const KoColorSpace*) const;
void setProofingSpace(const KoColorSpace*) const;
void setIntent(Intent renderingIntent) const;
void setConversionFlags(ConversionFlags conversionFlags) const;
Private * const d;
const KoColorSpace *m_proofingSpace;
};
Q_DECLARE_OPERATORS_FOR_FLAGS(KoColorProofingConversionTransformation::ConversionFlags)
#endif
......@@ -36,6 +36,7 @@
#include "KoMixColorsOp.h"
#include "KoConvolutionOp.h"
#include "KoCompositeOpRegistry.h"
#include "KoColorSpaceEngine.h"
#include <QThreadStorage>
#include <QByteArray>
......@@ -119,7 +120,7 @@ QPolygonF KoColorSpace::gamutXYY() const
if ((colorModelId().id()=="CMYKA" || colorModelId().id()=="LABA") && colorDepthId().id()=="F32") {
//boundaries for cmyka/laba have trouble getting the max values for Float, and are pretty awkward in general.
max = this->channels()[0]->getUIMax();
}
int samples = 5;//amount of samples in our color space.
QString name = KoColorSpaceRegistry::instance()->colorSpaceFactory("XYZAF32")->defaultProfile();
......@@ -175,7 +176,7 @@ QPolygonF KoColorSpace::gamutXYY() const
}
}
}
}
}
delete[] data;
......@@ -230,7 +231,7 @@ QPolygonF KoColorSpace::estimatedTRCXYY() const
for (int j=0; j<5; j++){
channelValuesF.fill(0.0);
channelValuesF[i] = ((max/4)*(j));
fromNormalisedChannelsValue(data, channelValuesF);
convertPixelsTo(data, data2, xyzColorSpace, 1, KoColorConversionTransformation::IntentAbsoluteColorimetric, KoColorConversionTransformation::adjustmentConversionFlags());
......@@ -417,11 +418,6 @@ KoColorConversionTransformation* KoColorSpace::createColorConverter(const KoColo
}
}
KoColorProofingConversionTransformation* KoColorSpace::createColorProofingConverter(const KoColorSpace * dstColorSpace, const KoColorSpace *proofingSpace, KoColorProofingConversionTransformation::Intent renderingIntent, KoColorProofingConversionTransformation::ConversionFlags conversionFlags) const
{
return KoColorSpaceRegistry::instance()->colorConversionSystem()->createColorProofingConverter(this, dstColorSpace, proofingSpace, renderingIntent, conversionFlags);
}
bool KoColorSpace::convertPixelsTo(const quint8 * src,
quint8 * dst,
const KoColorSpace * dstColorSpace,
......@@ -444,17 +440,24 @@ bool KoColorSpace::proofPixelsTo(const quint8 * src,
const KoColorSpace * dstColorSpace,
const KoColorSpace * proofingSpace,
quint32 numPixels,
KoColorProofingConversionTransformation::Intent renderingIntent,
KoColorProofingConversionTransformation::ConversionFlags conversionFlags) const
KoColorConversionTransformation::Intent renderingIntent,
KoColorConversionTransformation::ConversionFlags conversionFlags) const
{
if (*this == *dstColorSpace && *this == *proofingSpace) {
if (src != dst) {
memcpy(dst, src, numPixels * sizeof(quint8) * pixelSize());
}
} else {
KoColorProofingConversionTransformation cct = KoColorSpaceRegistry::instance()->colorConversionSystem()->createColorProofingConverter(this, dstColorSpace, proofingSpace, renderingIntent, conversionFlags);
cct->transform(src, dst, numPixels);
return true;
}
// Only the icc engine can do this kind of stuff
KoColorSpaceEngine *engine = KoColorSpaceEngineRegistry::instance()->get("icc");
qDebug() << ">>>>>>>>>>>>>>>>>>>> we got a proofing engine";
if (!engine) return false;
KoColorConversionTransformation *transform = engine->createColorProofingTransformation(this, dstColorSpace, proofingSpace, renderingIntent, conversionFlags);
Q_UNUSED(transform);
delete transform;
return true;
}
......
......@@ -108,17 +108,17 @@ public:
* maybe convert to 3d space in future?
*/
QPolygonF gamutXYY() const;
/*
* @returns a polygon with 5 samples per channel converted to xyY, but unlike
* gamutxyY it focuses on the luminance. This then can be used to visualise
* the approximate trc of a given colorspace.
*/
QPolygonF estimatedTRCXYY() const;
QVector <qreal> colorants() const;
QVector <qreal> lumaCoefficients() const;
//========== Channels =====================================================//
/// Return a list describing all the channels this color model has. The order
......@@ -355,10 +355,6 @@ public:
virtual KoColorConversionTransformation* createColorConverter(const KoColorSpace * dstColorSpace,
KoColorConversionTransformation::Intent renderingIntent,
KoColorConversionTransformation::ConversionFlags conversionFlags) const;
virtual KoColorProofingConversionTransformation* createColorProofingConverter(const KoColorSpace * dstColorSpace,
const KoColorSpace * proofingSpace,
KoColorProofingConversionTransformation::Intent renderingIntent,
KoColorProofingConversionTransformation::ConversionFlags conversionFlags) const;
/**
* Convert a byte array of srcLen pixels *src to the specified color space
......@@ -375,12 +371,24 @@ public:
quint32 numPixels,
KoColorConversionTransformation::Intent renderingIntent,
KoColorConversionTransformation::ConversionFlags conversionFlags) const;
/**
* @brief proofPixelsTo
* @param src
* @param dst
* @param dstColorSpace
* @param proofingSpace
* @param numPixels
* @param renderingIntent
* @param conversionFlags
* @return
*/
virtual bool proofPixelsTo(const quint8 * src,
quint8 * dst, const KoColorSpace * dstColorSpace,
const KoColorSpace * proofingSpace,
quint32 numPixels,
KoColorProofingConversionTransformation::Intent renderingIntent,
KoColorProofingConversionTransformation::ConversionFlags conversionFlags) const;
KoColorConversionTransformation::Intent renderingIntent,
KoColorConversionTransformation::ConversionFlags conversionFlags) const;
//============================== Manipulation functions ==========================//
......
......@@ -45,6 +45,7 @@ public:
const QString& name() const;
virtual void addProfile(const QString &filename) = 0;
virtual void removeProfile(const QString &filename) = 0;
private:
struct Private;
Private* const d;
......
......@@ -74,7 +74,7 @@ public:
* @param viewConverter the viewconverter for converting between
* window and document coordinates.
*/
KisCanvas2(KisCoordinatesConverter* coordConverter, KoCanvasResourceManager *resourceManager, KisView *view, KoShapeBasedDocumentBase* sc);
KisCanvas2(KisCoordinatesConverter *coordConverter, KoCanvasResourceManager *resourceManager, KisView *view, KoShapeBasedDocumentBase *sc);
virtual ~KisCanvas2();
......
......@@ -210,10 +210,10 @@ public:
}
void proofTo(const KoColorSpace* dstCS, const KoColorSpace* proofingSpace,
KoColorProofingConversionTransformation::Intent renderingIntent,
KoColorProofingConversionTransformation::ConversionFlags conversionFlags)
KoColorConversionTransformation::Intent renderingIntent,
KoColorConversionTransformation::ConversionFlags conversionFlags)
{
if (dstCS == m_patchColorSpace && conversionFlags == KoColorProofingConversionTransformation::Empty) return;
if (dstCS == m_patchColorSpace && conversionFlags == KoColorConversionTransformation::Empty) return;
if (m_patchRect.isValid()) {
const qint32 numPixels = m_patchRect.width() * m_patchRect.height();
......
......@@ -48,7 +48,7 @@ public:
|| srcCs->colorDepthId() == Integer16BitsColorDepthID) {
if ((srcProfile->name().contains(QLatin1String("linear"), Qt::CaseInsensitive) ||
dstProfile->name().contains(QLatin1String("linear"), Qt::CaseInsensitive)) &&
dstProfile->name().contains(QLatin1String("linear"), Qt::CaseInsensitive)) &&
!conversionFlags.testFlag(KoColorConversionTransformation::NoOptimization)) {
conversionFlags |= KoColorConversionTransformation::NoOptimization;
}
......@@ -94,15 +94,16 @@ public:
private:
mutable cmsHTRANSFORM m_transform;
};
class KoLcmsColorProofingConversionTransformation : public KoColorProofingConversionTransformation
{
public:
KoLcmsColorProofingConversionTransformation(const KoColorSpace *srcCs, quint32 srcColorSpaceType, LcmsColorProfileContainer *srcProfile,
const KoColorSpace *dstCs, quint32 dstColorSpaceType, LcmsColorProfileContainer *dstProfile,
const KoColorSpace *proofingSpace,
Intent renderingIntent,
ConversionFlags conversionFlags
)
const KoColorSpace *dstCs, quint32 dstColorSpaceType, LcmsColorProfileContainer *dstProfile,
const KoColorSpace *proofingSpace,
Intent renderingIntent,
ConversionFlags conversionFlags
)
: KoColorProofingConversionTransformation(srcCs, dstCs, proofingSpace, renderingIntent, conversionFlags)
, m_transform(0)
{
......@@ -115,8 +116,8 @@ public:
if ((srcProfile->name().contains(QLatin1String("linear"), Qt::CaseInsensitive) ||
dstProfile->name().contains(QLatin1String("linear"), Qt::CaseInsensitive)) &&
!conversionFlags.testFlag(KoColorProofingConversionTransformation::NoOptimization)) {
conversionFlags |= KoColorProofingConversionTransformation::NoOptimization;
!conversionFlags.testFlag(KoColorConversionTransformation::NoOptimization)) {
conversionFlags |= KoColorConversionTransformation::NoOptimization;
}
}
......@@ -128,13 +129,13 @@ public:
cmsSetAlarmCodes(alarm);
m_transform = cmsCreateProofingTransform(srcProfile->lcmsProfile(),
srcColorSpaceType,
dstProfile->lcmsProfile(),
dstColorSpaceType,
dynamic_cast<const IccColorProfile *>(proofingSpace->profile())->asLcms()->lcmsProfile(),
renderingIntent,
renderingIntent,
conversionFlags);
srcColorSpaceType,
dstProfile->lcmsProfile(),
dstColorSpaceType,
dynamic_cast<const IccColorProfile *>(proofingSpace->profile())->asLcms()->lcmsProfile(),
renderingIntent,
renderingIntent,
conversionFlags);
Q_ASSERT(m_transform);
}
......@@ -223,25 +224,25 @@ void IccColorSpaceEngine::removeProfile(const QString &filename)
}
KoColorConversionTransformation *IccColorSpaceEngine::createColorTransformation(const KoColorSpace *srcColorSpace,
const KoColorSpace *dstColorSpace,
KoColorConversionTransformation::Intent renderingIntent,
KoColorConversionTransformation::ConversionFlags conversionFlags) const
const KoColorSpace *dstColorSpace,
KoColorConversionTransformation::Intent renderingIntent,
KoColorConversionTransformation::ConversionFlags conversionFlags) const
{
Q_ASSERT(srcColorSpace);
Q_ASSERT(dstColorSpace);
return new KoLcmsColorConversionTransformation(
srcColorSpace, computeColorSpaceType(srcColorSpace),
dynamic_cast<const IccColorProfile *>(srcColorSpace->profile())->asLcms(), dstColorSpace, computeColorSpaceType(dstColorSpace),
dynamic_cast<const IccColorProfile *>(dstColorSpace->profile())->asLcms(), renderingIntent, conversionFlags);
srcColorSpace, computeColorSpaceType(srcColorSpace),
dynamic_cast<const IccColorProfile *>(srcColorSpace->profile())->asLcms(), dstColorSpace, computeColorSpaceType(dstColorSpace),
dynamic_cast<const IccColorProfile *>(dstColorSpace->profile())->asLcms(), renderingIntent, conversionFlags);
}
KoColorProofingConversionTransformation *IccColorSpaceEngine::createColorProofingTransformation(const KoColorSpace *srcColorSpace,
const KoColorSpace *dstColorSpace,
const KoColorSpace *proofingSpace,
KoColorProofingConversionTransformation::Intent renderingIntent,
KoColorProofingConversionTransformation::ConversionFlags conversionFlags
) const
const KoColorSpace *dstColorSpace,
const KoColorSpace *proofingSpace,
KoColorConversionTransformation::Intent renderingIntent,
KoColorConversionTransformation::ConversionFlags conversionFlags
) const
{
Q_ASSERT(srcColorSpace);
Q_ASSERT(dstColorSpace);
......
......@@ -36,8 +36,8 @@ public:
virtual KoColorProofingConversionTransformation *createColorProofingTransformation(const KoColorSpace *srcColorSpace,
const KoColorSpace *dstColorSpace,
const KoColorSpace *proofingSpace,
KoColorProofingConversionTransformation::Intent renderingIntent,
KoColorProofingConversionTransformation::ConversionFlags conversionFlags) const;
KoColorConversionTransformation::Intent renderingIntent,
KoColorConversionTransformation::ConversionFlags conversionFlags) const;
quint32 computeColorSpaceType(const KoColorSpace *cs) const;
private:
struct Private;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment