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