Krita Source Code Documentation
Loading...
Searching...
No Matches
kis_convolution_kernel.cc
Go to the documentation of this file.
1/*
2 * SPDX-FileCopyrightText: 2005, 2008 Cyrille Berger <cberger@cberger.net>
3 *
4 * SPDX-License-Identifier: GPL-2.0-or-later
5 */
6
8
9#include <math.h>
10
11#include <QImage>
12#include <kis_mask_generator.h>
13
14struct Q_DECL_HIDDEN KisConvolutionKernel::Private {
15 qreal offset;
16 qreal factor;
17 Eigen::Matrix<qreal, Eigen::Dynamic, Eigen::Dynamic> data;
18};
19
20KisConvolutionKernel::KisConvolutionKernel(quint32 _width, quint32 _height, qreal _offset, qreal _factor) : d(new Private)
21{
22 d->offset = _offset;
23 d->factor = _factor;
24 setSize(_width, _height);
25}
26
31
33{
34 return d->data.cols();
35}
36
38{
39 return d->data.rows();
40}
41
42void KisConvolutionKernel::setSize(quint32 width, quint32 height)
43{
44 d->data.resize(height, width);
45}
46
47
49{
50 return d->offset;
51}
52
54{
55 return d->factor;
56}
57
59{
60 d->factor = factor;
61}
62
63Eigen::Matrix<qreal, Eigen::Dynamic, Eigen::Dynamic>& KisConvolutionKernel::data()
64{
65 return d->data;
66}
67
68const Eigen::Matrix<qreal, Eigen::Dynamic, Eigen::Dynamic>* KisConvolutionKernel::data() const
69{
70 return &(d->data);
71}
72
74{
75 KisConvolutionKernelSP kernel = new KisConvolutionKernel(image.width(), image.height(), 0, 0);
76
77 Eigen::Matrix<qreal, Eigen::Dynamic, Eigen::Dynamic>& data = kernel->data();
78 const quint8* itImage = image.constBits();
79 qreal factor = 0;
80
81 for (int r = 0; r < image.height(); r++) {
82 for (int c = 0; c < image.width(); c++, itImage += 4)
83 {
84 uint value = 255 - (*itImage + *(itImage + 1) + *(itImage + 2)) / 3;
85 data(r, c) = value;
86 factor += value;
87 }
88 }
89
90 kernel->setFactor(factor);
91 return kernel;
92}
93
95{
96 Q_UNUSED(angle);
97
98 qint32 width = (int)(kmg->width() + 0.5);
99 qint32 height = (int)(kmg->height() + 0.5);
100
102
103 qreal cosa = cos(angle);
104 qreal sina = sin(angle);
105 qreal xc = 0.5 * width - 0.5;
106 qreal yc = 0.5 * height - 0.5;
107
108 Eigen::Matrix<qreal, Eigen::Dynamic, Eigen::Dynamic>& data = kernel->data();
109 qreal factor = 0;
110
111// dbgImage << ppVar(xc) << ppVar(yc);
112 for (int r = 0; r < height; ++r) {
113 for (int c = 0; c < width; ++c) {
114 qreal x_ = (c - xc);
115 qreal y_ = (r - yc);
116 qreal x = cosa * x_ - sina * y_;
117 qreal y = sina * x_ + cosa * y_;
118// dbgImage << ppVar(x) << ppVar(y) << ppVar(x_) << ppVar(y_) << ppVar( kmg->interpolatedValueAt( x,y) );
119 uint value = 255 - kmg->valueAt(x, y);
120 data(r, c) = value;
121 factor += value;
122 }
123 }
124 kernel->setFactor(factor);
125 return kernel;
126}
127
128KisConvolutionKernelSP KisConvolutionKernel::fromMatrix(Eigen::Matrix<qreal, Eigen::Dynamic, Eigen::Dynamic> matrix, qreal offset, qreal factor)
129{
130 KisConvolutionKernelSP kernel = new KisConvolutionKernel(matrix.cols(), matrix.rows(), offset, factor);
131 kernel->data() = matrix;
132
133 return kernel;
134}
135
136
137
138
139#if 0
140double xr = (x /*- m_xcenter*/);
141double yr = (y /*- m_ycenter*/);
142double n = norme(xr * m_xcoef, yr * m_ycoef);
143if (n > 1)
144{
145 return 255;
146} else
147{
148 double normeFade = norme(xr * m_xfadecoef, yr * m_yfadecoef);
149 if (normeFade > 1) {
150 double xle, yle;
151 // xle stands for x-coordinate limit exterior
152 // yle stands for y-coordinate limit exterior
153 // we are computing the coordinate on the external ellipse in order to compute
154 // the fade value
155 if (xr == 0) {
156 xle = 0;
157 yle = yr > 0 ? 1 / m_ycoef : -1 / m_ycoef;
158 } else {
159 double c = yr / (double)xr;
160 xle = sqrt(1 / norme(m_xcoef, c * m_ycoef));
161 xle = xr > 0 ? xle : -xle;
162 yle = xle * c;
163 }
164 // On the internal limit of the fade area, normeFade is equal to 1
165 double normeFadeLimitE = norme(xle * m_xfadecoef, yle * m_yfadecoef);
166 return (uchar)(255 *(normeFade - 1) / (normeFadeLimitE - 1));
167 } else {
168 return 0;
169 }
170}
171#endif
172
173#include "kis_debug.h"
174
175QDebug operator<<(QDebug debug, const KisConvolutionKernel &c)
176{
177 debug.nospace() << "[" << c.width() << "," << c.height() << "]{";
178 for (unsigned int i = 0; i < c.width(); ++i) {
179 debug.nospace() << " {";
180 for (unsigned int j = 0; j < c.height(); ++j) {
181 debug.nospace() << (*(c.data()))(j, i) << " ";
182 }
183 debug.nospace() << " }";
184 }
185 debug.nospace() << c.factor() << " " << c.offset() << " }";
186 return debug.space();
187}
float value(const T *src, size_t ch)
unsigned int uint
virtual quint8 valueAt(qreal x, qreal y) const =0
QDebug operator<<(QDebug debug, const KisConvolutionKernel &c)
KisConvolutionKernel(quint32 width, quint32 height, qreal offset, qreal factor)
void setSize(quint32 width, quint32 height)
static KisConvolutionKernelSP fromQImage(const QImage &image)
static KisConvolutionKernelSP fromMatrix(Eigen::Matrix< qreal, Eigen::Dynamic, Eigen::Dynamic > matrix, qreal offset, qreal factor)
Eigen::Matrix< qreal, Eigen::Dynamic, Eigen::Dynamic > data
static KisConvolutionKernelSP fromMaskGenerator(KisMaskGenerator *, qreal angle=0.0)