/* * Copyright (c) 2002 Patrick Julien * Copyright (c) 2004 Cyrille Berger * * 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 #include #include #include #include #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 parent the registry that owns this instance * @param profile the profile this colorspace uses for transforms */ KisAbstractColorSpace(const KisID & id, DWORD cmType, icColorSpaceSignature colorSpaceSignature, KisColorSpaceFactoryRegistry * parent, 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 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 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(srcRowStart); ColorType *dst = reinterpret_cast(dstRowStart); const TQ_UINT8 *mask = maskRowStart; TQ_INT32 columns = numColumns; while (columns > 0) { ColorType srcAlpha = src[AlphaPos]; ColorType dstAlpha = dst[AlphaPos]; // apply the alphamask if(mask != 0) { if(*mask != OPACITY_OPAQUE) srcAlpha = nativeMult(srcAlpha, uint8ToNative(*mask)); mask++; } 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 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 TransformMap; TransformMap m_transforms; // Cache for existing transforms KisAbstractColorSpace(const KisAbstractColorSpace&); KisAbstractColorSpace& operator=(const KisAbstractColorSpace&); TQMemArray m_conversionCache; // XXX: This will be a bad problem when we have threading. }; #endif // KIS_STRATEGY_COLORSPACE_H_