Commit 91a59f30 authored by Halla Rempt's avatar Halla Rempt

* Added configure checks for littlecms.

* Started integrating littlecms into Krita for conversion between color spaces
  and input/display/output, i.e., the foundations for real colour management.
* Load icm profiles as Krita resources.
* Renamed KisPixelRepresentation to KisPixel, added method to retrieve alpha
  and removed colorspace specific specializations
* Cleaned up API of color spaces -- get rid of unused QColor and QRgb
  methods.
* Made sure the iterators only initialize the KisPixels through the
  color strategies who know what's what.
* Implemented selection moving again (but it's slow, and marred by a
  bug in selection clearing).
* Added plugin to convert between image modes (i.e., colour spaces
  with alpha etc.) Just the UI -- implementation will start right
  after pressing ESC:wqENTER.
* Sundry bug fixes in cmyk, alpha and gray colour strategies caused
  by rampant global constants.

svn path=/trunk/koffice/; revision=367877
parent 80fba292
......@@ -30,7 +30,7 @@ kdemimedir = $(kde_mimedir)/application
rcdir = $(kde_datadir)/krita
rc_DATA = krita.rc krita_readonly.rc
SUBDIRS = ui core paintops . dtd tools plugins modules data pics
SUBDIRS = ui core paintops . dtd tools modules plugins data pics
# Needed to compile libkritacommon.la, which has no source files to itself
# but everything in static libs.
......
if test -z "$LCMS_LIBS"; then
echo ""
echo "LittleCMS is missing, Krita will not be built."
echo ""
echo "If you want to compile Krita you should install:"
if test -z "$LCMS_LIBS"; then
echo " * lcms 1.14 or newer (http://www.littlecms.com/)"
fi
echo ""
all_tests=bad
fi
......@@ -8,3 +8,59 @@ KDE_CHECK_LIB(Xi, XOpenDisplay, [
AC_DEFINE(HAVE_XINPUTEXT, 1, [Define if you have the X11 Input Extension])
])
AC_SUBST(LIB_XINPUTEXT)
# Check for lcms
have_lcms_header='no'
KDE_CHECK_HEADER(lcms/lcms.h,have_lcms_header='yes',,)
if test "$have_lcms_header" = 'yes'
then
LCMS_LIBS='-llcms'
AC_DEFINE(LCMS_HEADER, <lcms/lcms.h>, [The correct header])
else
# Alternative! Debian does it this way...
KDE_CHECK_HEADER(lcms.h,have_lcms_header='yes',,)
if test "$have_lcms_header" = 'yes'
then
LCMS_LIBS='-llcms'
AC_DEFINE(LCMS_HEADER, <lcms.h>, [The correct header])
# Try to find the full path of lcms.h
for a in $includedir $prefix/include /usr/include /usr/local/include $kde_extra_includes; do
for b in lcms.h lcms/lcms.h ; do
if test -d "$a" && test -f "$a/$b" ; then
LCMSHDR="$a/$b"
fi
done
done
# Check if lcms.h was found. If not then it means that we didn't search
# the right dirs since the kde check already found a usable lcms.h
if test -n "$LCMSHDR" ; then
# Get lcms version
lcms_ver_line=`cat $LCMSHDR | grep '^// Version' `
if test -z "$lcms_ver_line" ; then
# Some versions of lcms have the version in /* */
lcms_ver_line=`cat $LCMSHDR | grep '^/\* Version' `
fi
lcms_ver=`echo "$lcms_ver_line" | head -1 | cut -d ' ' -f 3 `
# Get major and minor version numbers
lcms_var_maj=`echo $lcms_ver | cut -d . -f 1`
# Some versions have a character attached to the end of minor version
lcms_var_min=`echo $lcms_ver | cut -d . -f 2 | sed 's,[^0-9],,g'`
if test "$lcms_var_maj" -gt 1 || test "$lcms_var_min" -lt 9 ; then
LCMS_LIBS=''
fi
fi
else
LCMS_LIBS=''
fi
fi
if test -z "$LCMS_LIBS"; then
DO_NOT_COMPILE="$DO_NOT_COMPILE krita"
fi
AC_SUBST(LCMS_LIBS)
......@@ -47,7 +47,14 @@
#include "../../../config.h"
namespace {
const PIXELTYPE PIXEL_BLUE = 0;
const PIXELTYPE PIXEL_GREEN = 1;
const PIXELTYPE PIXEL_RED = 2;
const PIXELTYPE PIXEL_ALPHA = 3;
inline
void pp2tile(KisPixelDataSP pd, const PixelPacket *pp)
{
......
......@@ -17,12 +17,14 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#include <lcms.h>
#include <limits.h>
#include <stdlib.h>
#include <qimage.h>
#include <kdebug.h>
#include <klocale.h>
#include "kis_colorspace_registry.h"
#include "kis_image.h"
......@@ -30,15 +32,16 @@
#include "tiles/kispixeldata.h"
#include "kis_iterators_pixel.h"
#include "kis_selection.h"
#include "kis_channelinfo.h"
namespace {
const Q_INT32 MAX_CHANNEL_ALPHA = 1;
}
KisChannelInfo KisColorSpaceAlpha::channelInfo[1] = { KisChannelInfo("Alpha", 0) };
KisChannelInfo KisColorSpaceAlpha::channelInfo[1] = { KisChannelInfo(i18n("alpha"), 0, ALPHA) };
KisColorSpaceAlpha::KisColorSpaceAlpha() :
KisStrategyColorSpace("alpha mask")
KisStrategyColorSpace("alpha mask", TYPE_GRAY_8)
{
m_maskColor = KoColor::white();
m_inverted = false;
......@@ -58,26 +61,6 @@ void KisColorSpaceAlpha::nativeColor(const KoColor& /*c*/, QUANTUM opacity, QUAN
dst[PIXEL_MASK] = opacity;
}
void KisColorSpaceAlpha::nativeColor(const QColor& /*c*/, QUANTUM *dst)
{
dst[PIXEL_MASK] = OPACITY_OPAQUE;
}
void KisColorSpaceAlpha::nativeColor(const QColor& /*c*/, QUANTUM opacity, QUANTUM *dst)
{
dst[PIXEL_MASK] = opacity;
}
void KisColorSpaceAlpha::nativeColor(QRgb /*rgb*/, QUANTUM *dst)
{
dst[PIXEL_MASK] = OPACITY_OPAQUE;
}
void KisColorSpaceAlpha::nativeColor(QRgb /*rgb*/, QUANTUM opacity, QUANTUM *dst)
{
dst[PIXEL_MASK] = opacity;
}
void KisColorSpaceAlpha::toKoColor(const QUANTUM */*src*/, KoColor *c)
{
c -> setRGB(m_maskColor.R(), m_maskColor.G(), m_maskColor.B());
......@@ -108,7 +91,7 @@ Q_INT32 KisColorSpaceAlpha::depth() const
return MAX_CHANNEL_ALPHA;
}
QImage KisColorSpaceAlpha::convertToImage(const QUANTUM *data, Q_INT32 width, Q_INT32 height, Q_INT32 stride) const
QImage KisColorSpaceAlpha::convertToQImage(const QUANTUM *data, Q_INT32 width, Q_INT32 height, Q_INT32 stride) const
{
// kdDebug() << "KisColorSpaceAlpha::convertToImage. W:" << width
// << ", H: " << height
......@@ -123,6 +106,10 @@ QImage KisColorSpaceAlpha::convertToImage(const QUANTUM *data, Q_INT32 width, Q_
*( j + PIXEL_MASK ) = *( data + i );
// XXX: for previews of the mask, it would be handy to
// make this always black.
PIXELTYPE PIXEL_BLUE = 0;
PIXELTYPE PIXEL_GREEN = 1;
PIXELTYPE PIXEL_RED = 2;
*( j + PIXEL_RED ) = m_maskColor.R();
*( j + PIXEL_GREEN ) = m_maskColor.G();
*( j + PIXEL_BLUE ) = m_maskColor.B();
......@@ -236,22 +223,3 @@ void KisColorSpaceAlpha::bitBlt(Q_INT32 stride,
}
}
void KisColorSpaceAlpha::computeDuplicatePixel(KisIteratorPixel* , KisIteratorPixel* , KisIteratorPixel* )
{
// KisPixelRepresentationGrayscale dstPR(*dst);
// KisPixelRepresentationGrayscale dabPR(*dab);
// KisPixelRepresentationGrayscale srcPR(*src);
// dstPR.gray() = ( (QUANTUM_MAX - dabPR.gray()) * (srcPR.gray()) ) / QUANTUM_MAX;
// dstPR.alpha() =( dabPR.alpha() * (srcPR.alpha()) ) / QUANTUM_MAX;
}
void KisColorSpaceAlpha::convertToRGBA(KisPixelRepresentation& , KisPixelRepresentationRGB& )
{
// XXX
}
void KisColorSpaceAlpha::convertFromRGBA(KisPixelRepresentationRGB& , KisPixelRepresentation& )
{
// XXXX
}
......@@ -24,7 +24,7 @@
#include "kis_global.h"
#include "kis_strategy_colorspace.h"
#include "kis_pixel_representation.h"
#include "kis_pixel.h"
const PIXELTYPE PIXEL_MASK = 0;
......@@ -40,24 +40,18 @@ public:
public:
virtual void nativeColor(const KoColor& c, QUANTUM *dst);
virtual void nativeColor(const KoColor& c, QUANTUM opacity, QUANTUM *dst);
virtual void nativeColor(const QColor& c, QUANTUM *dst);
virtual void nativeColor(const QColor& c, QUANTUM opacity, QUANTUM *dst);
virtual void nativeColor(QRgb rgb, QUANTUM *dst);
virtual void nativeColor(QRgb rgb, QUANTUM opacity, QUANTUM *dst);
virtual void toKoColor(const QUANTUM *src, KoColor *c);
virtual void toKoColor(const QUANTUM *src, KoColor *c, QUANTUM *opacity);
virtual KisPixelRO toKisPixelRO(QUANTUM *src) { return KisPixelRO (src, src); }
virtual KisPixel toKisPixel(QUANTUM *src) { return KisPixel (src, src); }
virtual KisChannelInfo* channels() const;
virtual bool alpha() const;
virtual Q_INT32 depth() const;
virtual QImage convertToImage(const QUANTUM *data, Q_INT32 width, Q_INT32 height, Q_INT32 stride) const;
virtual void computeDuplicatePixel(KisIteratorPixel* dst, KisIteratorPixel* dab, KisIteratorPixel* src);
virtual void convertToRGBA(KisPixelRepresentation& src, KisPixelRepresentationRGB& dst);
virtual void convertFromRGBA(KisPixelRepresentationRGB& src, KisPixelRepresentation& dst);
virtual Q_INT32 nColorChannels() const { return 0; };
virtual QImage convertToQImage(const QUANTUM *data, Q_INT32 width, Q_INT32 height, Q_INT32 stride) const;
virtual void setMaskColor(KoColor c) { m_maskColor = c; }
virtual void setInverted(bool b) { m_inverted = b; }
......
......@@ -29,12 +29,6 @@ KisColorSpaceRegistry::KisColorSpaceRegistry()
// kdDebug() << " creating a KisColorSpaceRegistry" << endl;
Q_ASSERT(KisColorSpaceRegistry::m_singleton == 0);
KisColorSpaceRegistry::m_singleton = this;
#if 0
// Hack to add the alpha color space which isn't a module or
// selections wouldn't work. It adds itself.
KisStrategyColorSpaceSP alpha = new KisColorSpaceAlpha();
add(alpha);
#endif
}
KisColorSpaceRegistry::~KisColorSpaceRegistry()
......
......@@ -20,43 +20,46 @@
#include <kdebug.h>
#include "kis_strategy_colorspace.h"
#include "kis_pixel_representation.h"
#include "kis_pixel.h"
#include "kis_global.h"
#include "kis_factory.h"
KisStrategyColorSpace::KisStrategyColorSpace(const QString& name) : m_name(name)
{
KisStrategyColorSpace::KisStrategyColorSpace(const QString& name, Q_UINT32 cmType)
: m_name(name),
m_cmType(cmType)
{
}
KisStrategyColorSpace::~KisStrategyColorSpace()
{
TransformMap::iterator it;
for ( it = m_transforms.begin(); it != m_transforms.end(); ++it ) {
cmsDeleteTransform(it.data());
}
m_transforms.clear();
}
void KisStrategyColorSpace::convertTo(KisPixelRepresentation& src, KisPixelRepresentation& dst, KisStrategyColorSpaceSP cs)
void KisStrategyColorSpace::convertTo(KisPixel& /*src*/, KisPixel& /*dst*/, KisStrategyColorSpaceSP /*cs*/)
{
KisPixelRepresentationRGB intermediate;
this->convertToRGBA(src, intermediate);
cs->convertFromRGBA(intermediate, dst);
// XXX: Call convertPixels
}
void KisStrategyColorSpace::convertPixels(QUANTUM * src, KisStrategyColorSpaceSP srcSpace, QUANTUM * dst, Q_UINT32 numPixels)
{
//kdDebug() << "Converting " << srcLen << " pixels from " << srcSpace -> name() << " to " << name() << "\n";
Q_INT32 srcPixelSize = srcSpace -> depth();
Q_INT32 dstPixelSize = depth();
KoColor c;
QUANTUM opacity = OPACITY_OPAQUE;
if (!m_transforms.contains(srcSpace -> colorModelType())) {
cmsHTRANSFORM tf = cmsCreateTransform(srcSpace -> getProfile(),
srcSpace -> colorModelType(),
getProfile(),
m_cmType,
INTENT_PERCEPTUAL,
0);
m_transforms[srcSpace -> colorModelType()] = tf;
}
for (Q_UINT32 i = 0, s = 0, d = 0; i < numPixels; i++, s += srcPixelSize, d += dstPixelSize) {
srcSpace -> toKoColor(&src[s], &c, &opacity);
nativeColor(c, opacity, &dst[d]);
cmsHTRANSFORM tf = m_transforms[srcSpace -> colorModelType()];
}
cmsDoTransform(tf, src, dst, numPixels);
}
void KisStrategyColorSpace::bitBlt(Q_INT32 stride,
......
......@@ -19,7 +19,7 @@
#ifndef KIS_STRATEGY_COLORSPACE_H_
#define KIS_STRATEGY_COLORSPACE_H_
#include <map>
#include <qmap.h>
#include <qcolor.h>
#include <ksharedptr.h>
......@@ -31,14 +31,20 @@
class QPainter;
class KisIteratorPixel;
class KisPixelRepresentation;
class KisPixelRepresentationRGB;
class KisPixel;
class KisPixelRO;
class KisStrategyColorSpace : public KShared {
public:
KisStrategyColorSpace(const QString& name);
/**
* Create a new colorspace strategy.
*
* @param name The user-friendly name of this strategy
* @param cmType The littlecms colorstrategy type we wrap.
*/
KisStrategyColorSpace(const QString& name, Q_UINT32 cmType);
virtual ~KisStrategyColorSpace();
public:
......@@ -47,46 +53,46 @@ public:
// the colorspace managed by this strategy.
virtual void nativeColor(const KoColor& c, QUANTUM *dst) = 0;
virtual void nativeColor(const KoColor& c, QUANTUM opacity, QUANTUM *dst) = 0;
virtual void nativeColor(const QColor& c, QUANTUM *dst) = 0;
virtual void nativeColor(const QColor& c, QUANTUM opacity, QUANTUM *dst) = 0;
virtual void nativeColor(QRgb rgb, QUANTUM *dst) = 0;
virtual void nativeColor(QRgb rgb, QUANTUM opacity, QUANTUM *dst) = 0;
virtual void toKoColor(const QUANTUM *src, KoColor *c) = 0;
virtual void toKoColor(const QUANTUM *src, KoColor *c, QUANTUM *opacity) = 0;
virtual KisPixelRO toKisPixelRO(QUANTUM *src) = 0;
virtual KisPixel toKisPixel(QUANTUM *src) = 0;
// XXX: make this a proper vector. Pointers to arrays are _so_ seventies, and
// Stroustrup assures us a vector is as effecient a mem array anyway.
virtual KisChannelInfo * channels() const = 0;
virtual Q_UINT32 colorModelType() { return m_cmType; };
/**
* The total number of channels for a single pixel in this color model
*/
virtual Q_INT32 depth() const = 0;
/**
* The total number of color channels (excludes alpha and substance) for a single
* pixel in this color model.
*/
virtual Q_INT32 nColorChannels() const = 0;
/**
* Whether this color model has a channel of type ALPHA
*/
virtual bool alpha() const = 0;
/**
* The user-friendly name of this color model.
*/
inline QString name() const { return m_name; };
/**
* This function is used to convert a KisPixelRepresentation to another color strategy.
* When implementing a color space, there is no need to implement a conversion to all strategies,
* if there is no direct conversion facilities, the function should use the conversion to/from RGBA
*
* XXX: bsar. RGBA is a bad choice for an intermediate format. Use koColor; which can be expanded to use
* littleCms.
*/
virtual void convertTo(KisPixelRepresentation& src, KisPixelRepresentation& dst, KisStrategyColorSpaceSP cs);
// XXX: convertToRGBA and convertFromRGBA must use LAB or XYZ; furthermore, they should
// use koColor for now, and littlecms later. XXX2: Now that we have toKoColor, these are deprecated
/** This function converts a pixel to RGBA */
virtual void convertToRGBA(KisPixelRepresentation& src, KisPixelRepresentationRGB& dst) KDE_DEPRECATED = 0;
/** This function converts a pixel from RGBA */
virtual void convertFromRGBA(KisPixelRepresentationRGB& src, KisPixelRepresentation& dst) KDE_DEPRECATED = 0;
virtual void convertTo(KisPixel& src, KisPixel& dst, KisStrategyColorSpaceSP cs);
virtual QImage convertToImage(const QUANTUM *data, Q_INT32 width, Q_INT32 height, Q_INT32 stride) const = 0;
virtual void computeDuplicatePixel(KisIteratorPixel* dst, KisIteratorPixel* dab, KisIteratorPixel* src) =0;
virtual QImage convertToQImage(const QUANTUM *data, Q_INT32 width, Q_INT32 height, Q_INT32 stride) const = 0;
/**
* Compose two arrays of pixels together. If source and target
......@@ -110,6 +116,8 @@ protected:
* Convert a byte array of srcLen pixels *src in the color space
* srcSpace to the current color model and put the converted
* bytes into the prepared byte array *dst.
*
* This uses littlecms by default with default icm profiles.
*/
virtual void convertPixels(QUANTUM * src, KisStrategyColorSpaceSP srcSpace, QUANTUM * dst, Q_UINT32 srcLen);
......@@ -127,15 +135,34 @@ protected:
Q_INT32 rows,
Q_INT32 cols,
CompositeOp op) = 0;
/**
* Set the icm profile for conversion between color spaces
*
* XXX: make user-definable for certain transforms. Maybe
* only in the switch color space dialog for the whole image.
*/
void setProfile(cmsHPROFILE profile) { m_profile = profile; }
/**
* Get the icm profile for conversion between color spaces.
*/
cmsHPROFILE getProfile() { return m_profile; }
private:
KisStrategyColorSpace(const KisStrategyColorSpace&);
KisStrategyColorSpace& operator=(const KisStrategyColorSpace&);
QString m_name; // The user-friendly name
Q_UINT32 m_cmType; // The colorspace type as defined by littlecms
typedef QMap<Q_UINT32, cmsHTRANSFORM> TransformMap;
TransformMap m_transforms; // Cache for existing transforms
private:
cmsHPROFILE m_profile; // THe default profile for this color strategy
QString m_name;
};
#endif // KIS_STRATEGY_COLORSPACE_H_
/*
* Copyright (c) 2004 Cyrille Berger <cberger@cberger.net>
* Copyright (c) 2004 Boudewijn Rempt <boud@valdyas.org>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
......@@ -15,47 +15,26 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#ifndef KIS_TRANSFORM_H_
#define KIS_TRANSFORM_H_
#include "kis_global.h"
#include "kis_quantum.h"
#include <lcms.h>
class KisTransform {
#ifndef _KIS_PIXEL_REPRESENTATION_H_
#define _KIS_PIXEL_REPRESENTATION_H_
class KisPixelRepresentationReadOnly {
public:
KisPixelRepresentationReadOnly() : m_channels(0) { }
KisPixelRepresentationReadOnly(QUANTUM* channels) : m_channels(channels) {}
public:
QUANTUM operator[](int index) { return m_channels[index]; };
private:
QUANTUM* m_channels;
};
KisTransform() {};
virtual ~KisTransform() {};
class KisPixelRepresentation {
public:
KisPixelRepresentation(QUANTUM* channels) : m_channels(channels) {}
KisPixelRepresentation(int nbchannel) : m_channels(new QUANTUM(nbchannel)) { }
public:
KisQuantum operator[](int index) { return KisQuantum(&m_channels[index]); };
private:
QUANTUM* m_channels;
};
// XXX: conversions always via koColor; this class is BAD. RGB is unsuited as
// an intermediary colourspace format, and besides, we must use koColor and later
// littleCMS for that.
class KisPixelRepresentationRGB : public KisPixelRepresentation {
public:
inline KisPixelRepresentationRGB( const KisPixelRepresentation& pr) : KisPixelRepresentation(pr) { };
inline KisPixelRepresentationRGB( ) : KisPixelRepresentation(4) { };
public:
inline KisQuantum red() { return (*this)[PIXEL_RED]; };
inline KisQuantum green() { return (*this)[PIXEL_GREEN]; };
inline KisQuantum blue() { return (*this)[PIXEL_BLUE]; };
inline KisQuantum alpha() { return (*this)[PIXEL_ALPHA]; };
};
cmsHTRANSFORM m_transform;
};
#endif
#endif // KIS_TRANSFORM_H_
......@@ -32,7 +32,12 @@ class KisPattern;
class KisToolControllerInterface;
class KisUndoAdapter;
class KisProgressDisplayInterface;
class KisSelectionManager;
/**
* The canvas subject is the subset of operations that are directy available to
* tools.
*/
class KisCanvasSubject {
public:
KisCanvasSubject();
......@@ -59,7 +64,7 @@ public:
virtual KisProgressDisplayInterface *progressDisplay() const = 0;
virtual KisFilterSP filterGet(const QString& name) = 0;
virtual QStringList filterList() = 0;
virtual KisSelectionManager * selectionManager() = 0;
private:
KisCanvasSubject(const KisCanvasSubject&);
KisCanvasSubject& operator=(const KisCanvasSubject&);
......
......@@ -20,36 +20,48 @@
#include "qstring.h"
enum enumChannelType {
COLOR,
ALPHA,
SUBSTANCE
};
/**
* This class gives some basic information about a channel,
* that is, one of the components that makes up a particular
* pixel.
*/
class KisChannelInfo {
public:
KisChannelInfo() { };