Krita Source Code Documentation
Loading...
Searching...
No Matches
LabF32ColorSpace.cpp
Go to the documentation of this file.
1/*
2 * SPDX-FileCopyrightText: 2006 Cyrille Berger <cberger@cberger.net>
3 * SPDX-FileCopyrightText: 2020-2021 L. E. Segovia <amy@amyspark.me>
4 *
5 * SPDX-License-Identifier: LGPL-2.1-or-later
6*/
7
8#include "LabF32ColorSpace.h"
9
10#include <QDomElement>
11
12#include <klocalizedstring.h>
13
14#include "../compositeops/KoCompositeOps.h"
16#include <KoColorConversions.h>
17#include <kis_dom_utils.h>
18
20 : LcmsColorSpace<KoLabF32Traits>(colorSpaceId(), name, TYPE_LabA_FLT, cmsSigLabData, p)
21{
22 const IccColorProfile *icc_p = dynamic_cast<const IccColorProfile *>(p);
23 Q_ASSERT(icc_p);
25 Q_ASSERT(uiRanges.size() == 3);
26
27 addChannel(new KoChannelInfo(i18nc("Lightness value in Lab color model", "Lightness"), 0 * sizeof(float), 0, KoChannelInfo::COLOR, KoChannelInfo::FLOAT32, sizeof(float), QColor(100, 100, 100), uiRanges[0]));
28 addChannel(new KoChannelInfo(i18n("a*"), 1 * sizeof(float), 1, KoChannelInfo::COLOR, KoChannelInfo::FLOAT32, sizeof(float), QColor(150, 150, 150), uiRanges[1]));
29 addChannel(new KoChannelInfo(i18n("b*"), 2 * sizeof(float), 2, KoChannelInfo::COLOR, KoChannelInfo::FLOAT32, sizeof(float), QColor(200, 200, 200), uiRanges[2]));
30 addChannel(new KoChannelInfo(i18n("Alpha"), 3 * sizeof(float), 3, KoChannelInfo::ALPHA, KoChannelInfo::FLOAT32, sizeof(float)));
31
32 init();
33
34 addStandardCompositeOps<KoLabF32Traits>(this);
35 addStandardDitherOps<KoLabF32Traits>(this);
36
37 dbgPlugins << "La*b* (float) channel bounds for: " << icc_p->name();
38 dbgPlugins << "L: " << uiRanges[0].minVal << uiRanges[0].maxVal;
39 dbgPlugins << "a: " << uiRanges[1].minVal << uiRanges[1].maxVal;
40 dbgPlugins << "b: " << uiRanges[2].minVal << uiRanges[2].maxVal;
41}
42
44{
45 if (independence == TO_RGBA16) {
46 return true;
47 } else {
48 return false;
49 }
50}
51
53{
54 return new LabF32ColorSpace(name(), profile()->clone());
55}
56
57void LabF32ColorSpace::colorToXML(const quint8 *pixel, QDomDocument &doc, QDomElement &colorElt) const
58{
59 const KoLabF32Traits::Pixel *p = reinterpret_cast<const KoLabF32Traits::Pixel *>(pixel);
60 QDomElement labElt = doc.createElement("Lab");
61
62 // we need 0-100, -128-+127
63
65
67
69 labElt.setAttribute("space", profile()->name());
70 colorElt.appendChild(labElt);
71}
72
73void LabF32ColorSpace::colorFromXML(quint8 *pixel, const QDomElement &elt) const
74{
75 KoLabF32Traits::Pixel *p = reinterpret_cast<KoLabF32Traits::Pixel *>(pixel);
79 p->alpha = 1.0;
80}
81
82void LabF32ColorSpace::toHSY(const QVector<double> &channelValues, qreal *hue, qreal *sat, qreal *luma) const
83{
84 LabToLCH(channelValues[0],channelValues[1],channelValues[2], luma, sat, hue);
85}
86
87QVector <double> LabF32ColorSpace::fromHSY(qreal *hue, qreal *sat, qreal *luma) const
88{
89 QVector <double> channelValues(4);
90 LCHToLab(*luma, *sat, *hue, &channelValues[0],&channelValues[1],&channelValues[2]);
91 channelValues[3]=1.0;
92 return channelValues;
93}
94void LabF32ColorSpace::toYUV(const QVector<double> &channelValues, qreal *y, qreal *u, qreal *v) const
95{
96 *y =channelValues[0];
97 *u=channelValues[1];
98 *v=channelValues[2];
99}
100
101QVector <double> LabF32ColorSpace::fromYUV(qreal *y, qreal *u, qreal *v) const
102{
103 QVector <double> channelValues(4);
104 channelValues[0]=*y;
105 channelValues[1]=*u;
106 channelValues[2]=*v;
107 channelValues[3]=1.0;
108 return channelValues;
109}
110
111quint8 LabF32ColorSpace::scaleToU8(const quint8 *srcPixel, qint32 channelIndex) const
112{
113 typename ColorSpaceTraits::channels_type c = ColorSpaceTraits::nativeArray(srcPixel)[channelIndex];
114 qreal b = 0;
115 switch (channelIndex) {
116 case ColorSpaceTraits::L_pos:
117 b = ((qreal)c) / ColorSpaceTraits::math_trait::unitValueL;
118 break;
119 case ColorSpaceTraits::a_pos:
120 case ColorSpaceTraits::b_pos:
121 if (c <= ColorSpaceTraits::math_trait::halfValueAB) {
122 b = ((qreal)c - ColorSpaceTraits::math_trait::zeroValueAB) / (2.0 * (ColorSpaceTraits::math_trait::halfValueAB - ColorSpaceTraits::math_trait::zeroValueAB));
123 } else {
124 b = 0.5 + ((qreal)c - ColorSpaceTraits::math_trait::halfValueAB) / (2.0 * (ColorSpaceTraits::math_trait::unitValueAB - ColorSpaceTraits::math_trait::halfValueAB));
125 }
126 break;
127 default:
128 b = ((qreal)c) / ColorSpaceTraits::math_trait::unitValue;
129 break;
130 }
131
133}
134
135void LabF32ColorSpace::convertChannelToVisualRepresentation(const quint8 *src, quint8 *dst, quint32 nPixels, const qint32 selectedChannelIndex) const
136{
137 for (uint pixelIndex = 0; pixelIndex < nPixels; ++pixelIndex) {
138 for (uint channelIndex = 0; channelIndex < ColorSpaceTraits::channels_nb; ++channelIndex) {
139 if (channelIndex != ColorSpaceTraits::alpha_pos) {
140 if (channelIndex == ColorSpaceTraits::L_pos) {
141 ColorSpaceTraits::channels_type c = ColorSpaceTraits::nativeArray((src + (pixelIndex * ColorSpaceTraits::pixelSize)))[selectedChannelIndex];
142 switch (selectedChannelIndex) {
143 case ColorSpaceTraits::L_pos:
144 break;
145 case ColorSpaceTraits::a_pos:
146 case ColorSpaceTraits::b_pos:
147 if (c <= ColorSpaceTraits::math_trait::halfValueAB) {
148 c = ColorSpaceTraits::math_trait::unitValueL * (((qreal)c - ColorSpaceTraits::math_trait::zeroValueAB) / (2.0 * (ColorSpaceTraits::math_trait::halfValueAB - ColorSpaceTraits::math_trait::zeroValueAB)));
149 } else {
150 c = ColorSpaceTraits::math_trait::unitValueL * (0.5 + ((qreal)c - ColorSpaceTraits::math_trait::halfValueAB) / (2.0 * (ColorSpaceTraits::math_trait::unitValueAB - ColorSpaceTraits::math_trait::halfValueAB)));
151 }
152 break;
153 // As per KoChannelInfo alpha channels are [0..1]
154 default:
155 c = ColorSpaceTraits::math_trait::unitValueL * (qreal)c / ColorSpaceTraits::math_trait::unitValue;
156 break;
157 }
158 ColorSpaceTraits::nativeArray(dst + (pixelIndex * ColorSpaceTraits::pixelSize))[channelIndex] = c;
159 } else {
160 ColorSpaceTraits::nativeArray(dst + (pixelIndex * ColorSpaceTraits::pixelSize))[channelIndex] = ColorSpaceTraits::math_trait::halfValueAB;
161 }
162 } else {
163 ColorSpaceTraits::nativeArray((dst + (pixelIndex * ColorSpaceTraits::pixelSize)))[channelIndex] =
164 ColorSpaceTraits::nativeArray((src + (pixelIndex * ColorSpaceTraits::pixelSize)))[channelIndex];
165 }
166 }
167 }
168}
169
170void LabF32ColorSpace::convertChannelToVisualRepresentation(const quint8 *src, quint8 *dst, quint32 nPixels, const QBitArray selectedChannels) const
171{
172 for (uint pixelIndex = 0; pixelIndex < nPixels; ++pixelIndex) {
173 for (uint channelIndex = 0; channelIndex < this->channelCount(); ++channelIndex) {
174 if (selectedChannels.testBit(channelIndex)) {
175 ColorSpaceTraits::nativeArray((dst + (pixelIndex * ColorSpaceTraits::pixelSize)))[channelIndex] =
176 ColorSpaceTraits::nativeArray((src + (pixelIndex * ColorSpaceTraits::pixelSize)))[channelIndex];
177 } else {
178 ColorSpaceTraits::channels_type v;
179 switch (channelIndex) {
180 case ColorSpaceTraits::L_pos:
181 v = ColorSpaceTraits::math_trait::halfValueL;
182 break;
183 case ColorSpaceTraits::a_pos:
184 case ColorSpaceTraits::b_pos:
185 v = ColorSpaceTraits::math_trait::halfValueAB;
186 break;
187 default:
188 v = ColorSpaceTraits::math_trait::zeroValue;
189 break;
190 }
191 ColorSpaceTraits::nativeArray((dst + (pixelIndex * ColorSpaceTraits::pixelSize)))[channelIndex] = v;
192 }
193 }
194 }
195}
const Params2D p
qreal v
qreal u
void LabToLCH(const qreal l, const qreal a, const qreal b, qreal *L, qreal *C, qreal *H)
void LCHToLab(const qreal L, const qreal C, const qreal H, qreal *l, qreal *a, qreal *b)
ColorSpaceIndependence
@ TO_RGBA16
unsigned int uint
const QVector< KoChannelInfo::DoubleRange > & getFloatUIMinMax(void) const
@ ALPHA
The channel represents the opacity of a pixel.
@ COLOR
The channel represents a color.
@ FLOAT32
use this for a float 32bits channel
quint32 channelCount() const override
static _Tdst scaleToA(_T a)
virtual void addChannel(KoChannelInfo *ci)
void convertChannelToVisualRepresentation(const quint8 *src, quint8 *dst, quint32 nPixels, const qint32 selectedChannelIndex) const override
QVector< double > fromYUV(qreal *y, qreal *u, qreal *v) const override
void toYUV(const QVector< double > &channelValues, qreal *y, qreal *u, qreal *v) const override
LabF32ColorSpace(const QString &name, KoColorProfile *p)
void colorFromXML(quint8 *pixel, const QDomElement &elt) const override
void toHSY(const QVector< double > &channelValues, qreal *hue, qreal *sat, qreal *luma) const override
virtual KoColorSpace * clone() const
void colorToXML(const quint8 *pixel, QDomDocument &doc, QDomElement &colorElt) const override
quint8 scaleToU8(const quint8 *srcPixel, qint32 channelIndex) const override
QVector< double > fromHSY(qreal *hue, qreal *sat, qreal *luma) const override
bool willDegrade(ColorSpaceIndependence independence) const override
const KoColorProfile * profile() const override
#define dbgPlugins
Definition kis_debug.h:51
double toDouble(const QString &str, bool *ok=nullptr)
QString toString(const QString &value)