You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
koffice/chalk/chalkcolor/kis_abstract_colorspace.h

313 lines
12 KiB

/*
* Copyright (c) 2002 Patrick Julien <freak@codepimps.org>
* Copyright (c) 2004 Cyrille Berger <cberger@cberger.net>
*
* 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
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#ifndef KIS_ABSTRACT_COLORSPACE_H_
#define KIS_ABSTRACT_COLORSPACE_H_
#include <strings.h>
#include <tqmap.h>
#include <tqcolor.h>
#include <tqstringlist.h>
#include <tqpair.h>
#include "kis_global.h"
#include "kis_channelinfo.h"
#include "kis_profile.h"
#include "kis_id.h"
#include "kis_composite_op.h"
#include "kis_colorspace.h"
#include "koffice_export.h"
class TQPainter;
class KisPixelRO;
class KisColorSpaceFactoryRegistry;
/**
* A colorspace strategy is the definition of a certain color model
* in Chalk.
*/
class KRITA_EXPORT KisAbstractColorSpace : public KisColorSpace {
public:
/**
* @param id The unique human and machine readable identifiation of this colorspace
* @param cmType the lcms type indentification for this colorspace, may be 0
* @param colorSpaceSignature the icc identification for this colorspace, may be 0
* @param tqparent the registry that owns this instance
* @param profile the profile this colorspace uses for transforms
*/
KisAbstractColorSpace(const KisID & id,
DWORD cmType,
icColorSpaceSignature colorSpaceSignature,
KisColorSpaceFactoryRegistry * tqparent,
KisProfile *profile);
void init();
virtual ~KisAbstractColorSpace();
virtual bool operator==(const KisAbstractColorSpace& rhs) const {
return (m_id == rhs.m_id && m_profile == rhs.m_profile);
}
//================== Information about this color strategy ========================//
public:
//========== Channels =====================================================//
// Return a vector describing all the channels this color model has.
virtual TQValueVector<KisChannelInfo *> channels() const = 0;
virtual TQ_UINT32 nChannels() const = 0;
virtual TQ_UINT32 nColorChannels() const = 0;
virtual TQ_UINT32 nSubstanceChannels() const { return 0; };
virtual TQ_UINT32 pixelSize() const = 0;
virtual TQString channelValueText(const TQ_UINT8 *pixel, TQ_UINT32 channelIndex) const = 0;
virtual TQString normalisedChannelValueText(const TQ_UINT8 *pixel, TQ_UINT32 channelIndex) const = 0;
virtual TQ_UINT8 scaleToU8(const TQ_UINT8 * srcPixel, TQ_INT32 channelPos) = 0;
virtual TQ_UINT16 scaleToU16(const TQ_UINT8 * srcPixel, TQ_INT32 channelPos) = 0;
virtual void getSingleChannelPixel(TQ_UINT8 *dstPixel, const TQ_UINT8 *srcPixel, TQ_UINT32 channelIndex);
//========== Identification ===============================================//
virtual KisID id() const { return m_id; }
void setColorSpaceType(TQ_UINT32 type) { m_cmType = type; }
TQ_UINT32 colorSpaceType() { return m_cmType; }
virtual icColorSpaceSignature colorSpaceSignature() { return m_colorSpaceSignature; }
//========== Capabilities =================================================//
virtual KisCompositeOpList userVisiblecompositeOps() const = 0;
/**
* Returns true if the colorspace supports channel values outside the
* (normalised) range 0 to 1.
*/
virtual bool hasHighDynamicRange() const { return false; }
//========== Display profiles =============================================//
virtual KisProfile * getProfile() const { return m_profile; };
//================= Conversion functions ==================================//
virtual void fromTQColor(const TQColor& c, TQ_UINT8 *dst, KisProfile * profile = 0);
virtual void fromTQColor(const TQColor& c, TQ_UINT8 opacity, TQ_UINT8 *dst, KisProfile * profile = 0);
virtual void toTQColor(const TQ_UINT8 *src, TQColor *c, KisProfile * profile = 0);
virtual void toTQColor(const TQ_UINT8 *src, TQColor *c, TQ_UINT8 *opacity, KisProfile * profile = 0);
virtual void toLabA16(const TQ_UINT8 * src, TQ_UINT8 * dst, const TQ_UINT32 nPixels) const;
virtual void fromLabA16(const TQ_UINT8 * src, TQ_UINT8 * dst, const TQ_UINT32 nPixels) const;
virtual TQImage convertToTQImage(const TQ_UINT8 *data, TQ_INT32 width, TQ_INT32 height,
KisProfile * dstProfile,
TQ_INT32 renderingIntent = INTENT_PERCEPTUAL,
float exposure = 0.0f);
virtual bool convertPixelsTo(const TQ_UINT8 * src,
TQ_UINT8 * dst, KisColorSpace * dstColorSpace,
TQ_UINT32 numPixels,
TQ_INT32 renderingIntent = INTENT_PERCEPTUAL);
//============================== Manipulation fucntions ==========================//
//
// The manipulation functions have default implementations that _convert_ the pixel
// to a TQColor and back. Reimplement these methods in your color strategy!
//
virtual KisColorAdjustment *createBrightnessContrastAdjustment(TQ_UINT16 *transferValues);
virtual KisColorAdjustment *createDesaturateAdjustment();
virtual KisColorAdjustment *createPerChannelAdjustment(TQ_UINT16 **transferValues);
virtual void applyAdjustment(const TQ_UINT8 *src, TQ_UINT8 *dst, KisColorAdjustment *, TQ_INT32 nPixels);
virtual void invertColor(TQ_UINT8 * src, TQ_INT32 nPixels);
virtual TQ_UINT8 difference(const TQ_UINT8* src1, const TQ_UINT8* src2);
virtual void mixColors(const TQ_UINT8 **colors, const TQ_UINT8 *weights, TQ_UINT32 nColors, TQ_UINT8 *dst) const;
virtual void convolveColors(TQ_UINT8** colors, TQ_INT32* kernelValues, KisChannelInfo::enumChannelFlags channelFlags, TQ_UINT8 *dst, TQ_INT32 factor, TQ_INT32 offset, TQ_INT32 nPixels) const;
virtual void darken(const TQ_UINT8 * src, TQ_UINT8 * dst, TQ_INT32 shade, bool compensate, double compensation, TQ_INT32 nPixels) const;
virtual TQ_UINT8 intensity8(const TQ_UINT8 * src) const;
virtual KisID mathToolboxID() const;
virtual void bitBlt(TQ_UINT8 *dst,
TQ_INT32 dststride,
KisColorSpace * srcSpace,
const TQ_UINT8 *src,
TQ_INT32 srcRowStride,
const TQ_UINT8 *srcAlphaMask,
TQ_INT32 maskRowStride,
TQ_UINT8 opacity,
TQ_INT32 rows,
TQ_INT32 cols,
const KisCompositeOp& op);
//========================== END of Public API ========================================//
protected:
/**
* Compose two byte arrays containing pixels in the same color
* model together.
*/
virtual void bitBlt(TQ_UINT8 *dst,
TQ_INT32 dstRowSize,
const TQ_UINT8 *src,
TQ_INT32 srcRowStride,
const TQ_UINT8 *srcAlphaMask,
TQ_INT32 maskRowStride,
TQ_UINT8 opacity,
TQ_INT32 rows,
TQ_INT32 cols,
const KisCompositeOp& op) = 0;
virtual cmsHTRANSFORM createTransform(KisColorSpace * dstColorSpace,
KisProfile * srcProfile,
KisProfile * dstProfile,
TQ_INT32 renderingIntent);
virtual void compositeCopy(TQ_UINT8 *dstRowStart, TQ_INT32 dstRowStride, const TQ_UINT8 *srcRowStart, TQ_INT32 srcRowStride, const TQ_UINT8 *maskRowStart, TQ_INT32 maskRowStride, TQ_INT32 rows, TQ_INT32 numColumns, TQ_UINT8 opacity);
// So I don't need to re-implement it everywhere.
template <typename ColorType,
typename NativeMult, typename Uint8ToNative, typename NativeOpacityTest,
int AlphaPos, int NonAlphaSize, int TotalSize>
void abstractCompositeAlphaDarken(TQ_UINT8 *dstRowStart, TQ_INT32 dstRowStride,
const TQ_UINT8 *srcRowStart, TQ_INT32 srcRowStride,
const TQ_UINT8 *maskRowStart, TQ_INT32 maskRowStride,
TQ_INT32 rows, TQ_INT32 numColumns, TQ_UINT8 opacity,
NativeMult nativeMult, Uint8ToNative uint8ToNative,
NativeOpacityTest nativeOpacityTest) {
while (rows > 0) {
const ColorType *src = reinterpret_cast<const ColorType*>(srcRowStart);
ColorType *dst = reinterpret_cast<ColorType*>(dstRowStart);
const TQ_UINT8 *tqmask = maskRowStart;
TQ_INT32 columns = numColumns;
while (columns > 0) {
ColorType srcAlpha = src[AlphaPos];
ColorType dstAlpha = dst[AlphaPos];
// apply the alphatqmask
if(tqmask != 0)
{
if(*tqmask != OPACITY_OPAQUE)
srcAlpha = nativeMult(srcAlpha, uint8ToNative(*tqmask));
tqmask++;
}
if (opacity != OPACITY_OPAQUE) {
srcAlpha = nativeMult(srcAlpha, uint8ToNative(opacity));
}
// not transparent
if (nativeOpacityTest(srcAlpha) && srcAlpha >= dstAlpha) {
dst[AlphaPos] = srcAlpha;
memcpy(dst, src, NonAlphaSize * sizeof(ColorType));
}
columns--;
src += TotalSize;
dst += TotalSize;
}
rows--;
srcRowStart += srcRowStride;
dstRowStart += dstRowStride;
if(maskRowStart)
maskRowStart += maskRowStride;
}
}
protected:
TQStringList m_profileFilenames;
TQ_UINT8 * m_qcolordata; // A small buffer for conversion from and to qcolor.
TQ_INT32 m_alphaPos; // The position in _bytes_ of the alpha channel
TQ_INT32 m_alphaSize; // The width in _bytes_ of the alpha channel
TQValueVector<KisChannelInfo *> m_channels;
KisColorSpaceFactoryRegistry * m_parent;
private:
cmsHTRANSFORM m_defaultToRGB; // Default transform to 8 bit sRGB
cmsHTRANSFORM m_defaultFromRGB; // Default transform from 8 bit sRGB
cmsHPROFILE m_lastRGBProfile; // Last used profile to transform to/from RGB
cmsHTRANSFORM m_lastToRGB; // Last used transform to transform to RGB
cmsHTRANSFORM m_lastFromRGB; // Last used transform to transform from RGB
cmsHTRANSFORM m_defaultToLab;
cmsHTRANSFORM m_defaultFromLab;
KisProfile * m_profile;
KisColorSpace *m_lastUsedDstColorSpace;
cmsHTRANSFORM m_lastUsedTransform;
KisID m_id;
DWORD m_cmType; // The colorspace type as defined by littlecms
icColorSpaceSignature m_colorSpaceSignature; // The colorspace signature as defined in icm/icc files
// cmsHTRANSFORM is a void *, so this should work.
typedef TQMap<KisColorSpace *, cmsHTRANSFORM> TransformMap;
TransformMap m_transforms; // Cache for existing transforms
KisAbstractColorSpace(const KisAbstractColorSpace&);
KisAbstractColorSpace& operator=(const KisAbstractColorSpace&);
TQMemArray<TQ_UINT8> m_conversionCache; // XXX: This will be a bad problem when we have threading.
};
#endif // KIS_STRATEGY_COLORSPACE_H_