Warning, file /office/calligra/libs/pigment/KoMixColorsOpImpl.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 KOMIXCOLORSOPIMPL_H
0022 #define KOMIXCOLORSOPIMPL_H
0023 
0024 #include "KoMixColorsOp.h"
0025 
0026 template<class _CSTrait>
0027 class KoMixColorsOpImpl : public KoMixColorsOp
0028 {
0029 public:
0030     KoMixColorsOpImpl() {
0031     }
0032     ~KoMixColorsOpImpl() override { }
0033     void mixColors(const quint8 * const* colors, const qint16 *weights, quint32 nColors, quint8 *dst) const override {
0034         mixColorsImpl(ArrayOfPointers(colors), weights, nColors, dst);
0035     }
0036 
0037     void mixColors(const quint8 *colors, const qint16 *weights, quint32 nColors, quint8 *dst) const override {
0038         mixColorsImpl(PointerToArray(colors, _CSTrait::pixelSize), weights, nColors, dst);
0039     }
0040 
0041 private:
0042     struct ArrayOfPointers {
0043         ArrayOfPointers(const quint8 * const* colors)
0044             : m_colors(colors)
0045         {
0046         }
0047 
0048         const quint8* getPixel() const {
0049             return *m_colors;
0050         }
0051 
0052         void nextPixel() {
0053             m_colors++;
0054         }
0055 
0056     private:
0057         const quint8 * const * m_colors;
0058     };
0059 
0060     struct PointerToArray {
0061         PointerToArray(const quint8 *colors, int pixelSize)
0062             : m_colors(colors),
0063               m_pixelSize(pixelSize)
0064         {
0065         }
0066 
0067         const quint8* getPixel() const {
0068             return m_colors;
0069         }
0070 
0071         void nextPixel() {
0072             m_colors += m_pixelSize;
0073         }
0074 
0075     private:
0076         const quint8 *m_colors;
0077         const int m_pixelSize;
0078     };
0079 
0080 
0081     template<class AbstractSource>
0082     void mixColorsImpl(AbstractSource source, const qint16 *weights, quint32 nColors, quint8 *dst) const {
0083         // Create and initialize to 0 the array of totals
0084         typename KoColorSpaceMathsTraits<typename _CSTrait::channels_type>::compositetype totals[_CSTrait::channels_nb];
0085         typename KoColorSpaceMathsTraits<typename _CSTrait::channels_type>::compositetype totalAlpha = 0;
0086 
0087         memset(totals, 0, sizeof(totals));
0088 
0089         // Compute the total for each channel by summing each colors multiplied by the weightlabcache
0090 
0091         while (nColors--) {
0092             const typename _CSTrait::channels_type* color = _CSTrait::nativeArray(source.getPixel());
0093             typename KoColorSpaceMathsTraits<typename _CSTrait::channels_type>::compositetype alphaTimesWeight;
0094 
0095             if (_CSTrait::alpha_pos != -1) {
0096                 alphaTimesWeight = color[_CSTrait::alpha_pos];
0097             } else {
0098                 alphaTimesWeight = KoColorSpaceMathsTraits<typename _CSTrait::channels_type>::unitValue;
0099             }
0100 
0101             alphaTimesWeight *= *weights;
0102 
0103             for (int i = 0; i < (int)_CSTrait::channels_nb; i++) {
0104                 if (i != _CSTrait::alpha_pos) {
0105                     totals[i] += color[i] * alphaTimesWeight;
0106                 }
0107             }
0108 
0109             totalAlpha += alphaTimesWeight;
0110             source.nextPixel();
0111             weights++;
0112         }
0113 
0114         // set totalAlpha to the minimum between its value and the unit value of the channels
0115         const int sumOfWeights = 255;
0116 
0117         if (totalAlpha > KoColorSpaceMathsTraits<typename _CSTrait::channels_type>::unitValue * sumOfWeights) {
0118             totalAlpha = KoColorSpaceMathsTraits<typename _CSTrait::channels_type>::unitValue * sumOfWeights;
0119         }
0120 
0121         typename _CSTrait::channels_type* dstColor = _CSTrait::nativeArray(dst);
0122 
0123         if (totalAlpha > 0) {
0124 
0125             for (int i = 0; i < (int)_CSTrait::channels_nb; i++) {
0126                 if (i != _CSTrait::alpha_pos) {
0127 
0128                     typename KoColorSpaceMathsTraits<typename _CSTrait::channels_type>::compositetype v = totals[i] / totalAlpha;
0129 
0130                     if (v > KoColorSpaceMathsTraits<typename _CSTrait::channels_type>::max) {
0131                         v = KoColorSpaceMathsTraits<typename _CSTrait::channels_type>::max;
0132                     }
0133                     if (v < KoColorSpaceMathsTraits<typename _CSTrait::channels_type>::min) {
0134                         v = KoColorSpaceMathsTraits<typename _CSTrait::channels_type>::min;
0135                     }
0136                     dstColor[ i ] = v;
0137                 }
0138             }
0139 
0140             if (_CSTrait::alpha_pos != -1) {
0141                 dstColor[ _CSTrait::alpha_pos ] = totalAlpha / sumOfWeights;
0142             }
0143         } else {
0144             memset(dst, 0, sizeof(typename _CSTrait::channels_type) * _CSTrait::channels_nb);
0145         }
0146     }
0147 };
0148 
0149 #endif