QGIS API Documentation  2.99.0-Master (5169e0d)
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 "qgsmaptopixel.h"
27 #include "qgsmessagelog.h"
29 #include "qgspainting.h"
32 #include "qgsproviderregistry.h"
33 #include "qgsrasterdataprovider.h"
34 #include "qgsrasterdrawer.h"
35 #include "qgsrasteriterator.h"
36 #include "qgsrasterlayer.h"
37 #include "qgsrasterlayerrenderer.h"
38 #include "qgsrasterprojector.h"
39 #include "qgsrasterrange.h"
42 #include "qgsrastershader.h"
43 #include "qgsrectangle.h"
44 #include "qgsrendercontext.h"
48 #include "qgssettings.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 <QSlider>
74 #include <QTime>
75 
76 // typedefs for provider plugin functions of interest
77 typedef bool isvalidrasterfilename_t( QString const &fileNameQString, QString &retErrMsg );
78 
79 #define ERR(message) QGS_ERROR_MESSAGE(message,"Raster layer")
80 
81 const double QgsRasterLayer::SAMPLE_SIZE = 250000;
82 
89 
96 
98  : QgsMapLayer( RasterLayer )
99  , QSTRING_NOT_SET( QStringLiteral( "Not Set" ) )
100  , TRSTRING_NOT_SET( tr( "Not Set" ) )
101  , mDataProvider( nullptr )
102 {
103  init();
104  mValid = false;
105 }
106 
107 QgsRasterLayer::QgsRasterLayer( const QString &uri,
108  const QString &baseName,
109  const QString &providerKey,
110  bool loadDefaultStyleFlag )
111  : QgsMapLayer( RasterLayer, baseName, uri )
112  // Constant that signals property not used.
113  , QSTRING_NOT_SET( QStringLiteral( "Not Set" ) )
114  , TRSTRING_NOT_SET( tr( "Not Set" ) )
115  , mDataProvider( nullptr )
116  , mProviderKey( providerKey )
117 {
118  QgsDebugMsgLevel( "Entered", 4 );
119  init();
120  setDataProvider( providerKey );
121  if ( !mValid ) return;
122 
123  // load default style
124  bool defaultLoadedFlag = false;
125  if ( mValid && loadDefaultStyleFlag )
126  {
127  loadDefaultStyle( defaultLoadedFlag );
128  }
129  if ( !defaultLoadedFlag )
130  {
132  }
133 
134  // TODO: Connect signals from the dataprovider to the qgisapp
135 
136  emit statusChanged( tr( "QgsRasterLayer created" ) );
137 } // QgsRasterLayer ctor
138 
140 {
141  emit willBeDeleted();
142 
143  mValid = false;
144  // Note: provider and other interfaces are owned and deleted by pipe
145 }
146 
148 //
149 // Static Methods and members
150 //
152 
156 bool QgsRasterLayer::isValidRasterFileName( const QString &fileNameQString, QString &retErrMsg )
157 {
158  isvalidrasterfilename_t *pValid = reinterpret_cast< isvalidrasterfilename_t * >( cast_to_fptr( QgsProviderRegistry::instance()->function( "gdal", "isValidRasterFileName" ) ) );
159  if ( ! pValid )
160  {
161  QgsDebugMsg( "Could not resolve isValidRasterFileName in gdal provider library" );
162  return false;
163  }
164 
165  bool myIsValid = pValid( fileNameQString, retErrMsg );
166  return myIsValid;
167 }
168 
169 bool QgsRasterLayer::isValidRasterFileName( QString const &fileNameQString )
170 {
171  QString retErrMsg;
172  return isValidRasterFileName( fileNameQString, retErrMsg );
173 }
174 
175 QDateTime QgsRasterLayer::lastModified( QString const &name )
176 {
177  QgsDebugMsgLevel( "name=" + name, 4 );
178  QDateTime t;
179 
180  QFileInfo fi( name );
181 
182  // Is it file?
183  if ( !fi.exists() )
184  return t;
185 
186  t = fi.lastModified();
187 
188  QgsDebugMsgLevel( "last modified = " + t.toString(), 4 );
189 
190  return t;
191 }
192 
193 // typedef for the QgsDataProvider class factory
194 typedef QgsDataProvider *classFactoryFunction_t( const QString * );
195 
197 //
198 // Non Static Public methods
199 //
201 
203 {
204  if ( !mDataProvider ) return 0;
205  return mDataProvider->bandCount();
206 }
207 
208 QString QgsRasterLayer::bandName( int bandNo ) const
209 {
210  return dataProvider()->generateBandName( bandNo );
211 }
212 
213 void QgsRasterLayer::setRendererForDrawingStyle( QgsRaster::DrawingStyle drawingStyle )
214 {
215  setRenderer( QgsApplication::rasterRendererRegistry()->defaultRendererForDrawingStyle( drawingStyle, mDataProvider ) );
216 }
217 
222 {
223  return mDataProvider;
224 }
225 
230 {
231  return mDataProvider;
232 }
233 
235 {
236  if ( mDataProvider )
237  {
238  mDataProvider->reloadData();
239  }
240 }
241 
243 {
244  return new QgsRasterLayerRenderer( this, rendererContext );
245 }
246 
247 
248 void QgsRasterLayer::draw( QPainter *theQPainter,
249  QgsRasterViewPort *rasterViewPort,
250  const QgsMapToPixel *qgsMapToPixel )
251 {
252  QgsDebugMsgLevel( " 3 arguments", 4 );
253  QTime time;
254  time.start();
255  //
256  //
257  // The goal here is to make as many decisions as possible early on (outside of the rendering loop)
258  // so that we can maximise performance of the rendering process. So now we check which drawing
259  // procedure to use :
260  //
261 
262  QgsRasterProjector *projector = mPipe.projector();
263 
264  // TODO add a method to interface to get provider and get provider
265  // params in QgsRasterProjector
266  if ( projector )
267  {
268  projector->setCrs( rasterViewPort->mSrcCRS, rasterViewPort->mDestCRS, rasterViewPort->mSrcDatumTransform, rasterViewPort->mDestDatumTransform );
269  }
270 
271  // Drawer to pipe?
272  QgsRasterIterator iterator( mPipe.last() );
273  QgsRasterDrawer drawer( &iterator );
274  drawer.draw( theQPainter, rasterViewPort, qgsMapToPixel );
275 
276  QgsDebugMsgLevel( QString( "total raster draw time (ms): %1" ).arg( time.elapsed(), 5 ), 4 );
277 } //end of draw method
278 
280 {
281  QList< QPair< QString, QColor > > symbolList;
283  if ( renderer )
284  {
285  renderer->legendSymbologyItems( symbolList );
286  }
287  return symbolList;
288 }
289 
291 {
292  QgsRasterDataProvider *provider = const_cast< QgsRasterDataProvider * >( mDataProvider );
293  QString myMetadata;
294  myMetadata += "<p class=\"glossy\">" + tr( "Driver" ) + "</p>\n";
295  myMetadata += QLatin1String( "<p>" );
296  myMetadata += mDataProvider->description();
297  myMetadata += QLatin1String( "</p>\n" );
298 
299  // Insert provider-specific (e.g. WMS-specific) metadata
300  // crashing
301  myMetadata += mDataProvider->metadata();
302 
303  myMetadata += QLatin1String( "<p class=\"glossy\">" );
304  myMetadata += tr( "No Data Value" );
305  myMetadata += QLatin1String( "</p>\n" );
306  myMetadata += QLatin1String( "<p>" );
307  // TODO: all bands
308  if ( mDataProvider->sourceHasNoDataValue( 1 ) )
309  {
310  myMetadata += QString::number( mDataProvider->sourceNoDataValue( 1 ) );
311  }
312  else
313  {
314  myMetadata += '*' + tr( "NoDataValue not set" ) + '*';
315  }
316  myMetadata += QLatin1String( "</p>\n" );
317 
318  myMetadata += QLatin1String( "</p>\n" );
319  myMetadata += QLatin1String( "<p class=\"glossy\">" );
320  myMetadata += tr( "Data Type" );
321  myMetadata += QLatin1String( "</p>\n" );
322  myMetadata += QLatin1String( "<p>" );
323  //just use the first band
324  switch ( mDataProvider->sourceDataType( 1 ) )
325  {
326  case Qgis::Byte:
327  myMetadata += tr( "Byte - Eight bit unsigned integer" );
328  break;
329  case Qgis::UInt16:
330  myMetadata += tr( "UInt16 - Sixteen bit unsigned integer " );
331  break;
332  case Qgis::Int16:
333  myMetadata += tr( "Int16 - Sixteen bit signed integer " );
334  break;
335  case Qgis::UInt32:
336  myMetadata += tr( "UInt32 - Thirty two bit unsigned integer " );
337  break;
338  case Qgis::Int32:
339  myMetadata += tr( "Int32 - Thirty two bit signed integer " );
340  break;
341  case Qgis::Float32:
342  myMetadata += tr( "Float32 - Thirty two bit floating point " );
343  break;
344  case Qgis::Float64:
345  myMetadata += tr( "Float64 - Sixty four bit floating point " );
346  break;
347  case Qgis::CInt16:
348  myMetadata += tr( "CInt16 - Complex Int16 " );
349  break;
350  case Qgis::CInt32:
351  myMetadata += tr( "CInt32 - Complex Int32 " );
352  break;
353  case Qgis::CFloat32:
354  myMetadata += tr( "CFloat32 - Complex Float32 " );
355  break;
356  case Qgis::CFloat64:
357  myMetadata += tr( "CFloat64 - Complex Float64 " );
358  break;
359  default:
360  myMetadata += tr( "Could not determine raster data type." );
361  }
362  myMetadata += QLatin1String( "</p>\n" );
363 
364  myMetadata += QLatin1String( "<p class=\"glossy\">" );
365  myMetadata += tr( "Pyramid overviews" );
366  myMetadata += QLatin1String( "</p>\n" );
367  myMetadata += QLatin1String( "<p>" );
368 
369  myMetadata += QLatin1String( "<p class=\"glossy\">" );
370  myMetadata += tr( "Layer Spatial Reference System" );
371  myMetadata += QLatin1String( "</p>\n" );
372  myMetadata += QLatin1String( "<p>" );
373  myMetadata += crs().toProj4();
374  myMetadata += QLatin1String( "</p>\n" );
375 
376  myMetadata += QLatin1String( "<p class=\"glossy\">" );
377  myMetadata += tr( "Layer Extent (layer original source projection)" );
378  myMetadata += QLatin1String( "</p>\n" );
379  myMetadata += QLatin1String( "<p>" );
380  myMetadata += mDataProvider->extent().toString();
381  myMetadata += QLatin1String( "</p>\n" );
382 
383  // output coordinate system
384  // TODO: this is not related to layer, to be removed? [MD]
385 #if 0
386  myMetadata += "<tr><td class=\"glossy\">";
387  myMetadata += tr( "Project Spatial Reference System" );
388  myMetadata += "</p>\n";
389  myMetadata += "<p>";
390  myMetadata += mCoordinateTransform->destCRS().toProj4();
391  myMetadata += "</p>\n";
392 #endif
393 
394  //
395  // Add the stats for each band to the output table
396  //
397  int myBandCountInt = bandCount();
398  for ( int myIteratorInt = 1; myIteratorInt <= myBandCountInt; ++myIteratorInt )
399  {
400  QgsDebugMsgLevel( "Raster properties : checking if band " + QString::number( myIteratorInt ) + " has stats? ", 4 );
401  //band name
402  myMetadata += QLatin1String( "<p class=\"glossy\">\n" );
403  myMetadata += tr( "Band" );
404  myMetadata += QLatin1String( "</p>\n" );
405  myMetadata += QLatin1String( "<p>" );
406  myMetadata += bandName( myIteratorInt );
407  myMetadata += QLatin1String( "</p>\n" );
408  //band number
409  myMetadata += QLatin1String( "<p>" );
410  myMetadata += tr( "Band No" );
411  myMetadata += QLatin1String( "</p>\n" );
412  myMetadata += QLatin1String( "<p>\n" );
413  myMetadata += QString::number( myIteratorInt );
414  myMetadata += QLatin1String( "</p>\n" );
415 
416  //check if full stats for this layer have already been collected
417  if ( !provider->hasStatistics( myIteratorInt ) ) //not collected
418  {
419  QgsDebugMsgLevel( ".....no", 4 );
420 
421  myMetadata += QLatin1String( "<p>" );
422  myMetadata += tr( "No Stats" );
423  myMetadata += QLatin1String( "</p>\n" );
424  myMetadata += QLatin1String( "<p>\n" );
425  myMetadata += tr( "No stats collected yet" );
426  myMetadata += QLatin1String( "</p>\n" );
427  }
428  else // collected - show full detail
429  {
430  QgsDebugMsgLevel( ".....yes", 4 );
431 
432  QgsRasterBandStats myRasterBandStats = provider->bandStatistics( myIteratorInt );
433  //Min Val
434  myMetadata += QLatin1String( "<p>" );
435  myMetadata += tr( "Min Val" );
436  myMetadata += QLatin1String( "</p>\n" );
437  myMetadata += QLatin1String( "<p>\n" );
438  myMetadata += QString::number( myRasterBandStats.minimumValue, 'f', 10 );
439  myMetadata += QLatin1String( "</p>\n" );
440 
441  // Max Val
442  myMetadata += QLatin1String( "<p>" );
443  myMetadata += tr( "Max Val" );
444  myMetadata += QLatin1String( "</p>\n" );
445  myMetadata += QLatin1String( "<p>\n" );
446  myMetadata += QString::number( myRasterBandStats.maximumValue, 'f', 10 );
447  myMetadata += QLatin1String( "</p>\n" );
448 
449  // Range
450  myMetadata += QLatin1String( "<p>" );
451  myMetadata += tr( "Range" );
452  myMetadata += QLatin1String( "</p>\n" );
453  myMetadata += QLatin1String( "<p>\n" );
454  myMetadata += QString::number( myRasterBandStats.range, 'f', 10 );
455  myMetadata += QLatin1String( "</p>\n" );
456 
457  // Mean
458  myMetadata += QLatin1String( "<p>" );
459  myMetadata += tr( "Mean" );
460  myMetadata += QLatin1String( "</p>\n" );
461  myMetadata += QLatin1String( "<p>\n" );
462  myMetadata += QString::number( myRasterBandStats.mean, 'f', 10 );
463  myMetadata += QLatin1String( "</p>\n" );
464 
465  //sum of squares
466  myMetadata += QLatin1String( "<p>" );
467  myMetadata += tr( "Sum of squares" );
468  myMetadata += QLatin1String( "</p>\n" );
469  myMetadata += QLatin1String( "<p>\n" );
470  myMetadata += QString::number( myRasterBandStats.sumOfSquares, 'f', 10 );
471  myMetadata += QLatin1String( "</p>\n" );
472 
473  //standard deviation
474  myMetadata += QLatin1String( "<p>" );
475  myMetadata += tr( "Standard Deviation" );
476  myMetadata += QLatin1String( "</p>\n" );
477  myMetadata += QLatin1String( "<p>\n" );
478  myMetadata += QString::number( myRasterBandStats.stdDev, 'f', 10 );
479  myMetadata += QLatin1String( "</p>\n" );
480 
481  //sum of all cells
482  myMetadata += QLatin1String( "<p>" );
483  myMetadata += tr( "Sum of all cells" );
484  myMetadata += QLatin1String( "</p>\n" );
485  myMetadata += QLatin1String( "<p>\n" );
486  myMetadata += QString::number( myRasterBandStats.sum, 'f', 10 );
487  myMetadata += QLatin1String( "</p>\n" );
488 
489  //number of cells
490  myMetadata += QLatin1String( "<p>" );
491  myMetadata += tr( "Cell Count" );
492  myMetadata += QLatin1String( "</p>\n" );
493  myMetadata += QLatin1String( "<p>\n" );
494  myMetadata += QString::number( myRasterBandStats.elementCount );
495  myMetadata += QLatin1String( "</p>\n" );
496  }
497  }
498 
499  QgsDebugMsgLevel( myMetadata, 4 );
500  return myMetadata;
501 }
502 
507 QPixmap QgsRasterLayer::paletteAsPixmap( int bandNumber )
508 {
509  //TODO: This function should take dimensions
510  QgsDebugMsgLevel( "entered.", 4 );
511 
512  // Only do this for the GDAL provider?
513  // Maybe WMS can do this differently using QImage::numColors and QImage::color()
514  if ( mDataProvider->colorInterpretation( bandNumber ) == QgsRaster::PaletteIndex )
515  {
516  QgsDebugMsgLevel( "....found paletted image", 4 );
517  QgsColorRampShader myShader;
518  QList<QgsColorRampShader::ColorRampItem> myColorRampItemList = mDataProvider->colorTable( bandNumber );
519  if ( !myColorRampItemList.isEmpty() )
520  {
521  QgsDebugMsgLevel( "....got color ramp item list", 4 );
522  myShader.setColorRampItemList( myColorRampItemList );
524  // Draw image
525  int mySize = 100;
526  QPixmap myPalettePixmap( mySize, mySize );
527  QPainter myQPainter( &myPalettePixmap );
528 
529  QImage myQImage = QImage( mySize, mySize, QImage::Format_RGB32 );
530  myQImage.fill( 0 );
531  myPalettePixmap.fill();
532 
533  double myStep = ( static_cast< double >( myColorRampItemList.size() ) - 1 ) / static_cast< double >( mySize * mySize );
534  double myValue = 0.0;
535  for ( int myRow = 0; myRow < mySize; myRow++ )
536  {
537  QRgb *myLineBuffer = reinterpret_cast< QRgb * >( myQImage.scanLine( myRow ) );
538  for ( int myCol = 0; myCol < mySize; myCol++ )
539  {
540  myValue = myStep * static_cast< double >( myCol + myRow * mySize );
541  int c1, c2, c3, c4;
542  myShader.shade( myValue, &c1, &c2, &c3, &c4 );
543  myLineBuffer[ myCol ] = qRgba( c1, c2, c3, c4 );
544  }
545  }
546 
547  myQPainter.drawImage( 0, 0, myQImage );
548  return myPalettePixmap;
549  }
550  QPixmap myNullPixmap;
551  return myNullPixmap;
552  }
553  else
554  {
555  //invalid layer was requested
556  QPixmap myNullPixmap;
557  return myNullPixmap;
558  }
559 }
560 
562 {
563  return mProviderKey;
564 }
565 
570 {
571 // We return one raster pixel per map unit pixel
572 // One raster pixel can have several raster units...
573 
574 // We can only use one of the mGeoTransform[], so go with the
575 // horisontal one.
576 
577  if ( mDataProvider->capabilities() & QgsRasterDataProvider::Size && mDataProvider->xSize() > 0 )
578  {
579  return mDataProvider->extent().width() / mDataProvider->xSize();
580  }
581  return 1;
582 }
583 
585 {
586  if ( mDataProvider->capabilities() & QgsRasterDataProvider::Size && mDataProvider->xSize() > 0 )
587  {
588  return mDataProvider->extent().height() / mDataProvider->ySize();
589  }
590  return 1;
591 }
592 
593 void QgsRasterLayer::init()
594 {
595  mRasterType = QgsRasterLayer::GrayOrUndefined;
596 
598 
599  setRendererForDrawingStyle( QgsRaster::UndefinedDrawingStyle );
600 
601  //Initialize the last view port structure, should really be a class
602  mLastViewPort.mWidth = 0;
603  mLastViewPort.mHeight = 0;
604 }
605 
606 void QgsRasterLayer::setDataProvider( QString const &provider )
607 {
608  QgsDebugMsgLevel( "Entered", 4 );
609  mValid = false; // assume the layer is invalid until we determine otherwise
610 
611  mPipe.remove( mDataProvider ); // deletes if exists
612  mDataProvider = nullptr;
613 
614  // XXX should I check for and possibly delete any pre-existing providers?
615  // XXX How often will that scenario occur?
616 
617  mProviderKey = provider;
618  // set the layer name (uppercase first character)
619  if ( ! mLayerName.isEmpty() ) // XXX shouldn't this happen in parent?
620  {
621  setName( mLayerName );
622  }
623 
624  //mBandCount = 0;
625 
626  mDataProvider = dynamic_cast< QgsRasterDataProvider * >( QgsProviderRegistry::instance()->provider( mProviderKey, mDataSource ) );
627  if ( !mDataProvider )
628  {
629  //QgsMessageLog::logMessage( tr( "Cannot instantiate the data provider" ), tr( "Raster" ) );
630  appendError( ERR( tr( "Cannot instantiate the '%1' data provider" ).arg( mProviderKey ) ) );
631  return;
632  }
633  QgsDebugMsgLevel( "Data provider created", 4 );
634 
635  // Set data provider into pipe even if not valid so that it is deleted with pipe (with layer)
636  mPipe.set( mDataProvider );
637  if ( !mDataProvider->isValid() )
638  {
639  setError( mDataProvider->error() );
640  appendError( ERR( tr( "Provider is not valid (provider: %1, URI: %2" ).arg( mProviderKey, mDataSource ) ) );
641  return;
642  }
643 
644  if ( provider == QLatin1String( "gdal" ) )
645  {
646  // make sure that the /vsigzip or /vsizip is added to uri, if applicable
647  mDataSource = mDataProvider->dataSourceUri();
648  }
649 
650  // get the extent
651  QgsRectangle mbr = mDataProvider->extent();
652 
653  // show the extent
654  QgsDebugMsgLevel( "Extent of layer: " + mbr.toString(), 4 );
655  // store the extent
656  setExtent( mbr );
657 
658  // upper case the first letter of the layer name
659  QgsDebugMsgLevel( "mLayerName: " + name(), 4 );
660 
661  // set up the raster drawing style
662  // Do not set any 'sensible' style here, the style is set later
663 
664  // Setup source CRS
665  setCrs( QgsCoordinateReferenceSystem( mDataProvider->crs() ) );
666 
667  QgsDebugMsgLevel( "using wkt:\n" + crs().toWkt(), 4 );
668 
669  //defaults - Needs to be set after the Contrast list has been build
670  //Try to read the default contrast enhancement from the config file
671 
672  //decide what type of layer this is...
673  //TODO Change this to look at the color interp and palette interp to decide which type of layer it is
674  QgsDebugMsgLevel( "bandCount = " + QString::number( mDataProvider->bandCount() ), 4 );
675  QgsDebugMsgLevel( "dataType = " + QString::number( mDataProvider->dataType( 1 ) ), 4 );
676  if ( ( mDataProvider->bandCount() > 1 ) )
677  {
678  // handle singleband gray with alpha
679  if ( mDataProvider->bandCount() == 2
680  && ( ( mDataProvider->colorInterpretation( 1 ) == QgsRaster::GrayIndex
681  && mDataProvider->colorInterpretation( 2 ) == QgsRaster::AlphaBand )
682  || ( mDataProvider->colorInterpretation( 1 ) == QgsRaster::AlphaBand
683  && mDataProvider->colorInterpretation( 2 ) == QgsRaster::GrayIndex ) ) )
684  {
685  mRasterType = GrayOrUndefined;
686  }
687  else
688  {
689  mRasterType = Multiband;
690  }
691  }
692  else if ( mDataProvider->dataType( 1 ) == Qgis::ARGB32
693  || mDataProvider->dataType( 1 ) == Qgis::ARGB32_Premultiplied )
694  {
695  mRasterType = ColorLayer;
696  }
697  else if ( mDataProvider->colorInterpretation( 1 ) == QgsRaster::PaletteIndex )
698  {
699  mRasterType = Palette;
700  }
701  else if ( mDataProvider->colorInterpretation( 1 ) == QgsRaster::ContinuousPalette )
702  {
703  mRasterType = Palette;
704  }
705  else
706  {
707  mRasterType = GrayOrUndefined;
708  }
709 
710  QgsDebugMsgLevel( "mRasterType = " + QString::number( mRasterType ), 4 );
711  if ( mRasterType == ColorLayer )
712  {
713  QgsDebugMsgLevel( "Setting drawing style to SingleBandColorDataStyle " + QString::number( QgsRaster::SingleBandColorDataStyle ), 4 );
714  setRendererForDrawingStyle( QgsRaster::SingleBandColorDataStyle );
715  }
716  else if ( mRasterType == Palette && mDataProvider->colorInterpretation( 1 ) == QgsRaster::PaletteIndex )
717  {
718  setRendererForDrawingStyle( QgsRaster::PalettedColor ); //sensible default
719  }
720  else if ( mRasterType == Palette && mDataProvider->colorInterpretation( 1 ) == QgsRaster::ContinuousPalette )
721  {
722  setRendererForDrawingStyle( QgsRaster::SingleBandPseudoColor );
723  // Load color table
724  QList<QgsColorRampShader::ColorRampItem> colorTable = mDataProvider->colorTable( 1 );
726  if ( r )
727  {
728  // TODO: this should go somewhere else
729  QgsRasterShader *shader = new QgsRasterShader();
730  QgsColorRampShader *colorRampShader = new QgsColorRampShader();
732  colorRampShader->setColorRampItemList( colorTable );
733  shader->setRasterShaderFunction( colorRampShader );
734  r->setShader( shader );
735  }
736  }
737  else if ( mRasterType == Multiband )
738  {
739  setRendererForDrawingStyle( QgsRaster::MultiBandColor ); //sensible default
740  }
741  else //GrayOrUndefined
742  {
743  setRendererForDrawingStyle( QgsRaster::SingleBandGray ); //sensible default
744  }
745 
746  // Auto set alpha band
747  for ( int bandNo = 1; bandNo <= mDataProvider->bandCount(); bandNo++ )
748  {
749  if ( mDataProvider->colorInterpretation( bandNo ) == QgsRaster::AlphaBand )
750  {
751  if ( mPipe.renderer() )
752  {
753  mPipe.renderer()->setAlphaBand( bandNo );
754  }
755  break;
756  }
757  }
758 
759  // brightness filter
761  mPipe.set( brightnessFilter );
762 
763  // hue/saturation filter
765  mPipe.set( hueSaturationFilter );
766 
767  //resampler (must be after renderer)
769  mPipe.set( resampleFilter );
770 
771  // projector (may be anywhere in pipe)
772  QgsRasterProjector *projector = new QgsRasterProjector;
773  mPipe.set( projector );
774 
775  // Set default identify format - use the richest format available
776  int capabilities = mDataProvider->capabilities();
778  if ( capabilities & QgsRasterInterface::IdentifyHtml )
779  {
780  // HTML is usually richest
781  identifyFormat = QgsRaster::IdentifyFormatHtml;
782  }
783  else if ( capabilities & QgsRasterInterface::IdentifyFeature )
784  {
785  identifyFormat = QgsRaster::IdentifyFormatFeature;
786  }
787  else if ( capabilities & QgsRasterInterface::IdentifyText )
788  {
789  identifyFormat = QgsRaster::IdentifyFormatText;
790  }
791  else if ( capabilities & QgsRasterInterface::IdentifyValue )
792  {
793  identifyFormat = QgsRaster::IdentifyFormatValue;
794  }
795  setCustomProperty( QStringLiteral( "identify/format" ), QgsRasterDataProvider::identifyFormatName( identifyFormat ) );
796 
797  // Store timestamp
798  // TODO move to provider
799  mLastModified = lastModified( mDataSource );
800 
801  // Do a passthrough for the status bar text
802  connect( mDataProvider, &QgsRasterDataProvider::statusChanged, this, &QgsRasterLayer::statusChanged );
803 
804  //mark the layer as valid
805  mValid = true;
806 
807  QgsDebugMsgLevel( "exiting.", 4 );
808 } // QgsRasterLayer::setDataProvider
809 
810 void QgsRasterLayer::closeDataProvider()
811 {
812  mValid = false;
813  mPipe.remove( mDataProvider );
814  mDataProvider = nullptr;
815 }
816 
817 void QgsRasterLayer::computeMinMax( int band,
818  const QgsRasterMinMaxOrigin &mmo,
820  const QgsRectangle &extent,
821  int sampleSize,
822  double &min, double &max )
823 {
824 
825  min = std::numeric_limits<double>::quiet_NaN();
826  max = std::numeric_limits<double>::quiet_NaN();
827 
828  if ( limits == QgsRasterMinMaxOrigin::MinMax )
829  {
830  QgsRasterBandStats myRasterBandStats = mDataProvider->bandStatistics( band, QgsRasterBandStats::Min | QgsRasterBandStats::Max, extent, sampleSize );
831  min = myRasterBandStats.minimumValue;
832  max = myRasterBandStats.maximumValue;
833  }
834  else if ( limits == QgsRasterMinMaxOrigin::StdDev )
835  {
836  QgsRasterBandStats myRasterBandStats = mDataProvider->bandStatistics( band, QgsRasterBandStats::Mean | QgsRasterBandStats::StdDev, extent, sampleSize );
837  min = myRasterBandStats.mean - ( mmo.stdDevFactor() * myRasterBandStats.stdDev );
838  max = myRasterBandStats.mean + ( mmo.stdDevFactor() * myRasterBandStats.stdDev );
839  }
840  else if ( limits == QgsRasterMinMaxOrigin::CumulativeCut )
841  {
842  const double myLower = mmo.cumulativeCutLower();
843  const double myUpper = mmo.cumulativeCutUpper();
844  QgsDebugMsgLevel( QString( "myLower = %1 myUpper = %2" ).arg( myLower ).arg( myUpper ), 4 );
845  mDataProvider->cumulativeCut( band, myLower, myUpper, min, max, extent, sampleSize );
846  }
847  QgsDebugMsgLevel( QString( "band = %1 min = %2 max = %3" ).arg( band ).arg( min ).arg( max ), 4 );
848 
849 }
850 
851 
852 void QgsRasterLayer::setContrastEnhancement( QgsContrastEnhancement::ContrastEnhancementAlgorithm algorithm, QgsRasterMinMaxOrigin::Limits limits, const QgsRectangle &extent, int sampleSize, bool generateLookupTableFlag )
853 {
854  setContrastEnhancement( algorithm,
855  limits,
856  extent,
857  sampleSize,
858  generateLookupTableFlag,
859  mPipe.renderer() );
860 }
861 
864  const QgsRectangle &extent,
865  int sampleSize,
866  bool generateLookupTableFlag,
867  QgsRasterRenderer *rasterRenderer )
868 {
869  QgsDebugMsgLevel( QString( "theAlgorithm = %1 limits = %2 extent.isEmpty() = %3" ).arg( algorithm ).arg( limits ).arg( extent.isEmpty() ), 4 );
870  if ( !rasterRenderer || !mDataProvider )
871  {
872  return;
873  }
874 
875  QList<int> myBands;
876  QList<QgsContrastEnhancement *> myEnhancements;
877  QgsRasterMinMaxOrigin myMinMaxOrigin;
878  QgsRasterRenderer *myRasterRenderer = nullptr;
879  QgsSingleBandGrayRenderer *myGrayRenderer = nullptr;
880  QgsSingleBandPseudoColorRenderer *myPseudoColorRenderer = nullptr;
881  QgsMultiBandColorRenderer *myMultiBandRenderer = nullptr;
882  QString rendererType = rasterRenderer->type();
883  if ( rendererType == QLatin1String( "singlebandgray" ) )
884  {
885  myGrayRenderer = dynamic_cast<QgsSingleBandGrayRenderer *>( rasterRenderer );
886  if ( !myGrayRenderer )
887  {
888  return;
889  }
890  myBands << myGrayRenderer->grayBand();
891  myRasterRenderer = myGrayRenderer;
892  myMinMaxOrigin = myGrayRenderer->minMaxOrigin();
893  }
894  else if ( rendererType == QLatin1String( "multibandcolor" ) )
895  {
896  myMultiBandRenderer = dynamic_cast<QgsMultiBandColorRenderer *>( rasterRenderer );
897  if ( !myMultiBandRenderer )
898  {
899  return;
900  }
901  myBands << myMultiBandRenderer->redBand() << myMultiBandRenderer->greenBand() << myMultiBandRenderer->blueBand();
902  myRasterRenderer = myMultiBandRenderer;
903  myMinMaxOrigin = myMultiBandRenderer->minMaxOrigin();
904  }
905  else if ( rendererType == QLatin1String( "singlebandpseudocolor" ) )
906  {
907  myPseudoColorRenderer = dynamic_cast<QgsSingleBandPseudoColorRenderer *>( rasterRenderer );
908  if ( !myPseudoColorRenderer )
909  {
910  return;
911  }
912  myBands << myPseudoColorRenderer->band();
913  myRasterRenderer = myPseudoColorRenderer;
914  myMinMaxOrigin = myPseudoColorRenderer->minMaxOrigin();
915  }
916  else
917  {
918  return;
919  }
920 
921  Q_FOREACH ( int myBand, myBands )
922  {
923  if ( myBand != -1 )
924  {
925  Qgis::DataType myType = static_cast< Qgis::DataType >( mDataProvider->dataType( myBand ) );
926  std::unique_ptr<QgsContrastEnhancement> myEnhancement( new QgsContrastEnhancement( static_cast< Qgis::DataType >( myType ) ) );
927  myEnhancement->setContrastEnhancementAlgorithm( algorithm, generateLookupTableFlag );
928 
929  double min;
930  double max;
931  computeMinMax( myBand, myMinMaxOrigin, limits, extent, sampleSize, min, max );
932 
933  if ( rendererType == QLatin1String( "singlebandpseudocolor" ) )
934  {
935  myPseudoColorRenderer->setClassificationMin( min );
936  myPseudoColorRenderer->setClassificationMax( max );
937  if ( myPseudoColorRenderer->shader() )
938  {
939  QgsColorRampShader *colorRampShader = dynamic_cast<QgsColorRampShader *>( myPseudoColorRenderer->shader()->rasterShaderFunction() );
940  if ( colorRampShader )
941  {
942  colorRampShader->classifyColorRamp( myPseudoColorRenderer->band(), extent, myPseudoColorRenderer->input() );
943  }
944  }
945  }
946  else
947  {
948  myEnhancement->setMinimumValue( min );
949  myEnhancement->setMaximumValue( max );
950  myEnhancements.append( myEnhancement.release() );
951  }
952  }
953  else
954  {
955  myEnhancements.append( nullptr );
956  }
957  }
958 
959  if ( rendererType == QLatin1String( "singlebandgray" ) )
960  {
961  if ( myEnhancements.first() ) myGrayRenderer->setContrastEnhancement( myEnhancements.takeFirst() );
962  }
963  else if ( rendererType == QLatin1String( "multibandcolor" ) )
964  {
965  if ( myEnhancements.first() ) myMultiBandRenderer->setRedContrastEnhancement( myEnhancements.takeFirst() );
966  if ( myEnhancements.first() ) myMultiBandRenderer->setGreenContrastEnhancement( myEnhancements.takeFirst() );
967  if ( myEnhancements.first() ) myMultiBandRenderer->setBlueContrastEnhancement( myEnhancements.takeFirst() );
968  }
969 
970  //delete all remaining unused enhancements
971  qDeleteAll( myEnhancements );
972 
973  myMinMaxOrigin.setLimits( limits );
974  if ( extent != QgsRectangle() &&
975  myMinMaxOrigin.extent() == QgsRasterMinMaxOrigin::WholeRaster )
976  {
978  }
979  if ( myRasterRenderer )
980  {
981  myRasterRenderer->setMinMaxOrigin( myMinMaxOrigin );
982  }
983 
984  if ( rasterRenderer == renderer() )
985  {
986  emit repaintRequested();
987  emit styleChanged();
988  emit rendererChanged();
989  }
990 }
991 
993 {
994  QgsSingleBandGrayRenderer *singleBandRenderer = nullptr;
995  QgsMultiBandColorRenderer *multiBandRenderer = nullptr;
996  const QgsContrastEnhancement *ce = nullptr;
997  if ( ( singleBandRenderer = dynamic_cast<QgsSingleBandGrayRenderer *>( renderer() ) ) )
998  {
999  ce = singleBandRenderer->contrastEnhancement();
1000  }
1001  else if ( ( multiBandRenderer = dynamic_cast<QgsMultiBandColorRenderer *>( renderer() ) ) )
1002  {
1003  ce = multiBandRenderer->redContrastEnhancement();
1004  }
1005 
1006  if ( ce )
1007  {
1012  extent,
1013  SAMPLE_SIZE,
1014  true,
1015  renderer() );
1016  }
1017  else
1018  {
1021  if ( defaultContrastEnhancementSettings( myAlgorithm, myLimits ) )
1022  {
1024  myLimits,
1025  extent,
1026  SAMPLE_SIZE,
1027  true,
1028  renderer() );
1029  }
1030  }
1031 }
1032 
1034  const QgsRectangle &extent )
1035 {
1036  if ( !( mDataProvider &&
1037  mLastRectangleUsedByRefreshContrastEnhancementIfNeeded != extent &&
1038  rasterRenderer->minMaxOrigin().limits() != QgsRasterMinMaxOrigin::None &&
1039  rasterRenderer->minMaxOrigin().extent() == QgsRasterMinMaxOrigin::UpdatedCanvas ) )
1040  return;
1041 
1042  QgsSingleBandGrayRenderer *singleBandRenderer = nullptr;
1043  QgsMultiBandColorRenderer *multiBandRenderer = nullptr;
1044  QgsSingleBandPseudoColorRenderer *sbpcr = nullptr;
1045  const QgsContrastEnhancement *ce = nullptr;
1046  if ( ( singleBandRenderer = dynamic_cast<QgsSingleBandGrayRenderer *>( rasterRenderer ) ) )
1047  {
1048  ce = singleBandRenderer->contrastEnhancement();
1049  }
1050  else if ( ( multiBandRenderer = dynamic_cast<QgsMultiBandColorRenderer *>( rasterRenderer ) ) )
1051  {
1052  ce = multiBandRenderer->redContrastEnhancement();
1053  }
1054  else if ( ( sbpcr = dynamic_cast<QgsSingleBandPseudoColorRenderer *>( rasterRenderer ) ) )
1055  {
1056  mLastRectangleUsedByRefreshContrastEnhancementIfNeeded = extent;
1057  double min;
1058  double max;
1059  computeMinMax( sbpcr->band(),
1060  rasterRenderer->minMaxOrigin(),
1061  rasterRenderer->minMaxOrigin().limits(), extent,
1062  SAMPLE_SIZE, min, max );
1063  sbpcr->setClassificationMin( min );
1064  sbpcr->setClassificationMax( max );
1065 
1066  if ( sbpcr->shader() )
1067  {
1068  QgsColorRampShader *colorRampShader = dynamic_cast<QgsColorRampShader *>( sbpcr->shader()->rasterShaderFunction() );
1069  if ( colorRampShader )
1070  {
1071  colorRampShader->classifyColorRamp( sbpcr->band(), extent, rasterRenderer->input() );
1072  }
1073  }
1074 
1076  r->setClassificationMin( min );
1077  r->setClassificationMax( max );
1078 
1079  if ( r->shader() )
1080  {
1081  QgsColorRampShader *colorRampShader = dynamic_cast<QgsColorRampShader *>( r->shader()->rasterShaderFunction() );
1082  if ( colorRampShader )
1083  {
1084  colorRampShader->classifyColorRamp( sbpcr->band(), extent, rasterRenderer->input() );
1085  }
1086  }
1087 
1088  emit repaintRequested();
1089  emit styleChanged();
1090  emit rendererChanged();
1091  return;
1092  }
1093 
1094  if ( ce &&
1096  {
1097  mLastRectangleUsedByRefreshContrastEnhancementIfNeeded = extent;
1098 
1100  rasterRenderer->minMaxOrigin().limits(),
1101  extent,
1102  SAMPLE_SIZE,
1103  true,
1104  rasterRenderer );
1105 
1106  // Update main renderer so that the legends get updated
1107  if ( singleBandRenderer )
1108  static_cast<QgsSingleBandGrayRenderer *>( renderer() )->setContrastEnhancement( new QgsContrastEnhancement( * singleBandRenderer->contrastEnhancement() ) );
1109  else if ( multiBandRenderer )
1110  {
1111  if ( multiBandRenderer->redContrastEnhancement() )
1112  {
1113  static_cast<QgsMultiBandColorRenderer *>( renderer() )->setRedContrastEnhancement( new QgsContrastEnhancement( *multiBandRenderer->redContrastEnhancement() ) );
1114  }
1115  if ( multiBandRenderer->greenContrastEnhancement() )
1116  {
1117  static_cast<QgsMultiBandColorRenderer *>( renderer() )->setGreenContrastEnhancement( new QgsContrastEnhancement( *multiBandRenderer->greenContrastEnhancement() ) );
1118  }
1119  if ( multiBandRenderer->blueContrastEnhancement() )
1120  {
1121  static_cast<QgsMultiBandColorRenderer *>( renderer() )->setBlueContrastEnhancement( new QgsContrastEnhancement( *multiBandRenderer->blueContrastEnhancement() ) );
1122  }
1123  }
1124 
1125  emit styleChanged();
1126  emit rendererChanged();
1127  }
1128 }
1129 
1132  QgsRasterMinMaxOrigin::Limits &myLimits ) const
1133 {
1134  QgsSettings mySettings;
1135 
1136  QString key;
1137  QString defaultAlg;
1138  QString defaultLimits;
1139 
1140  // TODO: we should not test renderer class here, move it somehow to renderers
1141  if ( dynamic_cast<QgsSingleBandGrayRenderer *>( renderer() ) )
1142  {
1143  key = QStringLiteral( "singleBand" );
1146  defaultLimits = QgsRasterMinMaxOrigin::limitsString(
1148  }
1149  else if ( dynamic_cast<QgsMultiBandColorRenderer *>( renderer() ) )
1150  {
1151  if ( QgsRasterBlock::typeSize( dataProvider()->sourceDataType( 1 ) ) == 1 )
1152  {
1153  key = QStringLiteral( "multiBandSingleByte" );
1156  defaultLimits = QgsRasterMinMaxOrigin::limitsString(
1158  }
1159  else
1160  {
1161  key = QStringLiteral( "multiBandMultiByte" );
1164  defaultLimits = QgsRasterMinMaxOrigin::limitsString(
1166  }
1167  }
1168 
1169  if ( key.isEmpty() )
1170  {
1171  QgsDebugMsg( "No default contrast enhancement for this drawing style" );
1173  myLimits = QgsRasterMinMaxOrigin::limitsFromString( QString() );
1174  return false;
1175  }
1176  QgsDebugMsgLevel( "key = " + key, 4 );
1177 
1178  QString myAlgorithmString = mySettings.value( "/Raster/defaultContrastEnhancementAlgorithm/" + key, defaultAlg ).toString();
1179  QgsDebugMsgLevel( "myAlgorithmString = " + myAlgorithmString, 4 );
1180 
1181  myAlgorithm = QgsContrastEnhancement::contrastEnhancementAlgorithmFromString( myAlgorithmString );
1182 
1183  QString myLimitsString = mySettings.value( "/Raster/defaultContrastEnhancementLimits/" + key, defaultLimits ).toString();
1184  QgsDebugMsgLevel( "myLimitsString = " + myLimitsString, 4 );
1185  myLimits = QgsRasterMinMaxOrigin::limitsFromString( myLimitsString );
1186 
1187  return true;
1188 }
1189 
1191 {
1192  QgsDebugMsgLevel( "Entered", 4 );
1193 
1196  defaultContrastEnhancementSettings( myAlgorithm, myLimits );
1197 
1198  setContrastEnhancement( myAlgorithm, myLimits );
1199 }
1200 
1201 void QgsRasterLayer::setLayerOrder( QStringList const &layers )
1202 {
1203  QgsDebugMsgLevel( "entered.", 4 );
1204 
1205  if ( mDataProvider )
1206  {
1207  QgsDebugMsgLevel( "About to mDataProvider->setLayerOrder(layers).", 4 );
1208  mDataProvider->setLayerOrder( layers );
1209  }
1210 
1211 }
1212 
1213 void QgsRasterLayer::setSubLayerVisibility( const QString &name, bool vis )
1214 {
1215 
1216  if ( mDataProvider )
1217  {
1218  QgsDebugMsgLevel( "About to mDataProvider->setSubLayerVisibility(name, vis).", 4 );
1219  mDataProvider->setSubLayerVisibility( name, vis );
1220  }
1221 
1222 }
1223 
1224 QDateTime QgsRasterLayer::timestamp() const
1225 {
1226  return mDataProvider->timestamp();
1227 }
1228 
1230 {
1231  QgsDebugMsgLevel( "Entered", 4 );
1232  if ( !renderer )
1233  {
1234  return;
1235  }
1236 
1237  mPipe.set( renderer );
1238  emit rendererChanged();
1239  emit styleChanged();
1240 }
1241 
1242 void QgsRasterLayer::showStatusMessage( QString const &message )
1243 {
1244  // QgsDebugMsg(QString("entered with '%1'.").arg(theMessage));
1245 
1246  // Pass-through
1247  // TODO: See if we can connect signal-to-signal. This is a kludge according to the Qt doc.
1248  emit statusChanged( message );
1249 }
1250 
1251 QStringList QgsRasterLayer::subLayers() const
1252 {
1253  return mDataProvider->subLayers();
1254 }
1255 
1256 // this function should be used when rendering with the MTR engine introduced in 2.3, as QPixmap is not thread safe (see bug #9626)
1257 // note: previewAsImage and previewAsPixmap should use a common low-level fct QgsRasterLayer::previewOnPaintDevice( QSize size, QColor bgColor, QPaintDevice &device )
1258 QImage QgsRasterLayer::previewAsImage( QSize size, const QColor &bgColor, QImage::Format format )
1259 {
1260  QImage myQImage( size, format );
1261 
1262  myQImage.setColor( 0, bgColor.rgba() );
1263  myQImage.fill( 0 ); //defaults to white, set to transparent for rendering on a map
1264 
1265  QgsRasterViewPort *myRasterViewPort = new QgsRasterViewPort();
1266 
1267  double myMapUnitsPerPixel;
1268  double myX = 0.0;
1269  double myY = 0.0;
1270  QgsRectangle myExtent = mDataProvider->extent();
1271  if ( myExtent.width() / myExtent.height() >= static_cast< double >( myQImage.width() ) / myQImage.height() )
1272  {
1273  myMapUnitsPerPixel = myExtent.width() / myQImage.width();
1274  myY = ( myQImage.height() - myExtent.height() / myMapUnitsPerPixel ) / 2;
1275  }
1276  else
1277  {
1278  myMapUnitsPerPixel = myExtent.height() / myQImage.height();
1279  myX = ( myQImage.width() - myExtent.width() / myMapUnitsPerPixel ) / 2;
1280  }
1281 
1282  double myPixelWidth = myExtent.width() / myMapUnitsPerPixel;
1283  double myPixelHeight = myExtent.height() / myMapUnitsPerPixel;
1284 
1285  myRasterViewPort->mTopLeftPoint = QgsPoint( myX, myY );
1286  myRasterViewPort->mBottomRightPoint = QgsPoint( myPixelWidth, myPixelHeight );
1287  myRasterViewPort->mWidth = myQImage.width();
1288  myRasterViewPort->mHeight = myQImage.height();
1289 
1290  myRasterViewPort->mDrawnExtent = myExtent;
1291  myRasterViewPort->mSrcCRS = QgsCoordinateReferenceSystem(); // will be invalid
1292  myRasterViewPort->mDestCRS = QgsCoordinateReferenceSystem(); // will be invalid
1293  myRasterViewPort->mSrcDatumTransform = -1;
1294  myRasterViewPort->mDestDatumTransform = -1;
1295 
1296  QgsMapToPixel *myMapToPixel = new QgsMapToPixel( myMapUnitsPerPixel );
1297 
1298  QPainter *myQPainter = new QPainter( &myQImage );
1299  draw( myQPainter, myRasterViewPort, myMapToPixel );
1300  delete myRasterViewPort;
1301  delete myMapToPixel;
1302  myQPainter->end();
1303  delete myQPainter;
1304 
1305  return myQImage;
1306 }
1307 
1309 //
1310 // Protected methods
1311 //
1313 /*
1314  * @param QDomNode node that will contain the symbology definition for this layer.
1315  * @param errorMessage reference to string that will be updated with any error messages
1316  * @return true in case of success.
1317  */
1318 bool QgsRasterLayer::readSymbology( const QDomNode &layer_node, QString &errorMessage )
1319 {
1320  Q_UNUSED( errorMessage );
1321  QDomElement rasterRendererElem;
1322 
1323  // pipe element was introduced in the end of 1.9 development when there were
1324  // already many project files in use so we support 1.9 backward compatibility
1325  // even it was never officially released -> use pipe element if present, otherwise
1326  // use layer node
1327  QDomNode pipeNode = layer_node.firstChildElement( QStringLiteral( "pipe" ) );
1328  if ( pipeNode.isNull() ) // old project
1329  {
1330  pipeNode = layer_node;
1331  }
1332 
1333  //rasterlayerproperties element there -> old format (1.8 and early 1.9)
1334  if ( !layer_node.firstChildElement( QStringLiteral( "rasterproperties" ) ).isNull() )
1335  {
1336  //copy node because layer_node is const
1337  QDomNode layerNodeCopy = layer_node.cloneNode();
1338  QDomDocument doc = layerNodeCopy.ownerDocument();
1339  QDomElement rasterPropertiesElem = layerNodeCopy.firstChildElement( QStringLiteral( "rasterproperties" ) );
1340  QgsProjectFileTransform::convertRasterProperties( doc, layerNodeCopy, rasterPropertiesElem,
1341  this );
1342  rasterRendererElem = layerNodeCopy.firstChildElement( QStringLiteral( "rasterrenderer" ) );
1343  QgsDebugMsgLevel( doc.toString(), 4 );
1344  }
1345  else
1346  {
1347  rasterRendererElem = pipeNode.firstChildElement( QStringLiteral( "rasterrenderer" ) );
1348  }
1349 
1350  if ( !rasterRendererElem.isNull() )
1351  {
1352  QString rendererType = rasterRendererElem.attribute( QStringLiteral( "type" ) );
1353  QgsRasterRendererRegistryEntry rendererEntry;
1354  if ( QgsApplication::rasterRendererRegistry()->rendererData( rendererType, rendererEntry ) )
1355  {
1356  QgsRasterRenderer *renderer = rendererEntry.rendererCreateFunction( rasterRendererElem, dataProvider() );
1357  mPipe.set( renderer );
1358  }
1359  }
1360 
1361  //brightness
1363  mPipe.set( brightnessFilter );
1364 
1365  //brightness coefficient
1366  QDomElement brightnessElem = pipeNode.firstChildElement( QStringLiteral( "brightnesscontrast" ) );
1367  if ( !brightnessElem.isNull() )
1368  {
1369  brightnessFilter->readXml( brightnessElem );
1370  }
1371 
1372  //hue/saturation
1374  mPipe.set( hueSaturationFilter );
1375 
1376  //saturation coefficient
1377  QDomElement hueSaturationElem = pipeNode.firstChildElement( QStringLiteral( "huesaturation" ) );
1378  if ( !hueSaturationElem.isNull() )
1379  {
1380  hueSaturationFilter->readXml( hueSaturationElem );
1381  }
1382 
1383  //resampler
1385  mPipe.set( resampleFilter );
1386 
1387  //max oversampling
1388  QDomElement resampleElem = pipeNode.firstChildElement( QStringLiteral( "rasterresampler" ) );
1389  if ( !resampleElem.isNull() )
1390  {
1391  resampleFilter->readXml( resampleElem );
1392  }
1393 
1394  // get and set the blend mode if it exists
1395  QDomNode blendModeNode = layer_node.namedItem( QStringLiteral( "blendMode" ) );
1396  if ( !blendModeNode.isNull() )
1397  {
1398  QDomElement e = blendModeNode.toElement();
1399  setBlendMode( QgsPainting::getCompositionMode( static_cast< QgsPainting::BlendMode >( e.text().toInt() ) ) );
1400  }
1401 
1402  readCustomProperties( layer_node );
1403 
1404  return true;
1405 }
1406 
1407 bool QgsRasterLayer::readStyle( const QDomNode &node, QString &errorMessage )
1408 {
1409  return readSymbology( node, errorMessage );
1410 } //readSymbology
1411 
1418 bool QgsRasterLayer::readXml( const QDomNode &layer_node )
1419 {
1420  QgsDebugMsgLevel( "Entered", 4 );
1421  // Make sure to read the file first so stats etc are initialized properly!
1422 
1423  //process provider key
1424  QDomNode pkeyNode = layer_node.namedItem( QStringLiteral( "provider" ) );
1425 
1426  if ( pkeyNode.isNull() )
1427  {
1428  mProviderKey = QStringLiteral( "gdal" );
1429  }
1430  else
1431  {
1432  QDomElement pkeyElt = pkeyNode.toElement();
1433  mProviderKey = pkeyElt.text();
1434  if ( mProviderKey.isEmpty() )
1435  {
1436  mProviderKey = QStringLiteral( "gdal" );
1437  }
1438  }
1439 
1440  // Open the raster source based on provider and datasource
1441 
1442  // Go down the raster-data-provider paradigm
1443 
1444  // Collect provider-specific information
1445 
1446  QDomNode rpNode = layer_node.namedItem( QStringLiteral( "rasterproperties" ) );
1447 
1448  if ( mProviderKey == QLatin1String( "wms" ) )
1449  {
1450  // >>> BACKWARD COMPATIBILITY < 1.9
1451  // The old WMS URI format does not contain all the information, we add them here.
1452  if ( !mDataSource.contains( QLatin1String( "crs=" ) ) && !mDataSource.contains( QLatin1String( "format=" ) ) )
1453  {
1454  QgsDebugMsgLevel( "Old WMS URI format detected -> adding params", 4 );
1455  QgsDataSourceUri uri;
1456  uri.setEncodedUri( mDataSource );
1457  QDomElement layerElement = rpNode.firstChildElement( QStringLiteral( "wmsSublayer" ) );
1458  while ( !layerElement.isNull() )
1459  {
1460  // TODO: sublayer visibility - post-0.8 release timeframe
1461 
1462  // collect name for the sublayer
1463  uri.setParam( QStringLiteral( "layers" ), layerElement.namedItem( QStringLiteral( "name" ) ).toElement().text() );
1464 
1465  // collect style for the sublayer
1466  uri.setParam( QStringLiteral( "styles" ), layerElement.namedItem( QStringLiteral( "style" ) ).toElement().text() );
1467 
1468  layerElement = layerElement.nextSiblingElement( QStringLiteral( "wmsSublayer" ) );
1469  }
1470 
1471  // Collect format
1472  QDomNode formatNode = rpNode.namedItem( QStringLiteral( "wmsFormat" ) );
1473  uri.setParam( QStringLiteral( "format" ), rpNode.namedItem( QStringLiteral( "wmsFormat" ) ).toElement().text() );
1474 
1475  // WMS CRS URL param should not be mixed with that assigned to the layer.
1476  // In the old WMS URI version there was no CRS and layer crs().authid() was used.
1477  uri.setParam( QStringLiteral( "crs" ), crs().authid() );
1478  mDataSource = uri.encodedUri();
1479  }
1480  // <<< BACKWARD COMPATIBILITY < 1.9
1481  }
1482 
1483  setDataProvider( mProviderKey );
1484  if ( !mValid ) return false;
1485 
1486  QString error;
1487  bool res = readSymbology( layer_node, error );
1488 
1489  // old wms settings we need to correct
1490  if ( res && mProviderKey == QLatin1String( "wms" ) && ( !renderer() || renderer()->type() != QLatin1String( "singlebandcolordata" ) ) )
1491  {
1492  setRendererForDrawingStyle( QgsRaster::SingleBandColorDataStyle );
1493  }
1494 
1495  // Check timestamp
1496  // This was probably introduced to reload completely raster if data changed and
1497  // reset completely symbology to reflect new data type etc. It creates however
1498  // problems, because user defined symbology is complete lost if data file time
1499  // changed (the content may be the same). See also 6900.
1500 #if 0
1501  QDomNode stampNode = layer_node.namedItem( "timestamp" );
1502  if ( !stampNode.isNull() )
1503  {
1504  QDateTime stamp = QDateTime::fromString( stampNode.toElement().text(), Qt::ISODate );
1505  // TODO: very bad, we have to load twice!!! Make QgsDataProvider::timestamp() static?
1506  if ( stamp < mDataProvider->dataTimestamp() )
1507  {
1508  QgsDebugMsg( "data changed, reload provider" );
1509  closeDataProvider();
1510  init();
1511  setDataProvider( mProviderKey );
1512  if ( !mValid ) return false;
1513  }
1514  }
1515 #endif
1516 
1517  // Load user no data value
1518  QDomElement noDataElement = layer_node.firstChildElement( QStringLiteral( "noData" ) );
1519 
1520  QDomNodeList noDataBandList = noDataElement.elementsByTagName( QStringLiteral( "noDataList" ) );
1521 
1522  for ( int i = 0; i < noDataBandList.size(); ++i )
1523  {
1524  QDomElement bandElement = noDataBandList.at( i ).toElement();
1525  bool ok;
1526  int bandNo = bandElement.attribute( QStringLiteral( "bandNo" ) ).toInt( &ok );
1527  QgsDebugMsgLevel( QString( "bandNo = %1" ).arg( bandNo ), 4 );
1528  if ( ok && ( bandNo > 0 ) && ( bandNo <= mDataProvider->bandCount() ) )
1529  {
1530  mDataProvider->setUseSourceNoDataValue( bandNo, bandElement.attribute( QStringLiteral( "useSrcNoData" ) ).toInt() );
1531  QgsRasterRangeList myNoDataRangeList;
1532 
1533  QDomNodeList rangeList = bandElement.elementsByTagName( QStringLiteral( "noDataRange" ) );
1534 
1535  myNoDataRangeList.reserve( rangeList.size() );
1536  for ( int j = 0; j < rangeList.size(); ++j )
1537  {
1538  QDomElement rangeElement = rangeList.at( j ).toElement();
1539  QgsRasterRange myNoDataRange( rangeElement.attribute( QStringLiteral( "min" ) ).toDouble(),
1540  rangeElement.attribute( QStringLiteral( "max" ) ).toDouble() );
1541  QgsDebugMsgLevel( QString( "min = %1 %2" ).arg( rangeElement.attribute( "min" ) ).arg( myNoDataRange.min() ), 4 );
1542  myNoDataRangeList << myNoDataRange;
1543  }
1544  mDataProvider->setUserNoDataValue( bandNo, myNoDataRangeList );
1545  }
1546  }
1547 
1548  readStyleManager( layer_node );
1549 
1550  return res;
1551 } // QgsRasterLayer::readXml( QDomNode & layer_node )
1552 
1553 /*
1554  * @param QDomNode the node that will have the style element added to it.
1555  * @param QDomDocument the document that will have the QDomNode added.
1556  * @param errorMessage reference to string that will be updated with any error messages
1557  * @return true in case of success.
1558  */
1559 bool QgsRasterLayer::writeSymbology( QDomNode &layer_node, QDomDocument &document, QString &errorMessage ) const
1560 {
1561  Q_UNUSED( errorMessage );
1562  QDomElement layerElem = layer_node.toElement();
1563 
1564  // Store pipe members (except provider) into pipe element, in future, it will be
1565  // possible to add custom filters into the pipe
1566  QDomElement pipeElement = document.createElement( QStringLiteral( "pipe" ) );
1567 
1568  for ( int i = 1; i < mPipe.size(); i++ )
1569  {
1570  QgsRasterInterface *interface = mPipe.at( i );
1571  if ( !interface ) continue;
1572  interface->writeXml( document, pipeElement );
1573  }
1574 
1575  layer_node.appendChild( pipeElement );
1576 
1577  // add blend mode node
1578  QDomElement blendModeElement = document.createElement( QStringLiteral( "blendMode" ) );
1579  QDomText blendModeText = document.createTextNode( QString::number( QgsPainting::getBlendModeEnum( blendMode() ) ) );
1580  blendModeElement.appendChild( blendModeText );
1581  layer_node.appendChild( blendModeElement );
1582 
1583  return true;
1584 }
1585 
1586 bool QgsRasterLayer::writeStyle( QDomNode &node, QDomDocument &doc, QString &errorMessage ) const
1587 {
1588  return writeSymbology( node, doc, errorMessage );
1589 
1590 } // bool QgsRasterLayer::writeSymbology
1591 
1592 /*
1593  * virtual
1594  * @note Called by QgsMapLayer::writeXml().
1595  */
1596 bool QgsRasterLayer::writeXml( QDomNode &layer_node,
1597  QDomDocument &document ) const
1598 {
1599  // first get the layer element so that we can append the type attribute
1600 
1601  QDomElement mapLayerNode = layer_node.toElement();
1602 
1603  if ( mapLayerNode.isNull() || "maplayer" != mapLayerNode.nodeName() )
1604  {
1605  QgsMessageLog::logMessage( tr( "<maplayer> not found." ), tr( "Raster" ) );
1606  return false;
1607  }
1608 
1609  mapLayerNode.setAttribute( QStringLiteral( "type" ), QStringLiteral( "raster" ) );
1610 
1611  // add provider node
1612 
1613  QDomElement provider = document.createElement( QStringLiteral( "provider" ) );
1614  QDomText providerText = document.createTextNode( mProviderKey );
1615  provider.appendChild( providerText );
1616  layer_node.appendChild( provider );
1617 
1618  // User no data
1619  QDomElement noData = document.createElement( QStringLiteral( "noData" ) );
1620 
1621  for ( int bandNo = 1; bandNo <= mDataProvider->bandCount(); bandNo++ )
1622  {
1623  QDomElement noDataRangeList = document.createElement( QStringLiteral( "noDataList" ) );
1624  noDataRangeList.setAttribute( QStringLiteral( "bandNo" ), bandNo );
1625  noDataRangeList.setAttribute( QStringLiteral( "useSrcNoData" ), mDataProvider->useSourceNoDataValue( bandNo ) );
1626 
1627  Q_FOREACH ( QgsRasterRange range, mDataProvider->userNoDataValues( bandNo ) )
1628  {
1629  QDomElement noDataRange = document.createElement( QStringLiteral( "noDataRange" ) );
1630 
1631  noDataRange.setAttribute( QStringLiteral( "min" ), QgsRasterBlock::printValue( range.min() ) );
1632  noDataRange.setAttribute( QStringLiteral( "max" ), QgsRasterBlock::printValue( range.max() ) );
1633  noDataRangeList.appendChild( noDataRange );
1634  }
1635 
1636  noData.appendChild( noDataRangeList );
1637 
1638  }
1639  if ( noData.hasChildNodes() )
1640  {
1641  layer_node.appendChild( noData );
1642  }
1643 
1644  writeStyleManager( layer_node, document );
1645 
1646  //write out the symbology
1647  QString errorMsg;
1648  return writeSymbology( layer_node, document, errorMsg );
1649 }
1650 
1652 {
1653  if ( !mDataProvider ) return 0;
1654  return mDataProvider->xSize();
1655 }
1656 
1658 {
1659  if ( !mDataProvider ) return 0;
1660  return mDataProvider->ySize();
1661 }
1662 
1664 //
1665 // Private methods
1666 //
1668 bool QgsRasterLayer::update()
1669 {
1670  QgsDebugMsgLevel( "entered.", 4 );
1671  // Check if data changed
1672  if ( mDataProvider->dataTimestamp() > mDataProvider->timestamp() )
1673  {
1674  QgsDebugMsgLevel( "reload data", 4 );
1675  closeDataProvider();
1676  init();
1677  setDataProvider( mProviderKey );
1678  emit dataChanged();
1679  }
1680  return mValid;
1681 }
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.
#define ERR(message)
IdentifyFormat
Definition: qgsraster.h:72
static QgsProviderRegistry * instance(const QString &pluginPath=QString::null)
Means of accessing canonical single instance.
A rectangle specified with double values.
Definition: qgsrectangle.h:38
Base class for all map layer types.
Definition: qgsmaplayer.h:53
Thirty two bit signed integer (qint32)
Definition: qgis.h:68
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.
void setColorRampItemList(const QList< QgsColorRampShader::ColorRampItem > &list)
Set custom colormap.
virtual QStringList subLayers() const override
Returns the sublayers of this layer - Useful for providers that manage their own layers, such as WMS.
static QString printValue(double value)
Print double value with all necessary significant digits.
void refreshContrastEnhancement(const QgsRectangle &extent)
Refresh contrast enhancement with new extent.
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.
const QgsContrastEnhancement * blueContrastEnhancement() const
Iterator for sequentially processing raster cells.
QString htmlMetadata() const override
Obtain a formatted HTML string containing assorted metadata for this layer.
static const QgsContrastEnhancement::ContrastEnhancementAlgorithm MULTIPLE_BAND_MULTI_BYTE_ENHANCEMENT_ALGORITHM
Default enhancement algorithm for multiple band raster of type different from Byte.
int bandCount() const
Get the number of bands in this layer.
This class is a composition of two QSettings instances:
Definition: qgssettings.h:54
QgsHueSaturationFilter * hueSaturationFilter() const
DrawingStyle
This enumerator describes the different kinds of drawing we can do.
Definition: qgsraster.h:104
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
void setRenderer(QgsRasterRenderer *renderer)
Set raster renderer. Takes ownership of the renderer object.
#define QgsDebugMsg(str)
Definition: qgslogger.h:36
virtual void setLayerOrder(const QStringList &layers) override
Reorders the previously selected sublayers of this layer from bottom to top.
double rasterUnitsPerPixelX() const
Returns the number of raster units per each raster pixel in X axis. In a world file, this is normally the first row (without the sign)
void willBeDeleted()
Emitted in the destructor when the layer is about to be deleted, but it is still in a perfectly valid...
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.
virtual QgsError error() const
Get current status error.
Definition: qgsmaplayer.h:448
void showStatusMessage(const QString &message)
virtual QgsRasterInterface * input() const
Current input.
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:67
void readCustomProperties(const QDomNode &layerNode, const QString &keyStartsWith=QString())
Read custom properties from project file.
static BlendMode getBlendModeEnum(QPainter::CompositionMode blendMode)
Returns a BlendMode corresponding to a QPainter::CompositionMode.
Definition: qgspainting.cpp:66
DataType
Raster data types.
Definition: qgis.h:61
QgsRasterInterface * last() const
Definition: qgsrasterpipe.h:91
QString toProj4() const
Returns a Proj4 string representation of this CRS.
double maximumValue
The maximum cell value in the raster band.
static Limits limitsFromString(const QString &limits)
Deserialize Limits.
const QgsContrastEnhancement * contrastEnhancement() const
virtual int ySize() const
int mWidth
Width, number of columns to be rendered.
double rasterUnitsPerPixelY() const
Returns the number of raster units per each raster pixel in Y axis. In a world file, this is normally the first row (without the sign)
static QDateTime lastModified(const QString &name)
Return time stamp for given file name.
double max() const
Raster values range container.
Resample filter pipe for rasters.
Abstract base class for spatial data provider implementations.
const QgsRasterMinMaxOrigin & minMaxOrigin() const
Returns const reference to origin of min/max values.
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:69
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.
QgsRasterShader * shader()
Returns the raster shader.
virtual void cumulativeCut(int bandNo, double lowerCount, double upperCount, double &lowerValue, double &upperValue, const QgsRectangle &extent=QgsRectangle(), int sampleSize=0)
Find values for cumulative pixel count cut.
void setLimits(Limits limits)
Set limits.
QgsMapLayer::LayerType type() const
Returns the type of the layer.
Definition: qgsmaplayer.cpp:96
QPixmap paletteAsPixmap(int bandNumber=1)
Get an 100x100 pixmap of the color palette. If the layer has no palette a white pixmap will be return...
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:66
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:71
virtual double sourceNoDataValue(int bandNo) const
Value representing no data value.
QString mLayerName
Name of the layer - used for display.
Definition: qgsmaplayer.h:935
void setShader(QgsRasterShader *shader)
Takes ownership of the shader.
void styleChanged()
Signal emitted whenever a change affects the layer&#39;s style.
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:70
Current extent of the canvas (at the time of computation) is used to compute statistics.
void setContrastEnhancement(QgsContrastEnhancement::ContrastEnhancementAlgorithm algorithm, QgsRasterMinMaxOrigin::Limits limits=QgsRasterMinMaxOrigin::MinMax, const QgsRectangle &extent=QgsRectangle(), int sampleSize=SAMPLE_SIZE, bool generateLookupTableFlag=true)
Set contrast enhancement algorithm.
static QString identifyFormatName(QgsRaster::IdentifyFormat format)
virtual QgsRectangle extent() const
Returns the extent of the layer.
QgsCoordinateReferenceSystem mDestCRS
Target coordinate system.
QgsBrightnessContrastFilter * brightnessFilter() const
void setCrs(const QgsCoordinateReferenceSystem &srcCRS, const QgsCoordinateReferenceSystem &destCRS, int srcDatumTransform=-1, int destDatumTransform=-1)
set source and destination CRS
void statusChanged(const QString &status)
Emit a signal with status (e.g. to be caught by QgisApp and display a msg on status bar) ...
double cumulativeCutLower() const
Return lower bound of cumulative cut method (between 0 and 1).
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:76
Perform transforms between map coordinates and device coordinates.
Definition: qgsmaptopixel.h:34
static const QgsRasterMinMaxOrigin::Limits MULTIPLE_BAND_SINGLE_BYTE_MIN_MAX_LIMITS
Default enhancement limits for multiple band raster of type Byte.
bool writeSymbology(QDomNode &, QDomDocument &doc, QString &errorMessage) const override
Write the symbology for the layer into the docment provided.
The drawing pipe for raster layers.
double stdDev
The standard deviation of the cell values.
Paletted (see associated color table)
Definition: qgsraster.h:39
void setColorRampType(QgsColorRampShader::Type colorRampType)
Set the color ramp type.
Alpha (0=transparent, 255=opaque)
Definition: qgsraster.h:47
QgsRasterDataProvider * dataProvider() override
This class describes the origin of min/max values.
The RasterBandStats struct is a container for statistics about a single raster band.
static bool isValidRasterFileName(const QString &fileNameQString, QString &retError)
This helper checks to see whether the file name appears to be a valid raster file name...
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:69
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:37
bool isEmpty() const
Returns true if the 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.
static const QgsContrastEnhancement::ContrastEnhancementAlgorithm SINGLE_BAND_ENHANCEMENT_ALGORITHM
Default enhancement algorithm for single band raster.
QString providerType() const
[ data provider interface ] Which provider is being used for this Raster Layer?
double width() const
Returns the width of the rectangle.
Definition: qgsrectangle.h:118
QgsRasterShaderFunction * rasterShaderFunction()
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.
Complex Float32.
Definition: qgis.h:73
virtual QString dataSourceUri(bool expandAuthConfig=false) const
Get the data source specification.
double cumulativeCutUpper() const
Return upper bound of cumulative cut method (between 0 and 1).
QString bandName(int bandNoInt) const
Get the name of a band given its number.
qgssize elementCount
The number of not no data cells in the band.
Constantly updated extent of the canvas is used to compute statistics.
QString toString(int precision=16) const
Returns a string representation of form xmin,ymin : xmax,ymax Coordinates will be truncated to the sp...
virtual bool hasStatistics(int bandNo, int stats=QgsRasterBandStats::All, const QgsRectangle &extent=QgsRectangle(), int sampleSize=0)
Returns true if histogram is available (cached, already calculated).
void setEncodedUri(const QByteArray &uri)
set complete encoded uri (generic mode)
Raster renderer pipe for single band pseudocolor.
Range is [ mean - stdDevFactor() * stddev, mean + stdDevFactor() * stddev ].
static QString contrastEnhancementAlgorithmString(ContrastEnhancementAlgorithm algorithm)
Return a string to serialize ContrastEnhancementAlgorithm.
QgsCoordinateReferenceSystem crs() const
Returns the layer&#39;s spatial reference system.
bool defaultContrastEnhancementSettings(QgsContrastEnhancement::ContrastEnhancementAlgorithm &myAlgorithm, QgsRasterMinMaxOrigin::Limits &myLimits) const
Return default contrast enhancemnt settings for that type of raster.
void draw(QPainter *theQPainter, QgsRasterViewPort *myRasterViewPort, const QgsMapToPixel *qgsMapToPixel=nullptr)
This is an overloaded version of the draw() function that is called by both draw() and thumbnailAsPix...
Raster renderer pipe for single band gray.
Complex Int32.
Definition: qgis.h:72
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:65
virtual void setLayerOrder(const QStringList &layers)
Reorder the list of layer names to be rendered by this provider (in order from bottom to top) ...
double ANALYSIS_EXPORT min(double x, double y)
Returns the minimum of two doubles or the first argument if both are equal.
Definition: MathUtils.cc:452
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:929
#define cast_to_fptr(f)
Definition: qgis.h:128
void setName(const QString &name)
Set the display name of the layer.
void setDataProvider(const QString &provider)
[ data provider interface ] Set the data provider
Range is [ min + cumulativeCutLower() * (max - min), min + cumulativeCutUpper() * (max - min) ]...
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:37
double ANALYSIS_EXPORT max(double x, double y)
Returns the maximum of two doubles or the first argument if both are equal.
Definition: MathUtils.cc:437
static const QgsRasterMinMaxOrigin::Limits SINGLE_BAND_MIN_MAX_LIMITS
Default enhancement limits for single band raster.
static QString limitsString(Limits limits)
Return a string to serialize Limits.
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.
int size() const
Definition: qgsrasterpipe.h:89
static ContrastEnhancementAlgorithm contrastEnhancementAlgorithmFromString(const QString &contrastEnhancementString)
Deserialize ContrastEnhancementAlgorithm.
void repaintRequested(bool deferredUpdate=false)
By emitting this signal the layer tells that either appearance or content have been changed and any v...
void setMinMaxOrigin(const QgsRasterMinMaxOrigin &origin)
Sets origin of min/max values.
Limits
This enumerator describes the limits used to compute min/max values.
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...
bool set(QgsRasterInterface *interface)
Insert a new known interface in default place or replace interface of the same role if it already exi...
Registry for raster renderer entries.
void setExtent(Extent extent)
Set extent.
virtual QgsRasterBandStats bandStatistics(int bandNo, int stats=QgsRasterBandStats::All, const QgsRectangle &extent=QgsRectangle(), int sampleSize=0, QgsRasterBlockFeedback *feedback=nullptr)
Get band statistics.
QList< QPair< QString, QColor > > QgsLegendColorList
QgsPoint mBottomRightPoint
Coordinate (in output device coordinate system) of bottom right corner of the part of the raster that...
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.
static void logMessage(const QString &message, const QString &tag=QString(), MessageLevel level=QgsMessageLog::WARNING)
add a message to the instance (and create it if necessary)
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.
const QgsContrastEnhancement * redContrastEnhancement() const
const QgsContrastEnhancement * greenContrastEnhancement() const
void classifyColorRamp(const int classes=0, const int band=-1, const QgsRectangle &extent=QgsRectangle(), QgsRasterInterface *input=nullptr)
Classify color ramp shader.
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
QString mDataSource
Data source description string, varies by layer type.
Definition: qgsmaplayer.h:932
Whole raster is used to compute statistics.
virtual QString metadata()=0
Get metadata in a format suitable for feeding directly into a subset of the GUI raster properties "Me...
QVariant value(const QString &key, const QVariant &defaultValue=QVariant(), const Section section=NoSection) const
Returns the value for setting key.
virtual void reloadData()
Reloads the data from the source.
QByteArray encodedUri() const
return complete encoded uri (generic mode)
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).
Color and saturation filter pipe for rasters.
virtual QString description() const =0
Return description.
double range
The range is the distance between min & max.
void setBlueContrastEnhancement(QgsContrastEnhancement *ce)
Takes ownership.
ContrastEnhancementAlgorithm contrastEnhancementAlgorithm() const
Greyscale.
Definition: qgsraster.h:37
bool isvalidrasterfilename_t(QString const &fileNameQString, QString &retErrMsg)
Extent extent() const
Return extent.
double minimumValue
The minimum cell value in the raster band.
Renderer for multiband images with the color components.
void dataChanged()
Data of layer changed.
void appendError(const QgsErrorMessage &error)
Add error message.
Definition: qgsmaplayer.h:921
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...
Interpolates the color between two class breaks linearly.
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.
void refreshRendererIfNeeded(QgsRasterRenderer *rasterRenderer, const QgsRectangle &extent)
Refresh renderer with new extent, if needed.
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.
Assigns the color of the higher class for every pixel between two class breaks.
virtual void legendSymbologyItems(QList< QPair< QString, QColor > > &symbolItems) const
Get symbology items if provided by renderer.
double min() const
virtual QString generateBandName(int bandNumber) const
helper function to create zero padded band names
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)
Complex Float64.
Definition: qgis.h:74
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.
double stdDevFactor() const
Return factor f so that the min/max range is [ mean - f * stddev , mean + f * stddev ]...
virtual int xSize() const
Get raster size.
static QgsRasterRendererRegistry * rasterRendererRegistry()
Returns the application&#39;s raster renderer registry, used for managing raster layer renderers...
Raster renderer pipe that applies colors to a raster.
QgsRasterRendererCreateFunc rendererCreateFunction
Limits limits() const
Return limits.
static const QgsContrastEnhancement::ContrastEnhancementAlgorithm MULTIPLE_BAND_SINGLE_BYTE_ENHANCEMENT_ALGORITHM
Default enhancement algorithm for multiple band raster of type Byte.
void setError(const QgsError &error)
Set error message.
Definition: qgsmaplayer.h:923
Eight bit unsigned integer (quint8)
Definition: qgis.h:64
static const QgsRasterMinMaxOrigin::Limits MULTIPLE_BAND_MULTI_BYTE_MIN_MAX_LIMITS
Default enhancement limits for multiple band raster of type different from Byte.
int band() const
Returns the band used by the renderer.
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:75
QPainter::CompositionMode blendMode() const
Returns the current blending mode for a layer.
double height() const
Returns the height of the rectangle.
Definition: qgsrectangle.h:125
virtual int colorInterpretation(int bandNo) const
Returns data type for the band specified by number.
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.