Skip to content

Commit

Permalink
Add some early exit paths to QgsImageOperation
Browse files Browse the repository at this point in the history
  • Loading branch information
nyalldawson committed Sep 24, 2021
1 parent 702e1cc commit 0d29288
Show file tree
Hide file tree
Showing 2 changed files with 47 additions and 11 deletions.
54 changes: 43 additions & 11 deletions src/core/effects/qgsimageoperation.cpp
Expand Up @@ -568,34 +568,51 @@ void QgsImageOperation::stackBlur( QImage &image, const int radius, const bool a
//ensure correct source format.
QImage::Format originalFormat = image.format();
QImage *pImage = ℑ
std::unique_ptr< QImage> convertedImage;
if ( !alphaOnly && originalFormat != QImage::Format_ARGB32_Premultiplied )
{
pImage = new QImage( image.convertToFormat( QImage::Format_ARGB32_Premultiplied ) );
convertedImage = std::make_unique< QImage >( image.convertToFormat( QImage::Format_ARGB32_Premultiplied ) );
pImage = convertedImage.get();
}
else if ( alphaOnly && originalFormat != QImage::Format_ARGB32 )
{
pImage = new QImage( image.convertToFormat( QImage::Format_ARGB32 ) );
convertedImage = std::make_unique< QImage >( image.convertToFormat( QImage::Format_ARGB32 ) );
pImage = convertedImage.get();
}

if ( feedback && feedback->isCanceled() )
return;

if ( alphaOnly )
i1 = i2 = ( QSysInfo::ByteOrder == QSysInfo::BigEndian ? 0 : 3 );

StackBlurLineOperation topToBottomBlur( alpha, QgsImageOperation::ByColumn, true, i1, i2, feedback );
runLineOperation( *pImage, topToBottomBlur );

if ( feedback && feedback->isCanceled() )
return;

StackBlurLineOperation leftToRightBlur( alpha, QgsImageOperation::ByRow, true, i1, i2, feedback );
runLineOperation( *pImage, leftToRightBlur );

if ( feedback && feedback->isCanceled() )
return;

StackBlurLineOperation bottomToTopBlur( alpha, QgsImageOperation::ByColumn, false, i1, i2, feedback );
runLineOperation( *pImage, bottomToTopBlur );

if ( feedback && feedback->isCanceled() )
return;

StackBlurLineOperation rightToLeftBlur( alpha, QgsImageOperation::ByRow, false, i1, i2, feedback );
runLineOperation( *pImage, rightToLeftBlur );

if ( feedback && feedback->isCanceled() )
return;

if ( pImage->format() != originalFormat )
{
image = pImage->convertToFormat( originalFormat );
delete pImage;
}
}

Expand All @@ -613,37 +630,46 @@ QImage *QgsImageOperation::gaussianBlur( QImage &image, const int radius, QgsFee
return copy;
}

double *kernel = createGaussianKernel( radius );
std::unique_ptr<double[]>kernel( createGaussianKernel( radius ) );
if ( feedback && feedback->isCanceled() )
return new QImage();

//ensure correct source format.
QImage::Format originalFormat = image.format();
QImage *pImage = &image;
std::unique_ptr< QImage> convertedImage;
if ( originalFormat != QImage::Format_ARGB32_Premultiplied )
{
pImage = new QImage( image.convertToFormat( QImage::Format_ARGB32_Premultiplied ) );
convertedImage = std::make_unique< QImage >( image.convertToFormat( QImage::Format_ARGB32_Premultiplied ) );
pImage = convertedImage.get();
}
if ( feedback && feedback->isCanceled() )
return new QImage();

//blur along rows
QImage xBlurImage = QImage( width, height, QImage::Format_ARGB32_Premultiplied );
GaussianBlurOperation rowBlur( radius, QgsImageOperation::ByRow, &xBlurImage, kernel.get(), feedback );
runRectOperation( *pImage, rowBlur );

if ( feedback && feedback->isCanceled() )
return new QImage();

//blur along columns
std::unique_ptr< QImage > yBlurImage = std::make_unique< QImage >( width, height, QImage::Format_ARGB32_Premultiplied );
GaussianBlurOperation colBlur( radius, QgsImageOperation::ByColumn, yBlurImage.get(), kernel.get(), feedback );
runRectOperation( xBlurImage, colBlur );

delete[] kernel;
if ( feedback && feedback->isCanceled() )
return new QImage();

kernel.reset();

if ( originalFormat != QImage::Format_ARGB32_Premultiplied )
{
QImage *convertedImage = new QImage( yBlurImage->convertToFormat( originalFormat ) );
delete yBlurImage;
delete pImage;
return convertedImage;
return new QImage( yBlurImage->convertToFormat( originalFormat ) );
}

return yBlurImage;
return yBlurImage.release();
}

void QgsImageOperation::GaussianBlurOperation::operator()( QgsImageOperation::ImageBlock &block )
Expand All @@ -662,6 +688,9 @@ void QgsImageOperation::GaussianBlurOperation::operator()( QgsImageOperation::Im
//blur along rows
for ( unsigned int y = block.beginLine; y < block.endLine; ++y, outputLineRef += mDestImageBpl )
{
if ( mFeedback && mFeedback->isCanceled() )
break;

sourceRef = sourceFirstLine;
destRef = reinterpret_cast< QRgb * >( outputLineRef );
for ( int x = 0; x < width; ++x, ++destRef, sourceRef += 4 )
Expand All @@ -675,6 +704,9 @@ void QgsImageOperation::GaussianBlurOperation::operator()( QgsImageOperation::Im
unsigned char *sourceRef = block.image->scanLine( block.beginLine );
for ( unsigned int y = block.beginLine; y < block.endLine; ++y, outputLineRef += mDestImageBpl, sourceRef += sourceBpl )
{
if ( mFeedback && mFeedback->isCanceled() )
break;

destRef = reinterpret_cast< QRgb * >( outputLineRef );
for ( int x = 0; x < width; ++x, ++destRef )
{
Expand Down
4 changes: 4 additions & 0 deletions src/core/effects/qgsimageoperation.h
Expand Up @@ -27,6 +27,7 @@
#include <cmath>

class QgsColorRamp;
class QgsFeedback;

/**
* \ingroup core
Expand Down Expand Up @@ -442,6 +443,9 @@ class CORE_EXPORT QgsImageOperation
p += increment;
for ( int j = 1; j < lineLength; ++j, p += increment )
{
if ( mFeedback && mFeedback->isCanceled() )
break;

for ( int i = mi1; i <= mi2; ++i )
{
p[i] = ( rgba[i] += ( ( p[i] << 4 ) - rgba[i] ) * mAlpha / 16 ) >> 4;
Expand Down

0 comments on commit 0d29288

Please sign in to comment.