QGIS API Documentation 3.43.0-Master (a6cade80589)
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
22#include "qgssldexportcontext.h"
23
24#include <QDomDocument>
25#include <QDomElement>
26#include <QImage>
27#include <QSet>
28
29QgsMultiBandColorRenderer::QgsMultiBandColorRenderer( QgsRasterInterface *input, int redBand, int greenBand, int blueBand,
30 QgsContrastEnhancement *redEnhancement,
31 QgsContrastEnhancement *greenEnhancement,
32 QgsContrastEnhancement *blueEnhancement )
33 : QgsRasterRenderer( input, QStringLiteral( "multibandcolor" ) )
34 , mRedBand( redBand )
35 , mGreenBand( greenBand )
36 , mBlueBand( blueBand )
37 , mRedContrastEnhancement( redEnhancement )
38 , mGreenContrastEnhancement( greenEnhancement )
39 , mBlueContrastEnhancement( blueEnhancement )
40{
41}
42
44
46{
47 QgsMultiBandColorRenderer *renderer = new QgsMultiBandColorRenderer( nullptr, mRedBand, mGreenBand, mBlueBand );
48 renderer->copyCommonProperties( this );
49
50 if ( mRedContrastEnhancement )
51 {
52 renderer->setRedContrastEnhancement( new QgsContrastEnhancement( *mRedContrastEnhancement ) );
53 }
54 if ( mGreenContrastEnhancement )
55 {
56 renderer->setGreenContrastEnhancement( new QgsContrastEnhancement( *mGreenContrastEnhancement ) );
57 }
58 if ( mBlueContrastEnhancement )
59 {
60 renderer->setBlueContrastEnhancement( new QgsContrastEnhancement( *mBlueContrastEnhancement ) );
61 }
62
63 return renderer;
64}
65
70
72{
73 if ( ce == mRedContrastEnhancement.get() )
74 return;
75
76 mRedContrastEnhancement.reset( ce );
77}
78
80{
81 return mGreenContrastEnhancement.get();
82}
83
85{
86 if ( ce == mGreenContrastEnhancement.get() )
87 return;
88
89 mGreenContrastEnhancement.reset( ce );
90}
91
93{
94 return mBlueContrastEnhancement.get();
95}
96
98{
99 if ( ce == mBlueContrastEnhancement.get() )
100 return;
101
102 mBlueContrastEnhancement.reset( ce );
103}
104
106{
107 if ( elem.isNull() )
108 {
109 return nullptr;
110 }
111
112 //red band, green band, blue band
113 const int redBand = elem.attribute( QStringLiteral( "redBand" ), QStringLiteral( "-1" ) ).toInt();
114 const int greenBand = elem.attribute( QStringLiteral( "greenBand" ), QStringLiteral( "-1" ) ).toInt();
115 const int blueBand = elem.attribute( QStringLiteral( "blueBand" ), QStringLiteral( "-1" ) ).toInt();
116
117 //contrast enhancements
119 const QDomElement redContrastElem = elem.firstChildElement( QStringLiteral( "redContrastEnhancement" ) );
120 if ( !redContrastElem.isNull() )
121 {
123 input->dataType( redBand ) ) );
124 redContrastEnhancement->readXml( redContrastElem );
125 }
126
128 const QDomElement greenContrastElem = elem.firstChildElement( QStringLiteral( "greenContrastEnhancement" ) );
129 if ( !greenContrastElem.isNull() )
130 {
132 input->dataType( greenBand ) ) );
133 greenContrastEnhancement->readXml( greenContrastElem );
134 }
135
137 const QDomElement blueContrastElem = elem.firstChildElement( QStringLiteral( "blueContrastEnhancement" ) );
138 if ( !blueContrastElem.isNull() )
139 {
141 input->dataType( blueBand ) ) );
142 blueContrastEnhancement->readXml( blueContrastElem );
143 }
144
147 r->readXml( elem );
148 return r;
149}
150
151QgsRasterBlock *QgsMultiBandColorRenderer::block( int bandNo, QgsRectangle const &extent, int width, int height, QgsRasterBlockFeedback *feedback )
152{
153 Q_UNUSED( bandNo )
154 auto outputBlock = std::make_unique<QgsRasterBlock>();
155 if ( !mInput )
156 {
157 return outputBlock.release();
158 }
159
160 //In some (common) cases, we can simplify the drawing loop considerably and save render time
161 bool fastDraw = ( !usesTransparency()
162 && mRedBand > 0 && mGreenBand > 0 && mBlueBand > 0
163 && mAlphaBand < 1 );
164
165 QList<int> bands;
166 if ( mRedBand > 0 )
167 {
168 bands << mRedBand;
169 }
170 if ( mGreenBand > 0 )
171 {
172 bands << mGreenBand;
173 }
174 if ( mBlueBand > 0 )
175 {
176 bands << mBlueBand;
177 }
178 if ( bands.empty() )
179 {
180 // no need to draw anything if no band is set
181 // TODO:: we should probably return default color block
182 return outputBlock.release();
183 }
184
185 if ( mAlphaBand > 0 )
186 {
187 bands << mAlphaBand;
188 }
189
190 QMap<int, QgsRasterBlock *> bandBlocks;
191 QgsRasterBlock *defaultPointer = nullptr;
192 QList<int>::const_iterator bandIt = bands.constBegin();
193 for ( ; bandIt != bands.constEnd(); ++bandIt )
194 {
195 bandBlocks.insert( *bandIt, defaultPointer );
196 }
197
198 QgsRasterBlock *redBlock = nullptr;
199 QgsRasterBlock *greenBlock = nullptr;
200 QgsRasterBlock *blueBlock = nullptr;
201 QgsRasterBlock *alphaBlock = nullptr;
202
203 bandIt = bands.constBegin();
204 for ( ; bandIt != bands.constEnd(); ++bandIt )
205 {
206 bandBlocks[*bandIt] = mInput->block( *bandIt, extent, width, height, feedback );
207 if ( !bandBlocks[*bandIt] )
208 {
209 // We should free the allocated mem from block().
210 QgsDebugError( QStringLiteral( "No input band" ) );
211 --bandIt;
212 for ( ; bandIt != bands.constBegin(); --bandIt )
213 {
214 delete bandBlocks[*bandIt];
215 }
216 return outputBlock.release();
217 }
218 }
219
220 if ( mRedBand > 0 )
221 {
222 redBlock = bandBlocks[mRedBand];
223 }
224 if ( mGreenBand > 0 )
225 {
226 greenBlock = bandBlocks[mGreenBand];
227 }
228 if ( mBlueBand > 0 )
229 {
230 blueBlock = bandBlocks[mBlueBand];
231 }
232 if ( mAlphaBand > 0 )
233 {
234 alphaBlock = bandBlocks[mAlphaBand];
235 }
236
237 if ( !outputBlock->reset( Qgis::DataType::ARGB32_Premultiplied, width, height ) )
238 {
239 for ( int i = 0; i < bandBlocks.size(); i++ )
240 {
241 delete bandBlocks.value( i );
242 }
243 return outputBlock.release();
244 }
245
246 QRgb *outputBlockColorData = outputBlock->colorData();
247
248 // faster data access to data for the common case that input data are coming from RGB image with 8-bit bands
249 const bool hasByteRgb = ( redBlock && greenBlock && blueBlock && redBlock->dataType() == Qgis::DataType::Byte && greenBlock->dataType() == Qgis::DataType::Byte && blueBlock->dataType() == Qgis::DataType::Byte );
250 const quint8 *redData = nullptr, *greenData = nullptr, *blueData = nullptr;
251 if ( hasByteRgb )
252 {
253 redData = redBlock->byteData();
254 greenData = greenBlock->byteData();
255 blueData = blueBlock->byteData();
256 }
257
258 const QRgb myDefaultColor = renderColorForNodataPixel();
259
260 if ( fastDraw )
261 {
262 // By default RGB raster layers have contrast enhancement assigned and normally that requires us to take the slow
263 // route that applies the enhancement. However if the algorithm type is "no enhancement" and all input bands are byte-sized,
264 // no transform would be applied to the input values and we can take the fast route.
265 bool hasEnhancement;
266 if ( hasByteRgb )
267 {
268 hasEnhancement =
269 ( mRedContrastEnhancement && mRedContrastEnhancement->contrastEnhancementAlgorithm() != QgsContrastEnhancement::NoEnhancement ) ||
270 ( mGreenContrastEnhancement && mGreenContrastEnhancement->contrastEnhancementAlgorithm() != QgsContrastEnhancement::NoEnhancement ) ||
271 ( mBlueContrastEnhancement && mBlueContrastEnhancement->contrastEnhancementAlgorithm() != QgsContrastEnhancement::NoEnhancement );
272 }
273 else
274 {
275 hasEnhancement = mRedContrastEnhancement || mGreenContrastEnhancement || mBlueContrastEnhancement;
276 }
277 if ( hasEnhancement )
278 fastDraw = false;
279 }
280
281 const qgssize count = ( qgssize )width * height;
282 for ( qgssize i = 0; i < count; i++ )
283 {
284 if ( fastDraw ) //fast rendering if no transparency, stretching, color inversion, etc.
285 {
286 if ( hasByteRgb )
287 {
288 if ( redBlock->isNoData( i ) ||
289 greenBlock->isNoData( i ) ||
290 blueBlock->isNoData( i ) )
291 {
292 outputBlock->setColor( i, myDefaultColor );
293 }
294 else
295 {
296 outputBlockColorData[i] = qRgb( redData[i], greenData[i], blueData[i] );
297 }
298 }
299 else
300 {
301 bool redIsNoData = false;
302 bool greenIsNoData = false;
303 bool blueIsNoData = false;
304 int redVal = 0;
305 int greenVal = 0;
306 int blueVal = 0;
307
308 redVal = redBlock->valueAndNoData( i, redIsNoData );
309 // as soon as any channel has a no data value, don't do any more work -- the result will
310 // always be the nodata color!
311 if ( !redIsNoData )
312 greenVal = greenBlock->valueAndNoData( i, greenIsNoData );
313 if ( !redIsNoData && !greenIsNoData )
314 blueVal = blueBlock->valueAndNoData( i, blueIsNoData );
315
316 if ( redIsNoData ||
317 greenIsNoData ||
318 blueIsNoData )
319 {
320 outputBlock->setColor( i, myDefaultColor );
321 }
322 else
323 {
324 outputBlockColorData[i] = qRgb( redVal, greenVal, blueVal );
325 }
326 }
327 continue;
328 }
329
330 bool isNoData = false;
331 double redVal = 0;
332 double greenVal = 0;
333 double blueVal = 0;
334 if ( mRedBand > 0 )
335 {
336 redVal = redBlock->valueAndNoData( i, isNoData );
337 }
338 if ( !isNoData && mGreenBand > 0 )
339 {
340 greenVal = greenBlock->valueAndNoData( i, isNoData );
341 }
342 if ( !isNoData && mBlueBand > 0 )
343 {
344 blueVal = blueBlock->valueAndNoData( i, isNoData );
345 }
346 if ( isNoData )
347 {
348 outputBlock->setColor( i, myDefaultColor );
349 continue;
350 }
351
352 //apply default color if red, green or blue not in displayable range
353 if ( ( mRedContrastEnhancement && !mRedContrastEnhancement->isValueInDisplayableRange( redVal ) )
354 || ( mGreenContrastEnhancement && !mGreenContrastEnhancement->isValueInDisplayableRange( redVal ) )
355 || ( mBlueContrastEnhancement && !mBlueContrastEnhancement->isValueInDisplayableRange( redVal ) ) )
356 {
357 outputBlock->setColor( i, myDefaultColor );
358 continue;
359 }
360
361 //stretch color values
362 if ( mRedContrastEnhancement )
363 {
364 redVal = mRedContrastEnhancement->enhanceContrast( redVal );
365 }
366 if ( mGreenContrastEnhancement )
367 {
368 greenVal = mGreenContrastEnhancement->enhanceContrast( greenVal );
369 }
370 if ( mBlueContrastEnhancement )
371 {
372 blueVal = mBlueContrastEnhancement->enhanceContrast( blueVal );
373 }
374
375 //opacity
376 double currentOpacity = mOpacity;
378 {
379 currentOpacity *= mRasterTransparency->opacityForRgbValues( redVal, greenVal, blueVal );
380 }
381 if ( mAlphaBand > 0 )
382 {
383 const double alpha = alphaBlock->value( i );
384 if ( alpha == 0 )
385 {
386 outputBlock->setColor( i, myDefaultColor );
387 continue;
388 }
389 else
390 {
391 currentOpacity *= alpha / 255.0;
392 }
393 }
394
395 if ( qgsDoubleNear( currentOpacity, 1.0 ) )
396 {
397 outputBlock->setColor( i, qRgba( redVal, greenVal, blueVal, 255 ) );
398 }
399 else
400 {
401 outputBlock->setColor( i, qRgba( currentOpacity * redVal, currentOpacity * greenVal, currentOpacity * blueVal, currentOpacity * 255 ) );
402 }
403 }
404
405 //delete input blocks
406 QMap<int, QgsRasterBlock *>::const_iterator bandDelIt = bandBlocks.constBegin();
407 for ( ; bandDelIt != bandBlocks.constEnd(); ++bandDelIt )
408 {
409 delete bandDelIt.value();
410 }
411
412 return outputBlock.release();
413}
414
416{
417 return mRedContrastEnhancement.get();
418}
419
420void QgsMultiBandColorRenderer::writeXml( QDomDocument &doc, QDomElement &parentElem ) const
421{
422 if ( parentElem.isNull() )
423 {
424 return;
425 }
426
427 QDomElement rasterRendererElem = doc.createElement( QStringLiteral( "rasterrenderer" ) );
428 _writeXml( doc, rasterRendererElem );
429 rasterRendererElem.setAttribute( QStringLiteral( "redBand" ), mRedBand );
430 rasterRendererElem.setAttribute( QStringLiteral( "greenBand" ), mGreenBand );
431 rasterRendererElem.setAttribute( QStringLiteral( "blueBand" ), mBlueBand );
432
433 //contrast enhancement
434 if ( mRedContrastEnhancement )
435 {
436 QDomElement redContrastElem = doc.createElement( QStringLiteral( "redContrastEnhancement" ) );
437 mRedContrastEnhancement->writeXml( doc, redContrastElem );
438 rasterRendererElem.appendChild( redContrastElem );
439 }
440 if ( mGreenContrastEnhancement )
441 {
442 QDomElement greenContrastElem = doc.createElement( QStringLiteral( "greenContrastEnhancement" ) );
443 mGreenContrastEnhancement->writeXml( doc, greenContrastElem );
444 rasterRendererElem.appendChild( greenContrastElem );
445 }
446 if ( mBlueContrastEnhancement )
447 {
448 QDomElement blueContrastElem = doc.createElement( QStringLiteral( "blueContrastEnhancement" ) );
449 mBlueContrastEnhancement->writeXml( doc, blueContrastElem );
450 rasterRendererElem.appendChild( blueContrastElem );
451 }
452 parentElem.appendChild( rasterRendererElem );
453}
454
456{
457 QList<int> bandList;
458 if ( mRedBand != -1 )
459 {
460 bandList << mRedBand;
461 }
462 if ( mGreenBand != -1 )
463 {
464 bandList << mGreenBand;
465 }
466 if ( mBlueBand != -1 )
467 {
468 bandList << mBlueBand;
469 }
470 return bandList;
471}
472
473QList<QgsLayerTreeModelLegendNode *> QgsMultiBandColorRenderer::createLegendNodes( QgsLayerTreeLayer *nodeLayer )
474{
475 QList<QgsLayerTreeModelLegendNode *> res;
476 if ( mRedBand != -1 )
477 {
478 res << new QgsRasterSymbolLegendNode( nodeLayer, QColor( 255, 0, 0 ), displayBandName( mRedBand ) );
479 }
480 if ( mGreenBand != -1 )
481 {
482 res << new QgsRasterSymbolLegendNode( nodeLayer, QColor( 0, 255, 0 ), displayBandName( mGreenBand ) );
483 }
484 if ( mBlueBand != -1 )
485 {
486 res << new QgsRasterSymbolLegendNode( nodeLayer, QColor( 0, 0, 255 ), displayBandName( mBlueBand ) );
487 }
488
489 return res;
490}
491
492void QgsMultiBandColorRenderer::toSld( QDomDocument &doc, QDomElement &element, const QVariantMap &props ) const
493{
494 QgsSldExportContext context;
495 context.setExtraProperties( props );
496 toSld( doc, element, context );
497}
498
499bool QgsMultiBandColorRenderer::toSld( QDomDocument &doc, QDomElement &element, QgsSldExportContext &context ) const
500{
501 // create base structure
502 QgsRasterRenderer::toSld( doc, element, context );
503
504
505#if 0
506 // TODO: the following jumped code is necessary to avoid to export channelSelection in
507 // case it's set as default value. The drawback is that it's necessary to calc band
508 // statistics that can be really slow depending on dataProvider and rastr location.
509 // this is the reason this part of code is commented and the channelSelection is
510 // always exported.
511 //
512 // before to export check if the band combination and contrast setting are the
513 // default ones to avoid to export this tags
514 bool isDefaultCombination = true;
515 QList<int> defaultBandCombination( { 1, 2, 3 } );
516
517 isDefaultCombination = isDefaultCombination && ( usesBands() == defaultBandCombination );
518 isDefaultCombination = isDefaultCombination && (
519 mRedContrastEnhancement->contrastEnhancementAlgorithm() == QgsContrastEnhancement::StretchToMinimumMaximum &&
520 mGreenContrastEnhancement->contrastEnhancementAlgorithm() == QgsContrastEnhancement::StretchToMinimumMaximum &&
521 mBlueContrastEnhancement->contrastEnhancementAlgorithm() == QgsContrastEnhancement::StretchToMinimumMaximum
522 );
523 // compute raster statistics (slow) only if true the previous conditions
524 if ( isDefaultCombination )
525 {
526 QgsRasterBandStats statRed = bandStatistics( 1, QgsRasterBandStats::Min | QgsRasterBandStats::Max );
527 isDefaultCombination = isDefaultCombination && (
528 ( mRedContrastEnhancement->minimumValue() == statRed.minimumValue &&
529 mRedContrastEnhancement->maximumValue() == statRed.maximumValue )
530 );
531 }
532 if ( isDefaultCombination )
533 {
534 QgsRasterBandStats statGreen = bandStatistics( 2, QgsRasterBandStats::Min | QgsRasterBandStats::Max );
535 isDefaultCombination = isDefaultCombination && (
536 ( mGreenContrastEnhancement->minimumValue() == statGreen.minimumValue &&
537 mGreenContrastEnhancement->maximumValue() == statGreen.maximumValue )
538 );
539 }
540 if ( isDefaultCombination )
541 {
542 QgsRasterBandStats statBlue = bandStatistics( 3, QgsRasterBandStats::Min | QgsRasterBandStats::Max );
543 isDefaultCombination = isDefaultCombination && (
544 ( mBlueContrastEnhancement->minimumValue() == statBlue.minimumValue &&
545 mBlueContrastEnhancement->maximumValue() == statBlue.maximumValue )
546 );
547 }
548 if ( isDefaultCombination )
549 return;
550#endif
551
552 // look for RasterSymbolizer tag
553 QDomNodeList elements = element.elementsByTagName( QStringLiteral( "sld:RasterSymbolizer" ) );
554 if ( elements.size() == 0 )
555 return false;
556
557 // there SHOULD be only one
558 QDomElement rasterSymbolizerElem = elements.at( 0 ).toElement();
559
560 // add Channel Selection tags
561 // Need to insert channelSelection in the correct sequence as in SLD standard e.g.
562 // after opacity or geometry or as first element after sld:RasterSymbolizer
563 QDomElement channelSelectionElem = doc.createElement( QStringLiteral( "sld:ChannelSelection" ) );
564 elements = rasterSymbolizerElem.elementsByTagName( QStringLiteral( "sld:Opacity" ) );
565 if ( elements.size() != 0 )
566 {
567 rasterSymbolizerElem.insertAfter( channelSelectionElem, elements.at( 0 ) );
568 }
569 else
570 {
571 elements = rasterSymbolizerElem.elementsByTagName( QStringLiteral( "sld:Geometry" ) );
572 if ( elements.size() != 0 )
573 {
574 rasterSymbolizerElem.insertAfter( channelSelectionElem, elements.at( 0 ) );
575 }
576 else
577 {
578 rasterSymbolizerElem.insertBefore( channelSelectionElem, rasterSymbolizerElem.firstChild() );
579 }
580 }
581
582 // for each mapped band
583 static QStringList tags { QStringLiteral( "sld:RedChannel" ), QStringLiteral( "sld:GreenChannel" ), QStringLiteral( "sld:BlueChannel" ) };
584
585 QList<QgsContrastEnhancement *> contrastEnhancements;
586 contrastEnhancements.append( mRedContrastEnhancement.get() );
587 contrastEnhancements.append( mGreenContrastEnhancement.get() );
588 contrastEnhancements.append( mBlueContrastEnhancement.get() );
589
590 const QList<int> bands = usesBands();
591 QList<int>::const_iterator bandIt = bands.constBegin();
592 for ( int tagCounter = 0 ; bandIt != bands.constEnd(); ++bandIt, ++tagCounter )
593 {
594 if ( *bandIt < 0 )
595 continue;
596
597 QDomElement channelElem = doc.createElement( tags[ tagCounter ] );
598 channelSelectionElem.appendChild( channelElem );
599
600 // set band
601 QDomElement sourceChannelNameElem = doc.createElement( QStringLiteral( "sld:SourceChannelName" ) );
602 sourceChannelNameElem.appendChild( doc.createTextNode( QString::number( *bandIt ) ) );
603 channelElem.appendChild( sourceChannelNameElem );
604
605 // set ContrastEnhancement for each band
606 // NO ContrastEnhancement parameter for the entire bands is managed e.g.
607 // because min/max values can vary depending on band.
608 if ( contrastEnhancements[ tagCounter ] )
609 {
610 QDomElement contrastEnhancementElem = doc.createElement( QStringLiteral( "sld:ContrastEnhancement" ) );
611 contrastEnhancements[ tagCounter ]->toSld( doc, contrastEnhancementElem );
612 channelElem.appendChild( contrastEnhancementElem );
613 }
614 }
615 return true;
616}
617
618bool QgsMultiBandColorRenderer::refresh( const QgsRectangle &extent, const QList<double> &min, const QList<double> &max, bool forceRefresh )
619{
620 if ( !needsRefresh( extent ) && !forceRefresh )
621 {
622 return false;
623 }
624
625 bool refreshed = false;
626 if ( min.size() >= 3 && max.size() >= 3 )
627 {
629
630 if ( mRedContrastEnhancement && mRedContrastEnhancement->contrastEnhancementAlgorithm() != QgsContrastEnhancement::NoEnhancement &&
631 !std::isnan( min[0] ) && !std::isnan( max[0] ) )
632 {
633 mRedContrastEnhancement->setMinimumValue( min[0] );
634 mRedContrastEnhancement->setMaximumValue( max[0] );
635 refreshed = true;
636 }
637
638 if ( mGreenContrastEnhancement && mGreenContrastEnhancement->contrastEnhancementAlgorithm() != QgsContrastEnhancement::NoEnhancement &&
639 !std::isnan( min[1] ) && !std::isnan( max[1] ) )
640 {
641 mGreenContrastEnhancement->setMinimumValue( min[1] );
642 mGreenContrastEnhancement->setMaximumValue( max[1] );
643 refreshed = true;
644 }
645
646 if ( mBlueContrastEnhancement && mBlueContrastEnhancement->contrastEnhancementAlgorithm() != QgsContrastEnhancement::NoEnhancement &&
647 !std::isnan( min[2] ) && !std::isnan( max[2] ) )
648 {
649 mBlueContrastEnhancement->setMinimumValue( min[2] );
650 mBlueContrastEnhancement->setMaximumValue( max[2] );
651 refreshed = true;
652 }
653 }
654
655 return refreshed;
656}
QFlags< RasterRendererFlag > RasterRendererFlags
Flags which control behavior of raster renderers.
Definition qgis.h:1475
@ InternalLayerOpacityHandling
The renderer internally handles the raster layer's opacity, so the default layer level opacity handli...
DataType
Raster data types.
Definition qgis.h:351
@ ARGB32_Premultiplied
Color, alpha, red, green, blue, 4 bytes the same as QImage::Format_ARGB32_Premultiplied.
@ Byte
Eight bit unsigned integer (quint8)
Handles contrast enhancement and clipping.
@ StretchToMinimumMaximum
Linear histogram.
@ NoEnhancement
Default color scaling algorithm, no scaling is applied.
void readXml(const QDomElement &elem)
Layer tree node points to a map layer.
Renderer for multiband images with the color components.
bool refresh(const QgsRectangle &extent, const QList< double > &min, const QList< double > &max, bool forceRefresh=false) override
Refreshes the renderer according to the min and max values associated with the extent.
QgsMultiBandColorRenderer(QgsRasterInterface *input, int redBand, int greenBand, int blueBand, QgsContrastEnhancement *redEnhancement=nullptr, QgsContrastEnhancement *greenEnhancement=nullptr, QgsContrastEnhancement *blueEnhancement=nullptr)
Constructor for QgsMultiBandColorRenderer.
const QgsContrastEnhancement * greenContrastEnhancement() const
Returns the contrast enhancement to use for the green channel.
QgsRasterBlock * block(int bandNo, const QgsRectangle &extent, int width, int height, QgsRasterBlockFeedback *feedback=nullptr) override
Read block of data using given extent and size.
Q_DECL_DEPRECATED void toSld(QDomDocument &doc, QDomElement &element, const QVariantMap &props=QVariantMap()) const override
Used from subclasses to create SLD Rule elements following SLD v1.0 specs.
Qgis::RasterRendererFlags flags() const override
Returns flags which dictate renderer behavior.
int blueBand() const
Returns the band number for the blue channel.
~QgsMultiBandColorRenderer() override
const QgsContrastEnhancement * blueContrastEnhancement() const
Returns the contrast enhancement to use for the blue channel.
void setGreenContrastEnhancement(QgsContrastEnhancement *ce)
Sets the contrast enhancement to use for the green channel.
QList< int > usesBands() const override
Returns a list of band numbers used by the renderer.
QgsMultiBandColorRenderer * clone() const override
Clone itself, create deep copy.
void setBlueContrastEnhancement(QgsContrastEnhancement *ce)
Sets the contrast enhancement to use for the blue channel.
static QgsRasterRenderer * create(const QDomElement &elem, QgsRasterInterface *input)
void setRedContrastEnhancement(QgsContrastEnhancement *ce)
Sets the contrast enhancement to use for the red channel.
void writeXml(QDomDocument &doc, QDomElement &parentElem) const override
Write base class members to xml.
const QgsContrastEnhancement * redContrastEnhancement() const
Returns the contrast enhancement to use for the red channel.
int redBand() const
Returns the band number for the red channel.
QList< QgsLayerTreeModelLegendNode * > createLegendNodes(QgsLayerTreeLayer *nodeLayer) override
Creates a set of legend nodes representing the renderer.
int greenBand() const
Returns the band number for the green channel.
The RasterBandStats struct is a container for statistics about a single raster band.
double minimumValue
The minimum cell value in the raster band.
double maximumValue
The maximum cell value in the raster band.
Feedback object tailored for raster block reading.
Raster data container.
double value(int row, int column) const
Read a single value if type of block is numeric.
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.
bool isNoData(int row, int column) const
Checks if value at position is no data.
Qgis::DataType dataType() const
Returns data type.
const quint8 * byteData() const
Gives direct access to the raster block data.
Base class for processing filters like renderers, reprojector, resampler etc.
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.
virtual Qgis::DataType dataType(int bandNo) const =0
Returns data type for the band specified by number.
Q_DECL_DEPRECATED QgsRasterBandStats bandStatistics(int bandNo, int stats, const QgsRectangle &extent=QgsRectangle(), int sampleSize=0, QgsRasterBlockFeedback *feedback=nullptr)
Returns the band statistics.
QString displayBandName(int bandNumber) const
Generates a friendly, descriptive name for the specified bandNumber.
QgsRasterInterface * mInput
virtual QgsRectangle extent() const
Gets the extent of the interface.
virtual QgsRasterInterface * input() const
Current input.
Raster renderer pipe that applies colors to a raster.
double mOpacity
Global alpha value (0-1)
int mAlphaBand
Read alpha value from band.
QgsRectangle mLastRectangleUsedByRefreshContrastEnhancementIfNeeded
To save computations and possible infinite cycle of notifications.
QRgb renderColorForNodataPixel() const
Returns the color for the renderer to use to represent nodata pixels.
void _writeXml(QDomDocument &doc, QDomElement &rasterRendererElem) const
Write upper class info into rasterrenderer element (called by writeXml method of subclasses)
QgsRasterTransparency * mRasterTransparency
Raster transparency per color or value. Overwrites global alpha value.
bool usesTransparency() const
void copyCommonProperties(const QgsRasterRenderer *other, bool copyMinMaxOrigin=true)
Copies common properties like opacity / transparency data from other renderer.
bool needsRefresh(const QgsRectangle &extent) const
Checks if the renderer needs to be refreshed according to extent.
virtual Q_DECL_DEPRECATED void toSld(QDomDocument &doc, QDomElement &element, const QVariantMap &props=QVariantMap()) const
Used from subclasses to create SLD Rule elements following SLD v1.0 specs.
void readXml(const QDomElement &rendererElem) override
Sets base class members from xml. Usually called from create() methods of subclasses.
Implementation of legend node interface for displaying raster legend entries.
double opacityForRgbValues(double redValue, double greenValue, double blueValue) const
Returns the opacity (as a value from 0 to 1) for a set of RGB pixel values.
A rectangle specified with double values.
Holds SLD export options and other information related to SLD export of a QGIS layer style.
void setExtraProperties(const QVariantMap &properties)
Sets the open ended set of properties that can drive/inform the SLD encoding.
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:6806
bool qgsDoubleNear(double a, double b, double epsilon=4 *std::numeric_limits< double >::epsilon())
Compare two doubles (but allow some difference)
Definition qgis.h:6302
#define QgsDebugError(str)
Definition qgslogger.h:40