15#include <klocalizedstring.h>
24#define SCALE_TO_FLOAT( v ) KoColorSpaceMaths< _channel_type_, float>::scaleToA( v )
25#define SCALE_FROM_FLOAT( v ) KoColorSpaceMaths< float, _channel_type_>::scaleToA( v )
27template<
typename _channel_type_>
28void clamp(
float* r,
float* g,
float* b);
30#define FLOAT_CLAMP( v ) *v = (*v < 0.0) ? 0.0 : ( (*v>1.0) ? 1.0 : *v )
50void clamp<half>(
float* r,
float* g,
float* b)
70 float x,
float m,
float M)
73 case 0: *r = M; *g = x + m; *b = m;
break;
74 case 1: *r = x + m; *g = M; *b = m;
break;
75 case 2: *r = m; *g = M; *b = x + m;
break;
76 case 3: *r = m; *g = x + m; *b = M;
break;
77 case 4: *r = x + m; *g = m; *b = M;
break;
78 case 5: *r = M; *g = m; *b = x + m;
break;
85 static const float EPSILON = 1e-9f;
89 inline float valueFromRGB(
float r,
float g,
float b,
float m,
float M) {
103 float x,
float c,
float v) {
105 const float m =
v - c;
113 static const float EPSILON = 1e-9f;
117 inline float valueFromRGB(
float r,
float g,
float b,
float m,
float M) {
121 return 0.5f * (M + m);
126 c = qMin(c, 2.0f - 2.0f *
v);
128 c = qMin(c, 2.0f *
v);
136 float x,
float c,
float v) {
138 const float M =
v + 0.5f * c;
139 const float m =
v - 0.5f * c;
148 static const float EPSILON = 1e-9f;
152 inline float valueFromRGB(
float r,
float g,
float b,
float m,
float M) {
155 return (r + g + b) / 3.0f;
159 static const float oneThird = 1.0f / 3.0f;
162 c = qMin(c, 1.5f * (1.0f -
v));
164 c = qMin(c, 3.0f *
v);
172 float x,
float c,
float v) {
174 static const float oneThird = 1.0f / 3.0f;
176 const float m =
v - oneThird * (c + x);
177 const float M = c + m;
185 HCYPolicy(
float _rCoeff = 0.299f,
float _gCoeff = 0.587f,
float _bCoeff = 0.114f)
197 static const float EPSILON = 1e-9f;
201 inline float valueFromRGB(
float r,
float g,
float b,
float m,
float M) {
217 float x,
float c,
float v) {
221 case 0: *r = c; *g = x; *b = 0;
break;
222 case 1: *r = x; *g = c; *b = 0;
break;
223 case 2: *r = 0; *g = c; *b = x;
break;
224 case 3: *r = 0; *g = x; *b = c;
break;
225 case 4: *r = x; *g = 0; *b = c;
break;
226 case 5: *r = c; *g = 0; *b = x;
break;
236template <
class ValuePolicy>
237void HSVTransform(
float *r,
float *g,
float *b,
float dh,
float ds,
float dv, ValuePolicy valuePolicy)
239 static const float EPSILON = 1e-9f;
243 float M = qMax(*r, qMax(*g, *b));
244 float m = qMin(*r, qMin(*g, *b));
246 float chroma = M - m;
248 float v = valuePolicy.valueFromRGB(*r, *g, *b, m, M);
250 if (!valuePolicy.hasChroma(
v)) {
256 v += dv * (1.0f -
v);
261 h = (*g - *b) / chroma;
263 h = 2 + (*b - *r) / chroma;
265 h = 4 + (*r - *g) / chroma;
278 chroma = qMin(1.0f, chroma * (1.0f + ds + 2.0f *
pow2(ds)));
288 const float dstV = dv > 0.0f ? 1.0f : 0.0f;
289 const float vCoeff = dstV -
v;
290 const float chromaCoeff = 0 - chroma;
291 const float movement = std::abs(dv);
293 v += movement * vCoeff;
294 chroma += movement * chromaCoeff;
297 v = qBound(0.0f,
v, 1.0f);
298 chroma = valuePolicy.fixupChroma(chroma,
v);
305 const int sextant =
static_cast<int>(h);
306 const float fract = h - sextant;
310 chroma - chroma * fract :
313 valuePolicy.writeRGB(r, g, b, sextant, x, chroma,
v);
318template<
typename _channel_type_,
typename traits>
340 void transform(
const quint8 *srcU8, quint8 *dstU8, qint32 nPixels)
const override
352 qreal lumaR, lumaG, lumaB;
363 while (nPixels > 0) {
367 if (h >= 360.0) h = 0;
375 float luminance = r * lumaR + g * lumaG + b * lumaB;
379 luminance += 1.0 - (1.0 -
m_adj_v);
434 qreal hue, sat, intensity;
435 RGBToHCI(red, green, blue, &hue, &sat, &intensity);
443 HCIToRGB(hue/360.0, sat, intensity, &red, &green, &blue);
460 qreal hue, sat, luma;
461 RGBToHCY(red, green, blue, &hue, &sat, &luma, lumaR, lumaG, lumaB);
469 HCYToRGB(hue/360.0, sat, luma, &red, &green, &blue, lumaR, lumaG, lumaB);
481 RGBToYUV(red, green, blue, &y, &cb, &cr, lumaR, lumaG, lumaB);
487 YUVToRGB(y, cb, cr, &red, &green, &blue, lumaR, lumaG, lumaB);
492 Q_ASSERT_X(
false,
"",
"invalid type");
496 clamp< _channel_type_ >(&r, &g, &b);
500 dst->alpha = src->alpha;
554 list <<
"h" <<
"s" <<
"v" <<
"type" <<
"colorize" <<
"lumaRed" <<
"lumaGreen"<<
"lumaBlue" <<
"compatibilityMode";
562 }
else if (name ==
"s") {
564 }
else if (name ==
"v") {
566 }
else if (name ==
"type") {
568 }
else if (name ==
"colorize") {
570 }
else if (name ==
"lumaRed") {
572 }
else if (name ==
"lumaGreen") {
574 }
else if (name ==
"lumaBlue") {
576 }
else if (name ==
"compatibilityMode") {
596 m_adj_h = parameter.toDouble();
599 m_adj_s = parameter.toDouble();
602 m_adj_v = parameter.toDouble();
605 m_type = parameter.toInt();
637template<
typename _channel_type_,
typename traits>
653 list <<
"curve" <<
"channel" <<
"driverChannel" <<
"relative" <<
"lumaRed" <<
"lumaGreen"<<
"lumaBlue";
659 if (name ==
"curve") {
661 }
else if (name ==
"channel") {
663 }
else if (name ==
"driverChannel") {
665 }
else if (name ==
"relative") {
667 }
else if (name ==
"lumaRed") {
669 }
else if (name ==
"lumaGreen") {
671 }
else if (name ==
"lumaBlue") {
695 int channel = parameter.toInt();
722 void transform(
const quint8 *srcU8, quint8 *dstU8, qint32 nPixels)
const override
726 float max =
m_curve.size() - 1;
736 float &r = component[traits::red_pos];
737 float &g = component[traits::green_pos];
738 float &b = component[traits::blue_pos];
741 while (nPixels > 0) {
756 adjustment = 2.0f * adjustment - 1.0f;
767 r = b = g = adjustment;
774 if (h > 360) h -= 360;
781 clamp< _channel_type_ >(&r, &g, &b);
799 if (max < 2)
return x;
802 float lookup = x * max;
803 float base = floor(lookup);
804 float offset = lookup - base;
810 int index = (int)base;
812 return (1.0f - offset) *
m_curve[index]
860 dbgKrita <<
"Unsupported color space " << colorSpace->
id() <<
" in KisHSVAdjustmentFactory::createTransformation";
876 dbgKrita <<
"Unsupported color space " << colorSpace->
id() <<
" in KisHSVAdjustmentFactory::createTransformation";
904 dbgKrita <<
"Unsupported color space " << colorSpace->
id() <<
" in KisHSVCurveAdjustmentFactory::createTransformation";
920 dbgKrita <<
"Unsupported color space " << colorSpace->
id() <<
" in KisHSVCurveAdjustmentFactory::createTransformation";
void RGBToHSV(float r, float g, float b, float *h, float *s, float *v)
void HCIToRGB(const qreal h, const qreal c, const qreal i, qreal *red, qreal *green, qreal *blue)
void RGBToYUV(const qreal r, const qreal g, const qreal b, qreal *y, qreal *u, qreal *v, qreal R, qreal G, qreal B)
void RGBToHCI(const qreal r, const qreal g, const qreal b, qreal *h, qreal *c, qreal *i)
void RGBToHCY(const qreal r, const qreal g, const qreal b, qreal *h, qreal *c, qreal *y, qreal R, qreal G, qreal B)
void RGBToHSL(float r, float g, float b, float *h, float *s, float *l)
void HSVToRGB(float h, float s, float v, float *r, float *g, float *b)
void YUVToRGB(const qreal y, const qreal u, const qreal v, qreal *r, qreal *g, qreal *b, qreal R, qreal G, qreal B)
void HSLToRGB(float h, float sl, float l, float *r, float *g, float *b)
void HCYToRGB(const qreal h, const qreal c, const qreal y, qreal *red, qreal *green, qreal *blue, qreal R, qreal G, qreal 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"))
QList< QPair< KoID, KoID > > supportedModels() const override
KisHSVAdjustmentFactory()
KoColorTransformation * createTransformation(const KoColorSpace *colorSpace, QHash< QString, QVariant > parameters) const override
int parameterId(const QString &name) const override
QList< QString > parameters() const override
void setParameter(int id, const QVariant ¶meter) override
void transform(const quint8 *srcU8, quint8 *dstU8, qint32 nPixels) const override
KoColorTransformation * createTransformation(const KoColorSpace *colorSpace, QHash< QString, QVariant > parameters) const override
QList< QPair< KoID, KoID > > supportedModels() const override
KisHSVCurveAdjustmentFactory()
int parameterId(const QString &name) const override
const float SCALE_FROM_16BIT
void setParameter(int id, const QVariant ¶meter) override
float lookupComponent(float x, float max) const
void transform(const quint8 *srcU8, quint8 *dstU8, qint32 nPixels) const override
QVector< quint16 > m_curve
QList< QString > parameters() const override
virtual KoID colorModelId() const =0
virtual KoID colorDepthId() const =0
#define KIS_ASSERT_RECOVER_RETURN(cond)
#define KIS_ASSERT_RECOVER_NOOP(cond)
std::enable_if< std::is_floating_point< T >::value, T >::type normalizeAngleDegrees(T a)
void clamp< quint8 >(float *r, float *g, float *b)
void clamp< float >(float *r, float *g, float *b)
void clamp< quint16 >(float *r, float *g, float *b)
#define SCALE_FROM_FLOAT(v)
void HSVTransform(float *r, float *g, float *b, float dh, float ds, float dv, ValuePolicy valuePolicy)
#define SCALE_TO_FLOAT(v)
static void writeRGBSimple(float *r, float *g, float *b, int sextant, float x, float m, float M)
void clamp(float *r, float *g, float *b)
void writeRGB(float *r, float *g, float *b, int sextant, float x, float c, float v)
float valueFromRGB(float r, float g, float b, float m, float M)
float fixupChroma(float c, float v)
void writeRGB(float *r, float *g, float *b, int sextant, float x, float c, float v)
float valueFromRGB(float r, float g, float b, float m, float M)
float fixupChroma(float c, float v)
HCYPolicy(float _rCoeff=0.299f, float _gCoeff=0.587f, float _bCoeff=0.114f)
float valueFromRGB(float r, float g, float b, float m, float M)
void writeRGB(float *r, float *g, float *b, int sextant, float x, float c, float v)
float fixupChroma(float c, float v)
float valueFromRGB(float r, float g, float b, float m, float M)
void writeRGB(float *r, float *g, float *b, int sextant, float x, float c, float v)
float fixupChroma(float c, float v)