File indexing completed on 2024-05-12 15:59:36

0001 /*
0002  *  SPDX-FileCopyrightText: 2018 Iván Santa María <ghevan@gmail.com>
0003  *  SPDX-FileCopyrightText: 2006 Cyrille Berger <cberger@cberger.net>
0004  *  SPDX-FileCopyrightText: 2007 Emanuele Tamponi <emanuele@valinor.it>
0005  *
0006  * SPDX-License-Identifier: LGPL-2.1-or-later
0007 */
0008 
0009 #ifndef KO_INVERT_COLOR_TRANSFORMATION_H
0010 #define KO_INVERT_COLOR_TRANSFORMATION_H
0011 
0012 #include "KoColorTransformation.h"
0013 
0014 #include "KoColorSpace.h"
0015 #include "KoColorSpaceMaths.h"
0016 
0017 #include "KoColorModelStandardIds.h"
0018 
0019 #include <KoConfig.h>
0020 #ifdef HAVE_OPENEXR
0021 #include <half.h>
0022 #endif
0023 class KoInvertColorTransformationT : public KoColorTransformation {
0024 
0025 public:
0026 
0027     KoInvertColorTransformationT(const KoColorSpace* cs)
0028         : m_colorSpace(cs)
0029         , m_psize(cs->pixelSize())
0030         , m_chanCount(cs->channelCount())
0031     {
0032         // Only invert COLOR channels
0033         QList<KoChannelInfo *> channels = cs->channels();
0034         for(quint8 i = 0; i < m_chanCount; i++){
0035             if(channels.at(i)->channelType() == KoChannelInfo::COLOR)
0036                 m_channels.append(i);
0037         }
0038     }
0039 
0040     template<typename T>
0041     void transformI(const quint8 *src, quint8 *dst, qint32 nPixels) const {
0042         T *m_rgba = (T*)(src);
0043         T *m_dst = (T*)(dst);
0044 
0045         while (nPixels--) {
0046             for(quint8 i : m_channels){
0047                 m_dst[i] = KoColorSpaceMaths<T>::invert(m_rgba[i]);
0048             }
0049             m_rgba += m_chanCount;
0050             m_dst += m_chanCount;
0051         }
0052 
0053     }
0054 
0055     void transformGen(const quint8 *src, quint8 *dst, qint32 nPixels) const {
0056         quint16 m_rgba[4];
0057         while (nPixels--) {
0058             m_colorSpace->toRgbA16(src, reinterpret_cast<quint8 *>(m_rgba), 1);
0059             m_rgba[0] = KoColorSpaceMathsTraits<quint16>::max - m_rgba[0];
0060             m_rgba[1] = KoColorSpaceMathsTraits<quint16>::max - m_rgba[1];
0061             m_rgba[2] = KoColorSpaceMathsTraits<quint16>::max - m_rgba[2];
0062             m_colorSpace->fromRgbA16(reinterpret_cast<quint8 *>(m_rgba), dst, 1);
0063             src += m_psize;
0064             dst += m_psize;
0065         }
0066     }
0067 
0068     // Once CMYK and LAB 32 float are normalized, this inverts will invert properly
0069 //    template<typename T>
0070 //    void transformC(const quint8 *src, quint8 *dst, qint32 nPixels) const {
0071 //        QVector<float> normChan(m_chanCount);
0072 
0073 //        float *m_rgba;
0074 //        float *m_dst = (float*)(dst);
0075 //        while (nPixels--) {
0076 //            m_colorSpace->normalisedChannelsValue(src, normChan);
0077 //            for(quint8 i : m_channels){
0078 //                normChan[i] = KoColorSpaceMaths<float>::invert(normChan[i]);
0079 //            }
0080 //            m_colorSpace->fromNormalisedChannelsValue(dst,normChan);
0081 //            //m_rgba += m_psize;
0082 //            src += m_psize;
0083 //            dst += m_psize;
0084 //        }
0085 //    }
0086 
0087 protected:
0088     QList<quint8> m_channels;
0089 private:
0090     const KoColorSpace* m_colorSpace;
0091     quint32 m_psize;
0092     quint32 m_chanCount;
0093 };
0094 
0095 class KoU8InvertColorTransformer : public KoInvertColorTransformationT {
0096 public:
0097     KoU8InvertColorTransformer(const KoColorSpace* cs)
0098        : KoInvertColorTransformationT(cs)
0099     {
0100     };
0101 
0102     void transform(const quint8 *src, quint8 *dst, qint32 nPixels) const override {
0103         transformI<quint8>(src,dst,nPixels);
0104     }
0105 };
0106 
0107 class KoU16InvertColorTransformer : public KoInvertColorTransformationT {
0108 public:
0109     KoU16InvertColorTransformer(const KoColorSpace* cs)
0110        : KoInvertColorTransformationT(cs)
0111     {
0112     };
0113 
0114     void transform(const quint8 *src, quint8 *dst, qint32 nPixels) const override {
0115         transformI<quint16>(src,dst,nPixels);
0116     }
0117 };
0118 
0119 #ifdef HAVE_OPENEXR
0120 class KoF16InvertColorTransformer : public KoInvertColorTransformationT {
0121 public:
0122     KoF16InvertColorTransformer(const KoColorSpace* cs)
0123        : KoInvertColorTransformationT(cs)
0124     {
0125     };
0126 
0127     void transform(const quint8 *src, quint8 *dst, qint32 nPixels) const override {
0128         transformI<half>(src,dst,nPixels);
0129     }
0130 };
0131 #endif
0132 
0133 class KoF32InvertColorTransformer : public KoInvertColorTransformationT {
0134 public:
0135     KoF32InvertColorTransformer(const KoColorSpace* cs)
0136        : KoInvertColorTransformationT(cs)
0137     {
0138     };
0139 
0140     void transform(const quint8 *src, quint8 *dst, qint32 nPixels) const override {
0141         transformI<float>(src,dst,nPixels);
0142     }
0143 };
0144 
0145 class KoF32GenInvertColorTransformer : public KoInvertColorTransformationT {
0146 public:
0147     KoF32GenInvertColorTransformer(const KoColorSpace* cs)
0148        : KoInvertColorTransformationT(cs)
0149     {
0150     };
0151 
0152     void transform(const quint8 *src, quint8 *dst, qint32 nPixels) const override {
0153         transformGen(src,dst,nPixels);
0154     }
0155 };
0156 
0157 
0158 class KoInvertColorTransformation
0159 {
0160 public:
0161   static KoColorTransformation* getTransformator(const KoColorSpace *cs)
0162   {
0163       KoID id = cs->colorDepthId();
0164       KoID modelId = cs->colorModelId();
0165       if (id == Integer8BitsColorDepthID) {
0166           return new KoU8InvertColorTransformer(cs);
0167       } else if (id == Integer16BitsColorDepthID) {
0168           return new KoU16InvertColorTransformer(cs);
0169 #ifdef HAVE_OPENEXR
0170       } else if (id == Float16BitsColorDepthID) {
0171           return new KoF16InvertColorTransformer(cs);
0172 #endif
0173       } else {
0174           if(modelId == LABAColorModelID || modelId == CMYKAColorModelID){
0175               return new KoF32GenInvertColorTransformer(cs);
0176           }
0177           return new KoF32InvertColorTransformer(cs);
0178       }
0179   }
0180 };
0181 
0182 #endif