[feature] Add WMS/XYZ interpretation type for Terrarium terrain tiles

Allows reading DEM tiles in the Terrarium terrain encoding type (e.g.
the global Mapzen terrain tiles freely available through AWS)
This commit is contained in:
Nyall Dawson 2022-01-09 11:42:32 +10:00
parent ba9daca9e4
commit a1e1a53b65
7 changed files with 99 additions and 4 deletions

View File

@ -4844,19 +4844,26 @@ QGISEXTERN QgsProviderMetadata *providerMetadataFactory()
}
#endif
Qgis::DataType QgsWmsInterpretationConverter::dataType() const
{
return Qgis::DataType::Float32;
}
std::unique_ptr<QgsWmsInterpretationConverter> QgsWmsInterpretationConverter::createConverter( const QString &key )
{
if ( key == QgsWmsInterpretationConverterMapTilerTerrainRGB::interpretationKey() )
return std::make_unique<QgsWmsInterpretationConverterMapTilerTerrainRGB>();
else if ( key == QgsWmsInterpretationConverterTerrariumRGB::interpretationKey() )
return std::make_unique<QgsWmsInterpretationConverterTerrariumRGB>();
return nullptr;
}
Qgis::DataType QgsWmsInterpretationConverter::dataType() const
{
return Qgis::DataType::Float32;
}
//
// QgsWmsInterpretationConverterMapTilerTerrainRGB
//
void QgsWmsInterpretationConverterMapTilerTerrainRGB::convert( const QRgb &color, float *converted ) const
{
int R = qRed( color );
@ -4879,3 +4886,36 @@ QgsRasterHistogram QgsWmsInterpretationConverterMapTilerTerrainRGB::histogram( i
{
return QgsRasterHistogram();
}
//
// QgsWmsInterpretationConverterTerrariumRGB
//
void QgsWmsInterpretationConverterTerrariumRGB::convert( const QRgb &color, float *converted ) const
{
// for description of the "terrarium" format:
// https://github.com/tilezen/joerd/blob/master/docs/formats.md
if ( qAlpha( color ) == 255 )
{
*converted = qRed( color ) * 256 + qGreen( color ) + qBlue( color ) / 256.f - 32768;
}
else
{
*converted = std::numeric_limits<float>::quiet_NaN();
}
}
QgsRasterBandStats QgsWmsInterpretationConverterTerrariumRGB::statistics( int, int, const QgsRectangle &, int, QgsRasterBlockFeedback * ) const
{
QgsRasterBandStats stat;
stat.minimumValue = -11000;
stat.maximumValue = 9000;
stat.statsGathered = QgsRasterBandStats::Min | QgsRasterBandStats::Max;
return stat;
}
QgsRasterHistogram QgsWmsInterpretationConverterTerrariumRGB::histogram( int, int, double, double, const QgsRectangle &, int, bool, QgsRasterBlockFeedback * ) const
{
return QgsRasterHistogram();
}

View File

@ -156,6 +156,30 @@ class QgsWmsInterpretationConverterMapTilerTerrainRGB : public QgsWmsInterpretat
static QString interpretationKey() {return QStringLiteral( "maptilerterrain" );}
};
//! Class to convert color to float value following the terrarium terrain RGB interpretation
class QgsWmsInterpretationConverterTerrariumRGB : public QgsWmsInterpretationConverter
{
public:
void convert( const QRgb &color, float *converted ) const override;
QgsRasterBandStats statistics( int bandNo,
int stats = QgsRasterBandStats::All,
const QgsRectangle &extent = QgsRectangle(),
int sampleSize = 0, QgsRasterBlockFeedback *feedback = nullptr ) const override;
QgsRasterHistogram histogram( int bandNo,
int binCount = 0,
double minimum = std::numeric_limits<double>::quiet_NaN(),
double maximum = std::numeric_limits<double>::quiet_NaN(),
const QgsRectangle &extent = QgsRectangle(),
int sampleSize = 0,
bool includeOutOfRange = false,
QgsRasterBlockFeedback *feedback = nullptr ) const override;
static QString displayName() {return QObject::tr( "Terrarium Terrain RGB" );}
static QString interpretationKey() {return QStringLiteral( "terrariumterrain" );}
};
/**
*
* \brief Data provider for OGC WMS layers.

View File

@ -1322,6 +1322,7 @@ QgsWmsInterpretationComboBox::QgsWmsInterpretationComboBox( QWidget *parent ): Q
{
addItem( tr( "Default" ), QString() );
addItem( QgsWmsInterpretationConverterMapTilerTerrainRGB::displayName(), QgsWmsInterpretationConverterMapTilerTerrainRGB::interpretationKey() );
addItem( QgsWmsInterpretationConverterTerrariumRGB::displayName(), QgsWmsInterpretationConverterTerrariumRGB::interpretationKey() );
}
void QgsWmsInterpretationComboBox::setInterpretation( const QString &interpretationKey )

View File

@ -26,6 +26,8 @@
#include <qgssinglebandpseudocolorrenderer.h>
#include <qgsrastershader.h>
#include <qgsstyle.h>
#include "qgssinglebandgrayrenderer.h"
#include "qgsrasterlayer.h"
/**
* \ingroup UnitTests
@ -271,6 +273,34 @@ class TestQgsWmsProvider: public QObject
QVERIFY( imageCheck( "convert_value", mapSettings ) );
}
void testTerrariumInterpretation()
{
QString dataDir( TEST_DATA_DIR );
QgsXyzConnection xyzConn;
xyzConn.interpretation = QgsWmsInterpretationConverterTerrariumRGB::interpretationKey();
xyzConn.url = QUrl::fromLocalFile( dataDir + QStringLiteral( "/terrarium_terrain_rgb.png" ) ).toString();
QgsRasterLayer layer( xyzConn.encodedUri(), "terrain", "wms" );
QVERIFY( layer.isValid() );
QVERIFY( layer.dataProvider()->dataType( 1 ) == Qgis::DataType::Float32 );
QgsSingleBandGrayRenderer *renderer = new QgsSingleBandGrayRenderer( layer.dataProvider(), 1 );
QgsContrastEnhancement *e = new QgsContrastEnhancement( Qgis::DataType::Float32 );
e->setMinimumValue( -50 );
e->setMaximumValue( 50 );
e->setContrastEnhancementAlgorithm( QgsContrastEnhancement::StretchToMinimumMaximum );
renderer->setContrastEnhancement( e );
layer.setRenderer( renderer );
QgsMapSettings mapSettings;
mapSettings.setLayers( QList<QgsMapLayer *>() << &layer );
mapSettings.setExtent( layer.extent() );
mapSettings.setOutputSize( QSize( 400, 400 ) );
mapSettings.setOutputDpi( 96 );
mapSettings.setDpiTarget( 48 );
QVERIFY( imageCheck( "terrarium_terrain", mapSettings ) );
}
bool imageCheck( const QString &testType, QgsMapSettings &mapSettings )
{
//use the QgsRenderChecker test utility class to

Binary file not shown.

After

Width:  |  Height:  |  Size: 38 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 626 KiB

BIN
tests/testdata/terrarium_terrain_rgb.png vendored Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 78 KiB