QGIS API Documentation  3.10.0-A Coruña (6c816b4204)
qgsmultibandcolorrenderer.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  qgsmultibandcolorrenderer.cpp
3  -----------------------------
4  begin : December 2011
5  copyright : (C) 2011 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 #include "qgscontrastenhancement.h"
20 #include "qgsrastertransparency.h"
21 #include "qgsrasterviewport.h"
22 
23 #include <QDomDocument>
24 #include <QDomElement>
25 #include <QImage>
26 #include <QSet>
27 
28 QgsMultiBandColorRenderer::QgsMultiBandColorRenderer( QgsRasterInterface *input, int redBand, int greenBand, int blueBand,
29  QgsContrastEnhancement *redEnhancement,
30  QgsContrastEnhancement *greenEnhancement,
31  QgsContrastEnhancement *blueEnhancement )
32  : QgsRasterRenderer( input, QStringLiteral( "multibandcolor" ) )
33  , mRedBand( redBand )
34  , mGreenBand( greenBand )
35  , mBlueBand( blueBand )
36  , mRedContrastEnhancement( redEnhancement )
37  , mGreenContrastEnhancement( greenEnhancement )
38  , mBlueContrastEnhancement( blueEnhancement )
39 {
40 }
41 
43 {
44  delete mRedContrastEnhancement;
45  delete mGreenContrastEnhancement;
46  delete mBlueContrastEnhancement;
47 }
48 
50 {
51  QgsMultiBandColorRenderer *renderer = new QgsMultiBandColorRenderer( nullptr, mRedBand, mGreenBand, mBlueBand );
52  renderer->copyCommonProperties( this );
53 
54  if ( mRedContrastEnhancement )
55  {
56  renderer->setRedContrastEnhancement( new QgsContrastEnhancement( *mRedContrastEnhancement ) );
57  }
58  if ( mGreenContrastEnhancement )
59  {
60  renderer->setGreenContrastEnhancement( new QgsContrastEnhancement( *mGreenContrastEnhancement ) );
61  }
62  if ( mBlueContrastEnhancement )
63  {
64  renderer->setBlueContrastEnhancement( new QgsContrastEnhancement( *mBlueContrastEnhancement ) );
65  }
66 
67  return renderer;
68 }
69 
71 {
72  delete mRedContrastEnhancement;
73  mRedContrastEnhancement = ce;
74 }
75 
77 {
78  delete mGreenContrastEnhancement;
79  mGreenContrastEnhancement = ce;
80 }
81 
83 {
84  delete mBlueContrastEnhancement;
85  mBlueContrastEnhancement = ce;
86 }
87 
89 {
90  if ( elem.isNull() )
91  {
92  return nullptr;
93  }
94 
95  //red band, green band, blue band
96  int redBand = elem.attribute( QStringLiteral( "redBand" ), QStringLiteral( "-1" ) ).toInt();
97  int greenBand = elem.attribute( QStringLiteral( "greenBand" ), QStringLiteral( "-1" ) ).toInt();
98  int blueBand = elem.attribute( QStringLiteral( "blueBand" ), QStringLiteral( "-1" ) ).toInt();
99 
100  //contrast enhancements
102  QDomElement redContrastElem = elem.firstChildElement( QStringLiteral( "redContrastEnhancement" ) );
103  if ( !redContrastElem.isNull() )
104  {
105  redContrastEnhancement = new QgsContrastEnhancement( ( Qgis::DataType )(
106  input->dataType( redBand ) ) );
107  redContrastEnhancement->readXml( redContrastElem );
108  }
109 
111  QDomElement greenContrastElem = elem.firstChildElement( QStringLiteral( "greenContrastEnhancement" ) );
112  if ( !greenContrastElem.isNull() )
113  {
114  greenContrastEnhancement = new QgsContrastEnhancement( ( Qgis::DataType )(
115  input->dataType( greenBand ) ) );
116  greenContrastEnhancement->readXml( greenContrastElem );
117  }
118 
120  QDomElement blueContrastElem = elem.firstChildElement( QStringLiteral( "blueContrastEnhancement" ) );
121  if ( !blueContrastElem.isNull() )
122  {
123  blueContrastEnhancement = new QgsContrastEnhancement( ( Qgis::DataType )(
124  input->dataType( blueBand ) ) );
125  blueContrastEnhancement->readXml( blueContrastElem );
126  }
127 
128  QgsRasterRenderer *r = new QgsMultiBandColorRenderer( input, redBand, greenBand, blueBand, redContrastEnhancement,
129  greenContrastEnhancement, blueContrastEnhancement );
130  r->readXml( elem );
131  return r;
132 }
133 
134 QgsRasterBlock *QgsMultiBandColorRenderer::block( int bandNo, QgsRectangle const &extent, int width, int height, QgsRasterBlockFeedback *feedback )
135 {
136  Q_UNUSED( bandNo )
137  std::unique_ptr< QgsRasterBlock > outputBlock( new QgsRasterBlock() );
138  if ( !mInput )
139  {
140  return outputBlock.release();
141  }
142 
143  //In some (common) cases, we can simplify the drawing loop considerably and save render time
144  bool fastDraw = ( !usesTransparency()
145  && mRedBand > 0 && mGreenBand > 0 && mBlueBand > 0
146  && mAlphaBand < 1 );
147 
148  QSet<int> bands;
149  if ( mRedBand > 0 )
150  {
151  bands << mRedBand;
152  }
153  if ( mGreenBand > 0 )
154  {
155  bands << mGreenBand;
156  }
157  if ( mBlueBand > 0 )
158  {
159  bands << mBlueBand;
160  }
161  if ( bands.empty() )
162  {
163  // no need to draw anything if no band is set
164  // TODO:: we should probably return default color block
165  return outputBlock.release();
166  }
167 
168  if ( mAlphaBand > 0 )
169  {
170  bands << mAlphaBand;
171  }
172 
173  QMap<int, QgsRasterBlock *> bandBlocks;
174  QgsRasterBlock *defaultPointer = nullptr;
175  QSet<int>::const_iterator bandIt = bands.constBegin();
176  for ( ; bandIt != bands.constEnd(); ++bandIt )
177  {
178  bandBlocks.insert( *bandIt, defaultPointer );
179  }
180 
181  QgsRasterBlock *redBlock = nullptr;
182  QgsRasterBlock *greenBlock = nullptr;
183  QgsRasterBlock *blueBlock = nullptr;
184  QgsRasterBlock *alphaBlock = nullptr;
185 
186  bandIt = bands.constBegin();
187  for ( ; bandIt != bands.constEnd(); ++bandIt )
188  {
189  bandBlocks[*bandIt] = mInput->block( *bandIt, extent, width, height, feedback );
190  if ( !bandBlocks[*bandIt] )
191  {
192  // We should free the alloced mem from block().
193  QgsDebugMsg( QStringLiteral( "No input band" ) );
194  --bandIt;
195  for ( ; bandIt != bands.constBegin(); --bandIt )
196  {
197  delete bandBlocks[*bandIt];
198  }
199  return outputBlock.release();
200  }
201  }
202 
203  if ( mRedBand > 0 )
204  {
205  redBlock = bandBlocks[mRedBand];
206  }
207  if ( mGreenBand > 0 )
208  {
209  greenBlock = bandBlocks[mGreenBand];
210  }
211  if ( mBlueBand > 0 )
212  {
213  blueBlock = bandBlocks[mBlueBand];
214  }
215  if ( mAlphaBand > 0 )
216  {
217  alphaBlock = bandBlocks[mAlphaBand];
218  }
219 
220  if ( !outputBlock->reset( Qgis::ARGB32_Premultiplied, width, height ) )
221  {
222  for ( int i = 0; i < bandBlocks.size(); i++ )
223  {
224  delete bandBlocks.value( i );
225  }
226  return outputBlock.release();
227  }
228 
229  QRgb *outputBlockColorData = outputBlock->colorData();
230 
231  // faster data access to data for the common case that input data are coming from RGB image with 8-bit bands
232  bool hasByteRgb = ( redBlock && greenBlock && blueBlock && redBlock->dataType() == Qgis::Byte && greenBlock->dataType() == Qgis::Byte && blueBlock->dataType() == Qgis::Byte );
233  const quint8 *redData = nullptr, *greenData = nullptr, *blueData = nullptr;
234  if ( hasByteRgb )
235  {
236  redData = redBlock->byteData();
237  greenData = greenBlock->byteData();
238  blueData = blueBlock->byteData();
239  }
240 
241  QRgb myDefaultColor = NODATA_COLOR;
242 
243  if ( fastDraw )
244  {
245  // By default RGB raster layers have contrast enhancement assigned and normally that requires us to take the slow
246  // route that applies the enhancement. However if the algorithm type is "no enhancement" and all input bands are byte-sized,
247  // no transform would be applied to the input values and we can take the fast route.
248  bool hasEnhancement;
249  if ( hasByteRgb )
250  {
251  hasEnhancement =
252  ( mRedContrastEnhancement && mRedContrastEnhancement->contrastEnhancementAlgorithm() != QgsContrastEnhancement::NoEnhancement ) ||
253  ( mGreenContrastEnhancement && mGreenContrastEnhancement->contrastEnhancementAlgorithm() != QgsContrastEnhancement::NoEnhancement ) ||
254  ( mBlueContrastEnhancement && mBlueContrastEnhancement->contrastEnhancementAlgorithm() != QgsContrastEnhancement::NoEnhancement );
255  }
256  else
257  {
258  hasEnhancement = mRedContrastEnhancement || mGreenContrastEnhancement || mBlueContrastEnhancement;
259  }
260  if ( hasEnhancement )
261  fastDraw = false;
262  }
263 
264  qgssize count = ( qgssize )width * height;
265  for ( qgssize i = 0; i < count; i++ )
266  {
267  if ( fastDraw ) //fast rendering if no transparency, stretching, color inversion, etc.
268  {
269  if ( redBlock->isNoData( i ) ||
270  greenBlock->isNoData( i ) ||
271  blueBlock->isNoData( i ) )
272  {
273  outputBlock->setColor( i, myDefaultColor );
274  }
275  else
276  {
277  if ( hasByteRgb )
278  {
279  outputBlockColorData[i] = qRgb( redData[i], greenData[i], blueData[i] );
280  }
281  else
282  {
283  int redVal = static_cast<int>( redBlock->value( i ) );
284  int greenVal = static_cast<int>( greenBlock->value( i ) );
285  int blueVal = static_cast<int>( blueBlock->value( i ) );
286  outputBlockColorData[i] = qRgb( redVal, greenVal, blueVal );
287  }
288  }
289  continue;
290  }
291 
292  bool isNoData = false;
293  double redVal = 0;
294  double greenVal = 0;
295  double blueVal = 0;
296  if ( mRedBand > 0 )
297  {
298  redVal = redBlock->valueAndNoData( i, isNoData );
299  }
300  if ( !isNoData && mGreenBand > 0 )
301  {
302  greenVal = greenBlock->valueAndNoData( i, isNoData );
303  }
304  if ( !isNoData && mBlueBand > 0 )
305  {
306  blueVal = blueBlock->valueAndNoData( i, isNoData );
307  }
308  if ( isNoData )
309  {
310  outputBlock->setColor( i, myDefaultColor );
311  continue;
312  }
313 
314  //apply default color if red, green or blue not in displayable range
315  if ( ( mRedContrastEnhancement && !mRedContrastEnhancement->isValueInDisplayableRange( redVal ) )
316  || ( mGreenContrastEnhancement && !mGreenContrastEnhancement->isValueInDisplayableRange( redVal ) )
317  || ( mBlueContrastEnhancement && !mBlueContrastEnhancement->isValueInDisplayableRange( redVal ) ) )
318  {
319  outputBlock->setColor( i, myDefaultColor );
320  continue;
321  }
322 
323  //stretch color values
324  if ( mRedContrastEnhancement )
325  {
326  redVal = mRedContrastEnhancement->enhanceContrast( redVal );
327  }
328  if ( mGreenContrastEnhancement )
329  {
330  greenVal = mGreenContrastEnhancement->enhanceContrast( greenVal );
331  }
332  if ( mBlueContrastEnhancement )
333  {
334  blueVal = mBlueContrastEnhancement->enhanceContrast( blueVal );
335  }
336 
337  //opacity
338  double currentOpacity = mOpacity;
339  if ( mRasterTransparency )
340  {
341  currentOpacity = mRasterTransparency->alphaValue( redVal, greenVal, blueVal, mOpacity * 255 ) / 255.0;
342  }
343  if ( mAlphaBand > 0 )
344  {
345  currentOpacity *= alphaBlock->value( i ) / 255.0;
346  }
347 
348  if ( qgsDoubleNear( currentOpacity, 1.0 ) )
349  {
350  outputBlock->setColor( i, qRgba( redVal, greenVal, blueVal, 255 ) );
351  }
352  else
353  {
354  outputBlock->setColor( i, qRgba( currentOpacity * redVal, currentOpacity * greenVal, currentOpacity * blueVal, currentOpacity * 255 ) );
355  }
356  }
357 
358  //delete input blocks
359  QMap<int, QgsRasterBlock *>::const_iterator bandDelIt = bandBlocks.constBegin();
360  for ( ; bandDelIt != bandBlocks.constEnd(); ++bandDelIt )
361  {
362  delete bandDelIt.value();
363  }
364 
365  return outputBlock.release();
366 }
367 
368 void QgsMultiBandColorRenderer::writeXml( QDomDocument &doc, QDomElement &parentElem ) const
369 {
370  if ( parentElem.isNull() )
371  {
372  return;
373  }
374 
375  QDomElement rasterRendererElem = doc.createElement( QStringLiteral( "rasterrenderer" ) );
376  _writeXml( doc, rasterRendererElem );
377  rasterRendererElem.setAttribute( QStringLiteral( "redBand" ), mRedBand );
378  rasterRendererElem.setAttribute( QStringLiteral( "greenBand" ), mGreenBand );
379  rasterRendererElem.setAttribute( QStringLiteral( "blueBand" ), mBlueBand );
380 
381  //contrast enhancement
382  if ( mRedContrastEnhancement )
383  {
384  QDomElement redContrastElem = doc.createElement( QStringLiteral( "redContrastEnhancement" ) );
385  mRedContrastEnhancement->writeXml( doc, redContrastElem );
386  rasterRendererElem.appendChild( redContrastElem );
387  }
388  if ( mGreenContrastEnhancement )
389  {
390  QDomElement greenContrastElem = doc.createElement( QStringLiteral( "greenContrastEnhancement" ) );
391  mGreenContrastEnhancement->writeXml( doc, greenContrastElem );
392  rasterRendererElem.appendChild( greenContrastElem );
393  }
394  if ( mBlueContrastEnhancement )
395  {
396  QDomElement blueContrastElem = doc.createElement( QStringLiteral( "blueContrastEnhancement" ) );
397  mBlueContrastEnhancement->writeXml( doc, blueContrastElem );
398  rasterRendererElem.appendChild( blueContrastElem );
399  }
400  parentElem.appendChild( rasterRendererElem );
401 }
402 
404 {
405  QList<int> bandList;
406  if ( mRedBand != -1 )
407  {
408  bandList << mRedBand;
409  }
410  if ( mGreenBand != -1 )
411  {
412  bandList << mGreenBand;
413  }
414  if ( mBlueBand != -1 )
415  {
416  bandList << mBlueBand;
417  }
418  return bandList;
419 }
420 
421 void QgsMultiBandColorRenderer::toSld( QDomDocument &doc, QDomElement &element, const QgsStringMap &props ) const
422 {
423  // create base structure
424  QgsRasterRenderer::toSld( doc, element, props );
425 
426 
427 #if 0
428  // TODO: the following jumped code is necessary to avoid to export channelSelection in
429  // case it's set as default value. The drawback is that it's necessary to calc band
430  // statistics that can be really slow depending on dataProvider and rastr localtion.
431  // this is the reason this part of code is commented and the channelSelection is
432  // always exported.
433  //
434  // before to export check if the band combination and contrast setting are the
435  // default ones to avoid to export this tags
436  bool isDefaultCombination = true;
437  QList<int> defaultBandCombination( { 1, 2, 3 } );
438 
439  isDefaultCombination = isDefaultCombination && ( usesBands() == defaultBandCombination );
440  isDefaultCombination = isDefaultCombination && (
444  );
445  // compute raster statistics (slow) only if true the previous conditions
446  if ( isDefaultCombination )
447  {
449  isDefaultCombination = isDefaultCombination && (
450  ( mRedContrastEnhancement->minimumValue() == statRed.minimumValue &&
451  mRedContrastEnhancement->maximumValue() == statRed.maximumValue )
452  );
453  }
454  if ( isDefaultCombination )
455  {
457  isDefaultCombination = isDefaultCombination && (
458  ( mGreenContrastEnhancement->minimumValue() == statGreen.minimumValue &&
459  mGreenContrastEnhancement->maximumValue() == statGreen.maximumValue )
460  );
461  }
462  if ( isDefaultCombination )
463  {
465  isDefaultCombination = isDefaultCombination && (
466  ( mBlueContrastEnhancement->minimumValue() == statBlue.minimumValue &&
467  mBlueContrastEnhancement->maximumValue() == statBlue.maximumValue )
468  );
469  }
470  if ( isDefaultCombination )
471  return;
472 #endif
473 
474  // look for RasterSymbolizer tag
475  QDomNodeList elements = element.elementsByTagName( QStringLiteral( "sld:RasterSymbolizer" ) );
476  if ( elements.size() == 0 )
477  return;
478 
479  // there SHOULD be only one
480  QDomElement rasterSymbolizerElem = elements.at( 0 ).toElement();
481 
482  // add Channel Selection tags
483  // Need to insert channelSelection in the correct sequence as in SLD standard e.g.
484  // after opacity or geometry or as first element after sld:RasterSymbolizer
485  QDomElement channelSelectionElem = doc.createElement( QStringLiteral( "sld:ChannelSelection" ) );
486  elements = rasterSymbolizerElem.elementsByTagName( QStringLiteral( "sld:Opacity" ) );
487  if ( elements.size() != 0 )
488  {
489  rasterSymbolizerElem.insertAfter( channelSelectionElem, elements.at( 0 ) );
490  }
491  else
492  {
493  elements = rasterSymbolizerElem.elementsByTagName( QStringLiteral( "sld:Geometry" ) );
494  if ( elements.size() != 0 )
495  {
496  rasterSymbolizerElem.insertAfter( channelSelectionElem, elements.at( 0 ) );
497  }
498  else
499  {
500  rasterSymbolizerElem.insertBefore( channelSelectionElem, rasterSymbolizerElem.firstChild() );
501  }
502  }
503 
504  // for each mapped band
505  static QStringList tags { QStringLiteral( "sld:RedChannel" ), QStringLiteral( "sld:GreenChannel" ), QStringLiteral( "sld:BlueChannel" ) };
506 
507  QList<QgsContrastEnhancement *> contrastEnhancements;
508  contrastEnhancements.append( mRedContrastEnhancement );
509  contrastEnhancements.append( mGreenContrastEnhancement );
510  contrastEnhancements.append( mBlueContrastEnhancement );
511 
512  QList<int> bands = usesBands();
513  QList<int>::const_iterator bandIt = bands.constBegin();
514  for ( int tagCounter = 0 ; bandIt != bands.constEnd(); ++bandIt, ++tagCounter )
515  {
516  if ( *bandIt < 0 )
517  continue;
518 
519  QDomElement channelElem = doc.createElement( tags[ tagCounter ] );
520  channelSelectionElem.appendChild( channelElem );
521 
522  // set band
523  QDomElement sourceChannelNameElem = doc.createElement( QStringLiteral( "sld:SourceChannelName" ) );
524  sourceChannelNameElem.appendChild( doc.createTextNode( QString::number( *bandIt ) ) );
525  channelElem.appendChild( sourceChannelNameElem );
526 
527  // set ContrastEnhancement for each band
528  // NO ContrastEnhancement parameter for the entire bands is managed e.g.
529  // because min/max values can vary depending on band.
530  if ( contrastEnhancements[ tagCounter ] )
531  {
532  QDomElement contrastEnhancementElem = doc.createElement( QStringLiteral( "sld:ContrastEnhancement" ) );
533  contrastEnhancements[ tagCounter ]->toSld( doc, contrastEnhancementElem );
534  channelElem.appendChild( contrastEnhancementElem );
535  }
536  }
537 }
double maximumValue() const
Returns the maximum value for the contrast enhancement range.
A rectangle specified with double values.
Definition: qgsrectangle.h:41
static QgsRasterRenderer * create(const QDomElement &elem, QgsRasterInterface *input)
const QgsContrastEnhancement * blueContrastEnhancement() const
void writeXml(QDomDocument &doc, QDomElement &parentElem) const override
Write base class members to xml.
virtual void toSld(QDomDocument &doc, QDomElement &element, const QgsStringMap &props=QgsStringMap()) const
Used from subclasses to create SLD Rule elements following SLD v1.0 specs.
Qgis::DataType dataType() const
Returns data type.
virtual QgsRectangle extent() const
Gets the extent of the interface.
#define QgsDebugMsg(str)
Definition: qgslogger.h:38
bool qgsDoubleNear(double a, double b, double epsilon=4 *std::numeric_limits< double >::epsilon())
Compare two doubles (but allow some difference)
Definition: qgis.h:280
virtual QgsRasterInterface * input() const
Current input.
double valueAndNoData(int row, int column, bool &isNoData) const
Reads a single value from the pixel at row and column, if type of block is numeric.
DataType
Raster data types.
Definition: qgis.h:80
double maximumValue
The maximum cell value in the raster band.
double minimumValue() const
Returns the minimum value for the contrast enhancement range.
virtual Qgis::DataType dataType(int bandNo) const =0
Returns data type for the band specified by number.
QgsMultiBandColorRenderer * clone() const override
Clone itself, create deep copy.
QMap< QString, QString > QgsStringMap
Definition: qgis.h:612
void setGreenContrastEnhancement(QgsContrastEnhancement *ce)
Takes ownership.
QList< int > usesBands() const override
Returns a list of band numbers used by the renderer.
QgsRasterBlock * block(int bandNo, const QgsRectangle &extent, int width, int height, QgsRasterBlockFeedback *feedback=nullptr) override
Read block of data using given extent and size.
QgsRasterTransparency * mRasterTransparency
Raster transparency per color or value. Overwrites global alpha value.
static const QRgb NODATA_COLOR
Color, alpha, red, green, blue, 4 bytes the same as QImage::Format_ARGB32_Premultiplied.
Definition: qgis.h:95
The RasterBandStats struct is a container for statistics about a single raster band.
Raster data container.
void setRedContrastEnhancement(QgsContrastEnhancement *ce)
Takes ownership.
virtual QgsRasterBlock * block(int bandNo, const QgsRectangle &extent, int width, int height, QgsRasterBlockFeedback *feedback=nullptr)=0
Read block of data using given extent and size.
const quint8 * byteData() const
Gives direct access to the raster block data.
void _writeXml(QDomDocument &doc, QDomElement &rasterRendererElem) const
Write upper class info into rasterrenderer element (called by writeXml method of subclasses) ...
void copyCommonProperties(const QgsRasterRenderer *other, bool copyMinMaxOrigin=true)
Copies common properties like opacity / transparency data from other renderer.
bool isValueInDisplayableRange(double value)
Returns true if a pixel value is in displayable range, false if pixel is outside of range (i...
bool usesTransparency() const
void readXml(const QDomElement &elem)
int mAlphaBand
Read alpha value from band.
void readXml(const QDomElement &rendererElem) override
Sets base class members from xml. Usually called from create() methods of subclasses.
bool isNoData(int row, int column) const
Checks if value at position is no data.
Base class for processing filters like renderers, reprojector, resampler etc.
int alphaValue(double value, int globalTransparency=255) const
Returns the transparency value for a single value pixel.
unsigned long long qgssize
Qgssize is used instead of size_t, because size_t is stdlib type, unknown by SIP, and it would be har...
Definition: qgis.h:621
void toSld(QDomDocument &doc, QDomElement &element, const QgsStringMap &props=QgsStringMap()) const override
Used from subclasses to create SLD Rule elements following SLD v1.0 specs.
virtual QgsRasterBandStats bandStatistics(int bandNo, int stats=QgsRasterBandStats::All, const QgsRectangle &extent=QgsRectangle(), int sampleSize=0, QgsRasterBlockFeedback *feedback=nullptr)
Returns the band statistics.
const QgsContrastEnhancement * redContrastEnhancement() const
const QgsContrastEnhancement * greenContrastEnhancement() const
void setBlueContrastEnhancement(QgsContrastEnhancement *ce)
Takes ownership.
double value(int row, int column) const
Read a single value if type of block is numeric.
ContrastEnhancementAlgorithm contrastEnhancementAlgorithm() const
double minimumValue
The minimum cell value in the raster band.
Renderer for multiband images with the color components.
void writeXml(QDomDocument &doc, QDomElement &parentElem) const
double mOpacity
Global alpha value (0-1)
Manipulates raster pixel values so that they enhanceContrast or clip into a specified numerical range...
QgsMultiBandColorRenderer(QgsRasterInterface *input, int redBand, int greenBand, int blueBand, QgsContrastEnhancement *redEnhancement=nullptr, QgsContrastEnhancement *greenEnhancement=nullptr, QgsContrastEnhancement *blueEnhancement=nullptr)
QgsRasterInterface * mInput
Feedback object tailored for raster block reading.
Raster renderer pipe that applies colors to a raster.
Eight bit unsigned integer (quint8)
Definition: qgis.h:83
int enhanceContrast(double value)
Applies the contrast enhancement to a value.