Members of the KDE Community are recommended to subscribe to the kde-community mailing list at https://mail.kde.org/mailman/listinfo/kde-community to allow them to participate in important discussions and receive other important announcements

Commit e3c0816b authored by Dmitry Kazakov's avatar Dmitry Kazakov

Fix border artifacts in edge-detection filters

KisConvolutionPainter::applyMatrix() will automatically read more
data outside the passed `areaSize` if it is needed for the kernel.
There is no need to pass bigger area to the painter.

BUG:419534
parent 9e9bfce2
......@@ -58,9 +58,14 @@ public:
/**
* Convolve all channels in src using the specified kernel; there is only one kernel for all
* channels possible. By default the border pixels are not convolved, that is, convolving
* starts with at (x + kernel.width/2, y + kernel.height/2) and stops at w - (kernel.width/2)
* and h - (kernel.height/2)
* channels possible.
*
* WARNING: The painter will read **more** pixels than you pass in \p areaSize.
* The actual processing area will be:
* QRect(x - kernel.width() / 2,
* y - kernel.height() / 2,
* w + 2 * (kernel.width() / 2),
* h + 2 * (kernel.height() / 2))
*
* The border op decides what to do with pixels too close to the edge of the rect as defined above.
*
......
......@@ -216,25 +216,22 @@ void KisEdgeDetectionKernel::applyEdgeDetection(KisPaintDeviceSP device,
KisConvolutionKernelSP kernelHorizLeftRight = KisEdgeDetectionKernel::createHorizontalKernel(xRadius, type);
KisConvolutionKernelSP kernelVerticalTopBottom = KisEdgeDetectionKernel::createVerticalKernel(yRadius, type);
qreal horizontalCenter = qreal(kernelHorizLeftRight->width()) / 2.0;
qreal verticalCenter = qreal(kernelVerticalTopBottom->height()) / 2.0;
KisConvolutionPainter horizPainterLR(x_denormalised);
horizPainterLR.setChannelFlags(channelFlags);
horizPainterLR.setProgress(progressUpdater);
horizPainterLR.applyMatrix(kernelHorizLeftRight, device,
srcTopLeft - QPoint(0, ceil(horizontalCenter)),
srcTopLeft - QPoint(0, ceil(horizontalCenter)),
rect.size() + QSize(0, 2 * ceil(horizontalCenter)), BORDER_REPEAT);
srcTopLeft,
srcTopLeft,
rect.size(), BORDER_REPEAT);
KisConvolutionPainter verticalPainterTB(y_denormalised);
verticalPainterTB.setChannelFlags(channelFlags);
verticalPainterTB.setProgress(progressUpdater);
verticalPainterTB.applyMatrix(kernelVerticalTopBottom, device,
srcTopLeft - QPoint(0, ceil(verticalCenter)),
srcTopLeft - QPoint(0, ceil(verticalCenter)),
rect.size() + QSize(0, 2 * ceil(verticalCenter)), BORDER_REPEAT);
srcTopLeft,
srcTopLeft,
rect.size(), BORDER_REPEAT);
KisSequentialIterator yItterator(y_denormalised, rect);
KisSequentialIterator xItterator(x_denormalised, rect);
......@@ -284,20 +281,15 @@ void KisEdgeDetectionKernel::applyEdgeDetection(KisPaintDeviceSP device,
}
} else {
KisConvolutionKernelSP kernel;
qreal center = 0;
bool denormalize = !writeToAlpha;
if (output == xGrowth) {
kernel = KisEdgeDetectionKernel::createHorizontalKernel(xRadius, type, denormalize);
center = qreal(kernel->width()) / 2.0;
} else if (output == xFall) {
kernel = KisEdgeDetectionKernel::createHorizontalKernel(xRadius, type, denormalize, true);
center = qreal(kernel->width()) / 2.0;
} else if (output == yGrowth) {
kernel = KisEdgeDetectionKernel::createVerticalKernel(yRadius, type, denormalize);
center = qreal(kernel->height()) / 2.0;
} else { //yFall
kernel = KisEdgeDetectionKernel::createVerticalKernel(yRadius, type, denormalize, true);
center = qreal(kernel->height()) / 2.0;
}
if (writeToAlpha) {
......@@ -308,9 +300,8 @@ void KisEdgeDetectionKernel::applyEdgeDetection(KisPaintDeviceSP device,
kernelP.setChannelFlags(channelFlags);
kernelP.setProgress(progressUpdater);
kernelP.applyMatrix(kernel, device,
srcTopLeft - QPoint(0, ceil(center)),
srcTopLeft - QPoint(0, ceil(center)),
rect.size() + QSize(0, 2 * ceil(center)), BORDER_REPEAT);
srcTopLeft, srcTopLeft,
rect.size(), BORDER_REPEAT);
KisSequentialIterator iterator(denormalised, rect);
KisSequentialIterator finalIt(device, rect);
const int pixelSize = device->colorSpace()->pixelSize();
......@@ -334,9 +325,8 @@ void KisEdgeDetectionKernel::applyEdgeDetection(KisPaintDeviceSP device,
kernelP.setChannelFlags(channelFlags);
kernelP.setProgress(progressUpdater);
kernelP.applyMatrix(kernel, device,
srcTopLeft - QPoint(0, ceil(center)),
srcTopLeft - QPoint(0, ceil(center)),
rect.size() + QSize(0, 2 * ceil(center)), BORDER_REPEAT);
srcTopLeft, srcTopLeft,
rect.size(), BORDER_REPEAT);
KisSequentialIterator finalIt(device, rect);
int numConseqPixels = finalIt.nConseqPixels();
......@@ -371,25 +361,21 @@ void KisEdgeDetectionKernel::convertToNormalMap(KisPaintDeviceSP device,
KisConvolutionKernelSP kernelHorizLeftRight = KisEdgeDetectionKernel::createHorizontalKernel(yRadius, type, true, !channelFlip[1]);
KisConvolutionKernelSP kernelVerticalTopBottom = KisEdgeDetectionKernel::createVerticalKernel(xRadius, type, true, !channelFlip[0]);
qreal horizontalCenter = qreal(kernelHorizLeftRight->width()) / 2.0;
qreal verticalCenter = qreal(kernelVerticalTopBottom->height()) / 2.0;
KisConvolutionPainter horizPainterLR(y_denormalised);
horizPainterLR.setChannelFlags(channelFlags);
horizPainterLR.setProgress(progressUpdater);
horizPainterLR.applyMatrix(kernelHorizLeftRight, device,
srcTopLeft - QPoint(ceil(horizontalCenter), 0),
srcTopLeft - QPoint(ceil(horizontalCenter), 0),
rect.size() + QSize(2 * ceil(horizontalCenter), 0), BORDER_REPEAT);
srcTopLeft, srcTopLeft,
rect.size(), BORDER_REPEAT);
KisConvolutionPainter verticalPainterTB(x_denormalised);
verticalPainterTB.setChannelFlags(channelFlags);
verticalPainterTB.setProgress(progressUpdater);
verticalPainterTB.applyMatrix(kernelVerticalTopBottom, device,
srcTopLeft - QPoint(0, ceil(verticalCenter)),
srcTopLeft - QPoint(0, ceil(verticalCenter)),
rect.size() + QSize(0, 2 * ceil(verticalCenter)), BORDER_REPEAT);
srcTopLeft,
srcTopLeft,
rect.size(), BORDER_REPEAT);
KisSequentialIterator yItterator(y_denormalised, rect);
KisSequentialIterator xItterator(x_denormalised, rect);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment