diff --git a/python/core/auto_additions/qgsrasterdataprovider.py b/python/core/auto_additions/qgsrasterdataprovider.py index b1b33d58ad87..aae419a9d036 100644 --- a/python/core/auto_additions/qgsrasterdataprovider.py +++ b/python/core/auto_additions/qgsrasterdataprovider.py @@ -1,7 +1,12 @@ # The following has been generated automatically from src/core/raster/qgsrasterdataprovider.h # monkey patching scoped based enum -QgsRasterDataProvider.ResamplingMethod.Nearest.__doc__ = "Nearest-neighbour resamplikng" -QgsRasterDataProvider.ResamplingMethod.Bilinear.__doc__ = "Bilinear resamplikng" -QgsRasterDataProvider.ResamplingMethod.Cubic.__doc__ = "Bicubic resamplikng" -QgsRasterDataProvider.ResamplingMethod.__doc__ = 'Resampling method for provider-level resampling.\n\n.. versionadded:: 3.16\n\n' + '* ``Nearest``: ' + QgsRasterDataProvider.ResamplingMethod.Nearest.__doc__ + '\n' + '* ``Bilinear``: ' + QgsRasterDataProvider.ResamplingMethod.Bilinear.__doc__ + '\n' + '* ``Cubic``: ' + QgsRasterDataProvider.ResamplingMethod.Cubic.__doc__ +QgsRasterDataProvider.ResamplingMethod.Nearest.__doc__ = "Nearest-neighbour resampling" +QgsRasterDataProvider.ResamplingMethod.Bilinear.__doc__ = "Bilinear (2x2 kernel) resampling" +QgsRasterDataProvider.ResamplingMethod.Cubic.__doc__ = "Cubic Convolution Approximation (4x4 kernel) resampling" +QgsRasterDataProvider.ResamplingMethod.CubicSpline.__doc__ = "Cubic B-Spline Approximation (4x4 kernel)" +QgsRasterDataProvider.ResamplingMethod.Lanczos.__doc__ = "Lanczos windowed sinc interpolation (6x6 kernel)" +QgsRasterDataProvider.ResamplingMethod.Average.__doc__ = "Average resampling" +QgsRasterDataProvider.ResamplingMethod.Mode.__doc__ = "Mode (selects the value which appears most often of all the sampled points)" +QgsRasterDataProvider.ResamplingMethod.Gauss.__doc__ = "Gauss blurring" +QgsRasterDataProvider.ResamplingMethod.__doc__ = 'Resampling method for provider-level resampling.\n\n.. versionadded:: 3.16\n\n' + '* ``Nearest``: ' + QgsRasterDataProvider.ResamplingMethod.Nearest.__doc__ + '\n' + '* ``Bilinear``: ' + QgsRasterDataProvider.ResamplingMethod.Bilinear.__doc__ + '\n' + '* ``Cubic``: ' + QgsRasterDataProvider.ResamplingMethod.Cubic.__doc__ + '\n' + '* ``CubicSpline``: ' + QgsRasterDataProvider.ResamplingMethod.CubicSpline.__doc__ + '\n' + '* ``Lanczos``: ' + QgsRasterDataProvider.ResamplingMethod.Lanczos.__doc__ + '\n' + '* ``Average``: ' + QgsRasterDataProvider.ResamplingMethod.Average.__doc__ + '\n' + '* ``Mode``: ' + QgsRasterDataProvider.ResamplingMethod.Mode.__doc__ + '\n' + '* ``Gauss``: ' + QgsRasterDataProvider.ResamplingMethod.Gauss.__doc__ # -- diff --git a/python/core/auto_generated/raster/qgsrasterdataprovider.sip.in b/python/core/auto_generated/raster/qgsrasterdataprovider.sip.in index 5f6e183252fd..c624c54b035c 100644 --- a/python/core/auto_generated/raster/qgsrasterdataprovider.sip.in +++ b/python/core/auto_generated/raster/qgsrasterdataprovider.sip.in @@ -559,6 +559,11 @@ Returns whether provider-level resampling is enabled. Nearest, Bilinear, Cubic, + CubicSpline, + Lanczos, + Average, + Mode, + Gauss }; virtual bool setZoomedInResamplingMethod( ResamplingMethod method ); diff --git a/src/core/providers/gdal/qgsgdalprovider.cpp b/src/core/providers/gdal/qgsgdalprovider.cpp index eab4fbc76ab8..cc6593584ef0 100644 --- a/src/core/providers/gdal/qgsgdalprovider.cpp +++ b/src/core/providers/gdal/qgsgdalprovider.cpp @@ -802,6 +802,26 @@ static GDALRIOResampleAlg getGDALResamplingAlg( QgsGdalProvider::ResamplingMetho case QgsGdalProvider::ResamplingMethod::Cubic: eResampleAlg = GRIORA_Cubic; break; + + case QgsRasterDataProvider::ResamplingMethod::CubicSpline: + eResampleAlg = GRIORA_CubicSpline; + break; + + case QgsRasterDataProvider::ResamplingMethod::Lanczos: + eResampleAlg = GRIORA_Lanczos; + break; + + case QgsRasterDataProvider::ResamplingMethod::Average: + eResampleAlg = GRIORA_Average; + break; + + case QgsRasterDataProvider::ResamplingMethod::Mode: + eResampleAlg = GRIORA_Mode; + break; + + case QgsRasterDataProvider::ResamplingMethod::Gauss: + eResampleAlg = GRIORA_Gauss; + break; } return eResampleAlg; diff --git a/src/core/raster/qgsrasterdataprovider.cpp b/src/core/raster/qgsrasterdataprovider.cpp index 9e61a8248efb..86b45ac28cc7 100644 --- a/src/core/raster/qgsrasterdataprovider.cpp +++ b/src/core/raster/qgsrasterdataprovider.cpp @@ -570,6 +570,26 @@ static QgsRasterDataProvider::ResamplingMethod resamplingMethodFromString( const { return QgsRasterDataProvider::ResamplingMethod::Cubic; } + else if ( str == QLatin1String( "cubicSpline" ) ) + { + return QgsRasterDataProvider::ResamplingMethod::CubicSpline; + } + else if ( str == QLatin1String( "lanczos" ) ) + { + return QgsRasterDataProvider::ResamplingMethod::Lanczos; + } + else if ( str == QLatin1String( "average" ) ) + { + return QgsRasterDataProvider::ResamplingMethod::Average; + } + else if ( str == QLatin1String( "mode" ) ) + { + return QgsRasterDataProvider::ResamplingMethod::Mode; + } + else if ( str == QLatin1String( "gauss" ) ) + { + return QgsRasterDataProvider::ResamplingMethod::Gauss; + } return QgsRasterDataProvider::ResamplingMethod::Nearest; } @@ -594,9 +614,22 @@ static QString resamplingMethodToString( QgsRasterDataProvider::ResamplingMethod { switch ( method ) { - case QgsRasterDataProvider::ResamplingMethod::Nearest : return QStringLiteral( "nearestNeighbour" ); - case QgsRasterDataProvider::ResamplingMethod::Bilinear : return QStringLiteral( "bilinear" ); - case QgsRasterDataProvider::ResamplingMethod::Cubic : return QStringLiteral( "cubic" ); + case QgsRasterDataProvider::ResamplingMethod::Nearest: + return QStringLiteral( "nearestNeighbour" ); + case QgsRasterDataProvider::ResamplingMethod::Bilinear: + return QStringLiteral( "bilinear" ); + case QgsRasterDataProvider::ResamplingMethod::Cubic: + return QStringLiteral( "cubic" ); + case QgsRasterDataProvider::ResamplingMethod::CubicSpline: + return QStringLiteral( "cubicSpline" ); + case QgsRasterDataProvider::ResamplingMethod::Lanczos: + return QStringLiteral( "lanczos" ); + case QgsRasterDataProvider::ResamplingMethod::Average: + return QStringLiteral( "average" ); + case QgsRasterDataProvider::ResamplingMethod::Mode: + return QStringLiteral( "mode" ); + case QgsRasterDataProvider::ResamplingMethod::Gauss: + return QStringLiteral( "gauss" ); } // should not happen return QStringLiteral( "nearestNeighbour" ); diff --git a/src/core/raster/qgsrasterdataprovider.h b/src/core/raster/qgsrasterdataprovider.h index 334848b7b216..c397ed51c65e 100644 --- a/src/core/raster/qgsrasterdataprovider.h +++ b/src/core/raster/qgsrasterdataprovider.h @@ -607,9 +607,14 @@ class CORE_EXPORT QgsRasterDataProvider : public QgsDataProvider, public QgsRast */ enum class ResamplingMethod { - Nearest, //!< Nearest-neighbour resamplikng - Bilinear, //!< Bilinear resamplikng - Cubic, //!< Bicubic resamplikng + Nearest, //!< Nearest-neighbour resampling + Bilinear, //!< Bilinear (2x2 kernel) resampling + Cubic,//!< Cubic Convolution Approximation (4x4 kernel) resampling + CubicSpline, //!< Cubic B-Spline Approximation (4x4 kernel) + Lanczos, //!< Lanczos windowed sinc interpolation (6x6 kernel) + Average, //!< Average resampling + Mode, //!< Mode (selects the value which appears most often of all the sampled points) + Gauss //!< Gauss blurring }; /** diff --git a/src/gui/raster/qgsresamplingutils.cpp b/src/gui/raster/qgsresamplingutils.cpp index 2065a9ab6cef..bea27b7a212d 100644 --- a/src/gui/raster/qgsresamplingutils.cpp +++ b/src/gui/raster/qgsresamplingutils.cpp @@ -44,13 +44,25 @@ void QgsResamplingUtils::initWidgets( QgsRasterLayer *rasterLayer, mMaximumOversamplingSpinBox = maximumOversamplingSpinBox; mCbEarlyResampling = cbEarlyResampling; - mZoomedInResamplingComboBox->addItem( QObject::tr( "Nearest neighbour" ), static_cast( QgsRasterDataProvider::ResamplingMethod::Nearest ) ); - mZoomedInResamplingComboBox->addItem( QObject::tr( "Bilinear" ), static_cast( QgsRasterDataProvider::ResamplingMethod::Bilinear ) ); - mZoomedInResamplingComboBox->addItem( QObject::tr( "Cubic" ), static_cast( QgsRasterDataProvider::ResamplingMethod::Cubic ) ); + for ( QComboBox *combo : {mZoomedInResamplingComboBox, mZoomedOutResamplingComboBox } ) + { + combo->addItem( QObject::tr( "Nearest Neighbour" ), static_cast( QgsRasterDataProvider::ResamplingMethod::Nearest ) ); + combo->addItem( QObject::tr( "Bilinear" ), static_cast( QgsRasterDataProvider::ResamplingMethod::Bilinear ) ); + combo->addItem( QObject::tr( "Cubic" ), static_cast( QgsRasterDataProvider::ResamplingMethod::Cubic ) ); + } + + if ( mCbEarlyResampling->isChecked() ) + { + addExtraEarlyResamplingMethodsToCombos(); + } - mZoomedOutResamplingComboBox->addItem( QObject::tr( "Nearest neighbour" ), static_cast( QgsRasterDataProvider::ResamplingMethod::Nearest ) ); - mZoomedOutResamplingComboBox->addItem( QObject::tr( "Bilinear" ), static_cast( QgsRasterDataProvider::ResamplingMethod::Bilinear ) ); - mZoomedOutResamplingComboBox->addItem( QObject::tr( "Cubic" ), static_cast( QgsRasterDataProvider::ResamplingMethod::Cubic ) ); + QObject::connect( mCbEarlyResampling, &QCheckBox::toggled, this, [ = ]( bool state ) + { + if ( state ) + addExtraEarlyResamplingMethodsToCombos(); + else + removeExtraEarlyResamplingMethodsFromCombos(); + } ); } void QgsResamplingUtils::refreshWidgetsFromLayer() @@ -60,6 +72,16 @@ void QgsResamplingUtils::refreshWidgetsFromLayer() provider && ( provider->providerCapabilities() & QgsRasterDataProvider::ProviderHintCanPerformProviderResampling ) ); mCbEarlyResampling->setChecked( mRasterLayer->resamplingStage() == QgsRasterPipe::ResamplingStage::Provider ); + switch ( mRasterLayer->resamplingStage() ) + { + case QgsRasterPipe::ResamplingStage::ResampleFilter: + removeExtraEarlyResamplingMethodsFromCombos(); + break; + case QgsRasterPipe::ResamplingStage::Provider: + addExtraEarlyResamplingMethodsToCombos(); + break; + } + if ( provider && mRasterLayer->resamplingStage() == QgsRasterPipe::ResamplingStage::Provider ) { mZoomedInResamplingComboBox->setCurrentIndex( mZoomedInResamplingComboBox->findData( static_cast( provider->zoomedInResamplingMethod() ) ) ); @@ -134,7 +156,7 @@ void QgsResamplingUtils::refreshLayerFromWidgets() QgsRasterResampleFilter *resampleFilter = mRasterLayer->resampleFilter(); if ( resampleFilter ) { - QgsRasterResampler *zoomedInResampler = nullptr; + std::unique_ptr< QgsRasterResampler > zoomedInResampler; switch ( zoomedInMethod ) { @@ -142,18 +164,27 @@ void QgsResamplingUtils::refreshLayerFromWidgets() break; case QgsRasterDataProvider::ResamplingMethod::Bilinear: - zoomedInResampler = new QgsBilinearRasterResampler(); + zoomedInResampler = qgis::make_unique< QgsBilinearRasterResampler >(); break; case QgsRasterDataProvider::ResamplingMethod::Cubic: - zoomedInResampler = new QgsCubicRasterResampler(); + zoomedInResampler = qgis::make_unique< QgsCubicRasterResampler >(); + break; + + case QgsRasterDataProvider::ResamplingMethod::CubicSpline: + case QgsRasterDataProvider::ResamplingMethod::Lanczos: + case QgsRasterDataProvider::ResamplingMethod::Average: + case QgsRasterDataProvider::ResamplingMethod::Mode: + case QgsRasterDataProvider::ResamplingMethod::Gauss: + + // not supported as late resampler methods break; } - resampleFilter->setZoomedInResampler( zoomedInResampler ); + resampleFilter->setZoomedInResampler( zoomedInResampler.release() ); //raster resampling - QgsRasterResampler *zoomedOutResampler = nullptr; + std::unique_ptr< QgsRasterResampler > zoomedOutResampler; switch ( zoomedOutMethod ) { @@ -161,18 +192,63 @@ void QgsResamplingUtils::refreshLayerFromWidgets() break; case QgsRasterDataProvider::ResamplingMethod::Bilinear: - zoomedOutResampler = new QgsBilinearRasterResampler(); + zoomedOutResampler = qgis::make_unique< QgsBilinearRasterResampler >(); break; case QgsRasterDataProvider::ResamplingMethod::Cubic: - zoomedOutResampler = new QgsCubicRasterResampler(); + zoomedOutResampler = qgis::make_unique< QgsCubicRasterResampler >(); + break; + + + case QgsRasterDataProvider::ResamplingMethod::CubicSpline: + case QgsRasterDataProvider::ResamplingMethod::Lanczos: + case QgsRasterDataProvider::ResamplingMethod::Average: + case QgsRasterDataProvider::ResamplingMethod::Mode: + case QgsRasterDataProvider::ResamplingMethod::Gauss: + // not supported as late resampler methods break; } - resampleFilter->setZoomedOutResampler( zoomedOutResampler ); + resampleFilter->setZoomedOutResampler( zoomedOutResampler.release() ); resampleFilter->setMaxOversampling( mMaximumOversamplingSpinBox->value() ); } } +void QgsResamplingUtils::addExtraEarlyResamplingMethodsToCombos() +{ + if ( mZoomedInResamplingComboBox->findData( static_cast( QgsRasterDataProvider::ResamplingMethod::CubicSpline ) ) != -1 ) + return; // already present + + for ( QComboBox *combo : {mZoomedInResamplingComboBox, mZoomedOutResamplingComboBox } ) + { + combo->addItem( QObject::tr( "Cubic Spline" ), static_cast( QgsRasterDataProvider::ResamplingMethod::CubicSpline ) ); + combo->addItem( QObject::tr( "Lanczos" ), static_cast( QgsRasterDataProvider::ResamplingMethod::Lanczos ) ); + combo->addItem( QObject::tr( "Average" ), static_cast( QgsRasterDataProvider::ResamplingMethod::Average ) ); + combo->addItem( QObject::tr( "Mode" ), static_cast( QgsRasterDataProvider::ResamplingMethod::Mode ) ); + combo->addItem( QObject::tr( "Gauss" ), static_cast( QgsRasterDataProvider::ResamplingMethod::Gauss ) ); + } +} + +void QgsResamplingUtils::removeExtraEarlyResamplingMethodsFromCombos() +{ + if ( mZoomedInResamplingComboBox->findData( static_cast( QgsRasterDataProvider::ResamplingMethod::CubicSpline ) ) == -1 ) + return; // already removed + + for ( QComboBox *combo : {mZoomedInResamplingComboBox, mZoomedOutResamplingComboBox } ) + { + for ( QgsRasterDataProvider::ResamplingMethod method : + { + QgsRasterDataProvider::ResamplingMethod::CubicSpline, + QgsRasterDataProvider::ResamplingMethod::Lanczos, + QgsRasterDataProvider::ResamplingMethod::Average, + QgsRasterDataProvider::ResamplingMethod::Mode, + QgsRasterDataProvider::ResamplingMethod::Gauss + } ) + { + combo->removeItem( combo->findData( static_cast< int >( method ) ) ); + } + } +} + /// @endcond PRIVATE diff --git a/src/gui/raster/qgsresamplingutils.h b/src/gui/raster/qgsresamplingutils.h index 0073c25a6fcc..2c5abf77d6b1 100644 --- a/src/gui/raster/qgsresamplingutils.h +++ b/src/gui/raster/qgsresamplingutils.h @@ -18,6 +18,8 @@ #ifndef QGSRESAMPLINGUTILS_H #define QGSRESAMPLINGUTILS_H +#include "qgis_gui.h" +#include class QgsRasterLayer; class QComboBox; @@ -32,8 +34,10 @@ class QCheckBox; * QgsRenderedRasterPropertiesWidget to deal with widgets related to * resampling settings. */ -class QgsResamplingUtils +class GUI_EXPORT QgsResamplingUtils : public QObject { + Q_OBJECT + QgsRasterLayer *mRasterLayer = nullptr; QComboBox *mZoomedInResamplingComboBox = nullptr; QComboBox *mZoomedOutResamplingComboBox = nullptr; @@ -59,6 +63,12 @@ class QgsResamplingUtils //! Synchronize QgsRasterLayer state from widgets void refreshLayerFromWidgets(); + + private: + + void addExtraEarlyResamplingMethodsToCombos(); + void removeExtraEarlyResamplingMethodsFromCombos(); + }; ///@endcond PRIVATE