QGIS API Documentation 4.3.0-Master (cc10e4e83e5)
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"
33#include "qgssettingstree.h"
37
38#include <QIcon>
39#include <QString>
40
41using namespace Qt::StringLiterals;
42
44 = 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 );
46 = 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 );
48 = 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 );
50 = 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 );
52 = 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 );
53
63
65{
66 return QgsApplication::getThemeIcon( QString( "styleicons/%1.svg" ).arg( name ) );
67}
68
70{
71 // insert items in a particular order, which is returned in renderersList()
72 insert( QgsRasterRendererRegistryEntry( u"multibandcolor"_s, QObject::tr( "Multiband color" ), QgsMultiBandColorRenderer::create, nullptr, Qgis::RasterRendererCapability::UsesMultipleBands ) );
73 insert( QgsRasterRendererRegistryEntry( u"paletted"_s, QObject::tr( "Paletted/Unique values" ), QgsPalettedRasterRenderer::create, nullptr ) );
74 insert( QgsRasterRendererRegistryEntry( u"singlebandgray"_s, QObject::tr( "Singleband gray" ), QgsSingleBandGrayRenderer::create, nullptr ) );
75 insert( QgsRasterRendererRegistryEntry( u"singlebandpseudocolor"_s, QObject::tr( "Singleband pseudocolor" ), QgsSingleBandPseudoColorRenderer::create, nullptr ) );
76 insert( QgsRasterRendererRegistryEntry( u"singlebandcolordata"_s, QObject::tr( "Singleband color data" ), QgsSingleBandColorDataRenderer::create, nullptr ) );
77 insert( QgsRasterRendererRegistryEntry( u"singlecolor"_s, QObject::tr( "Single color" ), QgsRasterSingleColorRenderer::create, nullptr ) );
78 insert( QgsRasterRendererRegistryEntry( u"hillshade"_s, QObject::tr( "Hillshade" ), QgsHillshadeRenderer::create, nullptr ) );
79 insert( QgsRasterRendererRegistryEntry( u"contour"_s, QObject::tr( "Contours" ), QgsRasterContourRenderer::create, nullptr ) );
81}
82
84{
85 mEntries.insert( entry.name, entry );
86 mSortedEntries.append( entry.name );
87}
88
90{
91 if ( !mEntries.contains( rendererName ) )
92 {
93 return;
94 }
95 mEntries[rendererName].widgetCreateFunction = func;
96}
97
98bool QgsRasterRendererRegistry::rendererData( const QString &rendererName, QgsRasterRendererRegistryEntry &data ) const
99{
100 const QHash< QString, QgsRasterRendererRegistryEntry >::const_iterator it = mEntries.find( rendererName );
101 if ( it == mEntries.constEnd() )
102 {
103 return false;
104 }
105 data = it.value();
106 return true;
107}
108
110{
111 return mSortedEntries;
112}
113
114QList< QgsRasterRendererRegistryEntry > QgsRasterRendererRegistry::entries() const
115{
116 QList< QgsRasterRendererRegistryEntry > result;
117
118 QHash< QString, QgsRasterRendererRegistryEntry >::const_iterator it = mEntries.constBegin();
119 for ( ; it != mEntries.constEnd(); ++it )
120 {
121 result.push_back( it.value() );
122 }
123 return result;
124}
125
127{
128 const QHash< QString, QgsRasterRendererRegistryEntry >::const_iterator it = mEntries.constFind( rendererName );
129 if ( it != mEntries.constEnd() )
130 {
131 return it.value().capabilities;
132 }
134}
135
137{
138 if ( !provider || provider->bandCount() < 1 )
139 {
140 return nullptr;
141 }
142
143 std::unique_ptr< QgsRasterRenderer > renderer;
144 switch ( drawingStyle )
145 {
147 {
148 const int grayBand = 1; //reasonable default
149
150 // first preference -- use attribute table to generate classes
151 const QgsRasterAttributeTable *attributeTable { provider->attributeTable( grayBand ) };
152 if ( attributeTable && attributeTable->hasColor() )
153 {
154 std::unique_ptr<QgsColorRamp> ramp;
156 if ( !classes.empty() )
157 {
158 renderer = std::make_unique< QgsPalettedRasterRenderer >( provider, grayBand, classes );
159 }
160 }
161
162 // second preference -- use raster color table to generate classes
163 if ( !renderer )
164 {
166 if ( !classes.empty() )
167 {
168 // If there is an attribute table (with no colors), try to get the labels for the colors
169 if ( attributeTable
170 && attributeTable->fieldsByUsage( Qgis::RasterAttributeTableFieldUsage::MinMax ).size() > 0
171 && attributeTable->fieldsByUsage( Qgis::RasterAttributeTableFieldUsage::Name ).size() > 0 )
172 {
175 const int fieldValueIndex = attributeTable->fields().indexOf( minMaxFld );
176 const int fieldNameIndex = attributeTable->fields().indexOf( nameFld );
177 QMap<double, QString> ratLabelsMap;
178 const QList<QList<QVariant>> constRatData = attributeTable->data();
179 for ( const auto &row : constRatData )
180 {
181 const double fieldValue = row.value( fieldValueIndex ).toDouble();
182 const QString fieldName = row.value( fieldNameIndex ).toString();
183 ratLabelsMap.insert( fieldValue, fieldName );
184 }
185
186 for ( qsizetype i = 0; i < classes.size(); ++i )
187 {
188 QgsPalettedRasterRenderer::Class &classData = classes[i];
189 if ( ratLabelsMap.contains( classData.value ) )
190 {
191 classData.label = ratLabelsMap.value( classData.value );
192 }
193 }
194 }
195 renderer = std::make_unique< QgsPalettedRasterRenderer >( provider, grayBand, classes );
196 }
197 }
198
199 // last preference -- just fallback to single band gray renderer if we couldn't determine color palette
200 if ( !renderer )
201 {
202 renderer = std::make_unique< QgsSingleBandGrayRenderer >( provider, grayBand );
203
204 QgsContrastEnhancement *ce = new QgsContrastEnhancement( ( Qgis::DataType ) ( provider->dataType( grayBand ) ) );
205
206 // 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).
207 qgis::down_cast< QgsSingleBandGrayRenderer * >( renderer.get() )->setContrastEnhancement( ce );
208 }
209 }
210 break;
211
214 {
215 const int grayBand = 1;
216
217 // If the raster band has an attribute table try to use it.
218 QString ratErrorMessage;
219 if ( QgsRasterAttributeTable *rat = provider->attributeTable( grayBand ); rat && rat->isValid( &ratErrorMessage ) )
220 {
221 renderer = rat->createRenderer( provider, grayBand );
222 }
223
224 if ( !ratErrorMessage.isEmpty() )
225 {
226 QgsDebugMsgLevel( u"Invalid RAT from band 1, RAT was not used to create the renderer: %1."_s.arg( ratErrorMessage ), 2 );
227 }
228
229 if ( !renderer )
230 {
231 renderer = std::make_unique< QgsSingleBandGrayRenderer >( provider, grayBand );
232
233 QgsContrastEnhancement *ce = new QgsContrastEnhancement( ( Qgis::DataType ) ( provider->dataType( grayBand ) ) );
234
235 // 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).
236 qgis::down_cast< QgsSingleBandGrayRenderer * >( renderer.get() )->setContrastEnhancement( ce );
237 }
238 break;
239 }
240
242 {
243 const int bandNo = 1;
244 double minValue = 0;
245 double maxValue = 0;
246 // TODO: avoid calculating statistics if not necessary (default style loaded)
247 minMaxValuesForBand( bandNo, provider, minValue, maxValue );
248 QgsRasterShader *shader = new QgsRasterShader( minValue, maxValue );
249 renderer = std::make_unique< QgsSingleBandPseudoColorRenderer >( provider, bandNo, shader );
250 break;
251 }
253 {
254 int redBand = settingsDefaultRedBand->value();
255 if ( redBand < 0 || redBand > provider->bandCount() )
256 {
257 redBand = -1;
258 }
259 int greenBand = settingsDefaultGreenBand->value();
260 if ( greenBand < 0 || greenBand > provider->bandCount() )
261 {
262 greenBand = -1;
263 }
264 int blueBand = settingsDefaultBlueBand->value();
265 if ( blueBand < 0 || blueBand > provider->bandCount() )
266 {
267 blueBand = -1;
268 }
269
270 renderer = std::make_unique< QgsMultiBandColorRenderer >( provider, redBand, greenBand, blueBand );
271 break;
272 }
274 {
275 renderer = std::make_unique< QgsSingleBandColorDataRenderer >( provider, 1 );
276 break;
277 }
278 default:
279 return nullptr;
280 }
281
282 auto tr = std::make_unique< QgsRasterTransparency >();
283 const int bandCount = renderer->usesBands().size();
284 if ( bandCount == 1 )
285 {
286 tr->setTransparentSingleValuePixelList( {} );
287 }
288 else if ( bandCount == 3 )
289 {
290 tr->setTransparentThreeValuePixelList( {} );
291 }
292 renderer->setRasterTransparency( tr.release() );
293 return renderer;
294}
295
296bool QgsRasterRendererRegistry::minMaxValuesForBand( int band, QgsRasterDataProvider *provider, double &minValue, double &maxValue ) const
297{
298 if ( !provider )
299 {
300 return false;
301 }
302
303 minValue = 0;
304 maxValue = 0;
305
306 if ( settingsUseStandardDeviation->value() )
307 {
308 const QgsRasterBandStats stats = provider->bandStatistics( band, Qgis::RasterBandStatistic::Mean | Qgis::RasterBandStatistic::StdDev );
309
310 const double stdDevFactor = settingsDefaultStandardDeviation->value();
311 const double diff = stdDevFactor * stats.stdDev;
312 minValue = stats.mean - diff;
313 maxValue = stats.mean + diff;
314 }
315 else
316 {
317 const QgsRasterBandStats stats = provider->bandStatistics( band, Qgis::RasterBandStatistic::Min | Qgis::RasterBandStatistic::Max );
318 minValue = stats.minimumValue;
319 maxValue = stats.maximumValue;
320 }
321 return true;
322}
RasterDrawingStyle
Raster drawing styles.
Definition qgis.h:5346
@ SingleBandGray
A single band image drawn as a range of gray colors.
Definition qgis.h:5348
@ MultiBandSingleBandGray
A layer containing 2 or more bands, but a single band drawn as a range of gray colors.
Definition qgis.h:5354
@ SingleBandColorData
ARGB values rendered directly.
Definition qgis.h:5357
@ 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:5356
@ PalettedColor
A "Palette" image drawn using color table.
Definition qgis.h:5350
@ SingleBandPseudoColor
A single band image drawn using a pseudocolor algorithm.
Definition qgis.h:5349
QFlags< RasterRendererCapability > RasterRendererCapabilities
Raster renderer capabilities.
Definition qgis.h:1703
@ StdDev
Standard deviation.
Definition qgis.h:6780
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).
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).
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