Krita Source Code Documentation
Loading...
Searching...
No Matches
kis_color_balance_adjustment.cpp
Go to the documentation of this file.
1/*
2 * SPDX-FileCopyrightText: 2013 Sahil Nagpal <nagpal.sahil01@gmail.com>
3 *
4 * SPDX-License-Identifier: LGPL-2.0-or-later
5*/
6
8#include <KoConfig.h>
9#ifdef HAVE_OPENEXR
10#include <half.h>
11#endif
12
13#include <kis_debug.h>
14#include <klocalizedstring.h>
15
16#include <KoColorConversions.h>
18#include <KoColorSpace.h>
19#include <KoColorSpaceTraits.h>
21#include <KoID.h>
22#include <kis_hsv_adjustment.h>
23
24
25#define SCALE_TO_FLOAT( v ) KoColorSpaceMaths< _channel_type_, float>::scaleToA( v )
26#define SCALE_FROM_FLOAT( v ) KoColorSpaceMaths< float, _channel_type_>::scaleToA( v )
27
29template<typename _channel_type_, typename traits>
31{
32 typedef traits RGBTrait;
33 typedef typename RGBTrait::Pixel RGBPixel;
34
35public:
37
38void transform(const quint8 *srcU8, quint8 *dstU8, qint32 nPixels) const override
39{
41 const RGBPixel* src = reinterpret_cast<const RGBPixel*>(srcU8);
42 RGBPixel* dst = reinterpret_cast<RGBPixel*>(dstU8);
43 float value_red, value_green, value_blue, hue, saturation, lightness;
44
45 while(nPixels > 0) {
46
47 float red = SCALE_TO_FLOAT(src->red);
48 float green = SCALE_TO_FLOAT(src->green);
49 float blue = SCALE_TO_FLOAT(src->blue);
50 RGBToHSL(red, green, blue, &hue, &saturation, &lightness);
51
55
57 {
58 float h2, s2, l2;
59 RGBToHSL(value_red, value_green, value_blue, &h2, &s2, &l2);
60 HSLToRGB(h2, s2, lightness, &value_red, &value_green, &value_blue);
61 }
62 dst->red = SCALE_FROM_FLOAT(value_red);
63 dst->green = SCALE_FROM_FLOAT(value_green);
64 dst->blue = SCALE_FROM_FLOAT(value_blue);
65 dst->alpha = src->alpha;
66
67 --nPixels;
68 ++src;
69 ++dst;
70 }
71}
72
73
74QList<QString> parameters() const override
75{
76 QList<QString> list;
77 list << "cyan_red_midtones" << "magenta_green_midtones" << "yellow_blue_midtones"
78 << "cyan_red_shadows" << "magenta_green_shadows" << "yellow_blue_shadows"
79 << "cyan_red_highlights" << "magenta_green_highlights" << "yellow_blue_highlights" << "preserve_luminosity";
80 return list;
81}
82
83int parameterId(const QString& name) const override
84{
85 if (name == "cyan_red_midtones")
86 return 0;
87 else if(name == "magenta_green_midtones")
88 return 1;
89 else if(name == "yellow_blue_midtones")
90 return 2;
91 else if (name == "cyan_red_shadows")
92 return 3;
93 else if(name == "magenta_green_shadows")
94 return 4;
95 else if(name == "yellow_blue_shadows")
96 return 5;
97 else if (name == "cyan_red_highlights")
98 return 6;
99 else if(name == "magenta_green_highlights")
100 return 7;
101 else if(name == "yellow_blue_highlights")
102 return 8;
103 else if(name == "preserve_luminosity")
104 return 9;
105 return -1;
106}
107
108void setParameter(int id, const QVariant& parameter) override
109{
110 switch(id)
111 {
112 case 0:
113 m_cyan_midtones = parameter.toDouble();
114 break;
115 case 1:
116 m_magenta_midtones = parameter.toDouble();
117 break;
118 case 2:
119 m_yellow_midtones = parameter.toDouble();
120 break;
121 case 3:
122 m_cyan_shadows = parameter.toDouble();
123 break;
124 case 4:
125 m_magenta_shadows = parameter.toDouble();
126 break;
127 case 5:
128 m_yellow_shadows = parameter.toDouble();
129 break;
130 case 6:
131 m_cyan_highlights = parameter.toDouble();
132 break;
133 case 7:
134 m_magenta_highlights = parameter.toDouble();
135 break;
136 case 8:
137 m_yellow_highlights = parameter.toDouble();
138 break;
139 case 9:
140 m_preserve_luminosity = parameter.toBool();
141 break;
142 default:
143 ;
144 }
145}
146private:
147
148 double m_cyan_midtones {0.0};
149 double m_magenta_midtones {0.0};
150 double m_yellow_midtones {0.0};
151 double m_cyan_shadows {0.0};
152 double m_magenta_shadows {0.0};
153 double m_yellow_shadows {0.0};
154 double m_cyan_highlights {0.0};
157
159};
160
165
167{
169 l.append(QPair< KoID, KoID >(RGBAColorModelID , Integer8BitsColorDepthID));
170 l.append(QPair< KoID, KoID >(RGBAColorModelID , Integer16BitsColorDepthID));
171 l.append(QPair< KoID, KoID >(RGBAColorModelID , Float16BitsColorDepthID));
172 l.append(QPair< KoID, KoID >(RGBAColorModelID , Float32BitsColorDepthID));
173 return l;
174}
175
176KoColorTransformation* KisColorBalanceAdjustmentFactory::createTransformation(const KoColorSpace* colorSpace, QHash<QString, QVariant> parameters) const
177{
179 if (colorSpace->colorModelId() != RGBAColorModelID) {
180 dbgKrita << "Unsupported color space " << colorSpace->id() << " in KisColorBalanceAdjustment::createTransformation";
181 return 0;
182 }
183 if (colorSpace->colorDepthId() == Float32BitsColorDepthID) {
185 }
186#ifdef HAVE_OPENEXR
187 else if (colorSpace->colorDepthId() == Float16BitsColorDepthID) {
189 }
190#endif
191 else if (colorSpace->colorDepthId() == Integer16BitsColorDepthID) {
193 } else if (colorSpace->colorDepthId() == Integer8BitsColorDepthID) {
195 } else {
196 dbgKrita << "Unsupported color space " << colorSpace->id() << " in KisColorBalanceAdjustment::createTransformation";
197 return 0;
198 }
199 adj->setParameters(parameters);
200 return adj;
201
202}
203
205
206
207float KisColorBalanceMath::colorBalanceTransform(float value, float lightness, float shadows, float midtones, float highlights)
208{
209 static const float a = 0.25, b = 0.333, scale = 0.7;
210
211 shadows *= CLAMP ((lightness - b) / -a + 0.5, 0, 1) * scale;
212 midtones *= CLAMP ((lightness - b) / a + 0.5, 0, 1) * CLAMP ((lightness + b - 1) / -a + 0.5, 0, 1) * scale;
213 highlights *= CLAMP ((lightness + b - 1) / a + 0.5, 0, 1) * scale;
214
215 value += shadows;
216 value += midtones;
217 value += highlights;
218 value = CLAMP (value, 0.0, 1.0);
219
220 return value;
221}
222
float value(const T *src, size_t ch)
QPointF s2
void RGBToHSL(float r, float g, float b, float *h, float *s, float *l)
void HSLToRGB(float h, float sl, float l, float *r, float *g, float *b)
const KoID Float32BitsColorDepthID("F32", ki18n("32-bit float/channel"))
const KoID Float16BitsColorDepthID("F16", ki18n("16-bit float/channel"))
const KoID Integer8BitsColorDepthID("U8", ki18n("8-bit integer/channel"))
const KoID Integer16BitsColorDepthID("U16", ki18n("16-bit integer/channel"))
const KoID RGBAColorModelID("RGBA", ki18n("RGB/Alpha"))
KoColorTransformation * createTransformation(const KoColorSpace *colorSpace, QHash< QString, QVariant > parameters) const override
QList< QPair< KoID, KoID > > supportedModels() const override
QList< QString > parameters() const override
void setParameter(int id, const QVariant &parameter) override
void transform(const quint8 *srcU8, quint8 *dstU8, qint32 nPixels) const override
int parameterId(const QString &name) const override
float colorBalanceTransform(float value, float lightness, float shadows, float midtones, float highlights)
virtual KoID colorModelId() const =0
virtual KoID colorDepthId() const =0
void setParameters(const QHash< QString, QVariant > &parameters)
#define CLAMP(x, l, h)
#define SCALE_FROM_FLOAT(v)
#define SCALE_TO_FLOAT(v)
#define dbgKrita
Definition kis_debug.h:45