Skip to content

Commit

Permalink
Deprecate old QgsRasterResampler interface, and add a new interface
Browse files Browse the repository at this point in the history
which doesn't require pre-allocation of a temporary QImage

The existing interface is very inefficient for the bilinear resampler,
because it requires allocation of a temporary QImage just to pass
the desired height and width to the resampler...
  • Loading branch information
nyalldawson committed Oct 31, 2019
1 parent 95fb8e6 commit dde8da4
Show file tree
Hide file tree
Showing 9 changed files with 151 additions and 14 deletions.
Expand Up @@ -10,7 +10,8 @@



class QgsBilinearRasterResampler: QgsRasterResampler

class QgsBilinearRasterResampler: QgsRasterResamplerV2
{
%Docstring
Bilinear Raster Resampler
Expand All @@ -25,10 +26,13 @@ Bilinear Raster Resampler
%Docstring
Constructor for QgsBilinearRasterResampler.
%End

virtual void resample( const QImage &srcImage, QImage &dstImage );


virtual QImage resampleV2( const QImage &source, const QSize &size );

virtual QString type() const;

virtual QgsBilinearRasterResampler *clone() const /Factory/;

};
Expand Down
Expand Up @@ -10,7 +10,7 @@



class QgsCubicRasterResampler: QgsRasterResampler
class QgsCubicRasterResampler: QgsRasterResamplerV2
{
%Docstring
Cubic Raster Resampler
Expand All @@ -27,10 +27,16 @@ Constructor for QgsCubicRasterResampler.
%End
virtual QgsCubicRasterResampler *clone() const /Factory/;


virtual QImage resampleV2( const QImage &source, const QSize &size );


virtual void resample( const QImage &srcImage, QImage &dstImage );


virtual QString type() const;


};

/************************************************************************
Expand Down
36 changes: 35 additions & 1 deletion python/core/auto_generated/raster/qgsrasterresampler.sip.in
Expand Up @@ -31,7 +31,17 @@ Interface for resampling rasters (e.g. to have a smoother appearance)
%End
public:
virtual ~QgsRasterResampler();
virtual void resample( const QImage &srcImage, QImage &dstImage ) = 0;

virtual void resample( const QImage &srcImage, QImage &dstImage ) = 0 /Deprecated/;
%Docstring
Resamples a source image to a destination image.

The size of the passed destination image should be respected during the resampling
process.

.. deprecated:: QGIS 3.10.1
use the more efficient QgsRasterResamplerV2 interface instead.
%End

virtual QString type() const = 0;
%Docstring
Expand All @@ -47,6 +57,30 @@ Ownership is transferred to the caller.
%End
};


class QgsRasterResamplerV2 : QgsRasterResampler
{
%Docstring
Interface for resampling rasters (V2) (e.g. to have a smoother appearance),
which provides a more efficient interface vs QgsRasterResampler.

.. versionadded:: 3.10.1
%End

%TypeHeaderCode
#include "qgsrasterresampler.h"
%End
public:

virtual QImage resampleV2( const QImage &source, const QSize &size ) = 0;
%Docstring
Resamples a ``source`` image to the specified ``size``.

Returns the resampled image, or a null QImage if the resampling fails.
%End

};

/************************************************************************
* This file has been generated automatically from *
* *
Expand Down
12 changes: 12 additions & 0 deletions src/core/raster/qgsbilinearrasterresampler.cpp
Expand Up @@ -24,7 +24,19 @@ QgsBilinearRasterResampler *QgsBilinearRasterResampler::clone() const
return new QgsBilinearRasterResampler();
}

Q_NOWARN_DEPRECATED_PUSH
void QgsBilinearRasterResampler::resample( const QImage &srcImage, QImage &dstImage )
{
dstImage = srcImage.scaled( dstImage.width(), dstImage.height(), Qt::IgnoreAspectRatio, Qt::SmoothTransformation );
}
Q_NOWARN_DEPRECATED_POP

QImage QgsBilinearRasterResampler::resampleV2( const QImage &source, const QSize &size )
{
return source.scaled( size.width(), size.height(), Qt::IgnoreAspectRatio, Qt::SmoothTransformation );
}

QString QgsBilinearRasterResampler::type() const
{
return QStringLiteral( "bilinear" );
}
9 changes: 6 additions & 3 deletions src/core/raster/qgsbilinearrasterresampler.h
Expand Up @@ -20,6 +20,8 @@

#include "qgsrasterresampler.h"
#include "qgis_sip.h"
#include "qgis.h"

#include <QColor>

#include "qgis_core.h"
Expand All @@ -28,17 +30,18 @@
* \ingroup core
Bilinear Raster Resampler
*/
class CORE_EXPORT QgsBilinearRasterResampler: public QgsRasterResampler
class CORE_EXPORT QgsBilinearRasterResampler: public QgsRasterResamplerV2
{
public:

/**
* Constructor for QgsBilinearRasterResampler.
*/
QgsBilinearRasterResampler() = default;

void resample( const QImage &srcImage, QImage &dstImage ) override;
QString type() const override { return QStringLiteral( "bilinear" ); }

QImage resampleV2( const QImage &source, const QSize &size ) override;
QString type() const override;
QgsBilinearRasterResampler *clone() const override SIP_FACTORY;
};

Expand Down
19 changes: 19 additions & 0 deletions src/core/raster/qgscubicrasterresampler.cpp
Expand Up @@ -24,6 +24,19 @@ QgsCubicRasterResampler *QgsCubicRasterResampler::clone() const
return new QgsCubicRasterResampler();
}

QImage QgsCubicRasterResampler::resampleV2( const QImage &source, const QSize &size )
{
QImage dest = QImage( size.width(), size.height(), QImage::Format_ARGB32 );

// note, when removing deprecated members, just make the existing overridden resample method private!
Q_NOWARN_DEPRECATED_PUSH
resample( source, dest );
Q_NOWARN_DEPRECATED_POP

return dest;
}

Q_NOWARN_DEPRECATED_PUSH
void QgsCubicRasterResampler::resample( const QImage &srcImage, QImage &dstImage )
{
int nCols = srcImage.width();
Expand Down Expand Up @@ -274,6 +287,12 @@ void QgsCubicRasterResampler::resample( const QImage &srcImage, QImage &dstImage
delete[] yDerivativeMatrixBlue;
delete[] yDerivativeMatrixAlpha;
}
Q_NOWARN_DEPRECATED_POP

QString QgsCubicRasterResampler::type() const
{
return QStringLiteral( "cubic" );
}

void QgsCubicRasterResampler::xDerivativeMatrix( int nCols, int nRows, double *matrix, const int *colorMatrix )
{
Expand Down
9 changes: 7 additions & 2 deletions src/core/raster/qgscubicrasterresampler.h
Expand Up @@ -20,6 +20,7 @@

#include "qgsrasterresampler.h"
#include "qgis_sip.h"
#include "qgis.h"
#include <QColor>

#include "qgis_core.h"
Expand All @@ -28,7 +29,7 @@
* \ingroup core
Cubic Raster Resampler
*/
class CORE_EXPORT QgsCubicRasterResampler: public QgsRasterResampler
class CORE_EXPORT QgsCubicRasterResampler: public QgsRasterResamplerV2
{
public:

Expand All @@ -37,8 +38,12 @@ class CORE_EXPORT QgsCubicRasterResampler: public QgsRasterResampler
*/
QgsCubicRasterResampler() = default;
QgsCubicRasterResampler *clone() const override SIP_FACTORY;

QImage resampleV2( const QImage &source, const QSize &size ) override;

void resample( const QImage &srcImage, QImage &dstImage ) override;
QString type() const override { return QStringLiteral( "cubic" ); }

QString type() const override;

private:
static void xDerivativeMatrix( int nCols, int nRows, double *matrix, const int *colorMatrix );
Expand Down
31 changes: 27 additions & 4 deletions src/core/raster/qgsrasterresamplefilter.cpp
Expand Up @@ -184,18 +184,41 @@ QgsRasterBlock *QgsRasterResampleFilter::block( int bandNo, QgsRectangle const

//resample image
QImage img = inputBlock->image();

QImage dstImg = QImage( width, height, QImage::Format_ARGB32_Premultiplied );
QImage dstImg;

if ( mZoomedInResampler && ( oversamplingX < 1.0 || qgsDoubleNear( oversampling, 1.0 ) ) )
{
QgsDebugMsgLevel( QStringLiteral( "zoomed in resampling" ), 4 );
mZoomedInResampler->resample( img, dstImg );

if ( QgsRasterResamplerV2 *resamplerV2 = dynamic_cast< QgsRasterResamplerV2 * >( mZoomedInResampler.get( ) ) )
{
dstImg = resamplerV2->resampleV2( img, QSize( width, height ) );
}
else
{
// old inefficient interface
Q_NOWARN_DEPRECATED_PUSH
QImage dstImg = QImage( width, height, QImage::Format_ARGB32_Premultiplied );
mZoomedInResampler->resample( img, dstImg );
Q_NOWARN_DEPRECATED_POP
}
}
else if ( mZoomedOutResampler && oversamplingX > 1.0 )
{
QgsDebugMsgLevel( QStringLiteral( "zoomed out resampling" ), 4 );
mZoomedOutResampler->resample( img, dstImg );

if ( QgsRasterResamplerV2 *resamplerV2 = dynamic_cast< QgsRasterResamplerV2 * >( mZoomedOutResampler.get( ) ) )
{
dstImg = resamplerV2->resampleV2( img, QSize( width, height ) );
}
else
{
// old inefficient interface
Q_NOWARN_DEPRECATED_PUSH
QImage dstImg = QImage( width, height, QImage::Format_ARGB32_Premultiplied );
mZoomedOutResampler->resample( img, dstImg );
Q_NOWARN_DEPRECATED_POP
}
}
else
{
Expand Down
33 changes: 32 additions & 1 deletion src/core/raster/qgsrasterresampler.h
Expand Up @@ -24,6 +24,7 @@

class QString;
class QImage;
class QSize;

/**
* \ingroup core
Expand All @@ -50,7 +51,16 @@ class CORE_EXPORT QgsRasterResampler

public:
virtual ~QgsRasterResampler() = default;
virtual void resample( const QImage &srcImage, QImage &dstImage ) = 0;

/**
* Resamples a source image to a destination image.
*
* The size of the passed destination image should be respected during the resampling
* process.
*
* \deprecated since QGIS 3.10.1, use the more efficient QgsRasterResamplerV2 interface instead.
*/
Q_DECL_DEPRECATED virtual void resample( const QImage &srcImage, QImage &dstImage ) = 0 SIP_DEPRECATED;

/**
* Gets a descriptive type identifier for this raster resampler.
Expand All @@ -66,4 +76,25 @@ class CORE_EXPORT QgsRasterResampler
virtual QgsRasterResampler *clone() const = 0 SIP_FACTORY;
};


/**
* \ingroup core
* Interface for resampling rasters (V2) (e.g. to have a smoother appearance),
* which provides a more efficient interface vs QgsRasterResampler.
*
* \since QGIS 3.10.1
*/
class CORE_EXPORT QgsRasterResamplerV2 : public QgsRasterResampler
{
public:

/**
* Resamples a \a source image to the specified \a size.
*
* Returns the resampled image, or a null QImage if the resampling fails.
*/
virtual QImage resampleV2( const QImage &source, const QSize &size ) = 0;

};

#endif // QGSRASTERRESAMPLER_H

0 comments on commit dde8da4

Please sign in to comment.