void KisConvolutionPainterTest::testGaussianBase(KisPaintDeviceSP dev, bool useFftw, const QString &prefix) { QBitArray channelFlags = KoColorSpaceRegistry::instance()->rgb8()->channelFlags(true, true); KisPainter gc(dev); qreal horizontalRadius = 5, verticalRadius = 5; for(int i = 0; i < 3 ; i++, horizontalRadius+=5, verticalRadius+=5) { QTime timer; timer.start(); gc.beginTransaction(); if (( horizontalRadius > 0 ) && ( verticalRadius > 0 )) { KisPaintDeviceSP interm = new KisPaintDevice(dev->colorSpace()); KisConvolutionKernelSP kernelHoriz = KisGaussianKernel::createHorizontalKernel(horizontalRadius); KisConvolutionKernelSP kernelVertical = KisGaussianKernel::createVerticalKernel(verticalRadius); const QRect applyRect = dev->exactBounds(); KisConvolutionPainter::TestingEnginePreference enginePreference = useFftw ? KisConvolutionPainter::FFTW : KisConvolutionPainter::SPATIAL; KisConvolutionPainter horizPainter(interm, enginePreference); horizPainter.setChannelFlags(channelFlags); horizPainter.applyMatrix(kernelHoriz, dev, applyRect.topLeft() - QPoint(0, verticalRadius), applyRect.topLeft() - QPoint(0, verticalRadius), applyRect.size() + QSize(0, 2 * verticalRadius), BORDER_REPEAT); KisConvolutionPainter verticalPainter(dev, enginePreference); verticalPainter.setChannelFlags(channelFlags); verticalPainter.applyMatrix(kernelVertical, interm, applyRect.topLeft(), applyRect.topLeft(), applyRect.size(), BORDER_REPEAT); QImage result = dev->convertToQImage(0, applyRect.x(), applyRect.y(), applyRect.width(), applyRect.height()); QString engine = useFftw ? "fftw" : "spatial"; QString testCaseName = QString("test_gaussian_%1_%2_%3.png").arg(horizontalRadius).arg(verticalRadius).arg(engine); TestUtil::checkQImage(result, "convolution_painter_test", QString("gaussian_") + prefix, testCaseName); gc.revertTransaction(); } dbgKrita << "Elapsed time:" << timer.elapsed() << "ms"; } }
void KisFeatherSelectionFilter::process(KisPixelSelectionSP pixelSelection, const QRect& rect) { // compute horizontal kernel const uint kernelSize = m_radius * 2 + 1; Matrix<qreal, Dynamic, Dynamic> gaussianMatrix(1, kernelSize); const qreal multiplicand = 1 / (2 * M_PI * m_radius * m_radius); const qreal exponentMultiplicand = 1 / (2 * m_radius * m_radius); for (uint x = 0; x < kernelSize; x++) { uint xDistance = qAbs((int)m_radius - (int)x); gaussianMatrix(0, x) = multiplicand * exp( -(qreal)((xDistance * xDistance) + (m_radius * m_radius)) * exponentMultiplicand ); } KisConvolutionKernelSP kernelHoriz = KisConvolutionKernel::fromMatrix(gaussianMatrix, 0, gaussianMatrix.sum()); KisConvolutionKernelSP kernelVertical = KisConvolutionKernel::fromMatrix(gaussianMatrix.transpose(), 0, gaussianMatrix.sum()); KisPaintDeviceSP interm = new KisPaintDevice(pixelSelection->colorSpace()); KisConvolutionPainter horizPainter(interm); horizPainter.setChannelFlags(interm->colorSpace()->channelFlags(false, true)); horizPainter.applyMatrix(kernelHoriz, pixelSelection, rect.topLeft(), rect.topLeft(), rect.size(), BORDER_REPEAT); horizPainter.end(); KisConvolutionPainter verticalPainter(pixelSelection); verticalPainter.setChannelFlags(pixelSelection->colorSpace()->channelFlags(false, true)); verticalPainter.applyMatrix(kernelVertical, interm, rect.topLeft(), rect.topLeft(), rect.size(), BORDER_REPEAT); verticalPainter.end(); }
void KisGaussianBlurFilter::process(KisPaintDeviceSP device, const QRect& rect, const KisFilterConfiguration* config, KoUpdater* progressUpdater ) const { QPoint srcTopLeft = rect.topLeft(); Q_ASSERT(device != 0); if (!config) config = new KisFilterConfiguration(id().id(), 1); QVariant value; config->getProperty("horizRadius", value); uint horizontalRadius = value.toUInt(); config->getProperty("vertRadius", value); uint verticalRadius = value.toUInt(); QBitArray channelFlags; if (config) { channelFlags = config->channelFlags(); } if (channelFlags.isEmpty() || !config) { channelFlags = QBitArray(device->colorSpace()->channelCount(), true); } // compute horizontal kernel uint horizKernelSize = horizontalRadius * 2 + 1; Matrix<qreal, Dynamic, Dynamic> horizGaussian(1, horizKernelSize); qreal horizSigma = horizontalRadius; const qreal horizMultiplicand = 1 / (2 * M_PI * horizSigma * horizSigma); const qreal horizExponentMultiplicand = 1 / (2 * horizSigma * horizSigma); for (uint x = 0; x < horizKernelSize; x++) { uint xDistance = qAbs((int)horizontalRadius - (int)x); horizGaussian(0, x) = horizMultiplicand * exp( -(qreal)((xDistance * xDistance) + (horizontalRadius * horizontalRadius)) * horizExponentMultiplicand ); } // compute vertical kernel uint verticalKernelSize = verticalRadius * 2 + 1; Matrix<qreal, Dynamic, Dynamic> verticalGaussian(verticalKernelSize, 1); qreal verticalSigma = verticalRadius; const qreal verticalMultiplicand = 1 / (2 * M_PI * verticalSigma * verticalSigma); const qreal verticalExponentMultiplicand = 1 / (2 * verticalSigma * verticalSigma); for (uint y = 0; y < verticalKernelSize; y++) { uint yDistance = qAbs((int)verticalRadius - (int)y); verticalGaussian(y, 0) = verticalMultiplicand * exp( -(qreal)((yDistance * yDistance) + (verticalRadius * verticalRadius)) * verticalExponentMultiplicand ); } if ( (horizontalRadius > 0) && (verticalRadius > 0) ) { KisPaintDeviceSP interm = new KisPaintDevice(device->colorSpace()); KisConvolutionKernelSP kernelHoriz = KisConvolutionKernel::fromMatrix(horizGaussian, 0, horizGaussian.sum()); KisConvolutionKernelSP kernelVertical = KisConvolutionKernel::fromMatrix(verticalGaussian, 0, verticalGaussian.sum()); KisConvolutionPainter horizPainter(interm); horizPainter.setChannelFlags(channelFlags); horizPainter.setProgress(progressUpdater); horizPainter.applyMatrix(kernelHoriz, device, srcTopLeft - QPoint(0, verticalRadius), srcTopLeft - QPoint(0, verticalRadius), rect.size() + QSize(0, 2 * verticalRadius), BORDER_REPEAT); KisConvolutionPainter verticalPainter(device); verticalPainter.setChannelFlags(channelFlags); verticalPainter.setProgress(progressUpdater); verticalPainter.applyMatrix(kernelVertical, interm, srcTopLeft, srcTopLeft, rect.size(), BORDER_REPEAT); } else { if (horizontalRadius > 0) { KisConvolutionPainter painter(device); painter.setChannelFlags(channelFlags); painter.setProgress(progressUpdater); KisConvolutionKernelSP kernelHoriz = KisConvolutionKernel::fromMatrix(horizGaussian, 0, horizGaussian.sum()); painter.applyMatrix(kernelHoriz, device, srcTopLeft, srcTopLeft, rect.size(), BORDER_REPEAT); } if (verticalRadius > 0) { KisConvolutionPainter painter(device); painter.setChannelFlags(channelFlags); painter.setProgress(progressUpdater); KisConvolutionKernelSP kernelVertical = KisConvolutionKernel::fromMatrix(verticalGaussian, 0, verticalGaussian.sum()); painter.applyMatrix(kernelVertical, device, srcTopLeft, srcTopLeft, rect.size(), BORDER_REPEAT); } } }