File indexing completed on 2024-05-12 15:59:34
0001 /* 0002 * SPDX-FileCopyrightText: 2005 Boudewijn Rempt <boud@valdyas.org> 0003 * SPDX-FileCopyrightText: 2006-2007 Cyrille Berger <cberger@cberger.net> 0004 * SPDX-FileCopyrightText: 2021 L. E. Segovia <amy@amyspark.me> 0005 * 0006 * SPDX-License-Identifier: LGPL-2.1-or-later 0007 */ 0008 #ifndef KOCOLORSPACE_H 0009 #define KOCOLORSPACE_H 0010 0011 #include <climits> 0012 0013 #include <QImage> 0014 #include <QHash> 0015 #include <QVector> 0016 #include <QList> 0017 0018 #include <boost/operators.hpp> 0019 #include "KoColorSpaceConstants.h" 0020 #include "KoColorConversionTransformation.h" 0021 #include "KoColorProofingConversionTransformation.h" 0022 #include "KoCompositeOp.h" 0023 #include "KisDitherOp.h" 0024 #include <KoID.h> 0025 #include "kritapigment_export.h" 0026 0027 class QDomDocument; 0028 class QDomElement; 0029 class KoChannelInfo; 0030 class KoColorProfile; 0031 class KoColorTransformation; 0032 class QBitArray; 0033 0034 enum Deletability { 0035 OwnedByRegistryDoNotDelete, 0036 OwnedByRegistryRegistryDeletes, 0037 NotOwnedByRegistry 0038 }; 0039 0040 enum ColorSpaceIndependence { 0041 FULLY_INDEPENDENT, 0042 TO_LAB16, 0043 TO_RGBA8, 0044 TO_RGBA16 0045 }; 0046 0047 class KoMixColorsOp; 0048 class KoConvolutionOp; 0049 0050 /** 0051 * A KoColorSpace is the definition of a certain color space. 0052 * 0053 * A color model and a color space are two related concepts. A color 0054 * model is more general in that it describes the channels involved and 0055 * how they in broad terms combine to describe a color. Examples are 0056 * RGB, HSV, CMYK. 0057 * 0058 * A color space is more specific in that it also describes exactly how 0059 * the channels are combined. So for each color model there can be a 0060 * number of specific color spaces. So RGB is the model and sRGB, 0061 * adobeRGB, etc are colorspaces. 0062 * 0063 * In Pigment KoColorSpace acts as both a color model and a color space. 0064 * You can think of the class definition as the color model, but the 0065 * instance of the class as representing a colorspace. 0066 * 0067 * A third concept is the profile represented by KoColorProfile. It 0068 * represents the info needed to specialize a color model into a color 0069 * space. 0070 * 0071 * KoColorSpace is an abstract class serving as an interface. 0072 * 0073 * Subclasses implement actual color spaces 0074 * Some subclasses implement only some parts and are named Traits 0075 * 0076 */ 0077 class KRITAPIGMENT_EXPORT KoColorSpace : public boost::equality_comparable<KoColorSpace> 0078 { 0079 friend class KoColorSpaceRegistry; 0080 friend class KoColorSpaceFactory; 0081 protected: 0082 /// Only for use by classes that serve as baseclass for real color spaces 0083 KoColorSpace(); 0084 0085 public: 0086 0087 /// Should be called by real color spaces 0088 KoColorSpace(const QString &id, const QString &name, KoMixColorsOp *mixColorsOp, KoConvolutionOp *convolutionOp); 0089 0090 virtual bool operator==(const KoColorSpace& rhs) const; 0091 protected: 0092 virtual ~KoColorSpace(); 0093 0094 public: 0095 //========== Gamut and other basic info ===================================// 0096 /* 0097 * @returns QPolygonF with 5*channel samples converted to xyY. 0098 * maybe convert to 3d space in future? 0099 */ 0100 QPolygonF gamutXYY() const; 0101 0102 /* 0103 * @returns a polygon with 5 samples per channel converted to xyY, but unlike 0104 * gamutxyY it focuses on the luminance. This then can be used to visualise 0105 * the approximate trc of a given colorspace. 0106 */ 0107 QPolygonF estimatedTRCXYY() const; 0108 0109 QVector <qreal> lumaCoefficients() const; 0110 0111 //========== Channels =====================================================// 0112 0113 /// Return a list describing all the channels this color model has. The order 0114 /// of the channels in the list is the order of channels in the pixel. To find 0115 /// out the preferred display position, use KoChannelInfo::displayPosition. 0116 QList<KoChannelInfo *> channels() const; 0117 0118 /** 0119 * The total number of channels for a single pixel in this color model 0120 */ 0121 virtual quint32 channelCount() const = 0; 0122 0123 /** 0124 * Position of the alpha channel in a pixel 0125 */ 0126 virtual quint32 alphaPos() const = 0; 0127 0128 /** 0129 * The total number of color channels (excludes alpha) for a single 0130 * pixel in this color model. 0131 */ 0132 virtual quint32 colorChannelCount() const = 0; 0133 0134 /** 0135 * returns a QBitArray that contains true for the specified 0136 * channel types: 0137 * 0138 * @param color if true, set all color channels to true 0139 * @param alpha if true, set all alpha channels to true 0140 * 0141 * The order of channels is the colorspace descriptive order, 0142 * not the pixel order. 0143 */ 0144 QBitArray channelFlags(bool color = true, bool alpha = false) const; 0145 0146 /** 0147 * The size in bytes of a single pixel in this color model 0148 */ 0149 virtual quint32 pixelSize() const = 0; 0150 0151 /** 0152 * Return a string with the channel's value suitable for display in the gui. 0153 */ 0154 virtual QString channelValueText(const quint8 *pixel, quint32 channelIndex) const = 0; 0155 0156 /** 0157 * Return a string with the channel's value with integer 0158 * channels normalised to the floating point range 0 to 1, if 0159 * appropriate. 0160 */ 0161 virtual QString normalisedChannelValueText(const quint8 *pixel, quint32 channelIndex) const = 0; 0162 0163 /** 0164 * Return a QVector of floats with channels' values normalized 0165 * to floating point range 0 to 1. 0166 */ 0167 virtual void normalisedChannelsValue(const quint8 *pixel, QVector<float> &channels) const = 0; 0168 0169 /** 0170 * Write in the pixel the value from the normalized vector. 0171 */ 0172 virtual void fromNormalisedChannelsValue(quint8 *pixel, const QVector<float> &values) const = 0; 0173 0174 /** 0175 * Convert the value of the channel at the specified position into 0176 * an 8-bit value. The position is not the number of bytes, but 0177 * the position of the channel as defined in the channel info list. 0178 */ 0179 virtual quint8 scaleToU8(const quint8 * srcPixel, qint32 channelPos) const = 0; 0180 0181 /** 0182 * Set dstPixel to the pixel containing only the given channel of srcPixel. The remaining channels 0183 * should be set to whatever makes sense for 'empty' channels of this color space, 0184 * with the intent being that the pixel should look like it only has the given channel. 0185 */ 0186 virtual void singleChannelPixel(quint8 *dstPixel, const quint8 *srcPixel, quint32 channelIndex) const = 0; 0187 0188 //========== Identification ===============================================// 0189 0190 /** 0191 * ID for use in files and internally: unchanging name. As the id must be unique 0192 * it is usually the concatenation of the id of the color model and of the color 0193 * depth, for instance "RGBA8" or "CMYKA16" or "XYZA32f". 0194 */ 0195 QString id() const; 0196 0197 /** 0198 * User visible name which contains the name of the color model and of the color depth. 0199 * For instance "RGBA (8-bits)" or "CMYKA (16-bits)". 0200 */ 0201 QString name() const; 0202 0203 /** 0204 * @return a string that identify the color model (for instance "RGB" or "CMYK" ...) 0205 * @see KoColorModelStandardIds.h 0206 */ 0207 virtual KoID colorModelId() const = 0; 0208 /** 0209 * @return a string that identify the bit depth (for instance "U8" or "F16" ...) 0210 * @see KoColorModelStandardIds.h 0211 */ 0212 virtual KoID colorDepthId() const = 0; 0213 0214 /** 0215 * @return true if the profile given in argument can be used by this color space 0216 */ 0217 virtual bool profileIsCompatible(const KoColorProfile* profile) const = 0; 0218 0219 /** 0220 * If false, images in this colorspace will degrade considerably by 0221 * functions, tools and filters that have the given measure of colorspace 0222 * independence. 0223 * 0224 * @param independence the measure to which this colorspace will suffer 0225 * from the manipulations of the tool or filter asking 0226 * @return false if no degradation will take place, true if degradation will 0227 * take place 0228 */ 0229 virtual bool willDegrade(ColorSpaceIndependence independence) const = 0; 0230 0231 //========== Capabilities =================================================// 0232 0233 /** 0234 * Tests if the colorspace offers the specific composite op. 0235 * @param srcSpace optional source color space. Some color spaces prefer blitting in source 0236 * color space. If already known, additional composite ops may be available. 0237 */ 0238 virtual bool hasCompositeOp(const QString & id, const KoColorSpace *srcSpace = nullptr) const; 0239 0240 /** 0241 * Returns the list of user-visible composite ops supported by this colorspace. 0242 */ 0243 virtual QList<KoCompositeOp*> compositeOps() const; 0244 0245 /** 0246 * Retrieve a single composite op from the ones this colorspace offers. 0247 * If the requeste composite op does not exist, COMPOSITE_OVER is returned. 0248 * @param srcSpace optional source color space. Some color spaces prefer blitting in source 0249 * color space. If already known, additional composite ops may be available. 0250 * _Note_: if given, the returned op is only safe to use with this exact source color space! 0251 */ 0252 const KoCompositeOp * compositeOp(const QString & id, const KoColorSpace *srcSpace = nullptr) const; 0253 0254 /** 0255 * add a composite op to this colorspace. 0256 */ 0257 virtual void addCompositeOp(const KoCompositeOp * op); 0258 0259 /** 0260 * Returns true if the colorspace supports channel values outside the 0261 * (normalised) range 0 to 1. 0262 */ 0263 virtual bool hasHighDynamicRange() const = 0; 0264 0265 //========== Display profiles =============================================// 0266 0267 /** 0268 * Return the profile of this color space. 0269 */ 0270 virtual const KoColorProfile * profile() const = 0; 0271 0272 0273 //================= Conversion functions ==================================// 0274 0275 0276 /** 0277 * The fromQColor methods take a given color defined as an RGB QColor 0278 * and fills a byte array with the corresponding color in the 0279 * the colorspace managed by this strategy. 0280 * 0281 * @param color the QColor that will be used to fill dst 0282 * @param dst a pointer to a pixel 0283 * @param profile the optional profile that describes the color values of QColor 0284 */ 0285 virtual void fromQColor(const QColor& color, quint8 *dst, const KoColorProfile * profile = 0) const = 0; 0286 0287 /** 0288 * The toQColor methods take a byte array that is at least pixelSize() long 0289 * and converts the contents to a QColor, using the given profile as a source 0290 * profile and the optional profile as a destination profile. 0291 * 0292 * @param src a pointer to the source pixel 0293 * @param c the QColor that will be filled with the color at src 0294 * @param profile the optional profile that describes the color in c, for instance the monitor profile 0295 */ 0296 virtual void toQColor(const quint8 *src, QColor *c, const KoColorProfile * profile = 0) const = 0; 0297 0298 /** 0299 * The toQColor16 methods take a byte array that is at least pixelSize() long 0300 * and converts the contents to a 16 bit QColor, using the given profile as a source 0301 * profile and the optional profile as a destination profile. 0302 * 0303 * @param src a pointer to the source pixel 0304 * @param c the QColor that will be filled with the color at src 0305 * @param profile the optional profile that describes the color in c, for instance the monitor profile 0306 */ 0307 virtual void toQColor16(const quint8 *src, QColor *c, const KoColorProfile * profile = 0) const = 0; 0308 0309 /** 0310 * Convert the pixels in data to (8-bit BGRA) QImage using the specified profiles. 0311 * 0312 * @param data A pointer to a contiguous memory region containing width * height pixels 0313 * @param width in pixels 0314 * @param height in pixels 0315 * @param dstProfile destination profile 0316 * @param renderingIntent the rendering intent 0317 * @param conversionFlags conversion flags 0318 */ 0319 virtual QImage convertToQImage(const quint8 *data, qint32 width, qint32 height, 0320 const KoColorProfile * dstProfile, 0321 KoColorConversionTransformation::Intent renderingIntent, 0322 KoColorConversionTransformation::ConversionFlags conversionFlags) const; 0323 0324 /** 0325 * Convert the specified data to Lab (D50). All colorspaces are guaranteed to support this 0326 * 0327 * @param src the source data 0328 * @param dst the destination data 0329 * @param nPixels the number of source pixels 0330 */ 0331 virtual void toLabA16(const quint8 * src, quint8 * dst, quint32 nPixels) const; 0332 0333 /** 0334 * Convert the specified data from Lab (D50). to this colorspace. All colorspaces are 0335 * guaranteed to support this. 0336 * 0337 * @param src the pixels in 16 bit lab format 0338 * @param dst the destination data 0339 * @param nPixels the number of pixels in the array 0340 */ 0341 virtual void fromLabA16(const quint8 * src, quint8 * dst, quint32 nPixels) const; 0342 0343 /** 0344 * Convert the specified data to sRGB 16 bits. All colorspaces are guaranteed to support this 0345 * 0346 * @param src the source data 0347 * @param dst the destination data 0348 * @param nPixels the number of source pixels 0349 */ 0350 virtual void toRgbA16(const quint8 * src, quint8 * dst, quint32 nPixels) const; 0351 0352 /** 0353 * Convert the specified data from sRGB 16 bits. to this colorspace. All colorspaces are 0354 * guaranteed to support this. 0355 * 0356 * @param src the pixels in 16 bit rgb format 0357 * @param dst the destination data 0358 * @param nPixels the number of pixels in the array 0359 */ 0360 virtual void fromRgbA16(const quint8 * src, quint8 * dst, quint32 nPixels) const; 0361 0362 /** 0363 * Create a color conversion transformation. 0364 */ 0365 virtual KoColorConversionTransformation* createColorConverter(const KoColorSpace * dstColorSpace, 0366 KoColorConversionTransformation::Intent renderingIntent, 0367 KoColorConversionTransformation::ConversionFlags conversionFlags) const; 0368 0369 /** 0370 * Retrieve the elevate-to-normalized floating point dithering op. 0371 */ 0372 virtual const KisDitherOp *ditherOp(const QString &depth, DitherType type) const; 0373 0374 virtual void addDitherOp(KisDitherOp *op); 0375 0376 /** 0377 * Convert a byte array of srcLen pixels *src to the specified color space 0378 * and put the converted bytes into the prepared byte array *dst. 0379 * 0380 * Returns false if the conversion failed, true if it succeeded 0381 * 0382 * This function is not thread-safe. If you want to apply multiple conversion 0383 * in different threads at the same time, you need to create one color converter 0384 * per-thread using createColorConverter. 0385 */ 0386 virtual bool convertPixelsTo(const quint8 * src, 0387 quint8 * dst, const KoColorSpace * dstColorSpace, 0388 quint32 numPixels, 0389 KoColorConversionTransformation::Intent renderingIntent, 0390 KoColorConversionTransformation::ConversionFlags conversionFlags) const; 0391 0392 virtual KoColorConversionTransformation *createProofingTransform(const KoColorSpace * dstColorSpace, 0393 const KoColorSpace * proofingSpace, 0394 KoColorConversionTransformation::Intent renderingIntent, 0395 KoColorConversionTransformation::Intent proofingIntent, 0396 KoColorConversionTransformation::ConversionFlags conversionFlags, 0397 quint8 *gamutWarning, double adaptationState) const; 0398 /** 0399 * @brief proofPixelsTo 0400 * @param src source 0401 * @param dst destination 0402 * @param numPixels the amount of pixels. 0403 * @param proofingTransform the intent used for proofing. 0404 * @return 0405 */ 0406 virtual bool proofPixelsTo(const quint8 * src, 0407 quint8 * dst, 0408 quint32 numPixels, 0409 KoColorConversionTransformation *proofingTransform) const; 0410 0411 /** 0412 * Convert @p nPixels pixels in @p src into their human-visible 0413 * visual representation. The channel is shown as grayscale. 0414 * 0415 * Both buffers are in the same color space. 0416 * 0417 * @param src source buffer in (*this) color space 0418 * @param dst destination buffer in the same color space as @p src 0419 * @param nPixels length of the buffers in number of pixels 0420 * @param pixelSize stride of each pixel in the destination buffer 0421 * @param selectedChannelIndex Index of the selected channel. 0422 */ 0423 virtual void convertChannelToVisualRepresentation(const quint8 *src, quint8 *dst, quint32 nPixels, const qint32 selectedChannelIndex) const = 0; 0424 0425 /** 0426 * Convert @p nPixels pixels in @p src into their human-visible 0427 * visual representation. The channels are shown as if other channels were null (or, if Lab, L = 1.0, *a = *b = 0.0). 0428 * 0429 * Both buffers are in the same color space. 0430 * 0431 * @param src source buffer in (*this) color space 0432 * @param dst destination buffer in the same color space as @p src 0433 * @param nPixels length of the buffers in number of pixels 0434 * @param pixelSize stride of each pixel in the destination buffer 0435 * @param selectedChannels Bitmap of selected channels 0436 */ 0437 virtual void convertChannelToVisualRepresentation(const quint8 *src, quint8 *dst, quint32 nPixels, const QBitArray selectedChannels) const = 0; 0438 0439 //============================== Manipulation functions ==========================// 0440 0441 0442 // 0443 // The manipulation functions have default implementations that _convert_ the pixel 0444 // to a QColor and back. Reimplement these methods in your color strategy! 0445 // 0446 0447 /** 0448 * Get the alpha value of the given pixel, downscaled to an 8-bit value. 0449 */ 0450 virtual quint8 opacityU8(const quint8 * pixel) const = 0; 0451 virtual qreal opacityF(const quint8 * pixel) const = 0; 0452 0453 /** 0454 * Set the alpha channel of the given run of pixels to the given value. 0455 * 0456 * pixels -- a pointer to the pixels that will have their alpha set to this value 0457 * alpha -- a downscaled 8-bit value for opacity 0458 * nPixels -- the number of pixels 0459 * 0460 */ 0461 virtual void setOpacity(quint8 * pixels, quint8 alpha, qint32 nPixels) const = 0; 0462 virtual void setOpacity(quint8 * pixels, qreal alpha, qint32 nPixels) const = 0; 0463 0464 0465 /** 0466 * Copy the opacity of a run of pixels. 0467 * 0468 * src -- pixels to get opacity from. This is in the source colorspace. 0469 * dst -- pixels in Alpha8 colorspace to be assigned the opacity of src pixel 0470 * nPixels -- the number of pixels 0471 * 0472 */ 0473 virtual void copyOpacityU8(quint8* src, quint8* dst, qint32 nPixels) const = 0; 0474 0475 /** 0476 * Multiply the alpha channel of the given run of pixels by the given value. 0477 * 0478 * pixels -- a pointer to the pixels that will have their alpha set to this value 0479 * alpha -- a downscaled 8-bit value for opacity 0480 * nPixels -- the number of pixels 0481 * 0482 */ 0483 virtual void multiplyAlpha(quint8 * pixels, quint8 alpha, qint32 nPixels) const = 0; 0484 0485 /** 0486 * Applies the specified 8-bit alpha mask to the pixels. We assume that there are just 0487 * as many alpha values as pixels but we do not check this; the alpha values 0488 * are assumed to be 8-bits. 0489 */ 0490 virtual void applyAlphaU8Mask(quint8 * pixels, const quint8 * alpha, qint32 nPixels) const = 0; 0491 0492 /** 0493 * Applies the inverted 8-bit alpha mask to the pixels. We assume that there are just 0494 * as many alpha values as pixels but we do not check this; the alpha values 0495 * are assumed to be 8-bits. 0496 */ 0497 virtual void applyInverseAlphaU8Mask(quint8 * pixels, const quint8 * alpha, qint32 nPixels) const = 0; 0498 0499 /** 0500 * Applies the specified float alpha mask to the pixels. We assume that there are just 0501 * as many alpha values as pixels but we do not check this; alpha values have to be between 0.0 and 1.0 0502 */ 0503 virtual void applyAlphaNormedFloatMask(quint8 * pixels, const float * alpha, qint32 nPixels) const = 0; 0504 0505 /** 0506 * Applies the inverted specified float alpha mask to the pixels. We assume that there are just 0507 * as many alpha values as pixels but we do not check this; alpha values have to be between 0.0 and 1.0 0508 */ 0509 virtual void applyInverseNormedFloatMask(quint8 * pixels, const float * alpha, qint32 nPixels) const = 0; 0510 0511 /** 0512 * Fills \p pixels with specified \p brushColor and then applies inverted brush 0513 * mask specified in \p alpha. 0514 */ 0515 virtual void fillInverseAlphaNormedFloatMaskWithColor(quint8 * pixels, const float * alpha, const quint8 *brushColor, qint32 nPixels) const = 0; 0516 0517 /** 0518 * Fills \p dst with specified \p brushColor and then applies inverted brush 0519 * mask specified in \p brush. Premultiplied red channel of the brush is 0520 * used as an alpha channel for destination pixels. 0521 * 0522 * The equation is: 0523 * 0524 * dstC = colorC; 0525 * dstA = qAlpha(brush) * (255 - qRed(brush)) / 255; 0526 */ 0527 virtual void fillGrayBrushWithColor(quint8 *dst, const QRgb *brush, quint8 *brushColor, qint32 nPixels) const = 0; 0528 0529 /** 0530 * Fills \p dst with specified \p brushColor and then applies inverted brush 0531 * mask specified in \p brush. Inverted red channel of the brush is used 0532 * as lightness of the destination. Alpha channel of the brush is used as 0533 * alpha of the destination. 0534 * 0535 * The equation is: 0536 * 0537 * dstL_hsl = preserveLightness(colorL_hsl, lightFactor); 0538 * dstA = qAlpha(brush); 0539 * 0540 * For details on preserveLightness() formula, 0541 * see KoColorSpacePreserveLightnessUtils.h 0542 */ 0543 virtual void fillGrayBrushWithColorAndLightnessOverlay(quint8 *dst, const QRgb *brush, quint8 *brushColor, qint32 nPixels) const; 0544 // Same as above, but with contrast adjusted by strength. Strength == 1 -> full contrast. Allows softer lightness adjustments. 0545 virtual void fillGrayBrushWithColorAndLightnessWithStrength(quint8* dst, const QRgb* brush, quint8* brushColor, qreal strength, qint32 nPixels) const; 0546 // Same as above, but applies lightness adjustment to \p dst in-place 0547 virtual void modulateLightnessByGrayBrush(quint8* dst, const QRgb *brush, qreal strength, qint32 nPixels) const; 0548 0549 /** 0550 * Create an adjustment object for adjusting the brightness and contrast 0551 * transferValues is a 256 bins array with values from 0 to 0xFFFF 0552 * This function is thread-safe, but you need to create one KoColorTransformation per thread. 0553 */ 0554 virtual KoColorTransformation *createBrightnessContrastAdjustment(const quint16 *transferValues) const = 0; 0555 0556 /** 0557 * Create an adjustment object for adjusting individual channels 0558 * transferValues is an array of colorChannelCount number of 256 bins array with values from 0 to 0xFFFF 0559 * This function is thread-safe, but you need to create one KoColorTransformation per thread. 0560 * 0561 * The layout of the channels must be the following: 0562 * 0563 * 0..N-2 - color channels of the pixel; 0564 * N-1 - alpha channel of the pixel (if exists) 0565 */ 0566 virtual KoColorTransformation *createPerChannelAdjustment(const quint16 * const* transferValues) const = 0; 0567 0568 /** 0569 * Darken all color channels with the given amount. If compensate is true, 0570 * the compensation factor will be used to limit the darkening. 0571 * 0572 */ 0573 virtual KoColorTransformation *createDarkenAdjustment(qint32 shade, bool compensate, qreal compensation) const = 0; 0574 0575 /** 0576 * Invert color channels of the given pixels 0577 * This function is thread-safe, but you need to create one KoColorTransformation per thread. 0578 */ 0579 virtual KoColorTransformation *createInvertTransformation() const = 0; 0580 0581 /** 0582 * Get the difference between 2 colors, normalized in the range (0,255). Only completely 0583 * opaque and completely transparent are taken into account when computing the difference; 0584 * other transparency levels are not regarded when finding the difference. 0585 * 0586 * Completely transparent pixels are treated as if they are completely 0587 * different from any non-transparent pixels. 0588 */ 0589 virtual quint8 difference(const quint8* src1, const quint8* src2) const = 0; 0590 0591 /** 0592 * Get the difference between 2 colors, normalized in the range (0,255). This function 0593 * takes the Alpha channel of the pixel into account. Alpha channel has the same 0594 * weight as Lightness channel. 0595 * 0596 * Completely transparent pixels are treated as if their color channels are 0597 * the same as ones of the other pixel. In other words, only alpha channel 0598 * difference is compared. 0599 */ 0600 virtual quint8 differenceA(const quint8* src1, const quint8* src2) const = 0; 0601 0602 /** 0603 * @return the mix color operation of this colorspace (do not delete it locally, it's deleted by the colorspace). 0604 */ 0605 virtual KoMixColorsOp* mixColorsOp() const; 0606 0607 /** 0608 * @return the convolution operation of this colorspace (do not delete it locally, it's deleted by the colorspace). 0609 */ 0610 virtual KoConvolutionOp* convolutionOp() const; 0611 0612 /** 0613 * Calculate the intensity of the given pixel, scaled down to the range 0-255. XXX: Maybe this should be more flexible 0614 */ 0615 virtual quint8 intensity8(const quint8 * src) const = 0; 0616 0617 /** 0618 * Calculate the intensity of the given pixel, scaled down to the range 0-1 0619 */ 0620 virtual qreal intensityF(const quint8 * src) const = 0; 0621 0622 /* 0623 *increase luminosity by step 0624 */ 0625 virtual void increaseLuminosity(quint8 * pixel, qreal step) const; 0626 virtual void decreaseLuminosity(quint8 * pixel, qreal step) const; 0627 virtual void increaseSaturation(quint8 * pixel, qreal step) const; 0628 virtual void decreaseSaturation(quint8 * pixel, qreal step) const; 0629 virtual void increaseHue(quint8 * pixel, qreal step) const; 0630 virtual void decreaseHue(quint8 * pixel, qreal step) const; 0631 virtual void increaseRed(quint8 * pixel, qreal step) const; 0632 virtual void increaseGreen(quint8 * pixel, qreal step) const; 0633 virtual void increaseBlue(quint8 * pixel, qreal step) const; 0634 virtual void increaseYellow(quint8 * pixel, qreal step) const; 0635 virtual void toHSY(const QVector<double> &channelValues, qreal *hue, qreal *sat, qreal *luma) const = 0; 0636 virtual QVector <double> fromHSY(qreal *hue, qreal *sat, qreal *luma) const = 0; 0637 virtual void toYUV(const QVector<double> &channelValues, qreal *y, qreal *u, qreal *v) const = 0; 0638 virtual QVector <double> fromYUV(qreal *y, qreal *u, qreal *v) const = 0; 0639 /** 0640 * Compose two arrays of pixels together. If source and target 0641 * are not the same color model, the source pixels will be 0642 * converted to the target model. We're "dst" -- "dst" pixels are always in _this_ 0643 * colorspace. 0644 * 0645 * @param srcSpace the colorspace of the source pixels that will be composited onto "us" 0646 * @param params the information needed for blitting e.g. the source and destination pixel data, 0647 * the opacity and flow, ... 0648 * @param op the composition operator instance to use, e.g. COPY_OVER. 0649 * This operator must belong to this (dst) color space, UNLESS preferCompositionInSourceColorSpace() 0650 * returns true. In this case, the operator should be from the source color space. Besides avoiding 0651 * recurring lookups via ::compositeOp(), this is necessary if this color space does not implement 0652 * the desired composite op, but srcPace does. 0653 * Use ::compositeOp() with valid srcSpace to get the appropriate op. 0654 * 0655 * @param renderingIntent the rendering intent 0656 * @param conversionFlags the conversion flags. 0657 * 0658 */ 0659 virtual void bitBlt(const KoColorSpace* srcSpace, const KoCompositeOp::ParameterInfo& params, const KoCompositeOp* op, 0660 KoColorConversionTransformation::Intent renderingIntent, 0661 KoColorConversionTransformation::ConversionFlags conversionFlags) const; 0662 0663 /** 0664 * Serialize this color following Create's swatch color specification available 0665 * at https://web.archive.org/web/20110826002520/http://create.freedesktop.org/wiki/Swatches_-_color_file_format/Draft 0666 * 0667 * This function doesn't create the \<color /\> element but rather the \<CMYK /\>, 0668 * \<sRGB /\>, \<RGB /\> ... elements. It is assumed that colorElt is the \<color /\> 0669 * element. 0670 * 0671 * @param pixel buffer to serialized 0672 * @param colorElt root element for the serialization, it is assumed that this 0673 * element is \<color /\> 0674 * @param doc is the document containing colorElt 0675 */ 0676 virtual void colorToXML(const quint8* pixel, QDomDocument& doc, QDomElement& colorElt) const = 0; 0677 0678 /** 0679 * Unserialize a color following Create's swatch color specification available 0680 * at https://web.archive.org/web/20110826002520/http://create.freedesktop.org/wiki/Swatches_-_color_file_format/Draft 0681 * 0682 * @param pixel buffer where the color will be unserialized 0683 * @param elt the element to unserialize (\<CMYK /\>, \<sRGB /\>, \<RGB /\>) 0684 * @return the unserialize color, or an empty color object if the function failed 0685 * to unserialize the color 0686 */ 0687 virtual void colorFromXML(quint8* pixel, const QDomElement& elt) const = 0; 0688 0689 KoColorTransformation* createColorTransformation(const QString & id, const QHash<QString, QVariant> & parameters) const; 0690 0691 protected: 0692 0693 /** 0694 * Use this function in the constructor of your colorspace to add the information about a channel. 0695 * @param ci a pointer to the information about a channel 0696 */ 0697 virtual void addChannel(KoChannelInfo * ci); 0698 const KoColorConversionTransformation* toLabA16Converter() const; 0699 const KoColorConversionTransformation* fromLabA16Converter() const; 0700 const KoColorConversionTransformation* toRgbA16Converter() const; 0701 const KoColorConversionTransformation* fromRgbA16Converter() const; 0702 0703 /** 0704 * Returns the thread-local conversion cache. If it doesn't exist 0705 * yet, it is created. If it is currently too small, it is resized. 0706 */ 0707 QVector<quint8> * threadLocalConversionCache(quint32 size) const; 0708 0709 /** 0710 * This function defines the behavior of the bitBlt function 0711 * when the composition of pixels in different colorspaces is 0712 * requested, that is in case: 0713 * 0714 * srcCS == any 0715 * dstCS == this 0716 * 0717 * 1) preferCompositionInSourceColorSpace() == false, 0718 * 0719 * the source pixels are first converted to *this color space 0720 * and then composition is performed. 0721 * 0722 * 2) preferCompositionInSourceColorSpace() == true, 0723 * 0724 * the destination pixels are first converted into *srcCS color 0725 * space, then the composition is done, and the result is finally 0726 * converted into *this colorspace. 0727 * 0728 * This is used by alpha8() color space mostly, because it has 0729 * weaker representation of the color, so the composition 0730 * should be done in CS with richer functionality. 0731 */ 0732 virtual bool preferCompositionInSourceColorSpace() const; 0733 0734 0735 struct Private; 0736 Private * const d; 0737 0738 }; 0739 0740 inline QDebug operator<<(QDebug dbg, const KoColorSpace *cs) 0741 { 0742 if (cs) { 0743 dbg.nospace() << cs->name() << " (" << cs->colorModelId().id() << "," << cs->colorDepthId().id() << " )"; 0744 } else { 0745 dbg.nospace() << "0x0"; 0746 } 0747 0748 return dbg.space(); 0749 } 0750 0751 0752 #endif // KOCOLORSPACE_H