QGIS API Documentation  2.99.0-Master (08ee180)
qgsrasterlayer.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  qgsrasterlayer.cpp - description
3  -------------------
4 begin : Sat Jun 22 2002
5 copyright : (C) 2003 by Tim Sutton, Steve Halasz and Gary E.Sherman
6 email : tim at linfiniti.com
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 #include "qgsapplication.h"
19 #include "qgscolorrampshader.h"
21 #include "qgscoordinatetransform.h"
22 #include "qgsdatasourceuri.h"
23 #include "qgshuesaturationfilter.h"
24 #include "qgslogger.h"
25 #include "qgsmaplayerlegend.h"
26 #include "qgsmaplayerregistry.h"
27 #include "qgsmaptopixel.h"
28 #include "qgsmessagelog.h"
30 #include "qgspainting.h"
33 #include "qgsproviderregistry.h"
34 #include "qgsrasterdataprovider.h"
35 #include "qgsrasterdrawer.h"
36 #include "qgsrasteriterator.h"
37 #include "qgsrasterlayer.h"
38 #include "qgsrasterlayerrenderer.h"
39 #include "qgsrasterprojector.h"
40 #include "qgsrasterrange.h"
43 #include "qgsrastershader.h"
44 #include "qgsrectangle.h"
45 #include "qgsrendercontext.h"
49 
50 #include <cmath>
51 #include <cstdio>
52 #include <limits>
53 #include <typeinfo>
54 
55 #include <QApplication>
56 #include <QCursor>
57 #include <QDomElement>
58 #include <QDomNode>
59 #include <QFile>
60 #include <QFileInfo>
61 #include <QFont>
62 #include <QFontMetrics>
63 #include <QFrame>
64 #include <QImage>
65 #include <QLabel>
66 #include <QLibrary>
67 #include <QList>
68 #include <QMatrix>
69 #include <QMessageBox>
70 #include <QPainter>
71 #include <QPixmap>
72 #include <QRegExp>
73 #include <QSettings>
74 #include <QSlider>
75 #include <QTime>
76 
77 // typedefs for provider plugin functions of interest
78 typedef bool isvalidrasterfilename_t( QString const & theFileNameQString, QString & retErrMsg );
79 
80 #define ERR(message) QGS_ERROR_MESSAGE(message,"Raster layer")
81 
82 const double QgsRasterLayer::CUMULATIVE_CUT_LOWER = 0.02;
83 const double QgsRasterLayer::CUMULATIVE_CUT_UPPER = 0.98;
84 const double QgsRasterLayer::SAMPLE_SIZE = 250000;
85 
87  : QgsMapLayer( RasterLayer )
88  , QSTRING_NOT_SET( QStringLiteral( "Not Set" ) )
89  , TRSTRING_NOT_SET( tr( "Not Set" ) )
90  , mDataProvider( nullptr )
91 {
92  init();
93  mValid = false;
94 }
95 
97  const QString& path,
98  const QString& baseName,
99  bool loadDefaultStyleFlag )
100  : QgsMapLayer( RasterLayer, baseName, path )
101  , QSTRING_NOT_SET( QStringLiteral( "Not Set" ) )
102  , TRSTRING_NOT_SET( tr( "Not Set" ) )
103  , mDataProvider( nullptr )
104 {
105  QgsDebugMsgLevel( "Entered", 4 );
106 
107  // TODO, call constructor with provider key
108  init();
109  setDataProvider( QStringLiteral( "gdal" ) );
110  if ( !mValid ) return;
111 
112  bool defaultLoadedFlag = false;
113  if ( mValid && loadDefaultStyleFlag )
114  {
115  loadDefaultStyle( defaultLoadedFlag );
116  }
117  if ( !defaultLoadedFlag )
118  {
120  }
121  return;
122 } // QgsRasterLayer ctor
123 
128 QgsRasterLayer::QgsRasterLayer( const QString & uri,
129  const QString & baseName,
130  const QString & providerKey,
131  bool loadDefaultStyleFlag )
132  : QgsMapLayer( RasterLayer, baseName, uri )
133  // Constant that signals property not used.
134  , QSTRING_NOT_SET( QStringLiteral( "Not Set" ) )
135  , TRSTRING_NOT_SET( tr( "Not Set" ) )
136  , mDataProvider( nullptr )
137  , mProviderKey( providerKey )
138 {
139  QgsDebugMsgLevel( "Entered", 4 );
140  init();
141  setDataProvider( providerKey );
142  if ( !mValid ) return;
143 
144  // load default style
145  bool defaultLoadedFlag = false;
146  if ( mValid && loadDefaultStyleFlag )
147  {
148  loadDefaultStyle( defaultLoadedFlag );
149  }
150  if ( !defaultLoadedFlag )
151  {
153  }
154 
155  // TODO: Connect signals from the dataprovider to the qgisapp
156 
157  emit statusChanged( tr( "QgsRasterLayer created" ) );
158 } // QgsRasterLayer ctor
159 
161 {
162  mValid = false;
163  // Note: provider and other interfaces are owned and deleted by pipe
164 }
165 
167 //
168 // Static Methods and members
169 //
171 
175 bool QgsRasterLayer::isValidRasterFileName( const QString& theFileNameQString, QString& retErrMsg )
176 {
177  isvalidrasterfilename_t *pValid = reinterpret_cast< isvalidrasterfilename_t * >( cast_to_fptr( QgsProviderRegistry::instance()->function( "gdal", "isValidRasterFileName" ) ) );
178  if ( ! pValid )
179  {
180  QgsDebugMsg( "Could not resolve isValidRasterFileName in gdal provider library" );
181  return false;
182  }
183 
184  bool myIsValid = pValid( theFileNameQString, retErrMsg );
185  return myIsValid;
186 }
187 
188 bool QgsRasterLayer::isValidRasterFileName( QString const & theFileNameQString )
189 {
190  QString retErrMsg;
191  return isValidRasterFileName( theFileNameQString, retErrMsg );
192 }
193 
194 QDateTime QgsRasterLayer::lastModified( QString const & name )
195 {
196  QgsDebugMsgLevel( "name=" + name, 4 );
197  QDateTime t;
198 
199  QFileInfo fi( name );
200 
201  // Is it file?
202  if ( !fi.exists() )
203  return t;
204 
205  t = fi.lastModified();
206 
207  QgsDebugMsgLevel( "last modified = " + t.toString(), 4 );
208 
209  return t;
210 }
211 
212 // typedef for the QgsDataProvider class factory
213 typedef QgsDataProvider * classFactoryFunction_t( const QString * );
214 
216 //
217 // Non Static Public methods
218 //
220 
222 {
223  if ( !mDataProvider ) return 0;
224  return mDataProvider->bandCount();
225 }
226 
227 QString QgsRasterLayer::bandName( int theBandNo ) const
228 {
229  return dataProvider()->generateBandName( theBandNo );
230 }
231 
232 void QgsRasterLayer::setRendererForDrawingStyle( QgsRaster::DrawingStyle theDrawingStyle )
233 {
234  setRenderer( QgsRasterRendererRegistry::instance()->defaultRendererForDrawingStyle( theDrawingStyle, mDataProvider ) );
235 }
236 
241 {
242  return mDataProvider;
243 }
244 
249 {
250  return mDataProvider;
251 }
252 
254 {
255  if ( mDataProvider )
256  {
257  mDataProvider->reloadData();
258  }
259 }
260 
262 {
263  return new QgsRasterLayerRenderer( this, rendererContext );
264 }
265 
266 
267 void QgsRasterLayer::draw( QPainter * theQPainter,
268  QgsRasterViewPort * theRasterViewPort,
269  const QgsMapToPixel* theQgsMapToPixel )
270 {
271  QgsDebugMsgLevel( " 3 arguments", 4 );
272  QTime time;
273  time.start();
274  //
275  //
276  // The goal here is to make as many decisions as possible early on (outside of the rendering loop)
277  // so that we can maximise performance of the rendering process. So now we check which drawing
278  // procedure to use :
279  //
280 
281  QgsRasterProjector *projector = mPipe.projector();
282 
283  // TODO add a method to interface to get provider and get provider
284  // params in QgsRasterProjector
285  if ( projector )
286  {
287  projector->setCrs( theRasterViewPort->mSrcCRS, theRasterViewPort->mDestCRS, theRasterViewPort->mSrcDatumTransform, theRasterViewPort->mDestDatumTransform );
288  }
289 
290  // Drawer to pipe?
291  QgsRasterIterator iterator( mPipe.last() );
292  QgsRasterDrawer drawer( &iterator );
293  drawer.draw( theQPainter, theRasterViewPort, theQgsMapToPixel );
294 
295  QgsDebugMsgLevel( QString( "total raster draw time (ms): %1" ).arg( time.elapsed(), 5 ), 4 );
296 } //end of draw method
297 
299 {
300  QList< QPair< QString, QColor > > symbolList;
302  if ( renderer )
303  {
304  renderer->legendSymbologyItems( symbolList );
305  }
306  return symbolList;
307 }
308 
310 {
311  QgsRasterDataProvider* provider = const_cast< QgsRasterDataProvider* >( mDataProvider );
312  QString myMetadata;
313  myMetadata += "<p class=\"glossy\">" + tr( "Driver" ) + "</p>\n";
314  myMetadata += QLatin1String( "<p>" );
315  myMetadata += mDataProvider->description();
316  myMetadata += QLatin1String( "</p>\n" );
317 
318  // Insert provider-specific (e.g. WMS-specific) metadata
319  // crashing
320  myMetadata += mDataProvider->metadata();
321 
322  myMetadata += QLatin1String( "<p class=\"glossy\">" );
323  myMetadata += tr( "No Data Value" );
324  myMetadata += QLatin1String( "</p>\n" );
325  myMetadata += QLatin1String( "<p>" );
326  // TODO: all bands
327  if ( mDataProvider->sourceHasNoDataValue( 1 ) )
328  {
329  myMetadata += QString::number( mDataProvider->sourceNoDataValue( 1 ) );
330  }
331  else
332  {
333  myMetadata += '*' + tr( "NoDataValue not set" ) + '*';
334  }
335  myMetadata += QLatin1String( "</p>\n" );
336 
337  myMetadata += QLatin1String( "</p>\n" );
338  myMetadata += QLatin1String( "<p class=\"glossy\">" );
339  myMetadata += tr( "Data Type" );
340  myMetadata += QLatin1String( "</p>\n" );
341  myMetadata += QLatin1String( "<p>" );
342  //just use the first band
343  switch ( mDataProvider->sourceDataType( 1 ) )
344  {
345  case Qgis::Byte:
346  myMetadata += tr( "Byte - Eight bit unsigned integer" );
347  break;
348  case Qgis::UInt16:
349  myMetadata += tr( "UInt16 - Sixteen bit unsigned integer " );
350  break;
351  case Qgis::Int16:
352  myMetadata += tr( "Int16 - Sixteen bit signed integer " );
353  break;
354  case Qgis::UInt32:
355  myMetadata += tr( "UInt32 - Thirty two bit unsigned integer " );
356  break;
357  case Qgis::Int32:
358  myMetadata += tr( "Int32 - Thirty two bit signed integer " );
359  break;
360  case Qgis::Float32:
361  myMetadata += tr( "Float32 - Thirty two bit floating point " );
362  break;
363  case Qgis::Float64:
364  myMetadata += tr( "Float64 - Sixty four bit floating point " );
365  break;
366  case Qgis::CInt16:
367  myMetadata += tr( "CInt16 - Complex Int16 " );
368  break;
369  case Qgis::CInt32:
370  myMetadata += tr( "CInt32 - Complex Int32 " );
371  break;
372  case Qgis::CFloat32:
373  myMetadata += tr( "CFloat32 - Complex Float32 " );
374  break;
375  case Qgis::CFloat64:
376  myMetadata += tr( "CFloat64 - Complex Float64 " );
377  break;
378  default:
379  myMetadata += tr( "Could not determine raster data type." );
380  }
381  myMetadata += QLatin1String( "</p>\n" );
382 
383  myMetadata += QLatin1String( "<p class=\"glossy\">" );
384  myMetadata += tr( "Pyramid overviews" );
385  myMetadata += QLatin1String( "</p>\n" );
386  myMetadata += QLatin1String( "<p>" );
387 
388  myMetadata += QLatin1String( "<p class=\"glossy\">" );
389  myMetadata += tr( "Layer Spatial Reference System" );
390  myMetadata += QLatin1String( "</p>\n" );
391  myMetadata += QLatin1String( "<p>" );
392  myMetadata += crs().toProj4();
393  myMetadata += QLatin1String( "</p>\n" );
394 
395  myMetadata += QLatin1String( "<p class=\"glossy\">" );
396  myMetadata += tr( "Layer Extent (layer original source projection)" );
397  myMetadata += QLatin1String( "</p>\n" );
398  myMetadata += QLatin1String( "<p>" );
399  myMetadata += mDataProvider->extent().toString();
400  myMetadata += QLatin1String( "</p>\n" );
401 
402  // output coordinate system
403  // TODO: this is not related to layer, to be removed? [MD]
404 #if 0
405  myMetadata += "<tr><td class=\"glossy\">";
406  myMetadata += tr( "Project Spatial Reference System" );
407  myMetadata += "</p>\n";
408  myMetadata += "<p>";
409  myMetadata += mCoordinateTransform->destCRS().toProj4();
410  myMetadata += "</p>\n";
411 #endif
412 
413  //
414  // Add the stats for each band to the output table
415  //
416  int myBandCountInt = bandCount();
417  for ( int myIteratorInt = 1; myIteratorInt <= myBandCountInt; ++myIteratorInt )
418  {
419  QgsDebugMsgLevel( "Raster properties : checking if band " + QString::number( myIteratorInt ) + " has stats? ", 4 );
420  //band name
421  myMetadata += QLatin1String( "<p class=\"glossy\">\n" );
422  myMetadata += tr( "Band" );
423  myMetadata += QLatin1String( "</p>\n" );
424  myMetadata += QLatin1String( "<p>" );
425  myMetadata += bandName( myIteratorInt );
426  myMetadata += QLatin1String( "</p>\n" );
427  //band number
428  myMetadata += QLatin1String( "<p>" );
429  myMetadata += tr( "Band No" );
430  myMetadata += QLatin1String( "</p>\n" );
431  myMetadata += QLatin1String( "<p>\n" );
432  myMetadata += QString::number( myIteratorInt );
433  myMetadata += QLatin1String( "</p>\n" );
434 
435  //check if full stats for this layer have already been collected
436  if ( !provider->hasStatistics( myIteratorInt ) ) //not collected
437  {
438  QgsDebugMsgLevel( ".....no", 4 );
439 
440  myMetadata += QLatin1String( "<p>" );
441  myMetadata += tr( "No Stats" );
442  myMetadata += QLatin1String( "</p>\n" );
443  myMetadata += QLatin1String( "<p>\n" );
444  myMetadata += tr( "No stats collected yet" );
445  myMetadata += QLatin1String( "</p>\n" );
446  }
447  else // collected - show full detail
448  {
449  QgsDebugMsgLevel( ".....yes", 4 );
450 
451  QgsRasterBandStats myRasterBandStats = provider->bandStatistics( myIteratorInt );
452  //Min Val
453  myMetadata += QLatin1String( "<p>" );
454  myMetadata += tr( "Min Val" );
455  myMetadata += QLatin1String( "</p>\n" );
456  myMetadata += QLatin1String( "<p>\n" );
457  myMetadata += QString::number( myRasterBandStats.minimumValue, 'f', 10 );
458  myMetadata += QLatin1String( "</p>\n" );
459 
460  // Max Val
461  myMetadata += QLatin1String( "<p>" );
462  myMetadata += tr( "Max Val" );
463  myMetadata += QLatin1String( "</p>\n" );
464  myMetadata += QLatin1String( "<p>\n" );
465  myMetadata += QString::number( myRasterBandStats.maximumValue, 'f', 10 );
466  myMetadata += QLatin1String( "</p>\n" );
467 
468  // Range
469  myMetadata += QLatin1String( "<p>" );
470  myMetadata += tr( "Range" );
471  myMetadata += QLatin1String( "</p>\n" );
472  myMetadata += QLatin1String( "<p>\n" );
473  myMetadata += QString::number( myRasterBandStats.range, 'f', 10 );
474  myMetadata += QLatin1String( "</p>\n" );
475 
476  // Mean
477  myMetadata += QLatin1String( "<p>" );
478  myMetadata += tr( "Mean" );
479  myMetadata += QLatin1String( "</p>\n" );
480  myMetadata += QLatin1String( "<p>\n" );
481  myMetadata += QString::number( myRasterBandStats.mean, 'f', 10 );
482  myMetadata += QLatin1String( "</p>\n" );
483 
484  //sum of squares
485  myMetadata += QLatin1String( "<p>" );
486  myMetadata += tr( "Sum of squares" );
487  myMetadata += QLatin1String( "</p>\n" );
488  myMetadata += QLatin1String( "<p>\n" );
489  myMetadata += QString::number( myRasterBandStats.sumOfSquares, 'f', 10 );
490  myMetadata += QLatin1String( "</p>\n" );
491 
492  //standard deviation
493  myMetadata += QLatin1String( "<p>" );
494  myMetadata += tr( "Standard Deviation" );
495  myMetadata += QLatin1String( "</p>\n" );
496  myMetadata += QLatin1String( "<p>\n" );
497  myMetadata += QString::number( myRasterBandStats.stdDev, 'f', 10 );
498  myMetadata += QLatin1String( "</p>\n" );
499 
500  //sum of all cells
501  myMetadata += QLatin1String( "<p>" );
502  myMetadata += tr( "Sum of all cells" );
503  myMetadata += QLatin1String( "</p>\n" );
504  myMetadata += QLatin1String( "<p>\n" );
505  myMetadata += QString::number( myRasterBandStats.sum, 'f', 10 );
506  myMetadata += QLatin1String( "</p>\n" );
507 
508  //number of cells
509  myMetadata += QLatin1String( "<p>" );
510  myMetadata += tr( "Cell Count" );
511  myMetadata += QLatin1String( "</p>\n" );
512  myMetadata += QLatin1String( "<p>\n" );
513  myMetadata += QString::number( myRasterBandStats.elementCount );
514  myMetadata += QLatin1String( "</p>\n" );
515  }
516  }
517 
518  QgsDebugMsgLevel( myMetadata, 4 );
519  return myMetadata;
520 }
521 
526 QPixmap QgsRasterLayer::paletteAsPixmap( int theBandNumber )
527 {
528  //TODO: This function should take dimensions
529  QgsDebugMsgLevel( "entered.", 4 );
530 
531  // Only do this for the GDAL provider?
532  // Maybe WMS can do this differently using QImage::numColors and QImage::color()
533  if ( mDataProvider->colorInterpretation( theBandNumber ) == QgsRaster::PaletteIndex )
534  {
535  QgsDebugMsgLevel( "....found paletted image", 4 );
536  QgsColorRampShader myShader;
537  QList<QgsColorRampShader::ColorRampItem> myColorRampItemList = mDataProvider->colorTable( theBandNumber );
538  if ( !myColorRampItemList.isEmpty() )
539  {
540  QgsDebugMsgLevel( "....got color ramp item list", 4 );
541  myShader.setColorRampItemList( myColorRampItemList );
543  // Draw image
544  int mySize = 100;
545  QPixmap myPalettePixmap( mySize, mySize );
546  QPainter myQPainter( &myPalettePixmap );
547 
548  QImage myQImage = QImage( mySize, mySize, QImage::Format_RGB32 );
549  myQImage.fill( 0 );
550  myPalettePixmap.fill();
551 
552  double myStep = ( static_cast< double >( myColorRampItemList.size() ) - 1 ) / static_cast< double >( mySize * mySize );
553  double myValue = 0.0;
554  for ( int myRow = 0; myRow < mySize; myRow++ )
555  {
556  QRgb* myLineBuffer = reinterpret_cast< QRgb* >( myQImage.scanLine( myRow ) );
557  for ( int myCol = 0; myCol < mySize; myCol++ )
558  {
559  myValue = myStep * static_cast< double >( myCol + myRow * mySize );
560  int c1, c2, c3, c4;
561  myShader.shade( myValue, &c1, &c2, &c3, &c4 );
562  myLineBuffer[ myCol ] = qRgba( c1, c2, c3, c4 );
563  }
564  }
565 
566  myQPainter.drawImage( 0, 0, myQImage );
567  return myPalettePixmap;
568  }
569  QPixmap myNullPixmap;
570  return myNullPixmap;
571  }
572  else
573  {
574  //invalid layer was requested
575  QPixmap myNullPixmap;
576  return myNullPixmap;
577  }
578 }
579 
581 {
582  return mProviderKey;
583 }
584 
589 {
590 // We return one raster pixel per map unit pixel
591 // One raster pixel can have several raster units...
592 
593 // We can only use one of the mGeoTransform[], so go with the
594 // horisontal one.
595 
596  if ( mDataProvider->capabilities() & QgsRasterDataProvider::Size && mDataProvider->xSize() > 0 )
597  {
598  return mDataProvider->extent().width() / mDataProvider->xSize();
599  }
600  return 1;
601 }
602 
604 {
605  if ( mDataProvider->capabilities() & QgsRasterDataProvider::Size && mDataProvider->xSize() > 0 )
606  {
607  return mDataProvider->extent().height() / mDataProvider->ySize();
608  }
609  return 1;
610 }
611 
612 void QgsRasterLayer::init()
613 {
614  mRasterType = QgsRasterLayer::GrayOrUndefined;
615 
617 
618  setRendererForDrawingStyle( QgsRaster::UndefinedDrawingStyle );
619 
620  //Initialize the last view port structure, should really be a class
621  mLastViewPort.mWidth = 0;
622  mLastViewPort.mHeight = 0;
623 }
624 
625 void QgsRasterLayer::setDataProvider( QString const & provider )
626 {
627  QgsDebugMsgLevel( "Entered", 4 );
628  mValid = false; // assume the layer is invalid until we determine otherwise
629 
630  mPipe.remove( mDataProvider ); // deletes if exists
631  mDataProvider = nullptr;
632 
633  // XXX should I check for and possibly delete any pre-existing providers?
634  // XXX How often will that scenario occur?
635 
636  mProviderKey = provider;
637  // set the layer name (uppercase first character)
638  if ( ! mLayerName.isEmpty() ) // XXX shouldn't this happen in parent?
639  {
640  setName( mLayerName );
641  }
642 
643  //mBandCount = 0;
644 
645  mDataProvider = dynamic_cast< QgsRasterDataProvider* >( QgsProviderRegistry::instance()->provider( mProviderKey, mDataSource ) );
646  if ( !mDataProvider )
647  {
648  //QgsMessageLog::logMessage( tr( "Cannot instantiate the data provider" ), tr( "Raster" ) );
649  appendError( ERR( tr( "Cannot instantiate the '%1' data provider" ).arg( mProviderKey ) ) );
650  return;
651  }
652  QgsDebugMsgLevel( "Data provider created", 4 );
653 
654  // Set data provider into pipe even if not valid so that it is deleted with pipe (with layer)
655  mPipe.set( mDataProvider );
656  if ( !mDataProvider->isValid() )
657  {
658  setError( mDataProvider->error() );
659  appendError( ERR( tr( "Provider is not valid (provider: %1, URI: %2" ).arg( mProviderKey, mDataSource ) ) );
660  return;
661  }
662 
663  if ( provider == QLatin1String( "gdal" ) )
664  {
665  // make sure that the /vsigzip or /vsizip is added to uri, if applicable
666  mDataSource = mDataProvider->dataSourceUri();
667  }
668 
669  // get the extent
670  QgsRectangle mbr = mDataProvider->extent();
671 
672  // show the extent
673  QgsDebugMsgLevel( "Extent of layer: " + mbr.toString(), 4 );
674  // store the extent
675  setExtent( mbr );
676 
677  // upper case the first letter of the layer name
678  QgsDebugMsgLevel( "mLayerName: " + name(), 4 );
679 
680  // set up the raster drawing style
681  // Do not set any 'sensible' style here, the style is set later
682 
683  // Setup source CRS
684  setCrs( QgsCoordinateReferenceSystem( mDataProvider->crs() ) );
685 
686  QgsDebugMsgLevel( "using wkt:\n" + crs().toWkt(), 4 );
687 
688  //defaults - Needs to be set after the Contrast list has been build
689  //Try to read the default contrast enhancement from the config file
690 
691  //decide what type of layer this is...
692  //TODO Change this to look at the color interp and palette interp to decide which type of layer it is
693  QgsDebugMsgLevel( "bandCount = " + QString::number( mDataProvider->bandCount() ), 4 );
694  QgsDebugMsgLevel( "dataType = " + QString::number( mDataProvider->dataType( 1 ) ), 4 );
695  if (( mDataProvider->bandCount() > 1 ) )
696  {
697  // handle singleband gray with alpha
698  if ( mDataProvider->bandCount() == 2
699  && (( mDataProvider->colorInterpretation( 1 ) == QgsRaster::GrayIndex
700  && mDataProvider->colorInterpretation( 2 ) == QgsRaster::AlphaBand )
701  || ( mDataProvider->colorInterpretation( 1 ) == QgsRaster::AlphaBand
702  && mDataProvider->colorInterpretation( 2 ) == QgsRaster::GrayIndex ) ) )
703  {
704  mRasterType = GrayOrUndefined;
705  }
706  else
707  {
708  mRasterType = Multiband;
709  }
710  }
711  else if ( mDataProvider->dataType( 1 ) == Qgis::ARGB32
712  || mDataProvider->dataType( 1 ) == Qgis::ARGB32_Premultiplied )
713  {
714  mRasterType = ColorLayer;
715  }
716  else if ( mDataProvider->colorInterpretation( 1 ) == QgsRaster::PaletteIndex )
717  {
718  mRasterType = Palette;
719  }
720  else if ( mDataProvider->colorInterpretation( 1 ) == QgsRaster::ContinuousPalette )
721  {
722  mRasterType = Palette;
723  }
724  else
725  {
726  mRasterType = GrayOrUndefined;
727  }
728 
729  QgsDebugMsgLevel( "mRasterType = " + QString::number( mRasterType ), 4 );
730  if ( mRasterType == ColorLayer )
731  {
732  QgsDebugMsgLevel( "Setting drawing style to SingleBandColorDataStyle " + QString::number( QgsRaster::SingleBandColorDataStyle ), 4 );
733  setRendererForDrawingStyle( QgsRaster::SingleBandColorDataStyle );
734  }
735  else if ( mRasterType == Palette && mDataProvider->colorInterpretation( 1 ) == QgsRaster::PaletteIndex )
736  {
737  setRendererForDrawingStyle( QgsRaster::PalettedColor ); //sensible default
738  }
739  else if ( mRasterType == Palette && mDataProvider->colorInterpretation( 1 ) == QgsRaster::ContinuousPalette )
740  {
741  setRendererForDrawingStyle( QgsRaster::SingleBandPseudoColor );
742  // Load color table
743  QList<QgsColorRampShader::ColorRampItem> colorTable = mDataProvider->colorTable( 1 );
745  if ( r )
746  {
747  // TODO: this should go somewhere else
748  QgsRasterShader* shader = new QgsRasterShader();
749  QgsColorRampShader* colorRampShader = new QgsColorRampShader();
751  colorRampShader->setColorRampItemList( colorTable );
752  shader->setRasterShaderFunction( colorRampShader );
753  r->setShader( shader );
754  }
755  }
756  else if ( mRasterType == Multiband )
757  {
758  setRendererForDrawingStyle( QgsRaster::MultiBandColor ); //sensible default
759  }
760  else //GrayOrUndefined
761  {
762  setRendererForDrawingStyle( QgsRaster::SingleBandGray ); //sensible default
763  }
764 
765  // Auto set alpha band
766  for ( int bandNo = 1; bandNo <= mDataProvider->bandCount(); bandNo++ )
767  {
768  if ( mDataProvider->colorInterpretation( bandNo ) == QgsRaster::AlphaBand )
769  {
770  if ( mPipe.renderer() )
771  {
772  mPipe.renderer()->setAlphaBand( bandNo );
773  }
774  break;
775  }
776  }
777 
778  // brightness filter
780  mPipe.set( brightnessFilter );
781 
782  // hue/saturation filter
784  mPipe.set( hueSaturationFilter );
785 
786  //resampler (must be after renderer)
788  mPipe.set( resampleFilter );
789 
790  // projector (may be anywhere in pipe)
791  QgsRasterProjector * projector = new QgsRasterProjector;
792  mPipe.set( projector );
793 
794  // Set default identify format - use the richest format available
795  int capabilities = mDataProvider->capabilities();
797  if ( capabilities & QgsRasterInterface::IdentifyHtml )
798  {
799  // HTML is usually richest
800  identifyFormat = QgsRaster::IdentifyFormatHtml;
801  }
802  else if ( capabilities & QgsRasterInterface::IdentifyFeature )
803  {
804  identifyFormat = QgsRaster::IdentifyFormatFeature;
805  }
806  else if ( capabilities & QgsRasterInterface::IdentifyText )
807  {
808  identifyFormat = QgsRaster::IdentifyFormatText;
809  }
810  else if ( capabilities & QgsRasterInterface::IdentifyValue )
811  {
812  identifyFormat = QgsRaster::IdentifyFormatValue;
813  }
814  setCustomProperty( QStringLiteral( "identify/format" ), QgsRasterDataProvider::identifyFormatName( identifyFormat ) );
815 
816  // Store timestamp
817  // TODO move to provider
818  mLastModified = lastModified( mDataSource );
819 
820  // Connect provider signals
821  connect( mDataProvider, &QgsRasterDataProvider::progress, this, &QgsRasterLayer::onProgress );
822 
823  // Do a passthrough for the status bar text
824  connect( mDataProvider, &QgsRasterDataProvider::statusChanged, this, &QgsRasterLayer::statusChanged );
825 
826  //mark the layer as valid
827  mValid = true;
828 
829  QgsDebugMsgLevel( "exiting.", 4 );
830 } // QgsRasterLayer::setDataProvider
831 
832 void QgsRasterLayer::closeDataProvider()
833 {
834  mValid = false;
835  mPipe.remove( mDataProvider );
836  mDataProvider = nullptr;
837 }
838 
839 void QgsRasterLayer::setContrastEnhancement( QgsContrastEnhancement::ContrastEnhancementAlgorithm theAlgorithm, QgsRaster::ContrastEnhancementLimits theLimits, const QgsRectangle& theExtent, int theSampleSize, bool theGenerateLookupTableFlag )
840 {
841  QgsDebugMsgLevel( QString( "theAlgorithm = %1 theLimits = %2 theExtent.isEmpty() = %3" ).arg( theAlgorithm ).arg( theLimits ).arg( theExtent.isEmpty() ), 4 );
842  if ( !mPipe.renderer() || !mDataProvider )
843  {
844  return;
845  }
846 
847  QList<int> myBands;
848  QList<QgsContrastEnhancement*> myEnhancements;
849  QgsSingleBandGrayRenderer* myGrayRenderer = nullptr;
850  QgsMultiBandColorRenderer* myMultiBandRenderer = nullptr;
851  QString rendererType = mPipe.renderer()->type();
852  if ( rendererType == QLatin1String( "singlebandgray" ) )
853  {
854  myGrayRenderer = dynamic_cast<QgsSingleBandGrayRenderer*>( mPipe.renderer() );
855  if ( !myGrayRenderer ) return;
856  myBands << myGrayRenderer->grayBand();
857  }
858  else if ( rendererType == QLatin1String( "multibandcolor" ) )
859  {
860  myMultiBandRenderer = dynamic_cast<QgsMultiBandColorRenderer*>( mPipe.renderer() );
861  if ( !myMultiBandRenderer ) return;
862  myBands << myMultiBandRenderer->redBand() << myMultiBandRenderer->greenBand() << myMultiBandRenderer->blueBand();
863  }
864 
865  Q_FOREACH ( int myBand, myBands )
866  {
867  if ( myBand != -1 )
868  {
869  Qgis::DataType myType = static_cast< Qgis::DataType >( mDataProvider->dataType( myBand ) );
870  QgsContrastEnhancement* myEnhancement = new QgsContrastEnhancement( static_cast< Qgis::DataType >( myType ) );
871  myEnhancement->setContrastEnhancementAlgorithm( theAlgorithm, theGenerateLookupTableFlag );
872 
873  double myMin = std::numeric_limits<double>::quiet_NaN();
874  double myMax = std::numeric_limits<double>::quiet_NaN();
875 
876  if ( theLimits == QgsRaster::ContrastEnhancementMinMax )
877  {
878  QgsRasterBandStats myRasterBandStats = mDataProvider->bandStatistics( myBand, QgsRasterBandStats::Min | QgsRasterBandStats::Max, theExtent, theSampleSize );
879  myMin = myRasterBandStats.minimumValue;
880  myMax = myRasterBandStats.maximumValue;
881  }
882  else if ( theLimits == QgsRaster::ContrastEnhancementStdDev )
883  {
884  double myStdDev = 1; // make optional?
885  QgsRasterBandStats myRasterBandStats = mDataProvider->bandStatistics( myBand, QgsRasterBandStats::Mean | QgsRasterBandStats::StdDev, theExtent, theSampleSize );
886  myMin = myRasterBandStats.mean - ( myStdDev * myRasterBandStats.stdDev );
887  myMax = myRasterBandStats.mean + ( myStdDev * myRasterBandStats.stdDev );
888  }
889  else if ( theLimits == QgsRaster::ContrastEnhancementCumulativeCut )
890  {
891  QSettings mySettings;
892  double myLower = mySettings.value( QStringLiteral( "/Raster/cumulativeCutLower" ), QString::number( CUMULATIVE_CUT_LOWER ) ).toDouble();
893  double myUpper = mySettings.value( QStringLiteral( "/Raster/cumulativeCutUpper" ), QString::number( CUMULATIVE_CUT_UPPER ) ).toDouble();
894  QgsDebugMsgLevel( QString( "myLower = %1 myUpper = %2" ).arg( myLower ).arg( myUpper ), 4 );
895  mDataProvider->cumulativeCut( myBand, myLower, myUpper, myMin, myMax, theExtent, theSampleSize );
896  }
897 
898  QgsDebugMsgLevel( QString( "myBand = %1 myMin = %2 myMax = %3" ).arg( myBand ).arg( myMin ).arg( myMax ), 4 );
899  myEnhancement->setMinimumValue( myMin );
900  myEnhancement->setMaximumValue( myMax );
901  myEnhancements.append( myEnhancement );
902  }
903  else
904  {
905  myEnhancements.append( nullptr );
906  }
907  }
908 
909  if ( rendererType == QLatin1String( "singlebandgray" ) )
910  {
911  if ( myEnhancements.first() ) myGrayRenderer->setContrastEnhancement( myEnhancements.takeFirst() );
912  }
913  else if ( rendererType == QLatin1String( "multibandcolor" ) )
914  {
915  if ( myEnhancements.first() ) myMultiBandRenderer->setRedContrastEnhancement( myEnhancements.takeFirst() );
916  if ( myEnhancements.first() ) myMultiBandRenderer->setGreenContrastEnhancement( myEnhancements.takeFirst() );
917  if ( myEnhancements.first() ) myMultiBandRenderer->setBlueContrastEnhancement( myEnhancements.takeFirst() );
918  }
919 
920  //delete all remaining unused enhancements
921  qDeleteAll( myEnhancements );
922 
923  emit repaintRequested();
924  emit styleChanged();
925 }
926 
928 {
929  QgsDebugMsgLevel( "Entered", 4 );
930 
931  QSettings mySettings;
932 
933  QString myKey;
934  QString myDefault;
935 
936  // TODO: we should not test renderer class here, move it somehow to renderers
937  if ( dynamic_cast<QgsSingleBandGrayRenderer*>( renderer() ) )
938  {
939  myKey = QStringLiteral( "singleBand" );
940  myDefault = QStringLiteral( "StretchToMinimumMaximum" );
941  }
942  else if ( dynamic_cast<QgsMultiBandColorRenderer*>( renderer() ) )
943  {
944  if ( QgsRasterBlock::typeSize( dataProvider()->sourceDataType( 1 ) ) == 1 )
945  {
946  myKey = QStringLiteral( "multiBandSingleByte" );
947  myDefault = QStringLiteral( "NoEnhancement" );
948  }
949  else
950  {
951  myKey = QStringLiteral( "multiBandMultiByte" );
952  myDefault = QStringLiteral( "StretchToMinimumMaximum" );
953  }
954  }
955 
956  if ( myKey.isEmpty() )
957  {
958  QgsDebugMsg( "No default contrast enhancement for this drawing style" );
959  }
960  QgsDebugMsgLevel( "myKey = " + myKey, 4 );
961 
962  QString myAlgorithmString = mySettings.value( "/Raster/defaultContrastEnhancementAlgorithm/" + myKey, myDefault ).toString();
963  QgsDebugMsgLevel( "myAlgorithmString = " + myAlgorithmString, 4 );
964 
966 
967  if ( myAlgorithm == QgsContrastEnhancement::NoEnhancement )
968  {
969  return;
970  }
971 
972  QString myLimitsString = mySettings.value( QStringLiteral( "/Raster/defaultContrastEnhancementLimits" ), "CumulativeCut" ).toString();
974 
975  setContrastEnhancement( myAlgorithm, myLimits );
976 }
977 
978 void QgsRasterLayer::setLayerOrder( QStringList const & layers )
979 {
980  QgsDebugMsgLevel( "entered.", 4 );
981 
982  if ( mDataProvider )
983  {
984  QgsDebugMsgLevel( "About to mDataProvider->setLayerOrder(layers).", 4 );
985  mDataProvider->setLayerOrder( layers );
986  }
987 
988 }
989 
990 void QgsRasterLayer::setSubLayerVisibility( const QString& name, bool vis )
991 {
992 
993  if ( mDataProvider )
994  {
995  QgsDebugMsgLevel( "About to mDataProvider->setSubLayerVisibility(name, vis).", 4 );
996  mDataProvider->setSubLayerVisibility( name, vis );
997  }
998 
999 }
1000 
1001 QDateTime QgsRasterLayer::timestamp() const
1002 {
1003  return mDataProvider->timestamp();
1004 }
1005 
1007 {
1008  QgsDebugMsgLevel( "Entered", 4 );
1009  if ( !theRenderer ) { return; }
1010  mPipe.set( theRenderer );
1011  emit rendererChanged();
1012  emit styleChanged();
1013 }
1014 
1015 void QgsRasterLayer::showProgress( int theValue )
1016 {
1017  emit progressUpdate( theValue );
1018 }
1019 
1020 
1021 void QgsRasterLayer::showStatusMessage( QString const & theMessage )
1022 {
1023  // QgsDebugMsg(QString("entered with '%1'.").arg(theMessage));
1024 
1025  // Pass-through
1026  // TODO: See if we can connect signal-to-signal. This is a kludge according to the Qt doc.
1027  emit statusChanged( theMessage );
1028 }
1029 
1030 QStringList QgsRasterLayer::subLayers() const
1031 {
1032  return mDataProvider->subLayers();
1033 }
1034 
1035 // this function should be used when rendering with the MTR engine introduced in 2.3, as QPixmap is not thread safe (see bug #9626)
1036 // note: previewAsImage and previewAsPixmap should use a common low-level fct QgsRasterLayer::previewOnPaintDevice( QSize size, QColor bgColor, QPaintDevice &device )
1037 QImage QgsRasterLayer::previewAsImage( QSize size, const QColor& bgColor, QImage::Format format )
1038 {
1039  QImage myQImage( size, format );
1040 
1041  myQImage.setColor( 0, bgColor.rgba() );
1042  myQImage.fill( 0 ); //defaults to white, set to transparent for rendering on a map
1043 
1044  QgsRasterViewPort *myRasterViewPort = new QgsRasterViewPort();
1045 
1046  double myMapUnitsPerPixel;
1047  double myX = 0.0;
1048  double myY = 0.0;
1049  QgsRectangle myExtent = mDataProvider->extent();
1050  if ( myExtent.width() / myExtent.height() >= static_cast< double >( myQImage.width() ) / myQImage.height() )
1051  {
1052  myMapUnitsPerPixel = myExtent.width() / myQImage.width();
1053  myY = ( myQImage.height() - myExtent.height() / myMapUnitsPerPixel ) / 2;
1054  }
1055  else
1056  {
1057  myMapUnitsPerPixel = myExtent.height() / myQImage.height();
1058  myX = ( myQImage.width() - myExtent.width() / myMapUnitsPerPixel ) / 2;
1059  }
1060 
1061  double myPixelWidth = myExtent.width() / myMapUnitsPerPixel;
1062  double myPixelHeight = myExtent.height() / myMapUnitsPerPixel;
1063 
1064  myRasterViewPort->mTopLeftPoint = QgsPoint( myX, myY );
1065  myRasterViewPort->mBottomRightPoint = QgsPoint( myPixelWidth, myPixelHeight );
1066  myRasterViewPort->mWidth = myQImage.width();
1067  myRasterViewPort->mHeight = myQImage.height();
1068 
1069  myRasterViewPort->mDrawnExtent = myExtent;
1070  myRasterViewPort->mSrcCRS = QgsCoordinateReferenceSystem(); // will be invalid
1071  myRasterViewPort->mDestCRS = QgsCoordinateReferenceSystem(); // will be invalid
1072  myRasterViewPort->mSrcDatumTransform = -1;
1073  myRasterViewPort->mDestDatumTransform = -1;
1074 
1075  QgsMapToPixel *myMapToPixel = new QgsMapToPixel( myMapUnitsPerPixel );
1076 
1077  QPainter * myQPainter = new QPainter( &myQImage );
1078  draw( myQPainter, myRasterViewPort, myMapToPixel );
1079  delete myRasterViewPort;
1080  delete myMapToPixel;
1081  myQPainter->end();
1082  delete myQPainter;
1083 
1084  return myQImage;
1085 }
1086 
1087 void QgsRasterLayer::onProgress( int theType, double theProgress, const QString& theMessage )
1088 {
1089  Q_UNUSED( theType );
1090  Q_UNUSED( theMessage );
1091  QgsDebugMsgLevel( QString( "theProgress = %1" ).arg( theProgress ), 4 );
1092  emit progressUpdate( static_cast< int >( theProgress ) );
1093 }
1094 
1096 //
1097 // Protected methods
1098 //
1100 /*
1101  * @param QDomNode node that will contain the symbology definition for this layer.
1102  * @param errorMessage reference to string that will be updated with any error messages
1103  * @return true in case of success.
1104  */
1105 bool QgsRasterLayer::readSymbology( const QDomNode& layer_node, QString& errorMessage )
1106 {
1107  Q_UNUSED( errorMessage );
1108  QDomElement rasterRendererElem;
1109 
1110  // pipe element was introduced in the end of 1.9 development when there were
1111  // already many project files in use so we support 1.9 backward compatibility
1112  // even it was never officialy released -> use pipe element if present, otherwise
1113  // use layer node
1114  QDomNode pipeNode = layer_node.firstChildElement( QStringLiteral( "pipe" ) );
1115  if ( pipeNode.isNull() ) // old project
1116  {
1117  pipeNode = layer_node;
1118  }
1119 
1120  //rasterlayerproperties element there -> old format (1.8 and early 1.9)
1121  if ( !layer_node.firstChildElement( QStringLiteral( "rasterproperties" ) ).isNull() )
1122  {
1123  //copy node because layer_node is const
1124  QDomNode layerNodeCopy = layer_node.cloneNode();
1125  QDomDocument doc = layerNodeCopy.ownerDocument();
1126  QDomElement rasterPropertiesElem = layerNodeCopy.firstChildElement( QStringLiteral( "rasterproperties" ) );
1127  QgsProjectFileTransform::convertRasterProperties( doc, layerNodeCopy, rasterPropertiesElem,
1128  this );
1129  rasterRendererElem = layerNodeCopy.firstChildElement( QStringLiteral( "rasterrenderer" ) );
1130  QgsDebugMsgLevel( doc.toString(), 4 );
1131  }
1132  else
1133  {
1134  rasterRendererElem = pipeNode.firstChildElement( QStringLiteral( "rasterrenderer" ) );
1135  }
1136 
1137  if ( !rasterRendererElem.isNull() )
1138  {
1139  QString rendererType = rasterRendererElem.attribute( QStringLiteral( "type" ) );
1140  QgsRasterRendererRegistryEntry rendererEntry;
1141  if ( QgsRasterRendererRegistry::instance()->rendererData( rendererType, rendererEntry ) )
1142  {
1143  QgsRasterRenderer *renderer = rendererEntry.rendererCreateFunction( rasterRendererElem, dataProvider() );
1144  mPipe.set( renderer );
1145  }
1146  }
1147 
1148  //brightness
1150  mPipe.set( brightnessFilter );
1151 
1152  //brightness coefficient
1153  QDomElement brightnessElem = pipeNode.firstChildElement( QStringLiteral( "brightnesscontrast" ) );
1154  if ( !brightnessElem.isNull() )
1155  {
1156  brightnessFilter->readXml( brightnessElem );
1157  }
1158 
1159  //hue/saturation
1161  mPipe.set( hueSaturationFilter );
1162 
1163  //saturation coefficient
1164  QDomElement hueSaturationElem = pipeNode.firstChildElement( QStringLiteral( "huesaturation" ) );
1165  if ( !hueSaturationElem.isNull() )
1166  {
1167  hueSaturationFilter->readXml( hueSaturationElem );
1168  }
1169 
1170  //resampler
1172  mPipe.set( resampleFilter );
1173 
1174  //max oversampling
1175  QDomElement resampleElem = pipeNode.firstChildElement( QStringLiteral( "rasterresampler" ) );
1176  if ( !resampleElem.isNull() )
1177  {
1178  resampleFilter->readXml( resampleElem );
1179  }
1180 
1181  // get and set the blend mode if it exists
1182  QDomNode blendModeNode = layer_node.namedItem( QStringLiteral( "blendMode" ) );
1183  if ( !blendModeNode.isNull() )
1184  {
1185  QDomElement e = blendModeNode.toElement();
1186  setBlendMode( QgsPainting::getCompositionMode( static_cast< QgsPainting::BlendMode >( e.text().toInt() ) ) );
1187  }
1188 
1189  readCustomProperties( layer_node );
1190 
1191  return true;
1192 }
1193 
1194 bool QgsRasterLayer::readStyle( const QDomNode &node, QString &errorMessage )
1195 {
1196  return readSymbology( node, errorMessage );
1197 } //readSymbology
1198 
1205 bool QgsRasterLayer::readXml( const QDomNode& layer_node )
1206 {
1207  QgsDebugMsgLevel( "Entered", 4 );
1209 
1210  //process provider key
1211  QDomNode pkeyNode = layer_node.namedItem( QStringLiteral( "provider" ) );
1212 
1213  if ( pkeyNode.isNull() )
1214  {
1215  mProviderKey = QStringLiteral( "gdal" );
1216  }
1217  else
1218  {
1219  QDomElement pkeyElt = pkeyNode.toElement();
1220  mProviderKey = pkeyElt.text();
1221  if ( mProviderKey.isEmpty() )
1222  {
1223  mProviderKey = QStringLiteral( "gdal" );
1224  }
1225  }
1226 
1227  // Open the raster source based on provider and datasource
1228 
1229  // Go down the raster-data-provider paradigm
1230 
1231  // Collect provider-specific information
1232 
1233  QDomNode rpNode = layer_node.namedItem( QStringLiteral( "rasterproperties" ) );
1234 
1235  if ( mProviderKey == QLatin1String( "wms" ) )
1236  {
1237  // >>> BACKWARD COMPATIBILITY < 1.9
1238  // The old WMS URI format does not contain all the information, we add them here.
1239  if ( !mDataSource.contains( QLatin1String( "crs=" ) ) && !mDataSource.contains( QLatin1String( "format=" ) ) )
1240  {
1241  QgsDebugMsgLevel( "Old WMS URI format detected -> adding params", 4 );
1242  QgsDataSourceUri uri;
1243  uri.setEncodedUri( mDataSource );
1244  QDomElement layerElement = rpNode.firstChildElement( QStringLiteral( "wmsSublayer" ) );
1245  while ( !layerElement.isNull() )
1246  {
1247  // TODO: sublayer visibility - post-0.8 release timeframe
1248 
1249  // collect name for the sublayer
1250  uri.setParam( QStringLiteral( "layers" ), layerElement.namedItem( QStringLiteral( "name" ) ).toElement().text() );
1251 
1252  // collect style for the sublayer
1253  uri.setParam( QStringLiteral( "styles" ), layerElement.namedItem( QStringLiteral( "style" ) ).toElement().text() );
1254 
1255  layerElement = layerElement.nextSiblingElement( QStringLiteral( "wmsSublayer" ) );
1256  }
1257 
1258  // Collect format
1259  QDomNode formatNode = rpNode.namedItem( QStringLiteral( "wmsFormat" ) );
1260  uri.setParam( QStringLiteral( "format" ), rpNode.namedItem( QStringLiteral( "wmsFormat" ) ).toElement().text() );
1261 
1262  // WMS CRS URL param should not be mixed with that assigned to the layer.
1263  // In the old WMS URI version there was no CRS and layer crs().authid() was used.
1264  uri.setParam( QStringLiteral( "crs" ), crs().authid() );
1265  mDataSource = uri.encodedUri();
1266  }
1267  // <<< BACKWARD COMPATIBILITY < 1.9
1268  }
1269 
1270  setDataProvider( mProviderKey );
1271  if ( !mValid ) return false;
1272 
1273  QString theError;
1274  bool res = readSymbology( layer_node, theError );
1275 
1276  // old wms settings we need to correct
1277  if ( res && mProviderKey == QLatin1String( "wms" ) && ( !renderer() || renderer()->type() != QLatin1String( "singlebandcolordata" ) ) )
1278  {
1279  setRendererForDrawingStyle( QgsRaster::SingleBandColorDataStyle );
1280  }
1281 
1282  // Check timestamp
1283  // This was probably introduced to reload completely raster if data changed and
1284  // reset completly symbology to reflect new data type etc. It creates however
1285  // problems, because user defined symbology is complete lost if data file time
1286  // changed (the content may be the same). See also 6900.
1287 #if 0
1288  QDomNode stampNode = layer_node.namedItem( "timestamp" );
1289  if ( !stampNode.isNull() )
1290  {
1291  QDateTime stamp = QDateTime::fromString( stampNode.toElement().text(), Qt::ISODate );
1292  // TODO: very bad, we have to load twice!!! Make QgsDataProvider::timestamp() static?
1293  if ( stamp < mDataProvider->dataTimestamp() )
1294  {
1295  QgsDebugMsg( "data changed, reload provider" );
1296  closeDataProvider();
1297  init();
1298  setDataProvider( mProviderKey );
1299  if ( !mValid ) return false;
1300  }
1301  }
1302 #endif
1303 
1304  // Load user no data value
1305  QDomElement noDataElement = layer_node.firstChildElement( QStringLiteral( "noData" ) );
1306 
1307  QDomNodeList noDataBandList = noDataElement.elementsByTagName( QStringLiteral( "noDataList" ) );
1308 
1309  for ( int i = 0; i < noDataBandList.size(); ++i )
1310  {
1311  QDomElement bandElement = noDataBandList.at( i ).toElement();
1312  bool ok;
1313  int bandNo = bandElement.attribute( QStringLiteral( "bandNo" ) ).toInt( &ok );
1314  QgsDebugMsgLevel( QString( "bandNo = %1" ).arg( bandNo ), 4 );
1315  if ( ok && ( bandNo > 0 ) && ( bandNo <= mDataProvider->bandCount() ) )
1316  {
1317  mDataProvider->setUseSourceNoDataValue( bandNo, bandElement.attribute( QStringLiteral( "useSrcNoData" ) ).toInt() );
1318  QgsRasterRangeList myNoDataRangeList;
1319 
1320  QDomNodeList rangeList = bandElement.elementsByTagName( QStringLiteral( "noDataRange" ) );
1321 
1322  myNoDataRangeList.reserve( rangeList.size() );
1323  for ( int j = 0; j < rangeList.size(); ++j )
1324  {
1325  QDomElement rangeElement = rangeList.at( j ).toElement();
1326  QgsRasterRange myNoDataRange( rangeElement.attribute( QStringLiteral( "min" ) ).toDouble(),
1327  rangeElement.attribute( QStringLiteral( "max" ) ).toDouble() );
1328  QgsDebugMsgLevel( QString( "min = %1 %2" ).arg( rangeElement.attribute( "min" ) ).arg( myNoDataRange.min() ), 4 );
1329  myNoDataRangeList << myNoDataRange;
1330  }
1331  mDataProvider->setUserNoDataValue( bandNo, myNoDataRangeList );
1332  }
1333  }
1334 
1335  readStyleManager( layer_node );
1336 
1337  return res;
1338 } // QgsRasterLayer::readXml( QDomNode & layer_node )
1339 
1340 /*
1341  * @param QDomNode the node that will have the style element added to it.
1342  * @param QDomDocument the document that will have the QDomNode added.
1343  * @param errorMessage reference to string that will be updated with any error messages
1344  * @return true in case of success.
1345  */
1346 bool QgsRasterLayer::writeSymbology( QDomNode & layer_node, QDomDocument & document, QString& errorMessage ) const
1347 {
1348  Q_UNUSED( errorMessage );
1349  QDomElement layerElem = layer_node.toElement();
1350 
1351  // Store pipe members (except provider) into pipe element, in future, it will be
1352  // possible to add custom filters into the pipe
1353  QDomElement pipeElement = document.createElement( QStringLiteral( "pipe" ) );
1354 
1355  for ( int i = 1; i < mPipe.size(); i++ )
1356  {
1357  QgsRasterInterface * interface = mPipe.at( i );
1358  if ( !interface ) continue;
1359  interface->writeXml( document, pipeElement );
1360  }
1361 
1362  layer_node.appendChild( pipeElement );
1363 
1364  // add blend mode node
1365  QDomElement blendModeElement = document.createElement( QStringLiteral( "blendMode" ) );
1366  QDomText blendModeText = document.createTextNode( QString::number( QgsPainting::getBlendModeEnum( blendMode() ) ) );
1367  blendModeElement.appendChild( blendModeText );
1368  layer_node.appendChild( blendModeElement );
1369 
1370  return true;
1371 }
1372 
1373 bool QgsRasterLayer::writeStyle( QDomNode &node, QDomDocument &doc, QString &errorMessage ) const
1374 {
1375  return writeSymbology( node, doc, errorMessage );
1376 
1377 } // bool QgsRasterLayer::writeSymbology
1378 
1379 /*
1380  * virtual
1381  * @note Called by QgsMapLayer::writeXml().
1382  */
1383 bool QgsRasterLayer::writeXml( QDomNode & layer_node,
1384  QDomDocument & document ) const
1385 {
1386  // first get the layer element so that we can append the type attribute
1387 
1388  QDomElement mapLayerNode = layer_node.toElement();
1389 
1390  if ( mapLayerNode.isNull() || "maplayer" != mapLayerNode.nodeName() )
1391  {
1392  QgsMessageLog::logMessage( tr( "<maplayer> not found." ), tr( "Raster" ) );
1393  return false;
1394  }
1395 
1396  mapLayerNode.setAttribute( QStringLiteral( "type" ), QStringLiteral( "raster" ) );
1397 
1398  // add provider node
1399 
1400  QDomElement provider = document.createElement( QStringLiteral( "provider" ) );
1401  QDomText providerText = document.createTextNode( mProviderKey );
1402  provider.appendChild( providerText );
1403  layer_node.appendChild( provider );
1404 
1405  // User no data
1406  QDomElement noData = document.createElement( QStringLiteral( "noData" ) );
1407 
1408  for ( int bandNo = 1; bandNo <= mDataProvider->bandCount(); bandNo++ )
1409  {
1410  QDomElement noDataRangeList = document.createElement( QStringLiteral( "noDataList" ) );
1411  noDataRangeList.setAttribute( QStringLiteral( "bandNo" ), bandNo );
1412  noDataRangeList.setAttribute( QStringLiteral( "useSrcNoData" ), mDataProvider->useSourceNoDataValue( bandNo ) );
1413 
1414  Q_FOREACH ( QgsRasterRange range, mDataProvider->userNoDataValues( bandNo ) )
1415  {
1416  QDomElement noDataRange = document.createElement( QStringLiteral( "noDataRange" ) );
1417 
1418  noDataRange.setAttribute( QStringLiteral( "min" ), QgsRasterBlock::printValue( range.min() ) );
1419  noDataRange.setAttribute( QStringLiteral( "max" ), QgsRasterBlock::printValue( range.max() ) );
1420  noDataRangeList.appendChild( noDataRange );
1421  }
1422 
1423  noData.appendChild( noDataRangeList );
1424 
1425  }
1426  if ( noData.hasChildNodes() )
1427  {
1428  layer_node.appendChild( noData );
1429  }
1430 
1431  writeStyleManager( layer_node, document );
1432 
1433  //write out the symbology
1434  QString errorMsg;
1435  return writeSymbology( layer_node, document, errorMsg );
1436 }
1437 
1439 {
1440  if ( !mDataProvider ) return 0;
1441  return mDataProvider->xSize();
1442 }
1443 
1445 {
1446  if ( !mDataProvider ) return 0;
1447  return mDataProvider->ySize();
1448 }
1449 
1451 //
1452 // Private methods
1453 //
1455 bool QgsRasterLayer::update()
1456 {
1457  QgsDebugMsgLevel( "entered.", 4 );
1458  // Check if data changed
1459  if ( mDataProvider->dataTimestamp() > mDataProvider->timestamp() )
1460  {
1461  QgsDebugMsgLevel( "reload data", 4 );
1462  closeDataProvider();
1463  init();
1464  setDataProvider( mProviderKey );
1465  emit dataChanged();
1466  }
1467  return mValid;
1468 }
virtual QgsRectangle extent() const override=0
Returns the extent of the layer.
bool writeStyle(QDomNode &node, QDomDocument &doc, QString &errorMessage) const override
Write the style for the layer into the docment provided.
QgsDataProvider * classFactoryFunction_t(const QString *)
static void convertRasterProperties(QDomDocument &doc, QDomNode &parentNode, QDomElement &rasterPropertiesElem, QgsRasterLayer *rlayer)
bool readSymbology(const QDomNode &node, QString &errorMessage) override
Read the symbology for the current layer from the Dom node supplied.
int width() const
Accessor that returns the width of the (unclipped) raster.
virtual int bandCount() const =0
Get number of bands.
virtual void setSubLayerVisibility(const QString &name, bool vis)
Set the visibility of the given sublayer name.
void onProgress(int, double, const QString &)
receive progress signal from provider
void setRenderer(QgsRasterRenderer *theRenderer)
Set raster renderer. Takes ownership of the renderer object.
#define ERR(message)
void setContrastEnhancementAlgorithm(ContrastEnhancementAlgorithm, bool generateTable=true)
Set the contrast enhancement algorithm.
IdentifyFormat
Definition: qgsraster.h:71
static QgsProviderRegistry * instance(const QString &pluginPath=QString::null)
Means of accessing canonical single instance.
A rectangle specified with double values.
Definition: qgsrectangle.h:35
Base class for all map layer types.
Definition: qgsmaplayer.h:49
Thirty two bit signed integer (qint32)
Definition: qgis.h:67
Interface for all raster shaders.
virtual QDateTime timestamp() const override
Time stamp of data source in the moment when data/metadata were loaded by provider.
virtual QStringList subLayers() const override
Returns the sublayers of this layer - Useful for providers that manage their own layers, such as WMS.
double rasterUnitsPerPixelY()
static QString printValue(double value)
Print double value with all necessary significant digits.
virtual void setUseSourceNoDataValue(int bandNo, bool use)
Set source nodata value usage.
double sum
The sum of all cells in the band. NO_DATA values are excluded.
Iterator for sequentially processing raster cells.
void readCustomProperties(const QDomNode &layerNode, const QString &keyStartsWith="")
Read custom properties from project file.
int bandCount() const
Get the number of bands in this layer.
QgsHueSaturationFilter * hueSaturationFilter() const
DrawingStyle
This enumerator describes the different kinds of drawing we can do.
Definition: qgsraster.h:112
A ramp shader will color a raster pixel based on a list of values ranges in a ramp.
virtual QList< QgsColorRampShader::ColorRampItem > colorTable(int bandNo) const
virtual QgsError error() const
Get current status error.
QgsRasterRenderer * renderer() const
#define QgsDebugMsg(str)
Definition: qgslogger.h:33
virtual QString generateBandName(int theBandNumber) const
helper function to create zero padded band names
virtual void setLayerOrder(const QStringList &layers) override
Reorders the previously selected sublayers of this layer from bottom to top.
void setContrastEnhancement(QgsContrastEnhancement::ContrastEnhancementAlgorithm theAlgorithm, QgsRaster::ContrastEnhancementLimits theLimits=QgsRaster::ContrastEnhancementMinMax, const QgsRectangle &theExtent=QgsRectangle(), int theSampleSize=SAMPLE_SIZE, bool theGenerateLookupTableFlag=true)
Set contrast enhancement algorithm.
bool readStyle(const QDomNode &node, QString &errorMessage) override
Read the style information for the current layer from the Dom node supplied.
void setDefaultContrastEnhancement()
Set default contrast enhancement.
QgsRasterProjector * projector() const
void setCustomProperty(const QString &key, const QVariant &value)
Set a custom property for layer.
virtual QString type() const
Thirty two bit unsigned integer (quint32)
Definition: qgis.h:66
static BlendMode getBlendModeEnum(QPainter::CompositionMode blendMode)
Returns a BlendMode corresponding to a QPainter::CompositionMode.
Definition: qgspainting.cpp:66
void setCrs(const QgsCoordinateReferenceSystem &theSrcCRS, const QgsCoordinateReferenceSystem &theDestCRS, int srcDatumTransform=-1, int destDatumTransform=-1)
set source and destination CRS
DataType
Raster data types.
Definition: qgis.h:60
QgsRasterInterface * last() const
Definition: qgsrasterpipe.h:88
QString toProj4() const
Returns a Proj4 string representation of this CRS.
double maximumValue
The maximum cell value in the raster band.
virtual int ySize() const
int mWidth
Width, number of columns to be rendered.
static QDateTime lastModified(const QString &name)
Return time stamp for given file name.
double max() const
Raster values range container.
QString bandName(int theBandNoInt) const
Get the name of a band given its number.
static bool isValidRasterFileName(const QString &theFileNameQString, QString &retError)
This helper checks to see whether the file name appears to be a valid raster file name...
Resample filter pipe for rasters.
Abstract base class for spatial data provider implementations.
void setColorRampItemList(const QList< QgsColorRampShader::ColorRampItem > &theList)
Set custom colormap.
QgsRasterRenderer * renderer() const
int height() const
Accessor that returns the height of the (unclipped) raster.
static const double SAMPLE_SIZE
Default sample size (number of pixels) for estimated statistics/histogram calculation.
Thirty two bit floating point (float)
Definition: qgis.h:68
bool readXml(const QDomNode &layer_node) override
Reads layer specific state from project file Dom node.
Implementation of threaded rendering for raster layers.
void setBlendMode(QPainter::CompositionMode blendMode)
Set the blending mode used for rendering a layer.
QgsMapLayer::LayerType type() const
Returns the type of the layer.
Definition: qgsmaplayer.cpp:95
static QPainter::CompositionMode getCompositionMode(BlendMode blendMode)
Returns a QPainter::CompositionMode corresponding to a BlendMode.
Definition: qgspainting.cpp:6
void readXml(const QDomElement &filterElem) override
Sets base class members from xml. Usually called from create() methods of subclasses.
Sixteen bit signed integer (qint16)
Definition: qgis.h:65
virtual QDateTime timestamp() const override
Time stamp of data source in the moment when data/metadata were loaded by provider.
Complex Int16.
Definition: qgis.h:70
virtual double sourceNoDataValue(int bandNo) const
Value representing no data value.
QString mLayerName
Name of the layer - used for display.
Definition: qgsmaplayer.h:826
void setShader(QgsRasterShader *shader)
Takes ownership of the shader.
void styleChanged()
Signal emitted whenever a change affects the layer&#39;s style.
double rasterUnitsPerPixelX()
Returns the number of raster units per each raster pixel. In a world file, this is normally the first...
void setGreenContrastEnhancement(QgsContrastEnhancement *ce)
Takes ownership.
void statusChanged(const QString &) const
Emit a message to be displayed on status bar, usually used by network providers (WMS,WCS)
Sixty four bit floating point (double)
Definition: qgis.h:69
static QString identifyFormatName(QgsRaster::IdentifyFormat format)
QgsCoordinateReferenceSystem mDestCRS
Target coordinate system.
QgsBrightnessContrastFilter * brightnessFilter() const
void statusChanged(const QString &status)
Emit a signal with status (e.g. to be caught by QgisApp and display a msg on status bar) ...
QString toString(bool automaticPrecision=false) const
returns string representation of form xmin,ymin xmax,ymax
virtual Qgis::DataType sourceDataType(int bandNo) const override=0
Returns source data type for the band specified by number, source data type may be shorter than dataT...
Color, alpha, red, green, blue, 4 bytes the same as QImage::Format_ARGB32_Premultiplied.
Definition: qgis.h:75
Perform transforms between map coordinates and device coordinates.
Definition: qgsmaptopixel.h:33
bool writeSymbology(QDomNode &, QDomDocument &doc, QString &errorMessage) const override
Write the symbology for the layer into the docment provided.
virtual QgsRasterBandStats bandStatistics(int theBandNo, int theStats=QgsRasterBandStats::All, const QgsRectangle &theExtent=QgsRectangle(), int theSampleSize=0)
Get band statistics.
The drawing pipe for raster layers.
double stdDev
The standard deviation of the cell values.
Paletted (see associated color table)
Definition: qgsraster.h:38
Alpha (0=transparent, 255=opaque)
Definition: qgsraster.h:46
The RasterBandStats struct is a container for statistics about a single raster band.
static QgsRasterRendererRegistry * instance()
static ContrastEnhancementLimits contrastEnhancementLimitsFromString(const QString &theLimits)
Definition: qgsraster.cpp:38
double mean
The mean cell value for the band. NO_DATA values are excluded.
virtual Qgis::DataType dataType(int bandNo) const override=0
Returns data type for the band specified by number.
Continuous palette, QGIS addition, GRASS.
Definition: qgsraster.h:68
void readStyleManager(const QDomNode &layerNode)
Read style manager&#39;s configuration (if any). To be called by subclasses.
bool writeXml(QDomNode &layer_node, QDomDocument &doc) const override
Write layer specific state to project file Dom node.
void setRedContrastEnhancement(QgsContrastEnhancement *ce)
Takes ownership.
QgsDataProvider * provider(const QString &providerKey, const QString &dataSource)
Create an instance of the provider.
#define QgsDebugMsgLevel(str, level)
Definition: qgslogger.h:34
bool isEmpty() const
test if rectangle is empty.
void setCrs(const QgsCoordinateReferenceSystem &srs, bool emitSignal=true)
Sets layer&#39;s spatial reference system.
virtual int capabilities() const
Returns a bitmask containing the supported capabilities.
virtual bool isValid() const =0
Returns true if this is a valid layer.
virtual QgsCoordinateReferenceSystem crs() const =0
Returns the coordinate system for the data source.
virtual QStringList subLayers() const override
Returns the sublayers of this layer - useful for providers that manage their own layers, such as WMS.
QString providerType() const
[ data provider interface ] Which provider is being used for this Raster Layer?
double width() const
Width of the rectangle.
Definition: qgsrectangle.h:211
virtual void setExtent(const QgsRectangle &rect)
Set the extent.
bool shade(double, int *, int *, int *, int *) override
Generates and new RGB value based on one input value.
QString metadata() const override
Obtain GDAL Metadata for this layer.
static const double CUMULATIVE_CUT_UPPER
Default cumulative cut upper limit.
Complex Float32.
Definition: qgis.h:72
~QgsRasterLayer()
The destructor.
ContrastEnhancementLimits
Contrast enhancement limits.
Definition: qgsraster.h:103
virtual QString dataSourceUri(bool expandAuthConfig=false) const
Get the data source specification.
qgssize elementCount
The number of not no data cells in the band.
void setMinimumValue(double, bool generateTable=true)
Return the minimum value for the contrast enhancement range.
static void logMessage(const QString &message, const QString &tag=QString::null, MessageLevel level=WARNING)
add a message to the instance (and create it if necessary)
void setEncodedUri(const QByteArray &uri)
set complete encoded uri (generic mode)
Raster renderer pipe for single band pseudocolor.
QgsCoordinateReferenceSystem crs() const
Returns the layer&#39;s spatial reference system.
bool isvalidrasterfilename_t(QString const &theFileNameQString, QString &retErrMsg)
Raster renderer pipe for single band gray.
Complex Int32.
Definition: qgis.h:71
static int typeSize(int dataType)
void setParam(const QString &key, const QString &value)
Set generic param (generic mode)
virtual QgsMapLayerRenderer * createMapRenderer(QgsRenderContext &rendererContext) override
Return new instance of QgsMapLayerRenderer that will be used for rendering of given context...
Sixteen bit unsigned integer (quint16)
Definition: qgis.h:64
virtual void setLayerOrder(const QStringList &layers)
Reorder the list of layer names to be rendered by this provider (in order from bottom to top) ...
void rendererChanged()
Signal emitted when renderer is changed.
void setAlphaBand(int band)
bool mValid
Indicates if the layer is valid and can be drawn.
Definition: qgsmaplayer.h:820
#define cast_to_fptr(f)
Definition: qgis.h:126
void setName(const QString &name)
Set the display name of the layer.
void setDataProvider(const QString &provider)
[ data provider interface ] Set the data provider
void setRasterShaderFunction(QgsRasterShaderFunction *)
A public method that allows the user to set their own shader function.
Base class for processing filters like renderers, reprojector, resampler etc.
A class to represent a point.
Definition: qgspoint.h:111
void setColorRampType(QgsColorRampShader::ColorRamp_TYPE theColorRampType)
Set the color ramp type.
virtual void setSubLayerVisibility(const QString &name, bool vis) override
Set the visibility of the given sublayer name.
virtual bool sourceHasNoDataValue(int bandNo) const
Return true if source band has no data value.
QPixmap paletteAsPixmap(int theBandNumber=1)
Get an 100x100 pixmap of the color palette. If the layer has no palette a white pixmap will be return...
int size() const
Definition: qgsrasterpipe.h:86
static ContrastEnhancementAlgorithm contrastEnhancementAlgorithmFromString(const QString &contrastEnhancementString)
QgsCoordinateReferenceSystem mSrcCRS
Source coordinate system.
void writeStyleManager(QDomNode &layerNode, QDomDocument &doc) const
Write style manager&#39;s configuration (if exists). To be called by subclasses.
QgsRasterProjector implements approximate projection support for it calculates grid of points in sour...
void progressUpdate(int theValue)
Signal for notifying listeners of long running processes.
void showProgress(int theValue)
[ data provider interface ] A wrapper function to emit a progress update signal
Registry for raster renderer entries.
QList< QPair< QString, QColor > > QgsLegendColorList
QgsPoint mBottomRightPoint
Coordinate (in output device coordinate system) of bottom right corner of the part of the raster that...
virtual bool hasStatistics(int theBandNo, int theStats=QgsRasterBandStats::All, const QgsRectangle &theExtent=QgsRectangle(), int theSampleSize=0)
Returns true if histogram is available (cached, already calculated).
QImage previewAsImage(QSize size, const QColor &bgColor=Qt::white, QImage::Format format=QImage::Format_ARGB32_Premultiplied)
Draws a preview of the rasterlayer into a QImage.
void setContrastEnhancement(QgsContrastEnhancement *ce)
Takes ownership.
ContrastEnhancementAlgorithm
This enumerator describes the types of contrast enhancement algorithms that can be used...
virtual QString loadDefaultStyle(bool &resultFlag)
Retrieve the default style for this layer if one exists (either as a .qml file on disk or as a record...
Contains information about the context of a rendering operation.
QString name() const
Returns the display name of the layer.
static QgsMapLayerLegend * defaultRasterLegend(QgsRasterLayer *rl)
Create new legend implementation for raster layer.
QgsRasterResampleFilter * resampleFilter() const
Set raster resample filter. Takes ownership of the resample filter object.
bool remove(int idx)
Remove and delete interface at given index if possible.
QList< QgsRasterRange > QgsRasterRangeList
void progress(int theType, double theProgress, const QString &theMessage)
Emit a signal to notify of the progress event.
QString mDataSource
Data source description string, varies by layer type.
Definition: qgsmaplayer.h:823
Interpolates the color between two class breaks linearly.
virtual QString metadata()=0
Get metadata in a format suitable for feeding directly into a subset of the GUI raster properties "Me...
virtual void reloadData()
Reloads the data from the source.
QByteArray encodedUri() const
return complete encoded uri (generic mode)
void repaintRequested()
By emitting this signal the layer tells that either appearance or content have been changed and any v...
int mHeight
Distance in map units from bottom edge to top edge for the part of the raster that is to be rendered...
Brightness/contrast filter pipe for rasters.
This class represents a coordinate reference system (CRS).
Assigns the color of the higher class for every pixel between two class breaks.
Color and saturation filter pipe for rasters.
void draw(QPainter *theQPainter, QgsRasterViewPort *myRasterViewPort, const QgsMapToPixel *theQgsMapToPixel=nullptr)
This is an overloaded version of the draw() function that is called by both draw() and thumbnailAsPix...
static const double CUMULATIVE_CUT_LOWER
Default cumulative cut lower limit.
virtual QString description() const =0
Return description.
double range
The range is the distance between min & max.
void setBlueContrastEnhancement(QgsContrastEnhancement *ce)
Takes ownership.
Greyscale.
Definition: qgsraster.h:36
double minimumValue
The minimum cell value in the raster band.
Renderer for multiband images with the color components.
virtual int colorInterpretation(int theBandNo) const
Returns data type for the band specified by number.
void dataChanged()
Data of layer changed.
void appendError(const QgsErrorMessage &error)
Add error message.
Definition: qgsmaplayer.h:812
virtual QgsRasterRangeList userNoDataValues(int bandNo) const
Get list of user no data value ranges.
Base class for utility classes that encapsulate information necessary for rendering of map layers...
Manipulates raster pixel values so that they enhanceContrast or clip into a specified numerical range...
void readXml(const QDomElement &filterElem) override
Sets base class members from xml. Usually called from create() methods of subclasses.
QgsRasterDataProvider * dataProvider()
Returns the data provider.
QgsPoint mTopLeftPoint
Coordinate (in output device coordinate system) of top left corner of the part of the raster that is ...
This class provides details of the viewable area that a raster will be rendered into.
virtual bool useSourceNoDataValue(int bandNo) const
Get source nodata value usage.
virtual void legendSymbologyItems(QList< QPair< QString, QColor > > &symbolItems) const
Get symbology items if provided by renderer.
double min() const
virtual void reload() override
Synchronises with changes in the datasource.
void setLegend(QgsMapLayerLegend *legend)
Assign a legend controller to the map layer.
Class for storing the component parts of a PostgreSQL/RDBMS datasource URI.
virtual void setUserNoDataValue(int bandNo, const QgsRasterRangeList &noData)
virtual void cumulativeCut(int theBandNo, double theLowerCount, double theUpperCount, double &theLowerValue, double &theUpperValue, const QgsRectangle &theExtent=QgsRectangle(), int theSampleSize=0)
Find values for cumulative pixel count cut.
Complex Float64.
Definition: qgis.h:73
QgsLegendColorList legendSymbologyItems() const
Returns a list with classification items (Text and color)
void readXml(const QDomElement &filterElem) override
Sets base class members from xml. Usually called from create() methods of subclasses.
bool set(QgsRasterInterface *theInterface)
Insert a new known interface in default place or replace interface of the same role if it already exi...
virtual int xSize() const
Get raster size.
Raster renderer pipe that applies colors to a raster.
QgsRasterRendererCreateFunc rendererCreateFunction
void setError(const QgsError &error)
Set error message.
Definition: qgsmaplayer.h:814
void setMaximumValue(double, bool generateTable=true)
Set the maximum value for the contrast enhancement range.
void showStatusMessage(const QString &theMessage)
Eight bit unsigned integer (quint8)
Definition: qgis.h:63
virtual QDateTime dataTimestamp() const override
Current time stamp of data source.
Color, alpha, red, green, blue, 4 bytes the same as QImage::Format_ARGB32.
Definition: qgis.h:74
QPainter::CompositionMode blendMode() const
Returns the current blending mode for a layer.
double height() const
Height of the rectangle.
Definition: qgsrectangle.h:216
QgsRectangle mDrawnExtent
Intersection of current map extent and layer extent.
Base class for raster data providers.
double sumOfSquares
The sum of the squares. Used to calculate standard deviation.
QgsRasterLayer()
Constructor. Provider is not set.