Krita Source Code Documentation
Loading...
Searching...
No Matches
kis_math_toolbox.cpp
Go to the documentation of this file.
1/*
2 * This file is part of the KDE project
3 *
4 * SPDX-FileCopyrightText: 2005 Cyrille Berger <cberger@cberger.net>
5 *
6 * SPDX-License-Identifier: GPL-2.0-or-later
7 */
8
9#include "kis_math_toolbox.h"
10
11#include <KoConfig.h>
12
13#ifdef HAVE_OPENEXR
14#include <half.h>
15#endif
16
17#include <QVector>
18#include <QGlobalStatic>
19
20#include <KoColorSpaceMaths.h>
21
22#include <kis_debug.h>
23#include "kis_iterator_ng.h"
24
25#include "math.h"
26
27template<typename T>
28inline double toDouble(const quint8* data, int channelpos)
29{
30 return (double)(*((T*)(data + channelpos)));
31}
32
33template<typename T>
34void fromDouble(quint8* data, int channelpos, double v)
35{
36 *((T*)(data + channelpos)) = (T)qRound(v);
37}
38
39template<typename T>
40void fromDoubleF(quint8* data, int channelpos, double v)
41{
42 *((T*)(data + channelpos)) = (T)v;
43}
44
45template<typename T>
46void fromDoubleCheckNull(quint8* data, int channelpos, double v, bool *isNull)
47{
48 T value = qRound(v);
49 *((T*)(data + channelpos)) = value;
50 *isNull = value == T(0);
51}
52
53template<typename T>
54void fromDoubleCheckNullF(quint8* data, int channelpos, double v, bool *isNull)
55{
56 T value = v;
57 *((T*)(data + channelpos)) = (T)v;
58 *isNull = value < std::numeric_limits<T>::epsilon();
59}
60
61
63{
64 qint32 depth = src->colorSpace()->colorChannelCount();
65 QList<KoChannelInfo *> cis = src->colorSpace()->channels();
66 // remove non-color channels
67 for (qint32 c = 0; c < cis.count(); ++c) {
68 if (cis[c]->channelType() != KoChannelInfo::COLOR)
69 cis.removeAt(c--);
70 }
71 QVector<PtrToDouble> f(depth);
72 if (!getToDoubleChannelPtr(cis, f))
73 return;
74
75 KisHLineConstIteratorSP srcIt = src->createHLineIteratorNG(rect.x(), rect.y(), rect.width());
76
77 for (int i = rect.y(); i < rect.height(); i++) {
78 float *dstIt = fr->coeffs + (i - rect.y()) * fr->size * fr->depth;
79 do {
80 const quint8* v1 = srcIt->oldRawData();
81 for (int k = 0; k < depth; k++) {
82 *dstIt = f[k](v1, cis[k]->pos());
83 ++dstIt;
84 }
85 } while (srcIt->nextPixel());
86 srcIt->nextRow();
87 }
88}
89
91{
92 qint32 channels = cis.count();
93
94 for (qint32 k = 0; k < channels; k++) {
95 switch (cis[k]->channelValueType()) {
97 f[k] = toDouble<quint8>;
98 break;
100 f[k] = toDouble<quint16>;
101 break;
102#ifdef HAVE_OPENEXR
104 f[k] = toDouble<half>;
105 break;
106#endif
108 f[k] = toDouble<float>;
109 break;
111 f[k] = toDouble<qint8>;
112 break;
114 f[k] = toDouble<qint16>;
115 break;
116 default:
117 warnKrita << "Unsupported value type in KisMathToolbox";
118 return false;
119 }
120 }
121
122 return true;
123}
124
126{
127 qint32 depth = dst->colorSpace()->colorChannelCount();
129 // remove non-color channels
130 for (qint32 c = 0; c < cis.count(); ++c) {
131 if (cis[c]->channelType() != KoChannelInfo::COLOR)
132 cis.removeAt(c--);
133 }
134
135 QVector<PtrFromDouble> f(depth);
136 if (!getFromDoubleChannelPtr(cis, f))
137 return;
138
139 KisHLineIteratorSP dstIt = dst->createHLineIteratorNG(rect.x(), rect.y(), rect.width());
140 for (int i = rect.y(); i < rect.height(); i++) {
141 float *srcIt = fr->coeffs + (i - rect.y()) * fr->size * fr->depth;
142 do {
143 quint8* v1 = dstIt->rawData();
144 for (int k = 0; k < depth; k++) {
145 f[k](v1, cis[k]->pos(), *srcIt);
146 ++srcIt;
147 }
148 } while(dstIt->nextPixel());
149 dstIt->nextRow();
150 }
151}
152
154{
155 qint32 channels = cis.count();
156
157 for (qint32 k = 0; k < channels; k++) {
158 switch (cis[k]->channelValueType()) {
160 f[k] = fromDouble<quint8>;
161 break;
163 f[k] = fromDouble<quint16>;
164 break;
165#ifdef HAVE_OPENEXR
167 f[k] = fromDoubleF<half>;
168 break;
169#endif
171 f[k] = fromDoubleF<float>;
172 break;
174 f[k] = fromDouble<qint8>;
175 break;
177 f[k] = fromDouble<qint16>;
178 break;
179 default:
180 warnKrita << "Unsupported value type in KisMathToolbox";
181 return false;
182 }
183 }
184
185 return true;
186}
187
189{
190 qint32 channels = cis.count();
191
192 for (qint32 k = 0; k < channels; k++) {
193 switch (cis[k]->channelValueType()) {
195 f[k] = fromDoubleCheckNull<quint8>;
196 break;
198 f[k] = fromDoubleCheckNull<quint16>;
199 break;
200#ifdef HAVE_OPENEXR
202 f[k] = fromDoubleCheckNullF<half>;
203 break;
204#endif
206 f[k] = fromDoubleCheckNullF<float>;
207 break;
209 f[k] = fromDoubleCheckNull<qint8>;
210 break;
212 f[k] = fromDoubleCheckNull<qint16>;
213 break;
214 default:
215 warnKrita << "Unsupported value type in KisMathToolbox";
216 return false;
217 }
218 }
219
220 return true;
221}
222
240
258
260{
261 uint l = (2 * halfsize) * wav->depth * sizeof(float);
262 for (uint i = 0; i < halfsize; i++) {
263 float * itLL = buff->coeffs + i * buff->size * buff->depth;
264 float * itHL = buff->coeffs + (i * buff->size + halfsize) * buff->depth;
265 float * itLH = buff->coeffs + (halfsize + i) * buff->size * buff->depth;
266 float * itHH = buff->coeffs + ((halfsize + i) * buff->size + halfsize) * buff->depth;
267 float * itS11 = wav->coeffs + 2 * i * wav->size * wav->depth;
268 float * itS12 = wav->coeffs + (2 * i * wav->size + 1) * wav->depth;
269 float * itS21 = wav->coeffs + (2 * i + 1) * wav->size * wav->depth;
270 float * itS22 = wav->coeffs + ((2 * i + 1) * wav->size + 1) * wav->depth;
271 for (uint j = 0; j < halfsize; j++) {
272 for (uint k = 0; k < wav->depth; k++) {
273 *(itLL++) = (*itS11 + *itS12 + *itS21 + *itS22) * M_SQRT1_2;
274 *(itHL++) = (*itS11 - *itS12 + *itS21 - *itS22) * M_SQRT1_2;
275 *(itLH++) = (*itS11 + *itS12 - *itS21 - *itS22) * M_SQRT1_2;
276 *(itHH++) = (*(itS11++) - *(itS12++) - *(itS21++) + *(itS22++)) * M_SQRT1_2;
277 }
278 itS11 += wav->depth; itS12 += wav->depth;
279 itS21 += wav->depth; itS22 += wav->depth;
280 }
281 }
282 for (uint i = 0; i < halfsize; i++) {
283 uint p = i * wav->size * wav->depth;
284 memcpy(wav->coeffs + p, buff->coeffs + p, l);
285 p = (i + halfsize) * wav->size * wav->depth;
286 memcpy(wav->coeffs + p, buff->coeffs + p, l);
287 }
288 if (halfsize != 1) {
289 wavetrans(wav, buff, halfsize / 2);
290 }
291}
292
294{
295 uint l = (2 * halfsize) * wav->depth * sizeof(float);
296 for (uint i = 0; i < halfsize; i++) {
297 float * itLL = wav->coeffs + i * buff->size * buff->depth;
298 float * itHL = wav->coeffs + (i * buff->size + halfsize) * buff->depth;
299 float * itLH = wav->coeffs + (halfsize + i) * buff->size * buff->depth;
300 float * itHH = wav->coeffs + ((halfsize + i) * buff->size + halfsize) * buff->depth;
301 float * itS11 = buff->coeffs + 2 * i * wav->size * wav->depth;
302 float * itS12 = buff->coeffs + (2 * i * wav->size + 1) * wav->depth;
303 float * itS21 = buff->coeffs + (2 * i + 1) * wav->size * wav->depth;
304 float * itS22 = buff->coeffs + ((2 * i + 1) * wav->size + 1) * wav->depth;
305 for (uint j = 0; j < halfsize; j++) {
306 for (uint k = 0; k < wav->depth; k++) {
307 *(itS11++) = (*itLL + *itHL + *itLH + *itHH) * 0.25 * M_SQRT2;
308 *(itS12++) = (*itLL - *itHL + *itLH - *itHH) * 0.25 * M_SQRT2;
309 *(itS21++) = (*itLL + *itHL - *itLH - *itHH) * 0.25 * M_SQRT2;
310 *(itS22++) = (*(itLL++) - *(itHL++) - *(itLH++) + *(itHH++)) * 0.25 * M_SQRT2;
311 }
312 itS11 += wav->depth; itS12 += wav->depth;
313 itS21 += wav->depth; itS22 += wav->depth;
314 }
315 }
316 for (uint i = 0; i < halfsize; i++) {
317 uint p = i * wav->size * wav->depth;
318 memcpy(wav->coeffs + p, buff->coeffs + p, l);
319 p = (i + halfsize) * wav->size * wav->depth;
320 memcpy(wav->coeffs + p, buff->coeffs + p, l);
321 }
322
323 if (halfsize != wav->size / 2) {
324 waveuntrans(wav, buff, halfsize*2);
325 }
326}
327
329{
330 if (buff == 0) {
331 buff = initWavelet(src, rect);
332 }
333 KisWavelet* wav = initWavelet(src, rect);
334 transformToFR(src, wav, rect);
335 wavetrans(wav, buff, wav->size / 2);
336
337 return wav;
338}
339
341{
342 if (buff == 0) {
343 buff = initWavelet(dst, rect);
344 }
345
346 waveuntrans(wav, buff, 1);
347 transformFromFR(dst, wav, rect);
348}
float value(const T *src, size_t ch)
const Params2D p
qreal v
unsigned int uint
virtual const quint8 * oldRawData() const =0
virtual bool nextPixel()=0
virtual void nextRow()=0
bool getToDoubleChannelPtr(QList< KoChannelInfo * > cis, QVector< PtrToDouble > &f)
void transformToFR(KisPaintDeviceSP src, KisFloatRepresentation *, const QRect &)
void wavetrans(KisWavelet *wav, KisWavelet *buff, uint halfsize)
bool getFromDoubleChannelPtr(QList< KoChannelInfo * > cis, QVector< PtrFromDouble > &f)
KisWavelet * initWavelet(KisPaintDeviceSP lay, const QRect &)
void waveuntrans(KisWavelet *wav, KisWavelet *buff, uint halfsize)
void fastWaveletUntransformation(KisPaintDeviceSP dst, const QRect &, KisWavelet *wav, KisWavelet *buff=0)
double minChannelValue(KoChannelInfo *)
double maxChannelValue(KoChannelInfo *)
void transformFromFR(KisPaintDeviceSP dst, KisFloatRepresentation *, const QRect &)
KisWavelet * fastWaveletTransformation(KisPaintDeviceSP src, const QRect &, KisWavelet *buff=0)
bool getFromDoubleCheckNullChannelPtr(QList< KoChannelInfo * > cis, QVector< PtrFromDoubleCheckNull > &f)
KisHLineIteratorSP createHLineIteratorNG(qint32 x, qint32 y, qint32 w)
const KoColorSpace * colorSpace() const
@ COLOR
The channel represents a color.
@ UINT8
use this for an unsigned integer 8bits channel
@ UINT16
use this for an integer 16bits channel
@ INT16
use this for an integer 16bits channel
@ INT8
use this for an integer 8bits channel
@ FLOAT32
use this for a float 32bits channel
@ FLOAT16
use this for a float 16bits channel
@ UINT32
use this for an unsigned integer 21bits channel
@ FLOAT64
use this for a float 64bits channel
enumChannelValueType channelValueType() const
QList< KoChannelInfo * > channels
virtual quint32 colorChannelCount() const =0
#define warnKrita
Definition kis_debug.h:87
double toDouble(const quint8 *data, int channelpos)
void fromDoubleF(quint8 *data, int channelpos, double v)
void fromDoubleCheckNullF(quint8 *data, int channelpos, double v, bool *isNull)
void fromDoubleCheckNull(quint8 *data, int channelpos, double v, bool *isNull)
void fromDouble(quint8 *data, int channelpos, double v)