1 /* 2 * Copyright (c) 2006-2007 Cyrille Berger <cberger@cberger.net> 3 * 4 * This library is free software; you can redistribute it and/or 5 * modify it under the terms of the GNU Lesser General Public 6 * License as published by the Free Software Foundation; either 7 * version 2.1 of the License, or (at your option) any later version. 8 * 9 * This library is distributed in the hope that it will be useful, 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 * Lesser General Public License for more details. 13 * 14 * You should have received a copy of the GNU Lesser General Public License 15 * along with this library; see the file COPYING.LIB. If not, write to 16 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 17 * Boston, MA 02110-1301, USA. 18 */ 19 20 #ifndef _KO_COLORSPACE_TRAITS_H_ 21 #define _KO_COLORSPACE_TRAITS_H_ 22 23 #include <QVector> 24 25 #include "KoColorSpaceConstants.h" 26 #include "KoColorSpaceMaths.h" 27 #include "DebugPigment.h" 28 29 /** 30 * This class is the base class to define the main characteristics of a colorspace 31 * which inherits KoColorSpaceAbstract. 32 * 33 * - _channels_type_ is the type of the value use for each channel, for example quint8 for 8bits per channel 34 * color spaces, or quint16 for 16bits integer per channel, float for 32bits per channel 35 * floating point color spaces 36 * - _channels_nb_ is the total number of channels in an image (for example RGB is 3 but RGBA is four) 37 * - _alpha_pos_ is the position of the alpha channel among the channels, if there is no alpha channel, 38 * then _alpha_pos_ is set to -1 39 * 40 * For instance a colorspace of three color channels and alpha channel in 16bits, 41 * will be defined as KoColorSpaceTrait\<quint16, 4, 3\>. The same without the alpha 42 * channel is KoColorSpaceTrait\<quint16,3,-1\> 43 * 44 */ 45 template<typename _channels_type_, int _channels_nb_, int _alpha_pos_> 46 struct KoColorSpaceTrait { 47 48 /// the type of the value of the channels of this color space 49 typedef _channels_type_ channels_type; 50 51 /// the number of channels in this color space 52 static const quint32 channels_nb = _channels_nb_; 53 54 /// the position of the alpha channel in the channels of the pixel (or -1 if no alpha 55 /// channel. 56 static const qint32 alpha_pos = _alpha_pos_; 57 58 /// the number of bit for each channel 59 static const int depth = KoColorSpaceMathsTraits<_channels_type_>::bits; 60 61 /** 62 * @return the size in byte of one pixel 63 */ 64 static const quint32 pixelSize = channels_nb * sizeof(channels_type); 65 66 /** 67 * @return the value of the alpha channel for this pixel in the 0..255 range 68 */ opacityU8KoColorSpaceTrait69 inline static quint8 opacityU8(const quint8 * U8_pixel) { 70 if (alpha_pos < 0) return OPACITY_OPAQUE_U8; 71 channels_type c = nativeArray(U8_pixel)[alpha_pos]; 72 return KoColorSpaceMaths<channels_type, quint8>::scaleToA(c); 73 } 74 opacityFKoColorSpaceTrait75 inline static qreal opacityF(const quint8 * U8_pixel) { 76 if (alpha_pos < 0) return OPACITY_OPAQUE_F; 77 channels_type c = nativeArray(U8_pixel)[alpha_pos]; 78 return KoColorSpaceMaths<channels_type, qreal>::scaleToA(c); 79 } 80 81 /** 82 * Set the alpha channel for this pixel from a value in the 0..255 range 83 */ setOpacityKoColorSpaceTrait84 inline static void setOpacity(quint8 * pixels, quint8 alpha, qint32 nPixels) { 85 if (alpha_pos < 0) return; 86 qint32 psize = pixelSize; 87 channels_type valpha = KoColorSpaceMaths<quint8, channels_type>::scaleToA(alpha); 88 for (; nPixels > 0; --nPixels, pixels += psize) { 89 nativeArray(pixels)[alpha_pos] = valpha; 90 } 91 } 92 setOpacityKoColorSpaceTrait93 inline static void setOpacity(quint8 * pixels, qreal alpha, qint32 nPixels) { 94 if (alpha_pos < 0) return; 95 qint32 psize = pixelSize; 96 channels_type valpha = KoColorSpaceMaths<qreal, channels_type>::scaleToA(alpha); 97 for (; nPixels > 0; --nPixels, pixels += psize) { 98 nativeArray(pixels)[alpha_pos] = valpha; 99 } 100 } 101 102 /** 103 * Convenient function for transforming a quint8* array in a pointer of the native channels type 104 */ nativeArrayKoColorSpaceTrait105 inline static const channels_type* nativeArray(const quint8 * a) { 106 return reinterpret_cast<const channels_type*>(a); 107 } 108 109 /** 110 * Convenient function for transforming a quint8* array in a pointer of the native channels type 111 */ nativeArrayKoColorSpaceTrait112 inline static channels_type* nativeArray(quint8 * a) { 113 return reinterpret_cast< channels_type*>(a); 114 } 115 116 /** 117 * Allocate nPixels pixels for this colorspace. 118 */ allocateKoColorSpaceTrait119 inline static quint8* allocate(quint32 nPixels) { 120 return new quint8[ nPixels * pixelSize ]; 121 } 122 singleChannelPixelKoColorSpaceTrait123 inline static void singleChannelPixel(quint8 *dstPixel, const quint8 *srcPixel, quint32 channelIndex) { 124 const channels_type* src = nativeArray(srcPixel); 125 channels_type* dst = nativeArray(dstPixel); 126 for (uint i = 0; i < channels_nb; i++) { 127 if (i != channelIndex) { 128 dst[i] = 0; 129 } else { 130 dst[i] = src[i]; 131 } 132 } 133 } 134 channelValueTextKoColorSpaceTrait135 inline static QString channelValueText(const quint8 *pixel, quint32 channelIndex) { 136 if (channelIndex > channels_nb) return QString("Error"); 137 channels_type c = nativeArray(pixel)[channelIndex]; 138 return QString().setNum(c); 139 } 140 normalisedChannelValueTextKoColorSpaceTrait141 inline static QString normalisedChannelValueText(const quint8 *pixel, quint32 channelIndex) { 142 if (channelIndex > channels_nb) return QString("Error"); 143 channels_type c = nativeArray(pixel)[channelIndex]; 144 return QString().setNum(100. *((qreal)c) / KoColorSpaceMathsTraits< channels_type>::unitValue); 145 } 146 normalisedChannelsValueKoColorSpaceTrait147 inline static void normalisedChannelsValue(const quint8 *pixel, QVector<qreal> &channels) { 148 Q_ASSERT((int)channels.count() == (int)channels_nb); 149 channels_type c; 150 for (uint i = 0; i < channels_nb; i++) { 151 c = nativeArray(pixel)[i]; 152 channels[i] = ((qreal)c) / KoColorSpaceMathsTraits<channels_type>::unitValue; 153 } 154 } 155 fromNormalisedChannelsValueKoColorSpaceTrait156 inline static void fromNormalisedChannelsValue(quint8 *pixel, const QVector<qreal> &values) { 157 Q_ASSERT((int)values.count() == (int)channels_nb); 158 channels_type c; 159 for (uint i = 0; i < channels_nb; i++) { 160 c = (channels_type) 161 ((float)KoColorSpaceMathsTraits<channels_type>::unitValue * values[i]); 162 nativeArray(pixel)[i] = c; 163 } 164 } multiplyAlphaKoColorSpaceTrait165 inline static void multiplyAlpha(quint8 * pixels, quint8 alpha, qint32 nPixels) { 166 if (alpha_pos < 0) return; 167 168 channels_type valpha = KoColorSpaceMaths<quint8, channels_type>::scaleToA(alpha); 169 170 for (; nPixels > 0; --nPixels, pixels += pixelSize) { 171 channels_type* alphapixel = nativeArray(pixels) + alpha_pos; 172 *alphapixel = KoColorSpaceMaths<channels_type>::multiply(*alphapixel, valpha); 173 } 174 } 175 applyAlphaU8MaskKoColorSpaceTrait176 inline static void applyAlphaU8Mask(quint8 * pixels, const quint8 * alpha, qint32 nPixels) { 177 if (alpha_pos < 0) return; 178 179 for (; nPixels > 0; --nPixels, pixels += pixelSize, ++alpha) { 180 channels_type valpha = KoColorSpaceMaths<quint8, channels_type>::scaleToA(*alpha); 181 channels_type* alphapixel = nativeArray(pixels) + alpha_pos; 182 *alphapixel = KoColorSpaceMaths<channels_type>::multiply(*alphapixel, valpha); 183 } 184 } 185 applyInverseAlphaU8MaskKoColorSpaceTrait186 inline static void applyInverseAlphaU8Mask(quint8 * pixels, const quint8 * alpha, qint32 nPixels) { 187 if (alpha_pos < 0) return; 188 189 for (; nPixels > 0; --nPixels, pixels += pixelSize, ++alpha) { 190 channels_type valpha = KoColorSpaceMaths<quint8, channels_type>::scaleToA(OPACITY_OPAQUE_U8 - *alpha); 191 channels_type* alphapixel = nativeArray(pixels) + alpha_pos; 192 *alphapixel = KoColorSpaceMaths<channels_type>::multiply(*alphapixel, valpha); 193 } 194 } 195 applyAlphaNormedFloatMaskKoColorSpaceTrait196 inline static void applyAlphaNormedFloatMask(quint8 * pixels, const float * alpha, qint32 nPixels) { 197 if (alpha_pos < 0) return; 198 199 for (; nPixels > 0; --nPixels, pixels += pixelSize, ++alpha) { 200 channels_type valpha = channels_type(KoColorSpaceMathsTraits<channels_type>::unitValue * (*alpha)); 201 channels_type* alphapixel = nativeArray(pixels) + alpha_pos; 202 *alphapixel = KoColorSpaceMaths<channels_type>::multiply(*alphapixel, valpha); 203 } 204 } 205 applyInverseAlphaNormedFloatMaskKoColorSpaceTrait206 inline static void applyInverseAlphaNormedFloatMask(quint8 * pixels, const float * alpha, qint32 nPixels) { 207 if (alpha_pos < 0) return; 208 209 for (; nPixels > 0; --nPixels, pixels += pixelSize, ++alpha) { 210 channels_type valpha = channels_type(KoColorSpaceMathsTraits<channels_type>::unitValue * (1.0f - *alpha)); 211 channels_type* alphapixel = nativeArray(pixels) + alpha_pos; 212 *alphapixel = KoColorSpaceMaths<channels_type>::multiply(*alphapixel, valpha); 213 } 214 } 215 }; 216 217 #include "KoRgbColorSpaceTraits.h" 218 #include "KoBgrColorSpaceTraits.h" 219 #include "KoGrayColorSpaceTraits.h" 220 #include "KoLabColorSpaceTraits.h" 221 #include "KoXyzColorSpaceTraits.h" 222 #include "KoYcbcrColorSpaceTraits.h" 223 #include "KoCmykColorSpaceTraits.h" 224 225 #endif 226