QGIS API Documentation  3.24.2-Tisler (13c1a02865)
qgspalettedrasterrenderer.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  qgspalettedrasterrenderer.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 "qgsrastertransparency.h"
20 #include "qgsrasterviewport.h"
21 #include "qgssymbollayerutils.h"
22 #include "qgsstyleentityvisitor.h"
23 #include "qgsmessagelog.h"
24 #include "qgsrasteriterator.h"
26 #include "qgscolorrampimpl.h"
27 
28 #include <QColor>
29 #include <QDomDocument>
30 #include <QDomElement>
31 #include <QImage>
32 #include <QVector>
33 #include <memory>
34 #include <set>
35 #include <QRegularExpression>
36 #include <QTextStream>
37 
38 const int QgsPalettedRasterRenderer::MAX_FLOAT_CLASSES = 65536;
39 
41  : QgsRasterRenderer( input, QStringLiteral( "paletted" ) )
42  , mBand( bandNumber )
43  , mClassData( classes )
44 {
45  updateArrays();
46 }
47 
49 {
50  QgsPalettedRasterRenderer *renderer = new QgsPalettedRasterRenderer( nullptr, mBand, mClassData );
51  if ( mSourceColorRamp )
52  renderer->setSourceColorRamp( mSourceColorRamp->clone() );
53 
54  renderer->copyCommonProperties( this );
55  return renderer;
56 }
57 
59 {
60  if ( elem.isNull() )
61  {
62  return nullptr;
63  }
64 
65  const int bandNumber = elem.attribute( QStringLiteral( "band" ), QStringLiteral( "-1" ) ).toInt();
66  ClassData classData;
67 
68  const QDomElement paletteElem = elem.firstChildElement( QStringLiteral( "colorPalette" ) );
69  if ( !paletteElem.isNull() )
70  {
71  const QDomNodeList paletteEntries = paletteElem.elementsByTagName( QStringLiteral( "paletteEntry" ) );
72 
73  QDomElement entryElem;
74  double value;
75 
76  for ( int i = 0; i < paletteEntries.size(); ++i )
77  {
78  QColor color;
79  QString label;
80  entryElem = paletteEntries.at( i ).toElement();
81  value = entryElem.attribute( QStringLiteral( "value" ), QStringLiteral( "0" ) ).toDouble();
82  color = QColor( entryElem.attribute( QStringLiteral( "color" ), QStringLiteral( "#000000" ) ) );
83  color.setAlpha( entryElem.attribute( QStringLiteral( "alpha" ), QStringLiteral( "255" ) ).toInt() );
84  label = entryElem.attribute( QStringLiteral( "label" ) );
85  QgsDebugMsgLevel( QStringLiteral( "Value: %1, label: %2, color: %3" ).arg( value ).arg( label, entryElem.attribute( QStringLiteral( "color" ) ) ), 4 );
86  classData << Class( value, color, label );
87  }
88  }
89 
90  QgsPalettedRasterRenderer *r = new QgsPalettedRasterRenderer( input, bandNumber, classData );
91  r->readXml( elem );
92 
93  // try to load color ramp (optional)
94  QDomElement sourceColorRampElem = elem.firstChildElement( QStringLiteral( "colorramp" ) );
95  if ( !sourceColorRampElem.isNull() && sourceColorRampElem.attribute( QStringLiteral( "name" ) ) == QLatin1String( "[source]" ) )
96  {
97  r->setSourceColorRamp( QgsSymbolLayerUtils::loadColorRamp( sourceColorRampElem ) );
98  }
99 
100  return r;
101 }
102 
104 {
105  return mClassData;
106 }
107 
108 QString QgsPalettedRasterRenderer::label( double idx ) const
109 {
110  const auto constMClassData = mClassData;
111  for ( const Class &c : constMClassData )
112  {
113  if ( c.value == idx )
114  return c.label;
115  }
116 
117  return QString();
118 }
119 
120 void QgsPalettedRasterRenderer::setLabel( double idx, const QString &label )
121 {
122  ClassData::iterator cIt = mClassData.begin();
123  for ( ; cIt != mClassData.end(); ++cIt )
124  {
125  if ( cIt->value == idx )
126  {
127  cIt->label = label;
128  return;
129  }
130  }
131 }
132 
133 QgsRasterBlock *QgsPalettedRasterRenderer::block( int, QgsRectangle const &extent, int width, int height, QgsRasterBlockFeedback *feedback )
134 {
135  std::unique_ptr< QgsRasterBlock > outputBlock( new QgsRasterBlock() );
136  if ( !mInput || mClassData.isEmpty() )
137  {
138  return outputBlock.release();
139  }
140 
141  const std::shared_ptr< QgsRasterBlock > inputBlock( mInput->block( mBand, extent, width, height, feedback ) );
142 
143  if ( !inputBlock || inputBlock->isEmpty() )
144  {
145  QgsDebugMsg( QStringLiteral( "No raster data!" ) );
146  return outputBlock.release();
147  }
148 
149  double currentOpacity = mOpacity;
150 
151  //rendering is faster without considering user-defined transparency
152  const bool hasTransparency = usesTransparency();
153 
154  std::shared_ptr< QgsRasterBlock > alphaBlock;
155 
156  if ( mAlphaBand > 0 && mAlphaBand != mBand )
157  {
158  alphaBlock.reset( mInput->block( mAlphaBand, extent, width, height, feedback ) );
159  if ( !alphaBlock || alphaBlock->isEmpty() )
160  {
161  return outputBlock.release();
162  }
163  }
164  else if ( mAlphaBand == mBand )
165  {
166  alphaBlock = inputBlock;
167  }
168 
169  if ( !outputBlock->reset( Qgis::DataType::ARGB32_Premultiplied, width, height ) )
170  {
171  return outputBlock.release();
172  }
173 
174  const QRgb myDefaultColor = renderColorForNodataPixel();
175 
176  //use direct data access instead of QgsRasterBlock::setValue
177  //because of performance
178  Q_ASSERT( outputBlock ); // to make cppcheck happy
179  unsigned int *outputData = ( unsigned int * )( outputBlock->bits() );
180 
181  const qgssize rasterSize = ( qgssize )width * height;
182  bool isNoData = false;
183  for ( qgssize i = 0; i < rasterSize; ++i )
184  {
185  const double value = inputBlock->valueAndNoData( i, isNoData );
186  if ( isNoData )
187  {
188  outputData[i] = myDefaultColor;
189  continue;
190  }
191  if ( !mColors.contains( value ) )
192  {
193  outputData[i] = myDefaultColor;
194  continue;
195  }
196 
197  if ( !hasTransparency )
198  {
199  outputData[i] = mColors.value( value );
200  }
201  else
202  {
203  currentOpacity = mOpacity;
204  if ( mRasterTransparency )
205  {
206  currentOpacity = mRasterTransparency->alphaValue( value, mOpacity * 255 ) / 255.0;
207  }
208  if ( mAlphaBand > 0 )
209  {
210  currentOpacity *= alphaBlock->value( i ) / 255.0;
211  }
212 
213  const QRgb c = mColors.value( value );
214  outputData[i] = qRgba( currentOpacity * qRed( c ), currentOpacity * qGreen( c ), currentOpacity * qBlue( c ), currentOpacity * qAlpha( c ) );
215  }
216  }
217 
218  return outputBlock.release();
219 }
220 
221 void QgsPalettedRasterRenderer::writeXml( QDomDocument &doc, QDomElement &parentElem ) const
222 {
223  if ( parentElem.isNull() )
224  {
225  return;
226  }
227 
228  QDomElement rasterRendererElem = doc.createElement( QStringLiteral( "rasterrenderer" ) );
229  _writeXml( doc, rasterRendererElem );
230 
231  rasterRendererElem.setAttribute( QStringLiteral( "band" ), mBand );
232  QDomElement colorPaletteElem = doc.createElement( QStringLiteral( "colorPalette" ) );
233  ClassData::const_iterator it = mClassData.constBegin();
234  for ( ; it != mClassData.constEnd(); ++it )
235  {
236  const QColor color = it->color;
237  QDomElement colorElem = doc.createElement( QStringLiteral( "paletteEntry" ) );
238  colorElem.setAttribute( QStringLiteral( "value" ), it->value );
239  colorElem.setAttribute( QStringLiteral( "color" ), color.name() );
240  colorElem.setAttribute( QStringLiteral( "alpha" ), color.alpha() );
241  if ( !it->label.isEmpty() )
242  {
243  colorElem.setAttribute( QStringLiteral( "label" ), it->label );
244  }
245  colorPaletteElem.appendChild( colorElem );
246  }
247  rasterRendererElem.appendChild( colorPaletteElem );
248 
249  // save source color ramp
250  if ( mSourceColorRamp )
251  {
252  const QDomElement colorRampElem = QgsSymbolLayerUtils::saveColorRamp( QStringLiteral( "[source]" ), mSourceColorRamp.get(), doc );
253  rasterRendererElem.appendChild( colorRampElem );
254  }
255 
256  parentElem.appendChild( rasterRendererElem );
257 }
258 
259 void QgsPalettedRasterRenderer::toSld( QDomDocument &doc, QDomElement &element, const QVariantMap &props ) const
260 {
261  // create base structure
262  QgsRasterRenderer::toSld( doc, element, props );
263 
264  // look for RasterSymbolizer tag
265  const QDomNodeList elements = element.elementsByTagName( QStringLiteral( "sld:RasterSymbolizer" ) );
266  if ( elements.size() == 0 )
267  return;
268 
269  // there SHOULD be only one
270  QDomElement rasterSymbolizerElem = elements.at( 0 ).toElement();
271 
272  // add Channel Selection tags
273  QDomElement channelSelectionElem = doc.createElement( QStringLiteral( "sld:ChannelSelection" ) );
274  rasterSymbolizerElem.appendChild( channelSelectionElem );
275 
276  // for the mapped band
277  QDomElement channelElem = doc.createElement( QStringLiteral( "sld:GrayChannel" ) );
278  channelSelectionElem.appendChild( channelElem );
279 
280  // set band
281  QDomElement sourceChannelNameElem = doc.createElement( QStringLiteral( "sld:SourceChannelName" ) );
282  sourceChannelNameElem.appendChild( doc.createTextNode( QString::number( band() ) ) );
283  channelElem.appendChild( sourceChannelNameElem );
284 
285  // add ColorMap tag
286  QDomElement colorMapElem = doc.createElement( QStringLiteral( "sld:ColorMap" ) );
287  colorMapElem.setAttribute( QStringLiteral( "type" ), QStringLiteral( "values" ) );
288  if ( this->classes().size() >= 255 )
289  colorMapElem.setAttribute( QStringLiteral( "extended" ), QStringLiteral( "true" ) );
290  rasterSymbolizerElem.appendChild( colorMapElem );
291 
292  // for each color set a ColorMapEntry tag nested into "sld:ColorMap" tag
293  // e.g. <ColorMapEntry color="#EEBE2F" quantity="-300" label="label" opacity="0"/>
294  const QList<QgsPalettedRasterRenderer::Class> classes = this->classes();
295  QList<QgsPalettedRasterRenderer::Class>::const_iterator classDataIt = classes.constBegin();
296  for ( ; classDataIt != classes.constEnd(); ++classDataIt )
297  {
298  QDomElement colorMapEntryElem = doc.createElement( QStringLiteral( "sld:ColorMapEntry" ) );
299  colorMapElem.appendChild( colorMapEntryElem );
300 
301  // set colorMapEntryElem attributes
302  colorMapEntryElem.setAttribute( QStringLiteral( "color" ), classDataIt->color.name() );
303  colorMapEntryElem.setAttribute( QStringLiteral( "quantity" ), QString::number( classDataIt->value ) );
304  colorMapEntryElem.setAttribute( QStringLiteral( "label" ), classDataIt->label );
305  if ( classDataIt->color.alphaF() != 1.0 )
306  {
307  colorMapEntryElem.setAttribute( QStringLiteral( "opacity" ), QString::number( classDataIt->color.alphaF() ) );
308  }
309  }
310 }
311 
313 {
314  if ( mSourceColorRamp )
315  {
316  QgsStyleColorRampEntity entity( mSourceColorRamp.get() );
317  if ( !visitor->visit( QgsStyleEntityVisitorInterface::StyleLeaf( &entity ) ) )
318  return false;
319  }
320 
321  return true;
322 }
323 
324 QList< QPair< QString, QColor > > QgsPalettedRasterRenderer::legendSymbologyItems() const
325 {
326  QList< QPair< QString, QColor > > symbolItems;
327  for ( const QgsPalettedRasterRenderer::Class &classData : mClassData )
328  {
329  const QString lab = classData.label.isEmpty() ? QString::number( classData.value ) : classData.label;
330  symbolItems << qMakePair( lab, classData.color );
331  }
332  return symbolItems;
333 }
334 
335 
336 QList<QgsLayerTreeModelLegendNode *> QgsPalettedRasterRenderer::createLegendNodes( QgsLayerTreeLayer *nodeLayer )
337 {
338  QList<QgsLayerTreeModelLegendNode *> res;
339 
340  const QString name = displayBandName( mBand );
341  if ( !name.isEmpty() )
342  {
343  res << new QgsSimpleLegendNode( nodeLayer, name );
344  }
345 
346  const QList< QPair< QString, QColor > > items = legendSymbologyItems();
347  res.reserve( res.size() + items.size() );
348  for ( const QPair< QString, QColor > &item : items )
349  {
350  res << new QgsRasterSymbolLegendNode( nodeLayer, item.second, item.first );
351  }
352 
353  return res;
354 }
355 
356 
358 {
359  QList<int> bandList;
360  if ( mBand != -1 )
361  {
362  bandList << mBand;
363  }
364  return bandList;
365 }
366 
368 {
369  mSourceColorRamp.reset( ramp );
370 }
371 
373 {
374  return mSourceColorRamp.get();
375 }
376 
377 QgsPalettedRasterRenderer::ClassData QgsPalettedRasterRenderer::colorTableToClassData( const QList<QgsColorRampShader::ColorRampItem> &table )
378 {
379  QList<QgsColorRampShader::ColorRampItem>::const_iterator colorIt = table.constBegin();
381  for ( ; colorIt != table.constEnd(); ++colorIt )
382  {
383  classes << QgsPalettedRasterRenderer::Class( colorIt->value, colorIt->color, colorIt->label );
384  }
385  return classes;
386 }
387 
389 {
391 
392  const QRegularExpression linePartRx( QStringLiteral( "[\\s,:]+" ) );
393 
394 #if QT_VERSION < QT_VERSION_CHECK(5, 15, 0)
395  const QStringList parts = string.split( '\n', QString::SkipEmptyParts );
396 #else
397  const QStringList parts = string.split( '\n', Qt::SkipEmptyParts );
398 #endif
399  for ( const QString &part : parts )
400  {
401 #if QT_VERSION < QT_VERSION_CHECK(5, 15, 0)
402  const QStringList lineParts = part.split( linePartRx, QString::SkipEmptyParts );
403 #else
404  const QStringList lineParts = part.split( linePartRx, Qt::SkipEmptyParts );
405 #endif
406  bool ok = false;
407  switch ( lineParts.count() )
408  {
409  case 1:
410  {
411  const int value = lineParts.at( 0 ).toInt( &ok );
412  if ( !ok )
413  continue;
414 
415  classes << Class( value );
416  break;
417  }
418 
419  case 2:
420  {
421  const int value = lineParts.at( 0 ).toInt( &ok );
422  if ( !ok )
423  continue;
424 
425  const QColor c( lineParts.at( 1 ) );
426 
427  classes << Class( value, c );
428  break;
429  }
430 
431  default:
432  {
433  if ( lineParts.count() < 4 )
434  continue;
435 
436  const int value = lineParts.at( 0 ).toInt( &ok );
437  if ( !ok )
438  continue;
439 
440  bool rOk = false;
441  const double r = lineParts.at( 1 ).toDouble( &rOk );
442  bool gOk = false;
443  const double g = lineParts.at( 2 ).toDouble( &gOk );
444  bool bOk = false;
445  const double b = lineParts.at( 3 ).toDouble( &bOk );
446 
447  QColor c;
448  if ( rOk && gOk && bOk )
449  {
450  c = QColor( r, g, b );
451  }
452 
453  if ( lineParts.count() >= 5 )
454  {
455  const double alpha = lineParts.at( 4 ).toDouble( &ok );
456  if ( ok )
457  c.setAlpha( alpha );
458  }
459 
460  QString label;
461  if ( lineParts.count() > 5 )
462  {
463  label = lineParts.mid( 5 ).join( ' ' );
464  }
465 
466  classes << Class( value, c, label );
467  break;
468  }
469  }
470 
471  }
472  return classes;
473 }
474 
476 {
477  QFile inputFile( path );
478  QString input;
479  if ( inputFile.open( QIODevice::ReadOnly ) )
480  {
481  QTextStream in( &inputFile );
482  input = in.readAll();
483  inputFile.close();
484  }
485  return classDataFromString( input );
486 }
487 
489 {
490  QStringList out;
491  // must be sorted
493  std::sort( cd.begin(), cd.end(), []( const Class & a, const Class & b ) -> bool
494  {
495  return a.value < b.value;
496  } );
497 
498  const auto constCd = cd;
499  for ( const Class &c : constCd )
500  {
501  out << QStringLiteral( "%1 %2 %3 %4 %5 %6" ).arg( c.value ).arg( c.color.red() )
502  .arg( c.color.green() ).arg( c.color.blue() ).arg( c.color.alpha() ).arg( c.label );
503  }
504  return out.join( '\n' );
505 }
506 
508 {
509  if ( !raster )
510  return ClassData();
511 
512  ClassData data;
513 
514  if ( bandNumber > 0 && bandNumber <= raster->bandCount() )
515  {
516  qlonglong numClasses = 0;
517 
518  if ( feedback )
519  feedback->setProgress( 0 );
520 
521  // Collect unique values for float rasters
522  if ( raster->dataType( bandNumber ) == Qgis::DataType::Float32 || raster->dataType( bandNumber ) == Qgis::DataType::Float64 )
523  {
524 
525  if ( feedback && feedback->isCanceled() )
526  {
527  return data;
528  }
529 
530  std::set<double> values;
531 
534 
535  QgsRasterIterator iter( raster );
536  iter.startRasterRead( bandNumber, raster->xSize(), raster->ySize(), raster->extent(), feedback );
537 
538  const int nbBlocksWidth = static_cast< int >( std::ceil( 1.0 * raster->xSize() / maxWidth ) );
539  const int nbBlocksHeight = static_cast< int >( std::ceil( 1.0 * raster->ySize() / maxHeight ) );
540  const int nbBlocks = nbBlocksWidth * nbBlocksHeight;
541 
542  int iterLeft = 0;
543  int iterTop = 0;
544  int iterCols = 0;
545  int iterRows = 0;
546  std::unique_ptr< QgsRasterBlock > rasterBlock;
547  QgsRectangle blockExtent;
548  bool isNoData = false;
549  while ( iter.readNextRasterPart( bandNumber, iterCols, iterRows, rasterBlock, iterLeft, iterTop, &blockExtent ) )
550  {
551  if ( feedback )
552  feedback->setProgress( 100 * ( ( iterTop / maxHeight * nbBlocksWidth ) + iterLeft / maxWidth ) / nbBlocks );
553 
554  if ( feedback && feedback->isCanceled() )
555  break;
556 
557  for ( int row = 0; row < iterRows; row++ )
558  {
559  if ( feedback && feedback->isCanceled() )
560  break;
561 
562  for ( int column = 0; column < iterCols; column++ )
563  {
564  if ( feedback && feedback->isCanceled() )
565  break;
566 
567  const double currentValue = rasterBlock->valueAndNoData( row, column, isNoData );
568  if ( numClasses >= MAX_FLOAT_CLASSES )
569  {
570  QgsMessageLog::logMessage( QStringLiteral( "Number of classes exceeded maximum (%1)." ).arg( MAX_FLOAT_CLASSES ), QStringLiteral( "Raster" ) );
571  break;
572  }
573  if ( !isNoData && values.find( currentValue ) == values.end() )
574  {
575  values.insert( currentValue );
576  data.push_back( Class( currentValue, QColor(), QLocale().toString( currentValue ) ) );
577  numClasses++;
578  }
579  }
580  }
581  }
582  // must be sorted
583  std::sort( data.begin(), data.end(), []( const Class & a, const Class & b ) -> bool
584  {
585  return a.value < b.value;
586  } );
587  }
588  else
589  {
590  // get min and max value from raster
591  const QgsRasterBandStats stats = raster->bandStatistics( bandNumber, QgsRasterBandStats::Min | QgsRasterBandStats::Max, QgsRectangle(), 0, feedback );
592  if ( feedback && feedback->isCanceled() )
593  return ClassData();
594 
595  const double min = stats.minimumValue;
596  const double max = stats.maximumValue;
597  // need count of every individual value
598  const int bins = std::ceil( max - min ) + 1;
599  if ( bins <= 0 )
600  return ClassData();
601 
602  const QgsRasterHistogram histogram = raster->histogram( bandNumber, bins, min, max, QgsRectangle(), 0, false, feedback );
603  if ( feedback && feedback->isCanceled() )
604  return ClassData();
605 
606  const double interval = ( histogram.maximum - histogram.minimum + 1 ) / histogram.binCount;
607  double currentValue = histogram.minimum;
608  for ( int idx = 0; idx < histogram.binCount; ++idx )
609  {
610  const int count = histogram.histogramVector.at( idx );
611  if ( count > 0 )
612  {
613  data << Class( currentValue, QColor(), QLocale().toString( currentValue ) );
614  numClasses++;
615  }
616  currentValue += interval;
617  }
618  }
619 
620  // assign colors from ramp
621  if ( ramp && numClasses > 0 )
622  {
623  int i = 0;
624 
625  if ( QgsRandomColorRamp *randomRamp = dynamic_cast<QgsRandomColorRamp *>( ramp ) )
626  {
627  //ramp is a random colors ramp, so inform it of the total number of required colors
628  //this allows the ramp to pregenerate a set of visually distinctive colors
629  randomRamp->setTotalColorCount( data.count() );
630  }
631 
632  if ( numClasses > 1 )
633  numClasses -= 1; //avoid duplicate first color
634 
635  QgsPalettedRasterRenderer::ClassData::iterator cIt = data.begin();
636  for ( ; cIt != data.end(); ++cIt )
637  {
638  if ( feedback )
639  {
640  // Show no less than 1%, then the max between class fill and real progress
641  feedback->setProgress( std::max<int>( 1, 100 * ( i + 1 ) / numClasses ) );
642  }
643  cIt->color = ramp->color( i / static_cast<double>( numClasses ) );
644  i++;
645  }
646  }
647  }
648  return data;
649 }
650 
651 void QgsPalettedRasterRenderer::updateArrays()
652 {
653  mColors.clear();
654  ClassData::const_iterator it = mClassData.constBegin();
655  for ( ; it != mClassData.constEnd(); ++it )
656  {
657  mColors[it->value] = qPremultiply( it->color.rgba() );
658  }
659 }
@ Float32
Thirty two bit floating point (float)
@ ARGB32_Premultiplied
Color, alpha, red, green, blue, 4 bytes the same as QImage::Format_ARGB32_Premultiplied.
@ Float64
Sixty four bit floating point (double)
Abstract base class for color ramps.
Definition: qgscolorramp.h:30
virtual QColor color(double value) const =0
Returns the color corresponding to a specified value.
bool isCanceled() const SIP_HOLDGIL
Tells whether the operation has been canceled already.
Definition: qgsfeedback.h:54
void setProgress(double progress)
Sets the current progress for the feedback object.
Definition: qgsfeedback.h:63
Layer tree node points to a map layer.
static void logMessage(const QString &message, const QString &tag=QString(), Qgis::MessageLevel level=Qgis::MessageLevel::Warning, bool notifyUser=true)
Adds a message to the log instance (and creates it if necessary).
Renderer for paletted raster images.
int band() const
Returns the raster band used for rendering the raster.
QgsRasterBlock * block(int bandNo, const QgsRectangle &extent, int width, int height, QgsRasterBlockFeedback *feedback=nullptr) override
Read block of data using given extent and size.
QList< QgsLayerTreeModelLegendNode * > createLegendNodes(QgsLayerTreeLayer *nodeLayer) override
Creates a set of legend nodes representing the renderer.
QgsColorRamp * sourceColorRamp() const
Gets the source color ramp.
static QgsPalettedRasterRenderer::ClassData classDataFromString(const QString &string)
Converts a string containing a color table or class data to to paletted renderer class data.
QString label(double idx) const
Returns optional category label.
void setSourceColorRamp(QgsColorRamp *ramp)
Set the source color ramp.
QList< int > usesBands() const override
Returns a list of band numbers used by the renderer.
void writeXml(QDomDocument &doc, QDomElement &parentElem) const override
Write base class members to xml.
QList< QgsPalettedRasterRenderer::Class > ClassData
Map of value to class properties.
bool accept(QgsStyleEntityVisitorInterface *visitor) const override
Accepts the specified symbology visitor, causing it to visit all symbols associated with the renderer...
static QgsPalettedRasterRenderer::ClassData classDataFromFile(const QString &path)
Opens a color table file and returns corresponding paletted renderer class data.
static QgsRasterRenderer * create(const QDomElement &elem, QgsRasterInterface *input)
static QgsPalettedRasterRenderer::ClassData colorTableToClassData(const QList< QgsColorRampShader::ColorRampItem > &table)
Converts a raster color table to paletted renderer class data.
ClassData classes() const
Returns a map of value to classes (colors) used by the renderer.
QList< QPair< QString, QColor > > legendSymbologyItems() const override
Returns symbology items if provided by renderer.
QgsPalettedRasterRenderer * clone() const override
Clone itself, create deep copy.
void setLabel(double idx, const QString &label)
Set category label.
static QgsPalettedRasterRenderer::ClassData classDataFromRaster(QgsRasterInterface *raster, int bandNumber, QgsColorRamp *ramp=nullptr, QgsRasterBlockFeedback *feedback=nullptr)
Generates class data from a raster, for the specified bandNumber.
static QString classDataToString(const QgsPalettedRasterRenderer::ClassData &classes)
Converts classes to a string representation, using the .clr/gdal color table file format.
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.
QgsPalettedRasterRenderer(QgsRasterInterface *input, int bandNumber, const ClassData &classes)
Constructor for QgsPalettedRasterRenderer.
Totally random color ramp.
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.
The QgsRasterHistogram is a container for histogram of a single raster band.
double minimum
The minimum histogram value.
double maximum
The maximum histogram value.
QgsRasterHistogram::HistogramVector histogramVector
Stores the histogram for a given layer.
int binCount
Number of bins (intervals,buckets) in histogram.
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.
virtual QgsRasterInterface * input() const
Current input.
virtual int xSize() const
Gets raster size.
virtual QgsRasterBandStats bandStatistics(int bandNo, int stats=QgsRasterBandStats::All, 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 int ySize() const
virtual QgsRectangle extent() const
Gets the extent of the interface.
virtual QgsRasterHistogram histogram(int bandNo, int binCount=0, double minimum=std::numeric_limits< double >::quiet_NaN(), double maximum=std::numeric_limits< double >::quiet_NaN(), const QgsRectangle &extent=QgsRectangle(), int sampleSize=0, bool includeOutOfRange=false, QgsRasterBlockFeedback *feedback=nullptr)
Returns a band histogram.
Iterator for sequentially processing raster cells.
static const int DEFAULT_MAXIMUM_TILE_WIDTH
Default maximum tile width.
bool readNextRasterPart(int bandNumber, int &nCols, int &nRows, QgsRasterBlock **block, int &topLeftCol, int &topLeftRow)
Fetches next part of raster data, caller takes ownership of the block and caller should delete the bl...
static const int DEFAULT_MAXIMUM_TILE_HEIGHT
Default maximum tile height.
void startRasterRead(int bandNumber, qgssize nCols, qgssize nRows, const QgsRectangle &extent, QgsRasterBlockFeedback *feedback=nullptr)
Start reading of raster band.
Raster renderer pipe that applies colors to a raster.
double mOpacity
Global alpha value (0-1)
int mAlphaBand
Read alpha value from band.
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)
int bandCount() const override
Gets number of bands.
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.
virtual 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.
int alphaValue(double value, int globalTransparency=255) const
Returns the transparency value for a single value pixel.
A rectangle specified with double values.
Definition: qgsrectangle.h:42
Implementation of legend node interface for displaying arbitrary label with icon.
A color ramp entity for QgsStyle databases.
Definition: qgsstyle.h:1254
An interface for classes which can visit style entity (e.g.
virtual bool visit(const QgsStyleEntityVisitorInterface::StyleLeaf &entity)
Called when the visitor will visit a style entity.
static QgsColorRamp * loadColorRamp(QDomElement &element)
Creates a color ramp from the settings encoded in an XML element.
static QDomElement saveColorRamp(const QString &name, QgsColorRamp *ramp, QDomDocument &doc)
Encodes a color ramp's settings to an XML element.
As part of the API refactoring and improvements which landed in the Processing API was substantially reworked from the x version This was done in order to allow much of the underlying Processing framework to be ported into c
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:2036
#define QgsDebugMsgLevel(str, level)
Definition: qgslogger.h:39
#define QgsDebugMsg(str)
Definition: qgslogger.h:38
Properties of a single value class.
Contains information relating to the style entity currently being visited.