Krita Source Code Documentation
Loading...
Searching...
No Matches
indexcolorpalette.cpp
Go to the documentation of this file.
1/*
2 * SPDX-FileCopyrightText: 2014 Manuel Riecke <spell1337@gmail.com>
3 *
4 * SPDX-License-Identifier: ICS
5 */
6
7#include "indexcolorpalette.h"
8
9#include <qmath.h>
10#include <QThread>
11
12#include <KoColorSpaceMaths.h>
16
18{
19 static const qreal max = KoColorSpaceMathsTraits<quint16>::max;
20
21 quint16 diffL = qAbs(c0.L - c1.L);
22 quint16 diffa = qAbs(c0.a - c1.a);
23 quint16 diffb = qAbs(c0.b - c1.b);
24
25
26 float valL = diffL / max * similarityFactors.L;
27 float valA = diffa / max * similarityFactors.a;
28 float valB = diffb / max * similarityFactors.b;
29
30 return 1.f - qSqrt(valL * valL + valA * valA + valB * valB);
31}
32
39
41{
42 return m_colors.size();
43}
44
46{
47 QVector<float> diffs;
48
49 int colorCount = numColors();
50 Q_ASSERT(colorCount > 0);
51
52 diffs.resize(colorCount);
53 diffs.fill(0.0);
54
55 for (int i = 0; i < colorCount; ++i) {
56 diffs[i] = similarity(m_colors[i], clr);
57 }
58
59 int primaryColor = 0;
60 float maxDiff = std::numeric_limits<float>::min();
61 for (int i = 0; i < colorCount; ++i) {
62 if (diffs[i] > maxDiff) {
63 primaryColor = i;
64 maxDiff = diffs[primaryColor];
65 }
66 }
67
68 return m_colors[primaryColor];
69}
70
71QPair<int, int> IndexColorPalette::getNeighbours(int mainClr) const
72{
73 QVector<float> diffs;
74 diffs.resize(numColors());
75 for(int i = 0; i < numColors(); ++i)
76 diffs[i] = similarity(m_colors[i], m_colors[mainClr]);
77
78 int darkerColor = 0;
79 int brighterColor = 0;
80 for(int i = 0; i < numColors(); ++i)
81 {
82 if(i != mainClr)
83 {
84 if (m_colors[i].L < m_colors[mainClr].L)
85 {
86 if(diffs[i] > diffs[darkerColor])
87 darkerColor = i;
88 }
89 else
90 {
91 if(diffs[i] > diffs[brighterColor])
92 brighterColor = i;
93 }
94 }
95 }
96
97 return qMakePair(darkerColor, brighterColor);
98}
99
101{
102 if(shades == 0) return;
103 qint16 lumaStep = (clrB.L - clrA.L) / (shades+1);
104 qint16 astarStep = (clrB.a - clrA.a) / (shades+1);
105 qint16 bstarStep = (clrB.b - clrA.b) / (shades+1);
106 for(int i = 0; i < shades; ++i)
107 {
108 clrA.L += lumaStep;
109 clrA.a += astarStep;
110 clrA.b += bstarStep;
111 insertColor(clrA);
112 }
113}
114
115void IndexColorPalette::insertShades(KoColor koclrA, KoColor koclrB, int shades)
116{
117 koclrA.convertTo(KoColorSpaceRegistry::instance()->lab16());
118 koclrB.convertTo(KoColorSpaceRegistry::instance()->lab16());
119 LabColor clrA = *(reinterpret_cast<LabColor*>(koclrA.data()));
120 LabColor clrB = *(reinterpret_cast<LabColor*>(koclrB.data()));
121 insertShades(clrA, clrB, shades);
122}
123
124void IndexColorPalette::insertShades(QColor qclrA, QColor qclrB, int shades)
125{
126 KoColor koclrA;
127 koclrA.fromQColor(qclrA);
128 koclrA.convertTo(KoColorSpaceRegistry::instance()->lab16());
129 KoColor koclrB;
130 koclrB.fromQColor(qclrB);
131 koclrB.convertTo(KoColorSpaceRegistry::instance()->lab16());
132 LabColor clrA = *(reinterpret_cast<LabColor*>(koclrA.data()));
133 LabColor clrB = *(reinterpret_cast<LabColor*>(koclrB.data()));
134 insertShades(clrA, clrB, shades);
135}
136
138{
139 m_colors.append(clr);
140}
141
143{
145 LabColor clr = *(reinterpret_cast<LabColor*>(koclr.data()));
146 insertColor(clr);
147}
148
150{
151 KoColor koclr;
152 koclr.fromQColor(qclr);
154 LabColor clr = *(reinterpret_cast<LabColor*>(koclr.data()));
155 insertColor(clr);
156}
157
158namespace
159{
160struct ColorString
161{
162 int color;
163 QPair<int, int> neighbours;
164 float similarity;
165};
166}
167
169{
170 QVector<ColorString> colorHood;
171 colorHood.resize(numColors());
172 for(int i = 0; i < numColors(); ++i)
173 {
174 colorHood[i].color = i;
175 colorHood[i].neighbours = getNeighbours(i);
176 float lSimilarity = 0.05f, rSimilarity = 0.05f;
177 // There will be exactly 2 colors that have only 1 neighbour, the darkest and the brightest, we don't want to remove those
178 if(colorHood[i].neighbours.first != -1)
179 lSimilarity = similarity(m_colors[colorHood[i].neighbours.first], m_colors[i]);
180 if(colorHood[i].neighbours.second != -1)
181 rSimilarity = similarity(m_colors[colorHood[i].neighbours.second], m_colors[i]);
182 colorHood[i].similarity = (lSimilarity + rSimilarity) / 2;
183 }
184 int mostSimilarColor = 0;
185 for(int i = 0; i < numColors(); ++i)
186 if(colorHood[i].similarity > colorHood[mostSimilarColor].similarity)
187 mostSimilarColor = i;
188
189 int darkerIndex = colorHood[mostSimilarColor].neighbours.first;
190 int brighterIndex = colorHood[mostSimilarColor].neighbours.second;
191 if(darkerIndex != -1 &&
192 brighterIndex != -1)
193 {
194 LabColor clrA = m_colors[darkerIndex];
195 LabColor clrB = m_colors[mostSimilarColor];
196 // Remove two, add one = 1 color less
197 m_colors.remove(darkerIndex);
198 m_colors.remove(mostSimilarColor);
199 //colors.remove(brighterIndex);
200 insertShades(clrA, clrB, 1);
201 //insertShades(clrB, clrC, 1);
202 }
203}
void convertTo(const KoColorSpace *cs, KoColorConversionTransformation::Intent renderingIntent, KoColorConversionTransformation::ConversionFlags conversionFlags)
Definition KoColor.cpp:136
void fromQColor(const QColor &c)
Convenient function for converting from a QColor.
Definition KoColor.cpp:213
quint8 * data()
Definition KoColor.h:144
float similarity(LabColor c0, LabColor c1) const
LabColor getNearestIndex(LabColor clr) const
void insertColor(QColor clr)
void insertShades(QColor clrA, QColor clrB, int shades)
QVector< LabColor > m_colors
QPair< int, int > getNeighbours(int mainClr) const
struct IndexColorPalette::@11 similarityFactors
static KoColorSpaceRegistry * instance()