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
18 #include "qgsrasterrendererregistry.h"
19 #include "qgsrasterdataprovider.h"
20 #include "qgsrastershader.h"
21 #include "qgsrastertransparency.h"
22 #include "qgsmultibandcolorrenderer.h"
23 #include "qgspalettedrasterrenderer.h"
24 #include "qgsrastercontourrenderer.h"
25 #include "qgssinglebandcolordatarenderer.h"
26 #include "qgssinglebandgrayrenderer.h"
27 #include "qgssinglebandpseudocolorrenderer.h"
28 #include "qgshillshaderenderer.h"
29 #include "qgsapplication.h"
30 #include "qgssettings.h"
31
32 #include <QIcon>
33
QgsRasterRendererRegistryEntry(const QString & name,const QString & visibleName,QgsRasterRendererCreateFunc rendererFunction,QgsRasterRendererWidgetCreateFunc widgetFunction)34 QgsRasterRendererRegistryEntry::QgsRasterRendererRegistryEntry( const QString &name, const QString &visibleName,
35 QgsRasterRendererCreateFunc rendererFunction,
36 QgsRasterRendererWidgetCreateFunc widgetFunction )
37 : name( name )
38 , visibleName( visibleName )
39 , rendererCreateFunction( rendererFunction )
40 , widgetCreateFunction( widgetFunction )
41 {
42 }
43
icon()44 QIcon QgsRasterRendererRegistryEntry::icon()
45 {
46 return QgsApplication::getThemeIcon( QString( "styleicons/%1.svg" ).arg( name ) );
47 }
48
QgsRasterRendererRegistry()49 QgsRasterRendererRegistry::QgsRasterRendererRegistry()
50 {
51 // insert items in a particular order, which is returned in renderersList()
52 insert( QgsRasterRendererRegistryEntry( QStringLiteral( "multibandcolor" ), QObject::tr( "Multiband color" ),
53 QgsMultiBandColorRenderer::create, nullptr ) );
54 insert( QgsRasterRendererRegistryEntry( QStringLiteral( "paletted" ), QObject::tr( "Paletted/Unique values" ), QgsPalettedRasterRenderer::create, nullptr ) );
55 insert( QgsRasterRendererRegistryEntry( QStringLiteral( "singlebandgray" ), QObject::tr( "Singleband gray" ),
56 QgsSingleBandGrayRenderer::create, nullptr ) );
57 insert( QgsRasterRendererRegistryEntry( QStringLiteral( "singlebandpseudocolor" ), QObject::tr( "Singleband pseudocolor" ),
58 QgsSingleBandPseudoColorRenderer::create, nullptr ) );
59 insert( QgsRasterRendererRegistryEntry( QStringLiteral( "singlebandcolordata" ), QObject::tr( "Singleband color data" ),
60 QgsSingleBandColorDataRenderer::create, nullptr ) );
61 insert( QgsRasterRendererRegistryEntry( QStringLiteral( "hillshade" ), QObject::tr( "Hillshade" ),
62 QgsHillshadeRenderer::create, nullptr ) );
63 insert( QgsRasterRendererRegistryEntry( QStringLiteral( "contour" ), QObject::tr( "Contours" ),
64 QgsRasterContourRenderer::create, nullptr ) );
65 }
66
insert(const QgsRasterRendererRegistryEntry & entry)67 void QgsRasterRendererRegistry::insert( const QgsRasterRendererRegistryEntry &entry )
68 {
69 mEntries.insert( entry.name, entry );
70 mSortedEntries.append( entry.name );
71 }
72
insertWidgetFunction(const QString & rendererName,QgsRasterRendererWidgetCreateFunc func)73 void QgsRasterRendererRegistry::insertWidgetFunction( const QString &rendererName, QgsRasterRendererWidgetCreateFunc func )
74 {
75 if ( !mEntries.contains( rendererName ) )
76 {
77 return;
78 }
79 mEntries[rendererName].widgetCreateFunction = func;
80 }
81
rendererData(const QString & rendererName,QgsRasterRendererRegistryEntry & data) const82 bool QgsRasterRendererRegistry::rendererData( const QString &rendererName, QgsRasterRendererRegistryEntry &data ) const
83 {
84 QHash< QString, QgsRasterRendererRegistryEntry >::const_iterator it = mEntries.find( rendererName );
85 if ( it == mEntries.constEnd() )
86 {
87 return false;
88 }
89 data = it.value();
90 return true;
91 }
92
renderersList() const93 QStringList QgsRasterRendererRegistry::renderersList() const
94 {
95 return mSortedEntries;
96 }
97
entries() const98 QList< QgsRasterRendererRegistryEntry > QgsRasterRendererRegistry::entries() const
99 {
100 QList< QgsRasterRendererRegistryEntry > result;
101
102 QHash< QString, QgsRasterRendererRegistryEntry >::const_iterator it = mEntries.constBegin();
103 for ( ; it != mEntries.constEnd(); ++it )
104 {
105 result.push_back( it.value() );
106 }
107 return result;
108 }
109
defaultRendererForDrawingStyle(QgsRaster::DrawingStyle drawingStyle,QgsRasterDataProvider * provider) const110 QgsRasterRenderer *QgsRasterRendererRegistry::defaultRendererForDrawingStyle( QgsRaster::DrawingStyle drawingStyle, QgsRasterDataProvider *provider ) const
111 {
112 if ( !provider || provider->bandCount() < 1 )
113 {
114 return nullptr;
115 }
116
117
118 QgsRasterRenderer *renderer = nullptr;
119 switch ( drawingStyle )
120 {
121 case QgsRaster::PalettedColor:
122 {
123 int grayBand = 1; //reasonable default
124 QgsPalettedRasterRenderer::ClassData classes = QgsPalettedRasterRenderer::colorTableToClassData( provider->colorTable( grayBand ) );
125 renderer = new QgsPalettedRasterRenderer( provider,
126 grayBand,
127 classes );
128 }
129 break;
130 case QgsRaster::MultiBandSingleBandGray:
131 case QgsRaster::SingleBandGray:
132 {
133 int grayBand = 1;
134 renderer = new QgsSingleBandGrayRenderer( provider, grayBand );
135
136 QgsContrastEnhancement *ce = new QgsContrastEnhancement( ( Qgis::DataType )(
137 provider->dataType( grayBand ) ) );
138
139 // 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).
140 ( ( QgsSingleBandGrayRenderer * )renderer )->setContrastEnhancement( ce );
141 break;
142 }
143 case QgsRaster::SingleBandPseudoColor:
144 {
145 int bandNo = 1;
146 double minValue = 0;
147 double maxValue = 0;
148 // TODO: avoid calculating statistics if not necessary (default style loaded)
149 minMaxValuesForBand( bandNo, provider, minValue, maxValue );
150 QgsRasterShader *shader = new QgsRasterShader( minValue, maxValue );
151 renderer = new QgsSingleBandPseudoColorRenderer( provider, bandNo, shader );
152 break;
153 }
154 case QgsRaster::MultiBandColor:
155 {
156 QgsSettings s;
157
158 int redBand = s.value( QStringLiteral( "/Raster/defaultRedBand" ), 1 ).toInt();
159 if ( redBand < 0 || redBand > provider->bandCount() )
160 {
161 redBand = -1;
162 }
163 int greenBand = s.value( QStringLiteral( "/Raster/defaultGreenBand" ), 2 ).toInt();
164 if ( greenBand < 0 || greenBand > provider->bandCount() )
165 {
166 greenBand = -1;
167 }
168 int blueBand = s.value( QStringLiteral( "/Raster/defaultBlueBand" ), 3 ).toInt();
169 if ( blueBand < 0 || blueBand > provider->bandCount() )
170 {
171 blueBand = -1;
172 }
173
174 renderer = new QgsMultiBandColorRenderer( provider, redBand, greenBand, blueBand );
175 break;
176 }
177 case QgsRaster::SingleBandColorDataStyle:
178 {
179 renderer = new QgsSingleBandColorDataRenderer( provider, 1 );
180 break;
181 }
182 default:
183 return nullptr;
184 }
185
186 QgsRasterTransparency *tr = new QgsRasterTransparency(); //renderer takes ownership
187 int bandCount = renderer->usesBands().size();
188 if ( bandCount == 1 )
189 {
190 QList<QgsRasterTransparency::TransparentSingleValuePixel> transparentSingleList;
191 tr->setTransparentSingleValuePixelList( transparentSingleList );
192 }
193 else if ( bandCount == 3 )
194 {
195 QList<QgsRasterTransparency::TransparentThreeValuePixel> transparentThreeValueList;
196 tr->setTransparentThreeValuePixelList( transparentThreeValueList );
197 }
198 renderer->setRasterTransparency( tr );
199 return renderer;
200 }
201
minMaxValuesForBand(int band,QgsRasterDataProvider * provider,double & minValue,double & maxValue) const202 bool QgsRasterRendererRegistry::minMaxValuesForBand( int band, QgsRasterDataProvider *provider, double &minValue, double &maxValue ) const
203 {
204 if ( !provider )
205 {
206 return false;
207 }
208
209 minValue = 0;
210 maxValue = 0;
211
212 QgsSettings s;
213 if ( s.value( QStringLiteral( "/Raster/useStandardDeviation" ), false ).toBool() )
214 {
215 QgsRasterBandStats stats = provider->bandStatistics( band, QgsRasterBandStats::Mean | QgsRasterBandStats::StdDev );
216
217 double stdDevFactor = s.value( QStringLiteral( "/Raster/defaultStandardDeviation" ), 2.0 ).toDouble();
218 double diff = stdDevFactor * stats.stdDev;
219 minValue = stats.mean - diff;
220 maxValue = stats.mean + diff;
221 }
222 else
223 {
224 QgsRasterBandStats stats = provider->bandStatistics( band, QgsRasterBandStats::Min | QgsRasterBandStats::Max );
225 minValue = stats.minimumValue;
226 maxValue = stats.maximumValue;
227 }
228 return true;
229 }
230