KoColorSpacePreserveLightnessUtils.h 3.74 KB
Newer Older
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
/*
 *  Copyright (c) 2020 Peter Schatz <voronwe13@gmail.com>
 *
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either version 2 of the License, or
 *  (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program; if not, write to the Free Software
 *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
 */


20
21
22
23
#ifndef KOCOLORSPACEPRESERVELIGHTNESSUTILS_H
#define KOCOLORSPACEPRESERVELIGHTNESSUTILS_H

#include <KoColorSpaceMaths.h>
24
#include "kis_global.h"
25
26

template<typename CSTraits>
27
inline static void fillGrayBrushWithColorPreserveLightnessRGB(quint8 *pixels, const QRgb *brush, quint8 *brushColor, qreal strength, qint32 nPixels) {
28
    using RGBPixel = typename CSTraits::Pixel;
29
30
31
32
33
34
35
36
        using channels_type = typename CSTraits::channels_type;
        static const quint32 pixelSize = CSTraits::pixelSize;

        const RGBPixel *brushColorRGB = reinterpret_cast<const RGBPixel*>(brushColor);

        const float brushColorR = KoColorSpaceMaths<channels_type, float>::scaleToA(brushColorRGB->red);
        const float brushColorG = KoColorSpaceMaths<channels_type, float>::scaleToA(brushColorRGB->green);
        const float brushColorB = KoColorSpaceMaths<channels_type, float>::scaleToA(brushColorRGB->blue);
37
        const float brushColorA = KoColorSpaceMaths<channels_type, float>::scaleToA(brushColorRGB->alpha);
38

39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
        /**
         * Lightness mixing algorithm is developed by Peter Schatz <voronwe13@gmail.com>
         *
         * We use a formula f(x) where f(0) = 0, f(1) = 1, and f(.5) = z,
         * where z is the lightness of the brush color. This can’t be linear unless
         * the color chosen is also .5. So we use a quadratic equation:
         *
         * f(x) = ax^2 + b^x +c
         * 0,0 -> 0 = a0^2 + b0 + c -> c = 0
         * 1,1 -> 1 = a1^2 +b1 + c -> 1 = a + b + 0 -> a = 1 - b
         * .5,z -> z = a*.5^2 + b*.5 + c -> z =
         *           = a/4 + b/2 + 0 -> z =
         *           = 1/4 - b/4 + b/2 -> z = 1/4 + b/4 -> b = 4z - 1
         *
         * f(x) = (1 - (4z - 1)) * x^2 + (4z - 1) * x
         */
55

56
57
58
        const float brushColorL = getLightness<HSLType, float>(brushColorR, brushColorG, brushColorB);
        const float lightnessB = 4 * brushColorL - 1;
        const float lightnessA = 1 - lightnessB;
59

60
61
        for (; nPixels > 0; --nPixels, pixels += pixelSize, ++brush) {
            RGBPixel *pixelRGB = reinterpret_cast<RGBPixel*>(pixels);
62

63
64
            float brushMaskL = qRed(*brush) / 255.0f;
            brushMaskL = (brushMaskL - 0.5) * strength + 0.5;
65
            const float finalLightness = lightnessA * pow2(brushMaskL) + lightnessB * brushMaskL;
66
            const float finalAlpha = qMin(qAlpha(*brush) / 255.0f, brushColorA);
67

68
69
70
            float pixelR = brushColorR;
            float pixelG = brushColorG;
            float pixelB = brushColorB;
71

72
            setLightness<HSLType, float>(pixelR, pixelG, pixelB, finalLightness);
73

74
75
76
            pixelRGB->red = KoColorSpaceMaths<float, channels_type>::scaleToA(pixelR);
            pixelRGB->green = KoColorSpaceMaths<float, channels_type>::scaleToA(pixelG);
            pixelRGB->blue = KoColorSpaceMaths<float, channels_type>::scaleToA(pixelB);
77
            pixelRGB->alpha = KoColorSpaceMaths<quint8, channels_type>::scaleToA(quint8(finalAlpha * 255));
78
        }
79
80
81
82
}


#endif // KOCOLORSPACEPRESERVELIGHTNESSUTILS_H