Krita Source Code Documentation
Loading...
Searching...
No Matches
KisColorSelectionPolicies.h
Go to the documentation of this file.
1/*
2 * SPDX-FileCopyrightText: 2014 Dmitry Kazakov <dimula73@gmail.com>
3 *
4 * SPDX-License-Identifier: GPL-2.0-or-later
5 */
6
7#ifndef KISCOLORSELECTIONPOLICIES
8#define KISCOLORSELECTIONPOLICIES
9
10#include <QStack>
11
12#include <KoAlwaysInline.h>
13#include <KoColor.h>
14#include <KoColorSpace.h>
16
18{
19
21{
22public:
23 SlowDifferencePolicy(const KoColor &referenceColor, int threshold)
24 : m_colorSpace(referenceColor.colorSpace())
25 , m_referenceColor(referenceColor)
28 , m_threshold(threshold)
29 {}
30
31 ALWAYS_INLINE quint8 difference(const quint8 *colorPtr) const
32 {
33 if (m_threshold == 1) {
34 const bool colorIsTransparent = (m_colorSpace->opacityU8(colorPtr) == OPACITY_TRANSPARENT_U8);
35 if ((m_referenceColorIsTransparent && colorIsTransparent) ||
36 memcmp(m_referenceColorPtr, colorPtr, m_colorSpace->pixelSize()) == 0) {
37 return 0;
38 }
39 return quint8_MAX;
40 }
41 else {
43 }
44 }
45
46protected:
49 const quint8 *m_referenceColorPtr;
52};
53
54template <typename SrcPixelType>
56{
57public:
58 OptimizedDifferencePolicy(const KoColor &referenceColor, int threshold)
59 : SlowDifferencePolicy(referenceColor, threshold)
60 {}
61
62 ALWAYS_INLINE quint8 difference(const quint8 *colorPtr) const
63 {
64 HashKeyType key = *reinterpret_cast<const HashKeyType*>(colorPtr);
65
66 quint8 result;
67
68 typename HashType::iterator it = m_differences.find(key);
69
70 if (it != m_differences.end()) {
71 result = *it;
72 } else {
73 result = SlowDifferencePolicy::difference(colorPtr);
74 m_differences.insert(key, result);
75 }
76
77 return result;
78 }
79
80protected:
81 using HashKeyType = SrcPixelType;
82 using HashType = QHash<HashKeyType, quint8>;
83
85};
86
88{
89public:
90 SlowColorOrTransparentDifferencePolicy(const KoColor &referenceColor, int threshold)
91 : SlowDifferencePolicy(referenceColor, threshold)
92 {}
93
94 ALWAYS_INLINE quint8 difference(const quint8 *colorPtr) const
95 {
96 if (m_threshold == 1) {
97 if (memcmp(m_referenceColorPtr, colorPtr, m_colorSpace->pixelSize()) == 0 ||
98 m_colorSpace->opacityU8(colorPtr) == 0) {
99 return 0;
100 }
101 return quint8_MAX;
102 }
103 else {
104 const quint8 colorDifference = m_colorSpace->difference(m_referenceColorPtr, colorPtr);
105 const quint8 opacityDifference = m_colorSpace->opacityU8(colorPtr) * 100 / quint8_MAX;
106 return qMin(colorDifference, opacityDifference);
107 }
108 }
109};
110
111template <typename SrcPixelType>
113{
114public:
115 OptimizedColorOrTransparentDifferencePolicy(const KoColor &referenceColor, int threshold)
116 : OptimizedDifferencePolicy<SrcPixelType>(referenceColor, threshold)
117 {}
118
119 ALWAYS_INLINE quint8 difference(const quint8 *colorPtr) const
120 {
121 HashKeyType key = *reinterpret_cast<const HashKeyType*>(colorPtr);
122
123 quint8 result;
124
125 typename HashType::iterator it = this->m_differences.find(key);
126
127 if (it != this->m_differences.end()) {
128 result = *it;
129 } else {
130 const quint8 colorDifference = this->m_colorSpace->difference(this->m_referenceColorPtr, colorPtr);
131 const quint8 opacityDifference = this->m_colorSpace->opacityU8(colorPtr) * 100 / quint8_MAX;
132 result = qMin(colorDifference, opacityDifference);
133 this->m_differences.insert(key, result);
134 }
135
136 return result;
137 }
138
139protected:
142};
143
145{
146public:
148 : m_pixelSize(pixelSize)
149 , m_testColor(pixelSize, 0)
150 {}
151
152 ALWAYS_INLINE quint8 difference(const quint8 *colorPtr) const
153 {
154 if (memcmp(m_testColor.data(), colorPtr, m_pixelSize) == 0) {
155 return 0;
156 }
157 return quint8_MAX;
158 }
159
160private:
161 int m_pixelSize {0};
162 QByteArray m_testColor;
163};
164
165template <typename SrcPixelType>
167{
168public:
169 ALWAYS_INLINE quint8 difference(const quint8 *colorPtr) const
170 {
171 const SrcPixelType *pixel = reinterpret_cast<const SrcPixelType*>(colorPtr);
172 return *pixel == 0;
173 }
174};
175
177{
178public:
179 HardSelectionPolicy(int threshold) : m_threshold(threshold) {}
180
181 ALWAYS_INLINE quint8 opacityFromDifference(quint8 difference) const
182 {
183 return difference <= m_threshold ? MAX_SELECTED : MIN_SELECTED;
184 }
185
186protected:
188};
189
191{
192public:
193 SoftSelectionPolicy(int threshold, int softness)
194 : HardSelectionPolicy(threshold)
195 , m_softness(softness)
196 {}
197
198 ALWAYS_INLINE quint8 opacityFromDifference(quint8 difference) const
199 {
200 if (m_threshold == 0) {
201 return MIN_SELECTED;
202 }
203 // Integer version of: (threshold - diff) / (threshold * softness)
204 if (difference < m_threshold) {
205 const int v = (m_threshold - difference) * MAX_SELECTED * 100 / (m_threshold * m_softness);
206 return v > MAX_SELECTED ? MAX_SELECTED : v;
207 } else {
208 return MIN_SELECTED;
209 }
210 }
211
212protected:
214};
215
217{
218public:
220 : HardSelectionPolicy(threshold)
221 {}
222
223 ALWAYS_INLINE quint8 opacityFromDifference(quint8 difference) const
224 {
225 return difference > m_threshold ? MAX_SELECTED : MIN_SELECTED;
226 }
227};
228
230{
231public:
232 SelectAllUntilColorSoftSelectionPolicy(int threshold, int softness)
233 : SoftSelectionPolicy(threshold, softness)
234 {}
235
236 ALWAYS_INLINE quint8 opacityFromDifference(quint8 difference) const
237 {
238 if (m_threshold == 0) {
239 return MAX_SELECTED;
240 }
241 // Integer version of: 1 - ((1-threshold) - diff) / ((1-threshold) * softness)
242 if (difference < m_threshold) {
243 const int v = MAX_SELECTED - (m_threshold - difference) * MAX_SELECTED * 100 / (m_threshold * m_softness);
244 return v < MIN_SELECTED ? MIN_SELECTED : v;
245 } else {
246 return MAX_SELECTED;
247 }
248 }
249};
250
251}
252
253#endif
qreal v
#define ALWAYS_INLINE
const quint8 OPACITY_TRANSPARENT_U8
ALWAYS_INLINE quint8 opacityFromDifference(quint8 difference) const
OptimizedColorOrTransparentDifferencePolicy(const KoColor &referenceColor, int threshold)
typename OptimizedDifferencePolicy< SrcPixelType >::HashKeyType HashKeyType
typename OptimizedDifferencePolicy< SrcPixelType >::HashType HashType
ALWAYS_INLINE quint8 difference(const quint8 *colorPtr) const
OptimizedDifferencePolicy(const KoColor &referenceColor, int threshold)
ALWAYS_INLINE quint8 difference(const quint8 *colorPtr) const
SlowColorOrTransparentDifferencePolicy(const KoColor &referenceColor, int threshold)
ALWAYS_INLINE quint8 difference(const quint8 *colorPtr) const
ALWAYS_INLINE quint8 difference(const quint8 *colorPtr) const
SlowDifferencePolicy(const KoColor &referenceColor, int threshold)
ALWAYS_INLINE quint8 difference(const quint8 *colorPtr) const
ALWAYS_INLINE quint8 opacityFromDifference(quint8 difference) const
virtual quint32 pixelSize() const =0
virtual quint8 difference(const quint8 *src1, const quint8 *src2) const =0
virtual quint8 differenceA(const quint8 *src1, const quint8 *src2) const =0
virtual quint8 opacityU8(const quint8 *pixel) const =0
const quint8 MAX_SELECTED
Definition kis_global.h:32
const quint8 quint8_MAX
Definition kis_global.h:24
const quint8 MIN_SELECTED
Definition kis_global.h:33