[wms] Fix unreported issue max tile size from capabilities ignored

Fix an unreported issue with WMS client ignoring the advertised tile
size from GetCapabilities (because the raster iterator always used
its own hardcoded default).

A new method was added to retrieve this information from data providers
only implemented for WMS at the moment.

The test has been reformatted for consistency with other core tests
by moving the implementation outside of the class. The actual change is
the addition of TestQgsWmsProvider::testMaxTileSize().

Funded by: M.O.S.S. Computer Grafik Systeme GmbH https://www.moss.de/
This commit is contained in:
Alessandro Pasotti 2024-10-16 09:29:36 +02:00
parent 1431d2c70e
commit 2078ef5c03
8 changed files with 649 additions and 487 deletions

View File

@ -144,6 +144,16 @@ Read band scale for raster value
Read band offset for raster value
%End
virtual QSize maximumTileSize() const;
%Docstring
Returns the maximum tile size in pixels for the data provider.
By default, the maximum tile size is set to :py:class:`QgsRasterIterator`.DEFAULT_MAXIMUM_TILE_WIDTH x
:py:class:`QgsRasterIterator`.DEFAULT_MAXIMUM_TILE_HEIGHT but can be overridden in subclasses (e.g. WMS
can retrieve that information from the GetCapabilities document).
.. versionadded:: 3.40
%End
virtual QgsRasterBlock *block( int bandNo, const QgsRectangle &boundingBox, int width, int height, QgsRasterBlockFeedback *feedback = 0 ) /Factory/;

View File

@ -144,6 +144,16 @@ Read band scale for raster value
Read band offset for raster value
%End
virtual QSize maximumTileSize() const;
%Docstring
Returns the maximum tile size in pixels for the data provider.
By default, the maximum tile size is set to :py:class:`QgsRasterIterator`.DEFAULT_MAXIMUM_TILE_WIDTH x
:py:class:`QgsRasterIterator`.DEFAULT_MAXIMUM_TILE_HEIGHT but can be overridden in subclasses (e.g. WMS
can retrieve that information from the GetCapabilities document).
.. versionadded:: 3.40
%End
virtual QgsRasterBlock *block( int bandNo, const QgsRectangle &boundingBox, int width, int height, QgsRasterBlockFeedback *feedback = 0 ) /Factory/;

View File

@ -157,6 +157,15 @@ class CORE_EXPORT QgsRasterDataProvider : public QgsDataProvider, public QgsRast
*/
virtual double bandOffset( int bandNo ) const { Q_UNUSED( bandNo ) return 0.0; }
/**
* Returns the maximum tile size in pixels for the data provider.
* By default, the maximum tile size is set to QgsRasterIterator::DEFAULT_MAXIMUM_TILE_WIDTH x
* QgsRasterIterator::DEFAULT_MAXIMUM_TILE_HEIGHT but can be overridden in subclasses (e.g. WMS
* can retrieve that information from the GetCapabilities document).
* \since QGIS 3.40
*/
virtual QSize maximumTileSize() const { return QSize( QgsRasterIterator::DEFAULT_MAXIMUM_TILE_WIDTH, QgsRasterIterator::DEFAULT_MAXIMUM_TILE_HEIGHT ); }
// TODO: remove or make protected all readBlock working with void*
//! Read block of data using given extent and size.

View File

@ -514,6 +514,16 @@ bool QgsRasterLayerRenderer::render()
// Drawer to pipe?
QgsRasterIterator iterator( mPipe->last() );
// Get the maximum tile size from the provider and set it as the maximum tile size for the iterator
QgsRasterDataProvider *provider { mPipe->provider() };
if ( provider )
{
const QSize maxTileSize {provider->maximumTileSize()};
iterator.setMaximumTileWidth( maxTileSize.width() );
iterator.setMaximumTileHeight( maxTileSize.height() );
}
QgsRasterDrawer drawer( &iterator );
drawer.draw( *( renderContext() ), mRasterViewPort, mFeedback );

View File

@ -1067,6 +1067,7 @@ class QgsWmsCapabilities
friend class QgsWmsProvider;
friend class TestQgsWmsCapabilities;
friend class TestQgsWmsProvider;
};

View File

@ -835,10 +835,13 @@ QImage *QgsWmsProvider::draw( const QgsRectangle &viewExtent, int pixelWidth, in
QImage *image = new QImage( pixelWidth, pixelHeight, QImage::Format_ARGB32 );
image->fill( 0 );
int maxWidth = mCaps.mCapabilities.service.maxWidth == 0 ? std::numeric_limits<int>::max() : mCaps.mCapabilities.service.maxWidth;
int maxHeight = mCaps.mCapabilities.service.maxHeight == 0 ? std::numeric_limits<int>::max() : mCaps.mCapabilities.service.maxHeight;
if ( !mSettings.mTiled && mSettings.mMaxWidth == 0 && mSettings.mMaxHeight == 0 && pixelWidth <= maxWidth && pixelHeight <= maxHeight )
const QSize maxTileSize { maximumTileSize() };
const int maxWidth { maxTileSize.width() };
const int maxHeight { maxTileSize.height() };
if ( !mSettings.mTiled && pixelWidth <= maxWidth && pixelHeight <= maxHeight )
{
QUrl url = createRequestUrlWMS( viewExtent, pixelWidth, pixelHeight );
@ -4104,6 +4107,32 @@ QgsLayerMetadata QgsWmsProvider::layerMetadata() const
return mLayerMetadata;
}
QSize QgsWmsProvider::maximumTileSize() const
{
const int capsMaxHeight { static_cast<int>( mCaps.mCapabilities.service.maxHeight ) };
const int capsMaxWidth { static_cast<int>( mCaps.mCapabilities.service.maxWidth ) };
if ( mSettings.mMaxHeight > 0 && mSettings.mMaxWidth > 0 )
{
if ( capsMaxHeight > 0 && capsMaxWidth > 0 )
{
return QSize( std::min( mSettings.mMaxWidth, capsMaxWidth ), std::min( mSettings.mMaxHeight, capsMaxHeight ) );
}
else
{
return QSize( mSettings.mMaxWidth, mSettings.mMaxHeight );
}
}
else if ( capsMaxHeight > 0 && capsMaxWidth > 0 )
{
return QSize( capsMaxWidth, capsMaxHeight );
}
else // default fallback
{
return QgsRasterDataProvider::maximumTileSize();
}
}
QgsRasterBandStats QgsWmsProvider::bandStatistics(
int bandNo,
Qgis::RasterBandStatistics stats,

View File

@ -313,6 +313,13 @@ class QgsWmsProvider final: public QgsRasterDataProvider
bool setZoomedInResamplingMethod( ResamplingMethod method ) override { mZoomedInResamplingMethod = method; return true; }
bool setZoomedOutResamplingMethod( ResamplingMethod method ) override { mZoomedOutResamplingMethod = method; return true; }
/*
* Overridden because WMS provider can retrieve this information from the capabilities document.
* The size defined by the user in the provider settings takes precedence but cannot exceed the
* maximum tile size advertised by the capabilities document (if not null).
*/
QSize maximumTileSize() const override;
// Statistics could be available if the provider has a converter from colors to other value type, the returned statistics depend on the converter
QgsRasterBandStats bandStatistics( int bandNo,
Qgis::RasterBandStatistics stats = Qgis::RasterBandStatistic::All,

File diff suppressed because it is too large Load Diff