Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
[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)
  • Loading branch information
nyalldawson committed Jan 10, 2022
1 parent ba9daca commit a1e1a53
Show file tree
Hide file tree
Showing 7 changed files with 99 additions and 4 deletions.
48 changes: 44 additions & 4 deletions src/providers/wms/qgswmsprovider.cpp
Expand Up @@ -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 );
Expand All @@ -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();
}
24 changes: 24 additions & 0 deletions src/providers/wms/qgswmsprovider.h
Expand Up @@ -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.
Expand Down
1 change: 1 addition & 0 deletions src/providers/wms/qgswmssourceselect.cpp
Expand Up @@ -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 )
Expand Down
30 changes: 30 additions & 0 deletions tests/src/providers/testqgswmsprovider.cpp
Expand Up @@ -26,6 +26,8 @@
#include <qgssinglebandpseudocolorrenderer.h>
#include <qgsrastershader.h>
#include <qgsstyle.h>
#include "qgssinglebandgrayrenderer.h"
#include "qgsrasterlayer.h"

/**
* \ingroup UnitTests
Expand Down Expand Up @@ -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
Expand Down
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added tests/testdata/terrarium_terrain_rgb.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.

0 comments on commit a1e1a53

Please sign in to comment.