QGIS API Documentation 4.3.0-Master (16eddb2670e)
Loading...
Searching...
No Matches
qgsrasterrendererregistry.cpp
Go to the documentation of this file.
1/***************************************************************************
2 qgsrasterrendererregistry.cpp
3 -----------------------------
4 begin : January 2012
5 copyright : (C) 2012 by Marco Hugentobler
6 email : marco at sourcepole dot ch
7 ***************************************************************************/
8
9/***************************************************************************
10 * *
11 * This program is free software; you can redistribute it and/or modify *
12 * it under the terms of the GNU General Public License as published by *
13 * the Free Software Foundation; either version 2 of the License, or *
14 * (at your option) any later version. *
15 * *
16 ***************************************************************************/
17
19
20#include "qgsapplication.h"
21#include "qgscolorrampimpl.h"
28#include "qgsrastershader.h"
32#include "qgssettingstree.h"
36
37#include <QIcon>
38#include <QString>
39
40using namespace Qt::StringLiterals;
41
43 = new QgsSettingsEntryInteger( u"default-red-band"_s, QgsSettingsTree::sTreeRaster, 1, u"Default band number assigned to the red channel when creating an RGB renderer for a multi-band raster."_s );
45 = new QgsSettingsEntryInteger( u"default-green-band"_s, QgsSettingsTree::sTreeRaster, 2, u"Default band number assigned to the green channel when creating an RGB renderer for a multi-band raster."_s );
47 = new QgsSettingsEntryInteger( u"default-blue-band"_s, QgsSettingsTree::sTreeRaster, 3, u"Default band number assigned to the blue channel when creating an RGB renderer for a multi-band raster."_s );
49 = new QgsSettingsEntryBool( u"use-standard-deviation"_s, QgsSettingsTree::sTreeRaster, false, u"If true, newly created raster renderers use a standard-deviation based contrast enhancement by default."_s );
51 = new QgsSettingsEntryDouble( u"default-standard-deviation"_s, QgsSettingsTree::sTreeRaster, 2.0, u"Default standard deviation multiplier used to compute min/max values for raster contrast enhancement when \"use-standard-deviation\" is enabled."_s );
52
62
64{
65 return QgsApplication::getThemeIcon( QString( "styleicons/%1.svg" ).arg( name ) );
66}
67
69{
70 // insert items in a particular order, which is returned in renderersList()
71 insert( QgsRasterRendererRegistryEntry( u"multibandcolor"_s, QObject::tr( "Multiband color" ), QgsMultiBandColorRenderer::create, nullptr, Qgis::RasterRendererCapability::UsesMultipleBands ) );
72 insert( QgsRasterRendererRegistryEntry( u"paletted"_s, QObject::tr( "Paletted/Unique values" ), QgsPalettedRasterRenderer::create, nullptr ) );
73 insert( QgsRasterRendererRegistryEntry( u"singlebandgray"_s, QObject::tr( "Singleband gray" ), QgsSingleBandGrayRenderer::create, nullptr ) );
74 insert( QgsRasterRendererRegistryEntry( u"singlebandpseudocolor"_s, QObject::tr( "Singleband pseudocolor" ), QgsSingleBandPseudoColorRenderer::create, nullptr ) );
75 insert( QgsRasterRendererRegistryEntry( u"singlebandcolordata"_s, QObject::tr( "Singleband color data" ), QgsSingleBandColorDataRenderer::create, nullptr ) );
76 insert( QgsRasterRendererRegistryEntry( u"singlecolor"_s, QObject::tr( "Single color" ), QgsRasterSingleColorRenderer::create, nullptr ) );
77 insert( QgsRasterRendererRegistryEntry( u"hillshade"_s, QObject::tr( "Hillshade" ), QgsHillshadeRenderer::create, nullptr ) );
78 insert( QgsRasterRendererRegistryEntry( u"contour"_s, QObject::tr( "Contours" ), QgsRasterContourRenderer::create, nullptr ) );
79}
80
82{
83 mEntries.insert( entry.name, entry );
84 mSortedEntries.append( entry.name );
85}
86
88{
89 if ( !mEntries.contains( rendererName ) )
90 {
91 return;
92 }
93 mEntries[rendererName].widgetCreateFunction = func;
94}
95
96bool QgsRasterRendererRegistry::rendererData( const QString &rendererName, QgsRasterRendererRegistryEntry &data ) const
97{
98 const QHash< QString, QgsRasterRendererRegistryEntry >::const_iterator it = mEntries.find( rendererName );
99 if ( it == mEntries.constEnd() )
100 {
101 return false;
102 }
103 data = it.value();
104 return true;
105}
106
108{
109 return mSortedEntries;
110}
111
112QList< QgsRasterRendererRegistryEntry > QgsRasterRendererRegistry::entries() const
113{
114 QList< QgsRasterRendererRegistryEntry > result;
115
116 QHash< QString, QgsRasterRendererRegistryEntry >::const_iterator it = mEntries.constBegin();
117 for ( ; it != mEntries.constEnd(); ++it )
118 {
119 result.push_back( it.value() );
120 }
121 return result;
122}
123
125{
126 const QHash< QString, QgsRasterRendererRegistryEntry >::const_iterator it = mEntries.constFind( rendererName );
127 if ( it != mEntries.constEnd() )
128 {
129 return it.value().capabilities;
130 }
132}
133
135{
136 if ( !provider || provider->bandCount() < 1 )
137 {
138 return nullptr;
139 }
140
141 std::unique_ptr< QgsRasterRenderer > renderer;
142 switch ( drawingStyle )
143 {
145 {
146 const int grayBand = 1; //reasonable default
147
148 // first preference -- use attribute table to generate classes
149 const QgsRasterAttributeTable *attributeTable { provider->attributeTable( grayBand ) };
150 if ( attributeTable && attributeTable->hasColor() )
151 {
152 std::unique_ptr<QgsColorRamp> ramp;
154 if ( !classes.empty() )
155 {
156 renderer = std::make_unique< QgsPalettedRasterRenderer >( provider, grayBand, classes );
157 }
158 }
159
160 // second preference -- use raster color table to generate classes
161 if ( !renderer )
162 {
164 if ( !classes.empty() )
165 {
166 // If there is an attribute table (with no colors), try to get the labels for the colors
167 if ( attributeTable
168 && attributeTable->fieldsByUsage( Qgis::RasterAttributeTableFieldUsage::MinMax ).size() > 0
169 && attributeTable->fieldsByUsage( Qgis::RasterAttributeTableFieldUsage::Name ).size() > 0 )
170 {
173 const int fieldValueIndex = attributeTable->fields().indexOf( minMaxFld );
174 const int fieldNameIndex = attributeTable->fields().indexOf( nameFld );
175 QMap<double, QString> ratLabelsMap;
176 const QList<QList<QVariant>> constRatData = attributeTable->data();
177 for ( const auto &row : constRatData )
178 {
179 const double fieldValue = row.value( fieldValueIndex ).toDouble();
180 const QString fieldName = row.value( fieldNameIndex ).toString();
181 ratLabelsMap.insert( fieldValue, fieldName );
182 }
183
184 for ( qsizetype i = 0; i < classes.size(); ++i )
185 {
186 QgsPalettedRasterRenderer::Class &classData = classes[i];
187 if ( ratLabelsMap.contains( classData.value ) )
188 {
189 classData.label = ratLabelsMap.value( classData.value );
190 }
191 }
192 }
193 renderer = std::make_unique< QgsPalettedRasterRenderer >( provider, grayBand, classes );
194 }
195 }
196
197 // last preference -- just fallback to single band gray renderer if we couldn't determine color palette
198 if ( !renderer )
199 {
200 renderer = std::make_unique< QgsSingleBandGrayRenderer >( provider, grayBand );
201
202 QgsContrastEnhancement *ce = new QgsContrastEnhancement( ( Qgis::DataType ) ( provider->dataType( grayBand ) ) );
203
204 // Default contrast enhancement is set from QgsRasterLayer, it has already setContrastEnhancementAlgorithm(). Default enhancement must only be set if default style was not loaded (to avoid stats calculation).
205 qgis::down_cast< QgsSingleBandGrayRenderer * >( renderer.get() )->setContrastEnhancement( ce );
206 }
207 }
208 break;
209
212 {
213 const int grayBand = 1;
214
215 // If the raster band has an attribute table try to use it.
216 QString ratErrorMessage;
217 if ( QgsRasterAttributeTable *rat = provider->attributeTable( grayBand ); rat && rat->isValid( &ratErrorMessage ) )
218 {
219 renderer = rat->createRenderer( provider, grayBand );
220 }
221
222 if ( !ratErrorMessage.isEmpty() )
223 {
224 QgsDebugMsgLevel( u"Invalid RAT from band 1, RAT was not used to create the renderer: %1."_s.arg( ratErrorMessage ), 2 );
225 }
226
227 if ( !renderer )
228 {
229 renderer = std::make_unique< QgsSingleBandGrayRenderer >( provider, grayBand );
230
231 QgsContrastEnhancement *ce = new QgsContrastEnhancement( ( Qgis::DataType ) ( provider->dataType( grayBand ) ) );
232
233 // Default contrast enhancement is set from QgsRasterLayer, it has already setContrastEnhancementAlgorithm(). Default enhancement must only be set if default style was not loaded (to avoid stats calculation).
234 qgis::down_cast< QgsSingleBandGrayRenderer * >( renderer.get() )->setContrastEnhancement( ce );
235 }
236 break;
237 }
238
240 {
241 const int bandNo = 1;
242 double minValue = 0;
243 double maxValue = 0;
244 // TODO: avoid calculating statistics if not necessary (default style loaded)
245 minMaxValuesForBand( bandNo, provider, minValue, maxValue );
246 QgsRasterShader *shader = new QgsRasterShader( minValue, maxValue );
247 renderer = std::make_unique< QgsSingleBandPseudoColorRenderer >( provider, bandNo, shader );
248 break;
249 }
251 {
252 int redBand = settingsDefaultRedBand->value();
253 if ( redBand < 0 || redBand > provider->bandCount() )
254 {
255 redBand = -1;
256 }
257 int greenBand = settingsDefaultGreenBand->value();
258 if ( greenBand < 0 || greenBand > provider->bandCount() )
259 {
260 greenBand = -1;
261 }
262 int blueBand = settingsDefaultBlueBand->value();
263 if ( blueBand < 0 || blueBand > provider->bandCount() )
264 {
265 blueBand = -1;
266 }
267
268 renderer = std::make_unique< QgsMultiBandColorRenderer >( provider, redBand, greenBand, blueBand );
269 break;
270 }
272 {
273 renderer = std::make_unique< QgsSingleBandColorDataRenderer >( provider, 1 );
274 break;
275 }
276 default:
277 return nullptr;
278 }
279
280 auto tr = std::make_unique< QgsRasterTransparency >();
281 const int bandCount = renderer->usesBands().size();
282 if ( bandCount == 1 )
283 {
284 tr->setTransparentSingleValuePixelList( {} );
285 }
286 else if ( bandCount == 3 )
287 {
288 tr->setTransparentThreeValuePixelList( {} );
289 }
290 renderer->setRasterTransparency( tr.release() );
291 return renderer;
292}
293
294bool QgsRasterRendererRegistry::minMaxValuesForBand( int band, QgsRasterDataProvider *provider, double &minValue, double &maxValue ) const
295{
296 if ( !provider )
297 {
298 return false;
299 }
300
301 minValue = 0;
302 maxValue = 0;
303
304 if ( settingsUseStandardDeviation->value() )
305 {
306 const QgsRasterBandStats stats = provider->bandStatistics( band, Qgis::RasterBandStatistic::Mean | Qgis::RasterBandStatistic::StdDev );
307
308 const double stdDevFactor = settingsDefaultStandardDeviation->value();
309 const double diff = stdDevFactor * stats.stdDev;
310 minValue = stats.mean - diff;
311 maxValue = stats.mean + diff;
312 }
313 else
314 {
315 const QgsRasterBandStats stats = provider->bandStatistics( band, Qgis::RasterBandStatistic::Min | Qgis::RasterBandStatistic::Max );
316 minValue = stats.minimumValue;
317 maxValue = stats.maximumValue;
318 }
319 return true;
320}
RasterDrawingStyle
Raster drawing styles.
Definition qgis.h:5334
@ SingleBandGray
A single band image drawn as a range of gray colors.
Definition qgis.h:5336
@ MultiBandSingleBandGray
A layer containing 2 or more bands, but a single band drawn as a range of gray colors.
Definition qgis.h:5342
@ SingleBandColorData
ARGB values rendered directly.
Definition qgis.h:5345
@ MultiBandColor
A layer containing 2 or more bands, mapped to RGB color space. In the case of a multiband with only t...
Definition qgis.h:5344
@ PalettedColor
A "Palette" image drawn using color table.
Definition qgis.h:5338
@ SingleBandPseudoColor
A single band image drawn using a pseudocolor algorithm.
Definition qgis.h:5337
QFlags< RasterRendererCapability > RasterRendererCapabilities
Raster renderer capabilities.
Definition qgis.h:1703
@ StdDev
Standard deviation.
Definition qgis.h:6768
DataType
Raster data types.
Definition qgis.h:413
@ MinMax
Field usage MinMax.
Definition qgis.h:1763
@ UsesMultipleBands
The renderer utilizes multiple raster bands for color data (note that alpha bands are not considered ...
Definition qgis.h:1694
static QIcon getThemeIcon(const QString &name, const QColor &fillColor=QColor(), const QColor &strokeColor=QColor())
Helper to get a theme icon.
Handles contrast enhancement and clipping.
static std::unique_ptr< QgsRasterRenderer > create(const QDomElement &elem, QgsRasterInterface *input)
Factory method to create a new renderer.
static std::unique_ptr< QgsRasterRenderer > create(const QDomElement &elem, QgsRasterInterface *input)
static QgsPalettedRasterRenderer::MultiValueClassData rasterAttributeTableToClassData(const QgsRasterAttributeTable *attributeTable, int classificationColumn=-1, QgsColorRamp *ramp=nullptr)
Reads and returns classes from the Raster Attribute Table attributeTable, optionally classifying the ...
QList< QgsPalettedRasterRenderer::Class > ClassData
Map of value to class properties.
QList< QgsPalettedRasterRenderer::MultiValueClass > MultiValueClassData
Map of multi value to class properties.
static QgsPalettedRasterRenderer::ClassData colorTableToClassData(const QList< QgsColorRampShader::ColorRampItem > &table)
Converts a raster color table to paletted renderer class data.
static std::unique_ptr< QgsRasterRenderer > create(const QDomElement &elem, QgsRasterInterface *input)
The Field class represents a Raster Attribute Table field, including its name, usage and type.
Represents a Raster Attribute Table (RAT).
bool hasColor() const
Returns true if the Raster Attribute Table has color RGBA information.
QList< QgsRasterAttributeTable::Field > fields() const
Returns the Raster Attribute Table fields.
const QList< QgsRasterAttributeTable::Field > fieldsByUsage(const Qgis::RasterAttributeTableFieldUsage fieldUsage) const
Returns the list of fields matching fieldUsage.
bool isValid(QString *errorMessage=nullptr) const
Returns true if the Raster Attribute Table is valid, optionally reporting validity checks results in ...
const QList< QList< QVariant > > data() const
Returns the Raster Attribute Table rows.
double mean
The mean cell value for the band. NO_DATA values are excluded.
double stdDev
The standard deviation of the cell values.
double minimumValue
The minimum cell value in the raster band.
double maximumValue
The maximum cell value in the raster band.
static std::unique_ptr< QgsRasterRenderer > create(const QDomElement &elem, QgsRasterInterface *input)
Creates an instance of the renderer based on definition from XML (used by renderer registry).
Base class for raster data providers.
QgsRasterAttributeTable * attributeTable(int bandNumber) const
Returns the (possibly nullptr) attribute table for the specified bandNumber.
Qgis::DataType dataType(int bandNo) const override=0
Returns data type for the band specified by number.
virtual QList< QgsColorRampShader::ColorRampItem > colorTable(int bandNo) const
Q_DECL_DEPRECATED QgsRasterBandStats bandStatistics(int bandNo, int stats, const QgsRectangle &extent=QgsRectangle(), int sampleSize=0, QgsRasterBlockFeedback *feedback=nullptr)
Returns the band statistics.
virtual int bandCount() const =0
Gets number of bands.
static const QgsSettingsEntryInteger * settingsDefaultGreenBand
void insertWidgetFunction(const QString &rendererName, QgsRasterRendererWidgetCreateFunc func)
Sets the widget creation function for a renderer.
QgsRasterRendererRegistry()
Constructor for QgsRasterRendererRegistry.
QList< QgsRasterRendererRegistryEntry > entries() const
Returns the list of registered renderers.
void insert(const QgsRasterRendererRegistryEntry &entry)
Inserts a new entry into the registry.
static const QgsSettingsEntryBool * settingsUseStandardDeviation
static const QgsSettingsEntryDouble * settingsDefaultStandardDeviation
bool rendererData(const QString &rendererName, QgsRasterRendererRegistryEntry &data) const
Retrieves renderer data from the registry.
static const QgsSettingsEntryInteger * settingsDefaultRedBand
Qgis::RasterRendererCapabilities rendererCapabilities(const QString &rendererName) const
Returns the capabilities for the renderer with the specified name.
std::unique_ptr< QgsRasterRenderer > defaultRendererForDrawingStyle(Qgis::RasterDrawingStyle drawingStyle, QgsRasterDataProvider *provider) const
Creates a default renderer for a raster drawing style (considering user options such as default contr...
QStringList renderersList() const
Returns a list of the names of registered renderers.
static const QgsSettingsEntryInteger * settingsDefaultBlueBand
Interface for all raster shaders.
static std::unique_ptr< QgsRasterRenderer > create(const QDomElement &elem, QgsRasterInterface *input)
Creates an instance of the renderer based on definition from XML (used by the renderer registry).
A boolean settings entry.
A double settings entry.
An integer settings entry.
static QgsSettingsTreeNode * sTreeRaster
static std::unique_ptr< QgsRasterRenderer > create(const QDomElement &elem, QgsRasterInterface *input)
static std::unique_ptr< QgsRasterRenderer > create(const QDomElement &elem, QgsRasterInterface *input)
static std::unique_ptr< QgsRasterRenderer > create(const QDomElement &elem, QgsRasterInterface *input)
#define QgsDebugMsgLevel(str, level)
Definition qgslogger.h:80
std::unique_ptr< QgsRasterRenderer >(* QgsRasterRendererCreateFunc)(const QDomElement &, QgsRasterInterface *input)
QgsRasterRendererWidget *(* QgsRasterRendererWidgetCreateFunc)(QgsRasterLayer *, const QgsRectangle &extent)
Properties of a single value class.
Registry for raster renderer entries.
QgsRasterRendererWidgetCreateFunc widgetCreateFunction
Qgis::RasterRendererCapabilities capabilities
Renderer capabilities.
QgsRasterRendererCreateFunc rendererCreateFunction