Krita Source Code Documentation
Loading...
Searching...
No Matches
KisEdgeDetectionKernel Class Reference

#include <kis_edge_detection_kernel.h>

Public Types

enum  FilterOutput {
  pythagorean , xGrowth , xFall , yGrowth ,
  yFall , radian
}
 
enum  FilterType { Simple , Prewitt , SobelVector }
 

Public Member Functions

 KisEdgeDetectionKernel ()
 

Static Public Member Functions

static void applyEdgeDetection (KisPaintDeviceSP device, const QRect &rect, qreal xRadius, qreal yRadius, FilterType type, const QBitArray &channelFlags, KoUpdater *progressUpdater, FilterOutput output=pythagorean, bool writeToAlpha=false)
 applyEdgeDetection This applies the edge detection filter to the device.
 
static void convertToNormalMap (KisPaintDeviceSP device, const QRect &rect, qreal xRadius, qreal yRadius, FilterType type, int channelToConvert, QVector< int > channelOrder, QVector< bool > channelFlip, const QBitArray &channelFlags, KoUpdater *progressUpdater, boost::optional< bool > useFftw=boost::none)
 convertToNormalMap Convert a channel of the device to a normal map. The channel will be interpreted as a heightmap.
 
static KisConvolutionKernelSP createHorizontalKernel (qreal radius, FilterType type, bool denormalize=true, bool reverse=false)
 
static Eigen::Matrix< qreal, Eigen::Dynamic, Eigen::Dynamic > createHorizontalMatrix (qreal radius, FilterType type, bool reverse=false)
 createHorizontalMatrix
 
static KisConvolutionKernelSP createVerticalKernel (qreal radius, FilterType type, bool denormalize=true, bool reverse=false)
 
static Eigen::Matrix< qreal, Eigen::Dynamic, Eigen::Dynamic > createVerticalMatrix (qreal radius, FilterType type, bool reverse=false)
 createVerticalMatrix
 
static int kernelSizeFromRadius (qreal radius)
 
static qreal sigmaFromRadius (qreal radius)
 

Detailed Description

Definition at line 18 of file kis_edge_detection_kernel.h.

Member Enumeration Documentation

◆ FilterOutput

◆ FilterType

Enumerator
Simple 
Prewitt 
SobelVector 

Definition at line 23 of file kis_edge_detection_kernel.h.

23 {
24 Simple, //A weird simple method used in our old sobel filter
25 Prewitt, //The simpler prewitt detection, which doesn't smooth.
26 SobelVector //Sobel does smooth. The creation of bigger kernels is based on an approach regarding vectors.
27 };

Constructor & Destructor Documentation

◆ KisEdgeDetectionKernel()

KisEdgeDetectionKernel::KisEdgeDetectionKernel ( )

Definition at line 17 of file kis_edge_detection_kernel.cpp.

18{
19
20}

Member Function Documentation

◆ applyEdgeDetection()

void KisEdgeDetectionKernel::applyEdgeDetection ( KisPaintDeviceSP device,
const QRect & rect,
qreal xRadius,
qreal yRadius,
KisEdgeDetectionKernel::FilterType type,
const QBitArray & channelFlags,
KoUpdater * progressUpdater,
FilterOutput output = pythagorean,
bool writeToAlpha = false )
static

applyEdgeDetection This applies the edge detection filter to the device.

Parameters
devicethe device to apply to.
rectthe affected rect.
xRadiusthe radius of the horizontal sampling, radius of 0 is effectively disabling it.
yRadiusthe radius of the vertical sampling, radius of 0 is effectively disabling it.
typethe type can be prewitt, sobel or simple, each of which have a different sampling for the eventual edge detection.
channelFlagsthe affected channels.
progressUpdaterthe progress updater if it exists.
outputthe output mode.
writeToAlphawhether or not to have the result applied to the transparency than the color channels, this is useful for fringe effects.

Definition at line 182 of file kis_edge_detection_kernel.cpp.

191{
192 QPoint srcTopLeft = rect.topLeft();
193 KisPainter finalPainter(device);
194 finalPainter.setChannelFlags(channelFlags);
195 finalPainter.setProgress(progressUpdater);
196 if (output == pythagorean || output == radian) {
197 KisPaintDeviceSP x_denormalised = new KisPaintDevice(device->colorSpace());
198 KisPaintDeviceSP y_denormalised = new KisPaintDevice(device->colorSpace());
199
200 x_denormalised->prepareClone(device);
201 y_denormalised->prepareClone(device);
202
203
205 KisConvolutionKernelSP kernelVerticalTopBottom = KisEdgeDetectionKernel::createVerticalKernel(yRadius, type);
206
207 KisConvolutionPainter horizPainterLR(x_denormalised);
208 horizPainterLR.setChannelFlags(channelFlags);
209 horizPainterLR.setProgress(progressUpdater);
210 horizPainterLR.applyMatrix(kernelHorizLeftRight, device,
211 srcTopLeft,
212 srcTopLeft,
213 rect.size(), BORDER_REPEAT);
214
215
216 KisConvolutionPainter verticalPainterTB(y_denormalised);
217 verticalPainterTB.setChannelFlags(channelFlags);
218 verticalPainterTB.setProgress(progressUpdater);
219 verticalPainterTB.applyMatrix(kernelVerticalTopBottom, device,
220 srcTopLeft,
221 srcTopLeft,
222 rect.size(), BORDER_REPEAT);
223
224 KisSequentialIterator yIterator(y_denormalised, rect);
225 KisSequentialIterator xIterator(x_denormalised, rect);
226 KisSequentialIterator finalIt(device, rect);
227 const int pixelSize = device->colorSpace()->pixelSize();
228 const int channels = device->colorSpace()->channelCount();
229 const int alphaPos = device->colorSpace()->alphaPos();
230 KIS_SAFE_ASSERT_RECOVER_RETURN(alphaPos >= 0);
231
232 QVector<float> yNormalised(channels);
233 QVector<float> xNormalised(channels);
234 QVector<float> finalNorm(channels);
235
236 while(yIterator.nextPixel() && xIterator.nextPixel() && finalIt.nextPixel()) {
237 device->colorSpace()->normalisedChannelsValue(yIterator.rawData(), yNormalised);
238 device->colorSpace()->normalisedChannelsValue(xIterator.rawData(), xNormalised);
239 device->colorSpace()->normalisedChannelsValue(finalIt.rawData(), finalNorm);
240
241 if (output == pythagorean) {
242 for (int c = 0; c<channels; c++) {
243 finalNorm[c] = 2 * sqrt( ((xNormalised[c]-0.5)*(xNormalised[c]-0.5)) + ((yNormalised[c]-0.5)*(yNormalised[c]-0.5)));
244 }
245 } else { //radian
246 for (int c = 0; c<channels; c++) {
247 finalNorm[c] = atan2(xNormalised[c]-0.5, yNormalised[c]-0.5);
248 }
249 }
250
251 if (writeToAlpha) {
252 KoColor col(finalIt.rawData(), device->colorSpace());
253 qreal alpha = 0;
254
255 for (int c = 0; c<(channels-1); c++) {
256 alpha = alpha+finalNorm[c];
257 }
258
259 alpha = qMin(alpha/(channels-1), col.opacityF());
260 col.setOpacity(alpha);
261 memcpy(finalIt.rawData(), col.data(), pixelSize);
262 } else {
263 quint8* f = finalIt.rawData();
264 finalNorm[alphaPos] = 1.0;
265 device->colorSpace()->fromNormalisedChannelsValue(f, finalNorm);
266 memcpy(finalIt.rawData(), f, pixelSize);
267 }
268
269 }
270 } else {
272 bool denormalize = !writeToAlpha;
273 if (output == xGrowth) {
274 kernel = KisEdgeDetectionKernel::createHorizontalKernel(xRadius, type, denormalize);
275 } else if (output == xFall) {
276 kernel = KisEdgeDetectionKernel::createHorizontalKernel(xRadius, type, denormalize, true);
277 } else if (output == yGrowth) {
278 kernel = KisEdgeDetectionKernel::createVerticalKernel(yRadius, type, denormalize);
279 } else { //yFall
280 kernel = KisEdgeDetectionKernel::createVerticalKernel(yRadius, type, denormalize, true);
281 }
282
283 if (writeToAlpha) {
284 KisPaintDeviceSP denormalised = new KisPaintDevice(device->colorSpace());
285 denormalised->prepareClone(device);
286
287 KisConvolutionPainter kernelP(denormalised);
288 kernelP.setChannelFlags(channelFlags);
289 kernelP.setProgress(progressUpdater);
290 kernelP.applyMatrix(kernel, device,
291 srcTopLeft, srcTopLeft,
292 rect.size(), BORDER_REPEAT);
293 KisSequentialIterator iterator(denormalised, rect);
294 KisSequentialIterator finalIt(device, rect);
295 const int pixelSize = device->colorSpace()->pixelSize();
296 const int channels = device->colorSpace()->colorChannelCount();
297 QVector<float> normalised(channels);
298 while (iterator.nextPixel() && finalIt.nextPixel()) {
299 device->colorSpace()->normalisedChannelsValue(iterator.rawData(), normalised);
300 KoColor col(finalIt.rawData(), device->colorSpace());
301 qreal alpha = 0;
302 for (int c = 0; c<channels; c++) {
303 alpha = alpha+normalised[c];
304 }
305 alpha = qMin(alpha/channels, col.opacityF());
306 col.setOpacity(alpha);
307 memcpy(finalIt.rawData(), col.data(), pixelSize);
308
309 }
310
311 } else {
312 KisConvolutionPainter kernelP(device);
313 kernelP.setChannelFlags(channelFlags);
314 kernelP.setProgress(progressUpdater);
315 kernelP.applyMatrix(kernel, device,
316 srcTopLeft, srcTopLeft,
317 rect.size(), BORDER_REPEAT);
318
319 KisSequentialIterator finalIt(device, rect);
320 int numConseqPixels = finalIt.nConseqPixels();
321 while (finalIt.nextPixels(numConseqPixels)) {
322 numConseqPixels = finalIt.nConseqPixels();
323 device->colorSpace()->setOpacity(finalIt.rawData(), 1.0, numConseqPixels);
324 }
325 }
326 }
327}
The KisConvolutionPainter class applies a convolution kernel to a paint device.
static KisConvolutionKernelSP createHorizontalKernel(qreal radius, FilterType type, bool denormalize=true, bool reverse=false)
static KisConvolutionKernelSP createVerticalKernel(qreal radius, FilterType type, bool denormalize=true, bool reverse=false)
const KoColorSpace * colorSpace() const
void prepareClone(KisPaintDeviceSP src)
virtual quint32 alphaPos() const =0
virtual quint32 pixelSize() const =0
virtual void setOpacity(quint8 *pixels, quint8 alpha, qint32 nPixels) const =0
virtual quint32 channelCount() const =0
virtual void normalisedChannelsValue(const quint8 *pixel, QVector< float > &channels) const =0
virtual void fromNormalisedChannelsValue(quint8 *pixel, const QVector< float > &values) const =0
virtual quint32 colorChannelCount() const =0
#define KIS_SAFE_ASSERT_RECOVER_RETURN(cond)
Definition kis_assert.h:128
KRITAIMAGE_EXPORT qreal atan2(qreal y, qreal x)
atan2 replacement

References KoColorSpace::alphaPos(), KisConvolutionPainter::applyMatrix(), BORDER_REPEAT, KoColorSpace::channelCount(), KoColorSpace::colorChannelCount(), KisPaintDevice::colorSpace(), createHorizontalKernel(), createVerticalKernel(), KoColor::data(), KoColorSpace::fromNormalisedChannelsValue(), KIS_SAFE_ASSERT_RECOVER_RETURN, KisSequentialIteratorBase< IteratorPolicy, SourcePolicy, ProgressPolicy >::nConseqPixels(), KisSequentialIteratorBase< IteratorPolicy, SourcePolicy, ProgressPolicy >::nextPixel(), KisSequentialIteratorBase< IteratorPolicy, SourcePolicy, ProgressPolicy >::nextPixels(), KoColorSpace::normalisedChannelsValue(), KoColor::opacityF(), KoColorSpace::pixelSize(), KisPaintDevice::prepareClone(), pythagorean, radian, KisSequentialIteratorBase< IteratorPolicy, SourcePolicy, ProgressPolicy >::rawData(), KisPainter::setChannelFlags(), KoColorSpace::setOpacity(), KoColor::setOpacity(), KisPainter::setProgress(), xFall, xGrowth, and yGrowth.

◆ convertToNormalMap()

void KisEdgeDetectionKernel::convertToNormalMap ( KisPaintDeviceSP device,
const QRect & rect,
qreal xRadius,
qreal yRadius,
KisEdgeDetectionKernel::FilterType type,
int channelToConvert,
QVector< int > channelOrder,
QVector< bool > channelFlip,
const QBitArray & channelFlags,
KoUpdater * progressUpdater,
boost::optional< bool > useFftw = boost::none )
static

convertToNormalMap Convert a channel of the device to a normal map. The channel will be interpreted as a heightmap.

Parameters
devicethe device
rectthe rectangle to apply this to.
xRadiusthe xradius
yRadiusthe yradius
typethe edge detection filter.
channelToConvertthe channel to use as a grayscale.
channelOrderthe order in which the xyz coordinates ought to be written to the pixels.
channelFlipwhether to flip the channels
channelFlagsthe channel flags
progressUpdater

Definition at line 329 of file kis_edge_detection_kernel.cpp.

340{
342
343 QPoint srcTopLeft = rect.topLeft();
344 KisPainter finalPainter(device);
345 finalPainter.setChannelFlags(channelFlags);
346 finalPainter.setProgress(progressUpdater);
347 KisPaintDeviceSP x_denormalised = new KisPaintDevice(device->colorSpace());
348 KisPaintDeviceSP y_denormalised = new KisPaintDevice(device->colorSpace());
349 x_denormalised->prepareClone(device);
350 y_denormalised->prepareClone(device);
351
352 KisConvolutionKernelSP kernelHorizLeftRight = KisEdgeDetectionKernel::createHorizontalKernel(yRadius, type, true, !channelFlip[1]);
353 KisConvolutionKernelSP kernelVerticalTopBottom = KisEdgeDetectionKernel::createVerticalKernel(xRadius, type, true, !channelFlip[0]);
354
355 KisConvolutionPainter horizPainterLR(y_denormalised);
356
357 if (useFftw) {
358 horizPainterLR.setEnginePreference(*useFftw ? KisConvolutionPainter::FFTW : KisConvolutionPainter::SPATIAL);
359 }
360
361 horizPainterLR.setChannelFlags(channelFlags);
362 horizPainterLR.setProgress(progressUpdater);
363 horizPainterLR.applyMatrix(kernelHorizLeftRight, device,
364 srcTopLeft, srcTopLeft,
365 rect.size(), BORDER_REPEAT);
366
367
368 KisConvolutionPainter verticalPainterTB(x_denormalised);
369
370 if (useFftw) {
371 verticalPainterTB.setEnginePreference(*useFftw ? KisConvolutionPainter::FFTW : KisConvolutionPainter::SPATIAL);
372 }
373
374 verticalPainterTB.setChannelFlags(channelFlags);
375 verticalPainterTB.setProgress(progressUpdater);
376 verticalPainterTB.applyMatrix(kernelVerticalTopBottom, device,
377 srcTopLeft,
378 srcTopLeft,
379 rect.size(), BORDER_REPEAT);
380
381 KisSequentialIterator yIterator(y_denormalised, rect);
382 KisSequentialIterator xIterator(x_denormalised, rect);
383 KisSequentialIterator finalIt(device, rect);
384 const int pixelSize = device->colorSpace()->pixelSize();
385 const int channels = device->colorSpace()->channelCount();
386 const int alphaPos = device->colorSpace()->alphaPos();
387 KIS_SAFE_ASSERT_RECOVER_RETURN(alphaPos >= 0);
388
389 QVector<float> yNormalised(channels);
390 QVector<float> xNormalised(channels);
391 QVector<float> finalNorm(channels);
392
393 const QList<KoChannelInfo *> channelInfo = device->colorSpace()->channels();
394
395 while(yIterator.nextPixel() && xIterator.nextPixel() && finalIt.nextPixel()) {
396 device->colorSpace()->normalisedChannelsValue(yIterator.rawData(), yNormalised);
397 device->colorSpace()->normalisedChannelsValue(xIterator.rawData(), xNormalised);
398
399 qreal z = 1.0;
400 if (channelFlip[2]==true){
401 z=-1.0;
402 }
403 QVector3D normal = QVector3D((xNormalised[channelToConvert]-0.5)*2, (yNormalised[channelToConvert]-0.5)*2, z);
404 normal.normalize();
405 finalNorm.fill(1.0);
406 for (int c = 0; c < 3; c++) {
407 finalNorm[channelInfo.at(channelOrder[c])->displayPosition()] = (normal[channelOrder[c]]/2)+0.5;
408 }
409
410 finalNorm[alphaPos]= 1.0;
411
412 quint8* pixel = finalIt.rawData();
413 device->colorSpace()->fromNormalisedChannelsValue(pixel, finalNorm);
414 memcpy(finalIt.rawData(), pixel, pixelSize);
415
416 }
417}
QList< KoChannelInfo * > channels
#define KIS_ASSERT_RECOVER_RETURN(cond)
Definition kis_assert.h:75

References KoColorSpace::alphaPos(), KisConvolutionPainter::applyMatrix(), BORDER_REPEAT, KoColorSpace::channelCount(), KoColorSpace::channels, KisPaintDevice::colorSpace(), createHorizontalKernel(), createVerticalKernel(), KisConvolutionPainter::FFTW, KoColorSpace::fromNormalisedChannelsValue(), KIS_ASSERT_RECOVER_RETURN, KIS_SAFE_ASSERT_RECOVER_RETURN, KisSequentialIteratorBase< IteratorPolicy, SourcePolicy, ProgressPolicy >::nextPixel(), KoColorSpace::normalisedChannelsValue(), KoColorSpace::pixelSize(), KisPaintDevice::prepareClone(), KisSequentialIteratorBase< IteratorPolicy, SourcePolicy, ProgressPolicy >::rawData(), KisPainter::setChannelFlags(), KisConvolutionPainter::setEnginePreference(), KisPainter::setProgress(), and KisConvolutionPainter::SPATIAL.

◆ createHorizontalKernel()

KisConvolutionKernelSP KisEdgeDetectionKernel::createHorizontalKernel ( qreal radius,
KisEdgeDetectionKernel::FilterType type,
bool denormalize = true,
bool reverse = false )
static

Definition at line 146 of file kis_edge_detection_kernel.cpp.

150{
151 Eigen::Matrix<qreal, Eigen::Dynamic, Eigen::Dynamic> matrix = createHorizontalMatrix(radius, type, reverse);
152 if (denormalize) {
153 return KisConvolutionKernel::fromMatrix(matrix, 0.5, 1);
154 } else {
155 return KisConvolutionKernel::fromMatrix(matrix, 0, matrix.sum());
156 }
157}
static Eigen::Matrix< qreal, Eigen::Dynamic, Eigen::Dynamic > createHorizontalMatrix(qreal radius, FilterType type, bool reverse=false)
createHorizontalMatrix
static KisConvolutionKernelSP fromMatrix(Eigen::Matrix< qreal, Eigen::Dynamic, Eigen::Dynamic > matrix, qreal offset, qreal factor)

References createHorizontalMatrix(), and KisConvolutionKernel::fromMatrix().

◆ createHorizontalMatrix()

Eigen::Matrix< qreal, Eigen::Dynamic, Eigen::Dynamic > KisEdgeDetectionKernel::createHorizontalMatrix ( qreal radius,
FilterType type,
bool reverse = false )
static

createHorizontalMatrix

Parameters
radiusthe radius. 1 makes a 3x3 kernel.
typeOne of the entries in the enum Filtertype
reversewhich direction the gradient goes. The horizontal gradient by default detects the rightmost edges. Reversed it selects the leftmost edges.
Returns

Definition at line 28 of file kis_edge_detection_kernel.cpp.

31{
32 int kernelSize = kernelSizeFromRadius(radius);
33 Eigen::Matrix<qreal, Eigen::Dynamic, Eigen::Dynamic> matrix(kernelSize, kernelSize);
34
35 KIS_ASSERT_RECOVER_NOOP(kernelSize & 0x1);
36 const int center = kernelSize / 2;
37
38 if (type==Prewitt) {
39 for (int x = 0; x < kernelSize; x++) {
40 for (int y=0; y<kernelSize; y++) {
41 qreal xDistance;
42 if (reverse) {
43 xDistance = x - center;
44 } else {
45 xDistance = center - x;
46 }
47 matrix(x, y) = xDistance;
48 }
49 }
50 } else if(type==Simple) {
51 matrix.resize(kernelSize, 1);
52 for (int x = 0; x < kernelSize; x++) {
53 qreal xDistance;
54 if (reverse) {
55 xDistance = x - center;
56 } else {
57 xDistance = center - x;
58 }
59 if (x==center) {
60 matrix(x, 0) = 0;
61 } else {
62 matrix(x, 0) = (1/xDistance);
63 }
64 }
65 } else {
66 for (int x = 0; x < kernelSize; x++) {
67 for (int y=0; y<kernelSize; y++) {
68 if (x==center && y==center) {
69 matrix(x, y) = 0;
70 } else {
71 qreal xD, yD;
72 if (reverse) {
73 xD = x - center;
74 yD = y - center;
75 } else {
76 xD = center - x;
77 yD = center - y;
78 }
79 matrix(x, y) = xD / (xD*xD + yD*yD);
80 }
81 }
82 }
83 }
84 return matrix;
85}
static int kernelSizeFromRadius(qreal radius)
#define KIS_ASSERT_RECOVER_NOOP(cond)
Definition kis_assert.h:97

References kernelSizeFromRadius(), KIS_ASSERT_RECOVER_NOOP, Prewitt, and Simple.

◆ createVerticalKernel()

KisConvolutionKernelSP KisEdgeDetectionKernel::createVerticalKernel ( qreal radius,
KisEdgeDetectionKernel::FilterType type,
bool denormalize = true,
bool reverse = false )
static

Definition at line 159 of file kis_edge_detection_kernel.cpp.

163{
164 Eigen::Matrix<qreal, Eigen::Dynamic, Eigen::Dynamic> matrix = createVerticalMatrix(radius, type, reverse);
165 if (denormalize) {
166 return KisConvolutionKernel::fromMatrix(matrix, 0.5, 1);
167 } else {
168 return KisConvolutionKernel::fromMatrix(matrix, 0, matrix.sum());
169 }
170}
static Eigen::Matrix< qreal, Eigen::Dynamic, Eigen::Dynamic > createVerticalMatrix(qreal radius, FilterType type, bool reverse=false)
createVerticalMatrix

References createVerticalMatrix(), and KisConvolutionKernel::fromMatrix().

◆ createVerticalMatrix()

Eigen::Matrix< qreal, Eigen::Dynamic, Eigen::Dynamic > KisEdgeDetectionKernel::createVerticalMatrix ( qreal radius,
FilterType type,
bool reverse = false )
static

createVerticalMatrix

Parameters
radiusthe radius. 1 makes a 3x3 kernel.
typeOne of the entries in the enum Filtertype
reversewhich direction the gradient goes. The vertical gradient by default detects the topmost edges. Reversed it selects the bottommost edges.
Returns

Definition at line 87 of file kis_edge_detection_kernel.cpp.

90{
91 int kernelSize = kernelSizeFromRadius(radius);
92
93 Eigen::Matrix<qreal, Eigen::Dynamic, Eigen::Dynamic> matrix(kernelSize, kernelSize);
94 KIS_ASSERT_RECOVER_NOOP(kernelSize & 0x1);
95 const int center = kernelSize / 2;
96
97 if (type==Prewitt) {
98 for (int y = 0; y < kernelSize; y++) {
99 for (int x=0; x<kernelSize; x++) {
100 qreal yDistance;
101 if (reverse) {
102 yDistance = y - center;
103 } else {
104 yDistance = center - y;
105 }
106 matrix(x, y) = yDistance;
107 }
108 }
109 } else if(type==Simple) {
110 matrix.resize(1, kernelSize);
111 for (int y = 0; y < kernelSize; y++) {
112 qreal yDistance;
113 if (reverse) {
114 yDistance = y - center;
115 } else {
116 yDistance = center - y;
117 }
118 if (y==center) {
119 matrix(0, y) = 0;
120 } else {
121 matrix(0, y) = (1/yDistance);
122 }
123 }
124 } else {
125 for (int y = 0; y < kernelSize; y++) {
126 for (int x=0; x<kernelSize; x++) {
127 if (x==center && y==center) {
128 matrix(x, y) = 0;
129 } else {
130 qreal xD, yD;
131 if (reverse) {
132 xD = x - center;
133 yD = y - center;
134 } else {
135 xD = center - x;
136 yD = center - y;
137 }
138 matrix(x, y) = yD / (xD*xD + yD*yD);
139 }
140 }
141 }
142 }
143 return matrix;
144}

References kernelSizeFromRadius(), KIS_ASSERT_RECOVER_NOOP, Prewitt, and Simple.

◆ kernelSizeFromRadius()

int KisEdgeDetectionKernel::kernelSizeFromRadius ( qreal radius)
static

Definition at line 172 of file kis_edge_detection_kernel.cpp.

173{
174 return qMax((int)(2 * ceil(sigmaFromRadius(radius)) + 1), 3);
175}
static qreal sigmaFromRadius(qreal radius)

References sigmaFromRadius().

◆ sigmaFromRadius()

qreal KisEdgeDetectionKernel::sigmaFromRadius ( qreal radius)
static

Definition at line 177 of file kis_edge_detection_kernel.cpp.

178{
179 return 0.3 * radius + 0.3;
180}

The documentation for this class was generated from the following files: