Skip to content

Commit

Permalink
Add QgsFeedback arguments to QgsImageOperation blur methods to support
Browse files Browse the repository at this point in the history
responsive cancelation of operations
  • Loading branch information
nyalldawson committed Sep 24, 2021
1 parent fcc7b29 commit 702e1cc
Show file tree
Hide file tree
Showing 3 changed files with 25 additions and 15 deletions.
6 changes: 4 additions & 2 deletions python/core/auto_generated/effects/qgsimageoperation.sip.in
Expand Up @@ -118,28 +118,30 @@ using a color ramp.
for the distance transform operation
%End

static void stackBlur( QImage &image, int radius, bool alphaOnly = false );
static void stackBlur( QImage &image, int radius, bool alphaOnly = false, QgsFeedback *feedback = 0 );
%Docstring
Performs a stack blur on an image. Stack blur represents a good balance between
speed and blur quality.

:param image: QImage to blur
:param radius: blur radius in pixels, maximum value of 16
:param alphaOnly: set to ``True`` to blur only the alpha component of the image
:param feedback: optional feedback object for responsive cancelation (since QGIS 3.22)

.. note::

for fastest operation, ensure the source image is ARGB32_Premultiplied if
alphaOnly is set to ``False``, or ARGB32 if alphaOnly is ``True``
%End

static QImage *gaussianBlur( QImage &image, int radius ) /Factory/;
static QImage *gaussianBlur( QImage &image, int radius, QgsFeedback *feedback = 0 ) /Factory/;
%Docstring
Performs a gaussian blur on an image. Gaussian blur is slower but results in a high
quality blur.

:param image: QImage to blur
:param radius: blur radius in pixels
:param feedback: optional feedback object for responsive cancelation (since QGIS 3.22)

:return: blurred image

Expand Down
19 changes: 10 additions & 9 deletions src/core/effects/qgsimageoperation.cpp
Expand Up @@ -19,6 +19,7 @@
#include "qgis.h"
#include "qgscolorramp.h"
#include "qgslogger.h"
#include "qgsfeedback.h"
#include <QtConcurrentMap>
#include <QColor>
#include <QPainter>
Expand Down Expand Up @@ -555,7 +556,7 @@ void QgsImageOperation::ShadeFromArrayOperation::operator()( QRgb &rgb, const in

//stack blur

void QgsImageOperation::stackBlur( QImage &image, const int radius, const bool alphaOnly )
void QgsImageOperation::stackBlur( QImage &image, const int radius, const bool alphaOnly, QgsFeedback *feedback )
{
// culled from Qt's qpixmapfilter.cpp, see: http://www.qtcentre.org/archive/index.php/t-26534.html
int tab[] = { 14, 10, 8, 6, 5, 5, 4, 3, 3, 3, 3, 2, 2, 2, 2, 2, 2 };
Expand All @@ -579,16 +580,16 @@ void QgsImageOperation::stackBlur( QImage &image, const int radius, const bool a
if ( alphaOnly )
i1 = i2 = ( QSysInfo::ByteOrder == QSysInfo::BigEndian ? 0 : 3 );

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

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

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

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

if ( pImage->format() != originalFormat )
Expand All @@ -600,7 +601,7 @@ void QgsImageOperation::stackBlur( QImage &image, const int radius, const bool a

//gaussian blur

QImage *QgsImageOperation::gaussianBlur( QImage &image, const int radius )
QImage *QgsImageOperation::gaussianBlur( QImage &image, const int radius, QgsFeedback *feedback )
{
int width = image.width();
int height = image.height();
Expand All @@ -624,12 +625,12 @@ QImage *QgsImageOperation::gaussianBlur( QImage &image, const int radius )

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

//blur along columns
QImage *yBlurImage = new QImage( width, height, QImage::Format_ARGB32_Premultiplied );
GaussianBlurOperation colBlur( radius, QgsImageOperation::ByColumn, yBlurImage, kernel );
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;
Expand Down
15 changes: 11 additions & 4 deletions src/core/effects/qgsimageoperation.h
Expand Up @@ -23,6 +23,7 @@
#include <QColor>

#include "qgis_core.h"
#include "qgsfeedback.h"
#include <cmath>

class QgsColorRamp;
Expand Down Expand Up @@ -156,20 +157,22 @@ class CORE_EXPORT QgsImageOperation
* \param image QImage to blur
* \param radius blur radius in pixels, maximum value of 16
* \param alphaOnly set to TRUE to blur only the alpha component of the image
* \param feedback optional feedback object for responsive cancelation (since QGIS 3.22)
* \note for fastest operation, ensure the source image is ARGB32_Premultiplied if
* alphaOnly is set to FALSE, or ARGB32 if alphaOnly is TRUE
*/
static void stackBlur( QImage &image, int radius, bool alphaOnly = false );
static void stackBlur( QImage &image, int radius, bool alphaOnly = false, QgsFeedback *feedback = nullptr );

/**
* Performs a gaussian blur on an image. Gaussian blur is slower but results in a high
* quality blur.
* \param image QImage to blur
* \param radius blur radius in pixels
* \param feedback optional feedback object for responsive cancelation (since QGIS 3.22)
* \returns blurred image
* \note for fastest operation, ensure the source image is ARGB32_Premultiplied
*/
static QImage *gaussianBlur( QImage &image, int radius ) SIP_FACTORY;
static QImage *gaussianBlur( QImage &image, int radius, QgsFeedback *feedback = nullptr ) SIP_FACTORY;

/**
* Flips an image horizontally or vertically
Expand Down Expand Up @@ -407,12 +410,13 @@ class CORE_EXPORT QgsImageOperation
class StackBlurLineOperation
{
public:
StackBlurLineOperation( int alpha, LineOperationDirection direction, bool forwardDirection, int i1, int i2 )
StackBlurLineOperation( int alpha, LineOperationDirection direction, bool forwardDirection, int i1, int i2, QgsFeedback *feedback )
: mAlpha( alpha )
, mDirection( direction )
, mForwardDirection( forwardDirection )
, mi1( i1 )
, mi2( i2 )
, mFeedback( feedback )
{ }

typedef void result_type;
Expand Down Expand Up @@ -451,19 +455,21 @@ class CORE_EXPORT QgsImageOperation
bool mForwardDirection;
int mi1;
int mi2;
QgsFeedback *mFeedback = nullptr;
};

static double *createGaussianKernel( int radius );

class GaussianBlurOperation
{
public:
GaussianBlurOperation( int radius, LineOperationDirection direction, QImage *destImage, double *kernel )
GaussianBlurOperation( int radius, LineOperationDirection direction, QImage *destImage, double *kernel, QgsFeedback *feedback )
: mRadius( radius )
, mDirection( direction )
, mDestImage( destImage )
, mDestImageBpl( destImage->bytesPerLine() )
, mKernel( kernel )
, mFeedback( feedback )
{}

typedef void result_type;
Expand All @@ -476,6 +482,7 @@ class CORE_EXPORT QgsImageOperation
QImage *mDestImage = nullptr;
int mDestImageBpl;
double *mKernel = nullptr;
QgsFeedback *mFeedback = nullptr;

inline QRgb gaussianBlurVertical( int posy, unsigned char *sourceFirstLine, int sourceBpl, int height );
inline QRgb gaussianBlurHorizontal( int posx, unsigned char *sourceFirstLine, int width );
Expand Down

0 comments on commit 702e1cc

Please sign in to comment.