Warning, file /office/calligra/libs/pigment/KoColorSpaceAbstract.h was not indexed or was modified since last indexation (in which case cross-reference links may be missing, inaccurate or erroneous).

0001 /*
0002  *  Copyright (c) 2006 Cyrille Berger <cberger@cberger.net>
0003  *  Copyright (c) 2007 Emanuele Tamponi <emanuele@valinor.it>
0004  *
0005  * This library is free software; you can redistribute it and/or
0006  * modify it under the terms of the GNU Lesser General Public
0007  * License as published by the Free Software Foundation; either
0008  * version 2.1 of the License, or (at your option) any later version.
0009  *
0010  * This library is distributed in the hope that it will be useful,
0011  * but WITHOUT ANY WARRANTY; without even the implied warranty of
0012  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
0013  * Lesser General Public License for more details.
0014  *
0015  * You should have received a copy of the GNU Lesser General Public License
0016  * along with this library; see the file COPYING.LIB.  If not, write to
0017  * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
0018  * Boston, MA 02110-1301, USA.
0019 */
0020 
0021 #ifndef KOCOLORSPACEABSTRACT_H
0022 #define KOCOLORSPACEABSTRACT_H
0023 
0024 #include <QBitArray>
0025 #include <klocalizedstring.h>
0026 
0027 #include <KoColorSpace.h>
0028 #include <KoColorProfile.h>
0029 #include <KoColorSpaceMaths.h>
0030 #include <KoColorSpaceRegistry.h>
0031 #include "KoFallBackColorTransformation.h"
0032 #include "KoLabDarkenColorTransformation.h"
0033 #include "KoMixColorsOpImpl.h"
0034 
0035 #include "KoConvolutionOpImpl.h"
0036 #include "KoInvertColorTransformation.h"
0037 
0038 
0039 /**
0040  * This in an implementation of KoColorSpace which can be used as a base for colorspaces with as many
0041  * different channels of the same type.
0042  *
0043  * The template parameters must be a class which inherits KoColorSpaceTrait (or a class with the same signature).
0044  *
0045  * SOMETYPE is the type of the channel for instance (quint8, quint32...),
0046  * SOMENBOFCHANNELS is the number of channels including the alpha channel
0047  * SOMEALPHAPOS is the position of the alpha channel in the pixel (can be equal to -1 if no alpha channel).
0048  */
0049 template<class _CSTrait>
0050 class KoColorSpaceAbstract : public KoColorSpace
0051 {
0052 public:
0053     KoColorSpaceAbstract(const QString &id, const QString &name) :
0054         KoColorSpace(id, name, new KoMixColorsOpImpl< _CSTrait>(), new KoConvolutionOpImpl< _CSTrait>()) {
0055     }
0056 
0057     quint32 colorChannelCount() const override {
0058         if (_CSTrait::alpha_pos == -1)
0059             return _CSTrait::channels_nb;
0060         else
0061             return _CSTrait::channels_nb - 1;
0062     }
0063 
0064     quint32 channelCount() const override {
0065         return _CSTrait::channels_nb;
0066     }
0067 
0068     quint32 pixelSize() const override {
0069         return _CSTrait::pixelSize;
0070     }
0071 
0072     QString channelValueText(const quint8 *pixel, quint32 channelIndex) const override {
0073         return _CSTrait::channelValueText(pixel, channelIndex);
0074     }
0075 
0076     QString normalisedChannelValueText(const quint8 *pixel, quint32 channelIndex) const override {
0077         return _CSTrait::normalisedChannelValueText(pixel, channelIndex);
0078     }
0079 
0080     void normalisedChannelsValue(const quint8 *pixel, QVector<qreal> &channels) const override {
0081         return _CSTrait::normalisedChannelsValue(pixel, channels);
0082     }
0083 
0084     void fromNormalisedChannelsValue(quint8 *pixel, const QVector<qreal> &values) const override {
0085         return _CSTrait::fromNormalisedChannelsValue(pixel, values);
0086     }
0087 
0088     quint8 scaleToU8(const quint8 * srcPixel, qint32 channelIndex) const override {
0089         typename _CSTrait::channels_type c = _CSTrait::nativeArray(srcPixel)[channelIndex];
0090         return KoColorSpaceMaths<typename _CSTrait::channels_type, quint8>::scaleToA(c);
0091     }
0092 
0093     void singleChannelPixel(quint8 *dstPixel, const quint8 *srcPixel, quint32 channelIndex) const override {
0094         _CSTrait::singleChannelPixel(dstPixel, srcPixel, channelIndex);
0095     }
0096 
0097     quint8 opacityU8(const quint8 * U8_pixel) const override {
0098         return _CSTrait::opacityU8(U8_pixel);
0099     }
0100 
0101     qreal opacityF(const quint8 * U8_pixel) const override {
0102         return _CSTrait::opacityF(U8_pixel);
0103     }
0104 
0105     void setOpacity(quint8 * pixels, quint8 alpha, qint32 nPixels) const override {
0106         _CSTrait::setOpacity(pixels, alpha, nPixels);
0107     }
0108 
0109     void setOpacity(quint8 * pixels, qreal alpha, qint32 nPixels) const override {
0110         _CSTrait::setOpacity(pixels, alpha, nPixels);
0111     }
0112 
0113     void multiplyAlpha(quint8 * pixels, quint8 alpha, qint32 nPixels) const override {
0114         _CSTrait::multiplyAlpha(pixels, alpha, nPixels);
0115     }
0116 
0117     void applyAlphaU8Mask(quint8 * pixels, const quint8 * alpha, qint32 nPixels) const override {
0118         _CSTrait::applyAlphaU8Mask(pixels, alpha, nPixels);
0119     }
0120 
0121     void applyInverseAlphaU8Mask(quint8 * pixels, const quint8 * alpha, qint32 nPixels) const override {
0122         _CSTrait::applyInverseAlphaU8Mask(pixels, alpha, nPixels);
0123     }
0124 
0125     void applyAlphaNormedFloatMask(quint8 * pixels, const float * alpha, qint32 nPixels) const override {
0126         _CSTrait::applyAlphaNormedFloatMask(pixels, alpha, nPixels);
0127     }
0128 
0129     void applyInverseNormedFloatMask(quint8 * pixels, const float * alpha, qint32 nPixels) const override {
0130         _CSTrait::applyInverseAlphaNormedFloatMask(pixels, alpha, nPixels);
0131     }
0132 
0133     quint8 intensity8(const quint8 * src) const override {
0134         QColor c;
0135         const_cast<KoColorSpaceAbstract<_CSTrait> *>(this)->toQColor(src, &c);
0136         return static_cast<quint8>((c.red() * 0.30 + c.green() * 0.59 + c.blue() * 0.11) + 0.5);
0137     }
0138 
0139     KoColorTransformation* createInvertTransformation() const override {
0140         return new KoInvertColorTransformation(this);
0141     }
0142 
0143     KoColorTransformation *createDarkenAdjustment(qint32 shade, bool compensate, qreal compensation) const override {
0144         return new KoFallBackColorTransformation(this, KoColorSpaceRegistry::instance()->lab16(""), new KoLabDarkenColorTransformation<quint16>(shade, compensate, compensation, KoColorSpaceRegistry::instance()->lab16("")));
0145     }
0146 
0147     bool convertPixelsTo(const quint8 *src,
0148                                  quint8 *dst, const KoColorSpace *dstColorSpace,
0149                                  quint32 numPixels,
0150                                  KoColorConversionTransformation::Intent renderingIntent,
0151                                  KoColorConversionTransformation::ConversionFlags conversionFlags) const override
0152     {
0153         
0154         // check whether we have the same profile and color model, but only a different bit
0155         // depth; in that case we don't convert as such, but scale
0156         bool scaleOnly = false;
0157 
0158         // Note: getting the id() is really, really expensive, so only do that if
0159         // we are sure there is a difference between the colorspaces
0160         if (!(*this == *dstColorSpace)) {
0161             scaleOnly = dstColorSpace->colorModelId().id() == colorModelId().id() &&
0162                          dstColorSpace->colorDepthId().id() != colorDepthId().id() &&
0163                          dstColorSpace->profile()->name()   == profile()->name();
0164         }
0165         
0166         if (scaleOnly && dynamic_cast<const KoColorSpaceAbstract*>(dstColorSpace)) {
0167             typedef typename _CSTrait::channels_type channels_type;
0168             
0169             switch(dstColorSpace->channels().at(0)->channelValueType())
0170             {
0171             case KoChannelInfo::UINT8:
0172                 scalePixels<_CSTrait::pixelSize, 1, channels_type, quint8>(src, dst, numPixels);
0173                 return true;
0174 //             case KoChannelInfo::INT8:
0175 //                 scalePixels<_CSTrait::pixelSize, 1, channels_type, qint8>(src, dst, numPixels);
0176 //                 return true;
0177             case KoChannelInfo::UINT16:
0178                 scalePixels<_CSTrait::pixelSize, 2, channels_type, quint16>(src, dst, numPixels);
0179                 return true;
0180             case KoChannelInfo::INT16:
0181                 scalePixels<_CSTrait::pixelSize, 2, channels_type, qint16>(src, dst, numPixels);
0182                 return true;
0183             case KoChannelInfo::UINT32:
0184                 scalePixels<_CSTrait::pixelSize, 4, channels_type, quint32>(src, dst, numPixels);
0185                 return true;
0186             default:
0187                 break;
0188             }
0189         }
0190         
0191         return KoColorSpace::convertPixelsTo(src, dst, dstColorSpace, numPixels, renderingIntent, conversionFlags);
0192     }
0193     
0194 private:
0195     template<int srcPixelSize, int dstChannelSize, class TSrcChannel, class TDstChannel>
0196     void scalePixels(const quint8* src, quint8* dst, quint32 numPixels) const {
0197         qint32 dstPixelSize = dstChannelSize * _CSTrait::channels_nb;
0198         
0199         for(quint32 i=0; i<numPixels; ++i) {
0200             const TSrcChannel* srcPixel = reinterpret_cast<const TSrcChannel*>(src + i * srcPixelSize);
0201             TDstChannel*       dstPixel = reinterpret_cast<TDstChannel*>(dst + i * dstPixelSize);
0202             
0203             for(quint32 c=0; c<_CSTrait::channels_nb; ++c)
0204                 dstPixel[c] = Arithmetic::scale<TDstChannel>(srcPixel[c]);
0205         }
0206     }
0207 };
0208 
0209 #endif // KOCOLORSPACEABSTRACT_H