QGIS API Documentation  3.2.0-Bonn (bc43194)
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"
25 #include "qgslogger.h"
26 #include "qgsmaplayerlegend.h"
27 #include "qgsmaptopixel.h"
28 #include "qgsmessagelog.h"
30 #include "qgspainting.h"
32 #include "qgspathresolver.h"
34 #include "qgsproviderregistry.h"
35 #include "qgsrasterdataprovider.h"
36 #include "qgsrasterdrawer.h"
37 #include "qgsrasteriterator.h"
38 #include "qgsrasterlayer.h"
39 #include "qgsrasterlayerrenderer.h"
40 #include "qgsrasterprojector.h"
41 #include "qgsrasterrange.h"
44 #include "qgsrastershader.h"
45 #include "qgsreadwritecontext.h"
46 #include "qgsrectangle.h"
47 #include "qgsrendercontext.h"
51 #include "qgssettings.h"
52 
53 #include <cmath>
54 #include <cstdio>
55 #include <limits>
56 #include <typeinfo>
57 
58 #include <QApplication>
59 #include <QCursor>
60 #include <QDomElement>
61 #include <QDomNode>
62 #include <QFile>
63 #include <QFileInfo>
64 #include <QFont>
65 #include <QFontMetrics>
66 #include <QFrame>
67 #include <QImage>
68 #include <QLabel>
69 #include <QLibrary>
70 #include <QList>
71 #include <QMatrix>
72 #include <QMessageBox>
73 #include <QPainter>
74 #include <QPixmap>
75 #include <QRegExp>
76 #include <QSlider>
77 #include <QTime>
78 
79 // typedefs for provider plugin functions of interest
80 typedef bool isvalidrasterfilename_t( QString const &fileNameQString, QString &retErrMsg );
81 
82 #define ERR(message) QGS_ERROR_MESSAGE(message,"Raster layer")
83 
84 const double QgsRasterLayer::SAMPLE_SIZE = 250000;
85 
92 
99 
101  : QgsMapLayer( RasterLayer )
102  , QSTRING_NOT_SET( QStringLiteral( "Not Set" ) )
103  , TRSTRING_NOT_SET( tr( "Not Set" ) )
104 
105 {
106  init();
107  mValid = false;
108 }
109 
110 QgsRasterLayer::QgsRasterLayer( const QString &uri,
111  const QString &baseName,
112  const QString &providerKey,
113  const LayerOptions &options )
114  : QgsMapLayer( RasterLayer, baseName, uri )
115  // Constant that signals property not used.
116  , QSTRING_NOT_SET( QStringLiteral( "Not Set" ) )
117  , TRSTRING_NOT_SET( tr( "Not Set" ) )
118  , mProviderKey( providerKey )
119 {
120  QgsDebugMsgLevel( "Entered", 4 );
121  init();
122 
123  QgsDataProvider::ProviderOptions providerOptions;
124  setDataProvider( providerKey, providerOptions );
125  if ( !mValid ) return;
126 
127  // load default style
128  bool defaultLoadedFlag = false;
129  if ( mValid && options.loadDefaultStyle )
130  {
131  loadDefaultStyle( defaultLoadedFlag );
132  }
133  if ( !defaultLoadedFlag )
134  {
136  }
137 
138  // TODO: Connect signals from the dataprovider to the qgisapp
139 
140  emit statusChanged( tr( "QgsRasterLayer created" ) );
141 } // QgsRasterLayer ctor
142 
144 {
145  emit willBeDeleted();
146 
147  mValid = false;
148  // Note: provider and other interfaces are owned and deleted by pipe
149 }
150 
152 {
153  QgsRasterLayer *layer = new QgsRasterLayer( source(), name(), mProviderKey );
154  QgsMapLayer::clone( layer );
155 
156  // do not clone data provider which is the first element in pipe
157  for ( int i = 1; i < mPipe.size(); i++ )
158  {
159  if ( mPipe.at( i ) )
160  layer->pipe()->set( mPipe.at( i )->clone() );
161  }
162 
163  return layer;
164 }
165 
167 //
168 // Static Methods and members
169 //
171 
172 bool QgsRasterLayer::isValidRasterFileName( const QString &fileNameQString, QString &retErrMsg )
173 {
174  isvalidrasterfilename_t *pValid = reinterpret_cast< isvalidrasterfilename_t * >( cast_to_fptr( QgsProviderRegistry::instance()->function( "gdal", "isValidRasterFileName" ) ) );
175  if ( ! pValid )
176  {
177  QgsDebugMsg( "Could not resolve isValidRasterFileName in gdal provider library" );
178  return false;
179  }
180 
181  bool myIsValid = pValid( fileNameQString, retErrMsg );
182  return myIsValid;
183 }
184 
185 bool QgsRasterLayer::isValidRasterFileName( QString const &fileNameQString )
186 {
187  QString retErrMsg;
188  return isValidRasterFileName( fileNameQString, retErrMsg );
189 }
190 
191 QDateTime QgsRasterLayer::lastModified( QString const &name )
192 {
193  QgsDebugMsgLevel( "name=" + name, 4 );
194  QDateTime t;
195 
196  QFileInfo fi( name );
197 
198  // Is it file?
199  if ( !fi.exists() )
200  return t;
201 
202  t = fi.lastModified();
203 
204  QgsDebugMsgLevel( "last modified = " + t.toString(), 4 );
205 
206  return t;
207 }
208 
209 void QgsRasterLayer::setDataProvider( const QString &provider )
210 {
212 }
213 
214 // typedef for the QgsDataProvider class factory
215 typedef QgsDataProvider *classFactoryFunction_t( const QString *, const QgsDataProvider::ProviderOptions &options );
216 
218 //
219 // Non Static Public methods
220 //
222 
224 {
225  if ( !mDataProvider ) return 0;
226  return mDataProvider->bandCount();
227 }
228 
229 QString QgsRasterLayer::bandName( int bandNo ) const
230 {
231  return dataProvider()->generateBandName( bandNo );
232 }
233 
234 void QgsRasterLayer::setRendererForDrawingStyle( QgsRaster::DrawingStyle drawingStyle )
235 {
236  setRenderer( QgsApplication::rasterRendererRegistry()->defaultRendererForDrawingStyle( drawingStyle, mDataProvider ) );
237 }
238 
240 {
241  return mDataProvider;
242 }
243 
245 {
246  return mDataProvider;
247 }
248 
250 {
251  if ( mDataProvider )
252  {
253  mDataProvider->reloadData();
254  }
255 }
256 
258 {
259  return new QgsRasterLayerRenderer( this, rendererContext );
260 }
261 
262 
263 void QgsRasterLayer::draw( QPainter *theQPainter,
264  QgsRasterViewPort *rasterViewPort,
265  const QgsMapToPixel *qgsMapToPixel )
266 {
267  QgsDebugMsgLevel( " 3 arguments", 4 );
268  QTime time;
269  time.start();
270  //
271  //
272  // The goal here is to make as many decisions as possible early on (outside of the rendering loop)
273  // so that we can maximise performance of the rendering process. So now we check which drawing
274  // procedure to use :
275  //
276 
277  QgsRasterProjector *projector = mPipe.projector();
278 
279  // TODO add a method to interface to get provider and get provider
280  // params in QgsRasterProjector
281  if ( projector )
282  {
283  projector->setCrs( rasterViewPort->mSrcCRS, rasterViewPort->mDestCRS, rasterViewPort->mSrcDatumTransform, rasterViewPort->mDestDatumTransform );
284  }
285 
286  // Drawer to pipe?
287  QgsRasterIterator iterator( mPipe.last() );
288  QgsRasterDrawer drawer( &iterator );
289  drawer.draw( theQPainter, rasterViewPort, qgsMapToPixel );
290 
291  QgsDebugMsgLevel( QString( "total raster draw time (ms): %1" ).arg( time.elapsed(), 5 ), 4 );
292 } //end of draw method
293 
295 {
296  QList< QPair< QString, QColor > > symbolList;
298  if ( renderer )
299  {
300  renderer->legendSymbologyItems( symbolList );
301  }
302  return symbolList;
303 }
304 
306 {
307  QgsLayerMetadataFormatter htmlFormatter( metadata() );
308  QString myMetadata = QStringLiteral( "<html>\n<body>\n" );
309 
310  // Begin Provider section
311  myMetadata += QStringLiteral( "<h1>" ) + tr( "Information from provider" ) + QStringLiteral( "</h1>\n<hr>\n" );
312  myMetadata += QLatin1String( "<table class=\"list-view\">\n" );
313 
314  // original name
315  myMetadata += QStringLiteral( "<tr><td class=\"highlight\">" ) + tr( "Original" ) + QStringLiteral( "</td><td>" ) + name() + QStringLiteral( "</td></tr>\n" );
316 
317  // name
318  myMetadata += QStringLiteral( "<tr><td class=\"highlight\">" ) + tr( "Name" ) + QStringLiteral( "</td><td>" ) + name() + QStringLiteral( "</td></tr>\n" );
319 
320  // data source
321  myMetadata += QStringLiteral( "<tr><td class=\"highlight\">" ) + tr( "Source" ) + QStringLiteral( "</td><td>" ) + publicSource() + QStringLiteral( "</td></tr>\n" );
322 
323  // storage type
324  myMetadata += QStringLiteral( "<tr><td class=\"highlight\">" ) + tr( "Provider" ) + QStringLiteral( "</td><td>" ) + providerType() + QStringLiteral( "</td></tr>\n" );
325 
326  // EPSG
327  myMetadata += QStringLiteral( "<tr><td class=\"highlight\">" ) + tr( "CRS" ) + QStringLiteral( "</td><td>" );
328  if ( crs().isValid() )
329  {
330  myMetadata += crs().authid() + QStringLiteral( " - " );
331  myMetadata += crs().description() + QStringLiteral( " - " );
332  if ( crs().isGeographic() )
333  myMetadata += tr( "Geographic" );
334  else
335  myMetadata += tr( "Projected" );
336  }
337  myMetadata += QLatin1String( "</td></tr>\n" );
338 
339  // Extent
340  myMetadata += QStringLiteral( "<tr><td class=\"highlight\">" ) + tr( "Extent" ) + QStringLiteral( "</td><td>" ) + extent().toString() + QStringLiteral( "</td></tr>\n" );
341 
342  // unit
343  myMetadata += QStringLiteral( "<tr><td class=\"highlight\">" ) + tr( "Unit" ) + QStringLiteral( "</td><td>" ) + QgsUnitTypes::toString( crs().mapUnits() ) + QStringLiteral( "</td></tr>\n" );
344 
345  // Raster Width
346  myMetadata += QStringLiteral( "<tr><td class=\"highlight\">" ) + tr( "Width" ) + QStringLiteral( "</td><td>" );
347  if ( dataProvider()->capabilities() & QgsRasterDataProvider::Size )
348  myMetadata += QString::number( width() );
349  else
350  myMetadata += tr( "n/a" );
351  myMetadata += QLatin1String( "</td></tr>\n" );
352 
353  // Raster height
354  myMetadata += QStringLiteral( "<tr><td class=\"highlight\">" ) + tr( "Height" ) + QStringLiteral( "</td><td>" );
355  if ( dataProvider()->capabilities() & QgsRasterDataProvider::Size )
356  myMetadata += QString::number( height() );
357  else
358  myMetadata += tr( "n/a" );
359  myMetadata += QLatin1String( "</td></tr>\n" );
360 
361  // Data type
362  myMetadata += QStringLiteral( "<tr><td class=\"highlight\">" ) + tr( "Data type" ) + QStringLiteral( "</td><td>" );
363  // Just use the first band
364  switch ( mDataProvider->sourceDataType( 1 ) )
365  {
366  case Qgis::Byte:
367  myMetadata += tr( "Byte - Eight bit unsigned integer" );
368  break;
369  case Qgis::UInt16:
370  myMetadata += tr( "UInt16 - Sixteen bit unsigned integer " );
371  break;
372  case Qgis::Int16:
373  myMetadata += tr( "Int16 - Sixteen bit signed integer " );
374  break;
375  case Qgis::UInt32:
376  myMetadata += tr( "UInt32 - Thirty two bit unsigned integer " );
377  break;
378  case Qgis::Int32:
379  myMetadata += tr( "Int32 - Thirty two bit signed integer " );
380  break;
381  case Qgis::Float32:
382  myMetadata += tr( "Float32 - Thirty two bit floating point " );
383  break;
384  case Qgis::Float64:
385  myMetadata += tr( "Float64 - Sixty four bit floating point " );
386  break;
387  case Qgis::CInt16:
388  myMetadata += tr( "CInt16 - Complex Int16 " );
389  break;
390  case Qgis::CInt32:
391  myMetadata += tr( "CInt32 - Complex Int32 " );
392  break;
393  case Qgis::CFloat32:
394  myMetadata += tr( "CFloat32 - Complex Float32 " );
395  break;
396  case Qgis::CFloat64:
397  myMetadata += tr( "CFloat64 - Complex Float64 " );
398  break;
399  default:
400  myMetadata += tr( "Could not determine raster data type." );
401  }
402  myMetadata += QLatin1String( "</td></tr>\n" );
403 
404  // Insert provider-specific (e.g. WMS-specific) metadata
405  myMetadata += mDataProvider->htmlMetadata();
406 
407  // End Provider section
408  myMetadata += QLatin1String( "</table>\n<br><br>" );
409 
410  // Identification section
411  myMetadata += QStringLiteral( "<h1>" ) + tr( "Identification" ) + QStringLiteral( "</h1>\n<hr>\n" );
412  myMetadata += htmlFormatter.identificationSectionHtml();
413  myMetadata += QLatin1String( "<br><br>\n" );
414 
415  // extent section
416  myMetadata += QStringLiteral( "<h1>" ) + tr( "Extent" ) + QStringLiteral( "</h1>\n<hr>\n" );
417  myMetadata += htmlFormatter.extentSectionHtml( );
418  myMetadata += QLatin1String( "<br><br>\n" );
419 
420  // Start the Access section
421  myMetadata += QStringLiteral( "<h1>" ) + tr( "Access" ) + QStringLiteral( "</h1>\n<hr>\n" );
422  myMetadata += htmlFormatter.accessSectionHtml( );
423  myMetadata += QLatin1String( "<br><br>\n" );
424 
425  // Bands section
426  myMetadata += QStringLiteral( "</table>\n<br><br><h1>" ) + tr( "Bands" ) + QStringLiteral( "</h1>\n<hr>\n<table class=\"list-view\">\n" );
427 
428  // Band count
429  myMetadata += QStringLiteral( "<tr><td class=\"highlight\">" ) + tr( "Band count" ) + QStringLiteral( "</td><td>" ) + QString::number( bandCount() ) + QStringLiteral( "</td></tr>\n" );
430 
431  // Band table
432  myMetadata += QLatin1String( "</table>\n<br><table width=\"100%\" class=\"tabular-view\">\n" );
433  myMetadata += "<tr><th>" + tr( "Number" ) + "</th><th>" + tr( "Band" ) + "</th><th>" + tr( "No-Data" ) + "</th><th>" + tr( "Min" ) + "</th><th>" + tr( "Max" ) + "</th></tr>\n";
434 
435  QgsRasterDataProvider *provider = const_cast< QgsRasterDataProvider * >( mDataProvider );
436  for ( int i = 1; i <= bandCount(); i++ )
437  {
438  QString rowClass;
439  if ( i % 2 )
440  rowClass = QStringLiteral( "class=\"odd-row\"" );
441  myMetadata += "<tr " + rowClass + "><td>" + QString::number( i ) + "</td><td>" + bandName( i ) + "</td><td>";
442 
443  if ( dataProvider()->sourceHasNoDataValue( i ) )
444  myMetadata += QString::number( dataProvider()->sourceNoDataValue( i ) );
445  else
446  myMetadata += tr( "n/a" );
447  myMetadata += QLatin1String( "</td>" );
448 
449  if ( provider->hasStatistics( i ) )
450  {
451  QgsRasterBandStats myRasterBandStats = provider->bandStatistics( i );
452  myMetadata += "<td>" + QString::number( myRasterBandStats.minimumValue, 'f', 10 ) + "</td>";
453  myMetadata += "<td>" + QString::number( myRasterBandStats.maximumValue, 'f', 10 ) + "</td>";
454  }
455  else
456  {
457  myMetadata += "<td>" + tr( "n/a" ) + "</td><td>" + tr( "n/a" ) + "</td>";
458  }
459 
460  myMetadata += QLatin1String( "</tr>\n" );
461  }
462 
463  //close previous bands table
464  myMetadata += QLatin1String( "</table>\n<br><br>" );
465 
466  // Start the contacts section
467  myMetadata += QStringLiteral( "<h1>" ) + tr( "Contacts" ) + QStringLiteral( "</h1>\n<hr>\n" );
468  myMetadata += htmlFormatter.contactsSectionHtml( );
469  myMetadata += QLatin1String( "<br><br>\n" );
470 
471  // Start the links section
472  myMetadata += QStringLiteral( "<h1>" ) + tr( "References" ) + QStringLiteral( "</h1>\n<hr>\n" );
473  myMetadata += htmlFormatter.linksSectionHtml( );
474  myMetadata += QLatin1String( "<br><br>\n" );
475 
476  // Start the history section
477  myMetadata += QStringLiteral( "<h1>" ) + tr( "History" ) + QStringLiteral( "</h1>\n<hr>\n" );
478  myMetadata += htmlFormatter.historySectionHtml( );
479  myMetadata += QLatin1String( "<br><br>\n" );
480 
481  myMetadata += QStringLiteral( "\n</body>\n</html>\n" );
482  return myMetadata;
483 }
484 
485 QPixmap QgsRasterLayer::paletteAsPixmap( int bandNumber )
486 {
487  //TODO: This function should take dimensions
488  QgsDebugMsgLevel( "entered.", 4 );
489 
490  // Only do this for the GDAL provider?
491  // Maybe WMS can do this differently using QImage::numColors and QImage::color()
492  if ( mDataProvider->colorInterpretation( bandNumber ) == QgsRaster::PaletteIndex )
493  {
494  QgsDebugMsgLevel( "....found paletted image", 4 );
495  QgsColorRampShader myShader;
496  QList<QgsColorRampShader::ColorRampItem> myColorRampItemList = mDataProvider->colorTable( bandNumber );
497  if ( !myColorRampItemList.isEmpty() )
498  {
499  QgsDebugMsgLevel( "....got color ramp item list", 4 );
500  myShader.setColorRampItemList( myColorRampItemList );
502  // Draw image
503  int mySize = 100;
504  QPixmap myPalettePixmap( mySize, mySize );
505  QPainter myQPainter( &myPalettePixmap );
506 
507  QImage myQImage = QImage( mySize, mySize, QImage::Format_RGB32 );
508  myQImage.fill( 0 );
509  myPalettePixmap.fill();
510 
511  double myStep = ( static_cast< double >( myColorRampItemList.size() ) - 1 ) / static_cast< double >( mySize * mySize );
512  double myValue = 0.0;
513  for ( int myRow = 0; myRow < mySize; myRow++ )
514  {
515  QRgb *myLineBuffer = reinterpret_cast< QRgb * >( myQImage.scanLine( myRow ) );
516  for ( int myCol = 0; myCol < mySize; myCol++ )
517  {
518  myValue = myStep * static_cast< double >( myCol + myRow * mySize );
519  int c1, c2, c3, c4;
520  myShader.shade( myValue, &c1, &c2, &c3, &c4 );
521  myLineBuffer[ myCol ] = qRgba( c1, c2, c3, c4 );
522  }
523  }
524 
525  myQPainter.drawImage( 0, 0, myQImage );
526  return myPalettePixmap;
527  }
528  QPixmap myNullPixmap;
529  return myNullPixmap;
530  }
531  else
532  {
533  //invalid layer was requested
534  QPixmap myNullPixmap;
535  return myNullPixmap;
536  }
537 }
538 
540 {
541  return mProviderKey;
542 }
543 
545 {
546 // We return one raster pixel per map unit pixel
547 // One raster pixel can have several raster units...
548 
549 // We can only use one of the mGeoTransform[], so go with the
550 // horisontal one.
551 
552  if ( mDataProvider->capabilities() & QgsRasterDataProvider::Size && !qgsDoubleNear( mDataProvider->xSize(), 0.0 ) )
553  {
554  return mDataProvider->extent().width() / mDataProvider->xSize();
555  }
556  return 1;
557 }
558 
560 {
561  if ( mDataProvider->capabilities() & QgsRasterDataProvider::Size && !qgsDoubleNear( mDataProvider->ySize(), 0.0 ) )
562  {
563  return mDataProvider->extent().height() / mDataProvider->ySize();
564  }
565  return 1;
566 }
567 
568 void QgsRasterLayer::init()
569 {
570  mRasterType = QgsRasterLayer::GrayOrUndefined;
571 
573 
574  setRendererForDrawingStyle( QgsRaster::UndefinedDrawingStyle );
575 
576  //Initialize the last view port structure, should really be a class
577  mLastViewPort.mWidth = 0;
578  mLastViewPort.mHeight = 0;
579 }
580 
581 void QgsRasterLayer::setDataProvider( QString const &provider, const QgsDataProvider::ProviderOptions &options )
582 {
583  QgsDebugMsgLevel( "Entered", 4 );
584  mValid = false; // assume the layer is invalid until we determine otherwise
585 
586  mPipe.remove( mDataProvider ); // deletes if exists
587  mDataProvider = nullptr;
588 
589  // XXX should I check for and possibly delete any pre-existing providers?
590  // XXX How often will that scenario occur?
591 
592  mProviderKey = provider;
593  // set the layer name (uppercase first character)
594  if ( ! mLayerName.isEmpty() ) // XXX shouldn't this happen in parent?
595  {
596  setName( mLayerName );
597  }
598 
599  //mBandCount = 0;
600 
601  mDataProvider = dynamic_cast< QgsRasterDataProvider * >( QgsProviderRegistry::instance()->createProvider( mProviderKey, mDataSource, options ) );
602  if ( !mDataProvider )
603  {
604  //QgsMessageLog::logMessage( tr( "Cannot instantiate the data provider" ), tr( "Raster" ) );
605  appendError( ERR( tr( "Cannot instantiate the '%1' data provider" ).arg( mProviderKey ) ) );
606  return;
607  }
608  QgsDebugMsgLevel( "Data provider created", 4 );
609  mDataProvider->setParent( this );
610 
611  // Set data provider into pipe even if not valid so that it is deleted with pipe (with layer)
612  mPipe.set( mDataProvider );
613  if ( !mDataProvider->isValid() )
614  {
615  setError( mDataProvider->error() );
616  appendError( ERR( tr( "Provider is not valid (provider: %1, URI: %2" ).arg( mProviderKey, mDataSource ) ) );
617  return;
618  }
619 
621  {
622  setMetadata( mDataProvider->layerMetadata() );
623  QgsDebugMsgLevel( QString( "Set Data provider QgsLayerMetadata identifier[%1]" ).arg( metadata().identifier() ), 4 );
624  }
625 
626  if ( provider == QLatin1String( "gdal" ) )
627  {
628  // make sure that the /vsigzip or /vsizip is added to uri, if applicable
629  mDataSource = mDataProvider->dataSourceUri();
630  }
631 
632  // get the extent
633  QgsRectangle mbr = mDataProvider->extent();
634 
635  // show the extent
636  QgsDebugMsgLevel( "Extent of layer: " + mbr.toString(), 4 );
637  // store the extent
638  setExtent( mbr );
639 
640  // upper case the first letter of the layer name
641  QgsDebugMsgLevel( "mLayerName: " + name(), 4 );
642 
643  // set up the raster drawing style
644  // Do not set any 'sensible' style here, the style is set later
645 
646  // Setup source CRS
647  setCrs( QgsCoordinateReferenceSystem( mDataProvider->crs() ) );
648 
649  QgsDebugMsgLevel( "using wkt:\n" + crs().toWkt(), 4 );
650 
651  //defaults - Needs to be set after the Contrast list has been build
652  //Try to read the default contrast enhancement from the config file
653 
654  //decide what type of layer this is...
655  //TODO Change this to look at the color interp and palette interp to decide which type of layer it is
656  QgsDebugMsgLevel( "bandCount = " + QString::number( mDataProvider->bandCount() ), 4 );
657  QgsDebugMsgLevel( "dataType = " + QString::number( mDataProvider->dataType( 1 ) ), 4 );
658  if ( ( mDataProvider->bandCount() > 1 ) )
659  {
660  // handle singleband gray with alpha
661  if ( mDataProvider->bandCount() == 2
662  && ( ( mDataProvider->colorInterpretation( 1 ) == QgsRaster::GrayIndex
663  && mDataProvider->colorInterpretation( 2 ) == QgsRaster::AlphaBand )
664  || ( mDataProvider->colorInterpretation( 1 ) == QgsRaster::AlphaBand
665  && mDataProvider->colorInterpretation( 2 ) == QgsRaster::GrayIndex ) ) )
666  {
667  mRasterType = GrayOrUndefined;
668  }
669  else
670  {
671  mRasterType = Multiband;
672  }
673  }
674  else if ( mDataProvider->dataType( 1 ) == Qgis::ARGB32
675  || mDataProvider->dataType( 1 ) == Qgis::ARGB32_Premultiplied )
676  {
677  mRasterType = ColorLayer;
678  }
679  else if ( mDataProvider->colorInterpretation( 1 ) == QgsRaster::PaletteIndex )
680  {
681  mRasterType = Palette;
682  }
683  else if ( mDataProvider->colorInterpretation( 1 ) == QgsRaster::ContinuousPalette )
684  {
685  mRasterType = Palette;
686  }
687  else
688  {
689  mRasterType = GrayOrUndefined;
690  }
691 
692  QgsDebugMsgLevel( "mRasterType = " + QString::number( mRasterType ), 4 );
693  if ( mRasterType == ColorLayer )
694  {
695  QgsDebugMsgLevel( "Setting drawing style to SingleBandColorDataStyle " + QString::number( QgsRaster::SingleBandColorDataStyle ), 4 );
696  setRendererForDrawingStyle( QgsRaster::SingleBandColorDataStyle );
697  }
698  else if ( mRasterType == Palette && mDataProvider->colorInterpretation( 1 ) == QgsRaster::PaletteIndex )
699  {
700  setRendererForDrawingStyle( QgsRaster::PalettedColor ); //sensible default
701  }
702  else if ( mRasterType == Palette && mDataProvider->colorInterpretation( 1 ) == QgsRaster::ContinuousPalette )
703  {
704  setRendererForDrawingStyle( QgsRaster::SingleBandPseudoColor );
705  // Load color table
706  QList<QgsColorRampShader::ColorRampItem> colorTable = mDataProvider->colorTable( 1 );
708  if ( r )
709  {
710  // TODO: this should go somewhere else
711  QgsRasterShader *shader = new QgsRasterShader();
712  QgsColorRampShader *colorRampShader = new QgsColorRampShader();
714  colorRampShader->setColorRampItemList( colorTable );
715  shader->setRasterShaderFunction( colorRampShader );
716  r->setShader( shader );
717  }
718  }
719  else if ( mRasterType == Multiband )
720  {
721  setRendererForDrawingStyle( QgsRaster::MultiBandColor ); //sensible default
722  }
723  else //GrayOrUndefined
724  {
725  setRendererForDrawingStyle( QgsRaster::SingleBandGray ); //sensible default
726  }
727 
728  // Auto set alpha band
729  for ( int bandNo = 1; bandNo <= mDataProvider->bandCount(); bandNo++ )
730  {
731  if ( mDataProvider->colorInterpretation( bandNo ) == QgsRaster::AlphaBand )
732  {
733  if ( mPipe.renderer() )
734  {
735  mPipe.renderer()->setAlphaBand( bandNo );
736  }
737  break;
738  }
739  }
740 
741  // brightness filter
743  mPipe.set( brightnessFilter );
744 
745  // hue/saturation filter
747  mPipe.set( hueSaturationFilter );
748 
749  //resampler (must be after renderer)
751  mPipe.set( resampleFilter );
752 
753  // projector (may be anywhere in pipe)
754  QgsRasterProjector *projector = new QgsRasterProjector;
755  mPipe.set( projector );
756 
757  // Set default identify format - use the richest format available
758  int capabilities = mDataProvider->capabilities();
760  if ( capabilities & QgsRasterInterface::IdentifyHtml )
761  {
762  // HTML is usually richest
763  identifyFormat = QgsRaster::IdentifyFormatHtml;
764  }
765  else if ( capabilities & QgsRasterInterface::IdentifyFeature )
766  {
767  identifyFormat = QgsRaster::IdentifyFormatFeature;
768  }
769  else if ( capabilities & QgsRasterInterface::IdentifyText )
770  {
771  identifyFormat = QgsRaster::IdentifyFormatText;
772  }
773  else if ( capabilities & QgsRasterInterface::IdentifyValue )
774  {
775  identifyFormat = QgsRaster::IdentifyFormatValue;
776  }
777  setCustomProperty( QStringLiteral( "identify/format" ), QgsRasterDataProvider::identifyFormatName( identifyFormat ) );
778 
779  // Store timestamp
780  // TODO move to provider
781  mLastModified = lastModified( mDataSource );
782 
783  // Do a passthrough for the status bar text
784  connect( mDataProvider, &QgsRasterDataProvider::statusChanged, this, &QgsRasterLayer::statusChanged );
785 
786  //mark the layer as valid
787  mValid = true;
788 
789  QgsDebugMsgLevel( "exiting.", 4 );
790 } // QgsRasterLayer::setDataProvider
791 
792 void QgsRasterLayer::closeDataProvider()
793 {
794  mValid = false;
795  mPipe.remove( mDataProvider );
796  mDataProvider = nullptr;
797 }
798 
799 void QgsRasterLayer::computeMinMax( int band,
800  const QgsRasterMinMaxOrigin &mmo,
802  const QgsRectangle &extent,
803  int sampleSize,
804  double &min, double &max )
805 {
806 
807  min = std::numeric_limits<double>::quiet_NaN();
808  max = std::numeric_limits<double>::quiet_NaN();
809 
810  if ( limits == QgsRasterMinMaxOrigin::MinMax )
811  {
812  QgsRasterBandStats myRasterBandStats = mDataProvider->bandStatistics( band, QgsRasterBandStats::Min | QgsRasterBandStats::Max, extent, sampleSize );
813  min = myRasterBandStats.minimumValue;
814  max = myRasterBandStats.maximumValue;
815  }
816  else if ( limits == QgsRasterMinMaxOrigin::StdDev )
817  {
818  QgsRasterBandStats myRasterBandStats = mDataProvider->bandStatistics( band, QgsRasterBandStats::Mean | QgsRasterBandStats::StdDev, extent, sampleSize );
819  min = myRasterBandStats.mean - ( mmo.stdDevFactor() * myRasterBandStats.stdDev );
820  max = myRasterBandStats.mean + ( mmo.stdDevFactor() * myRasterBandStats.stdDev );
821  }
822  else if ( limits == QgsRasterMinMaxOrigin::CumulativeCut )
823  {
824  const double myLower = mmo.cumulativeCutLower();
825  const double myUpper = mmo.cumulativeCutUpper();
826  QgsDebugMsgLevel( QString( "myLower = %1 myUpper = %2" ).arg( myLower ).arg( myUpper ), 4 );
827  mDataProvider->cumulativeCut( band, myLower, myUpper, min, max, extent, sampleSize );
828  }
829  QgsDebugMsgLevel( QString( "band = %1 min = %2 max = %3" ).arg( band ).arg( min ).arg( max ), 4 );
830 
831 }
832 
833 
835 {
836  setContrastEnhancement( algorithm,
837  limits,
838  extent,
839  sampleSize,
840  generateLookupTableFlag,
841  mPipe.renderer() );
842 }
843 
846  const QgsRectangle &extent,
847  int sampleSize,
848  bool generateLookupTableFlag,
849  QgsRasterRenderer *rasterRenderer )
850 {
851  QgsDebugMsgLevel( QString( "theAlgorithm = %1 limits = %2 extent.isEmpty() = %3" ).arg( algorithm ).arg( limits ).arg( extent.isEmpty() ), 4 );
852  if ( !rasterRenderer || !mDataProvider )
853  {
854  return;
855  }
856 
857  QList<int> myBands;
858  QList<QgsContrastEnhancement *> myEnhancements;
859  QgsRasterMinMaxOrigin myMinMaxOrigin;
860  QgsRasterRenderer *myRasterRenderer = nullptr;
861  QgsSingleBandGrayRenderer *myGrayRenderer = nullptr;
862  QgsSingleBandPseudoColorRenderer *myPseudoColorRenderer = nullptr;
863  QgsMultiBandColorRenderer *myMultiBandRenderer = nullptr;
864  QString rendererType = rasterRenderer->type();
865  if ( rendererType == QLatin1String( "singlebandgray" ) )
866  {
867  myGrayRenderer = dynamic_cast<QgsSingleBandGrayRenderer *>( rasterRenderer );
868  if ( !myGrayRenderer )
869  {
870  return;
871  }
872  myBands << myGrayRenderer->grayBand();
873  myRasterRenderer = myGrayRenderer;
874  myMinMaxOrigin = myGrayRenderer->minMaxOrigin();
875  }
876  else if ( rendererType == QLatin1String( "multibandcolor" ) )
877  {
878  myMultiBandRenderer = dynamic_cast<QgsMultiBandColorRenderer *>( rasterRenderer );
879  if ( !myMultiBandRenderer )
880  {
881  return;
882  }
883  myBands << myMultiBandRenderer->redBand() << myMultiBandRenderer->greenBand() << myMultiBandRenderer->blueBand();
884  myRasterRenderer = myMultiBandRenderer;
885  myMinMaxOrigin = myMultiBandRenderer->minMaxOrigin();
886  }
887  else if ( rendererType == QLatin1String( "singlebandpseudocolor" ) )
888  {
889  myPseudoColorRenderer = dynamic_cast<QgsSingleBandPseudoColorRenderer *>( rasterRenderer );
890  if ( !myPseudoColorRenderer )
891  {
892  return;
893  }
894  myBands << myPseudoColorRenderer->band();
895  myRasterRenderer = myPseudoColorRenderer;
896  myMinMaxOrigin = myPseudoColorRenderer->minMaxOrigin();
897  }
898  else
899  {
900  return;
901  }
902 
903  Q_FOREACH ( int myBand, myBands )
904  {
905  if ( myBand != -1 )
906  {
907  Qgis::DataType myType = static_cast< Qgis::DataType >( mDataProvider->dataType( myBand ) );
908  std::unique_ptr<QgsContrastEnhancement> myEnhancement( new QgsContrastEnhancement( static_cast< Qgis::DataType >( myType ) ) );
909  myEnhancement->setContrastEnhancementAlgorithm( algorithm, generateLookupTableFlag );
910 
911  double min;
912  double max;
913  computeMinMax( myBand, myMinMaxOrigin, limits, extent, sampleSize, min, max );
914 
915  if ( rendererType == QLatin1String( "singlebandpseudocolor" ) )
916  {
917  myPseudoColorRenderer->setClassificationMin( min );
918  myPseudoColorRenderer->setClassificationMax( max );
919  if ( myPseudoColorRenderer->shader() )
920  {
921  QgsColorRampShader *colorRampShader = dynamic_cast<QgsColorRampShader *>( myPseudoColorRenderer->shader()->rasterShaderFunction() );
922  if ( colorRampShader )
923  {
924  colorRampShader->classifyColorRamp( myPseudoColorRenderer->band(), extent, myPseudoColorRenderer->input() );
925  }
926  }
927  }
928  else
929  {
930  myEnhancement->setMinimumValue( min );
931  myEnhancement->setMaximumValue( max );
932  myEnhancements.append( myEnhancement.release() );
933  }
934  }
935  else
936  {
937  myEnhancements.append( nullptr );
938  }
939  }
940 
941  if ( rendererType == QLatin1String( "singlebandgray" ) )
942  {
943  if ( myEnhancements.first() ) myGrayRenderer->setContrastEnhancement( myEnhancements.takeFirst() );
944  }
945  else if ( rendererType == QLatin1String( "multibandcolor" ) )
946  {
947  if ( myEnhancements.first() ) myMultiBandRenderer->setRedContrastEnhancement( myEnhancements.takeFirst() );
948  if ( myEnhancements.first() ) myMultiBandRenderer->setGreenContrastEnhancement( myEnhancements.takeFirst() );
949  if ( myEnhancements.first() ) myMultiBandRenderer->setBlueContrastEnhancement( myEnhancements.takeFirst() );
950  }
951 
952  //delete all remaining unused enhancements
953  qDeleteAll( myEnhancements );
954 
955  myMinMaxOrigin.setLimits( limits );
956  if ( extent != QgsRectangle() &&
957  myMinMaxOrigin.extent() == QgsRasterMinMaxOrigin::WholeRaster )
958  {
960  }
961  if ( myRasterRenderer )
962  {
963  myRasterRenderer->setMinMaxOrigin( myMinMaxOrigin );
964  }
965 
966  if ( rasterRenderer == renderer() )
967  {
968  emit repaintRequested();
969  emit styleChanged();
970  emit rendererChanged();
971  }
972 }
973 
975 {
976  QgsSingleBandGrayRenderer *singleBandRenderer = nullptr;
977  QgsMultiBandColorRenderer *multiBandRenderer = nullptr;
978  const QgsContrastEnhancement *ce = nullptr;
979  if ( ( singleBandRenderer = dynamic_cast<QgsSingleBandGrayRenderer *>( renderer() ) ) )
980  {
981  ce = singleBandRenderer->contrastEnhancement();
982  }
983  else if ( ( multiBandRenderer = dynamic_cast<QgsMultiBandColorRenderer *>( renderer() ) ) )
984  {
985  ce = multiBandRenderer->redContrastEnhancement();
986  }
987 
988  if ( ce )
989  {
994  extent,
995  SAMPLE_SIZE,
996  true,
997  renderer() );
998  }
999  else
1000  {
1003  if ( defaultContrastEnhancementSettings( myAlgorithm, myLimits ) )
1004  {
1006  myLimits,
1007  extent,
1008  SAMPLE_SIZE,
1009  true,
1010  renderer() );
1011  }
1012  }
1013 }
1014 
1016  const QgsRectangle &extent )
1017 {
1018  if ( !( mDataProvider &&
1019  mLastRectangleUsedByRefreshContrastEnhancementIfNeeded != extent &&
1020  rasterRenderer->minMaxOrigin().limits() != QgsRasterMinMaxOrigin::None &&
1021  rasterRenderer->minMaxOrigin().extent() == QgsRasterMinMaxOrigin::UpdatedCanvas ) )
1022  return;
1023 
1024  QgsSingleBandGrayRenderer *singleBandRenderer = nullptr;
1025  QgsMultiBandColorRenderer *multiBandRenderer = nullptr;
1026  QgsSingleBandPseudoColorRenderer *sbpcr = nullptr;
1027  const QgsContrastEnhancement *ce = nullptr;
1028  if ( ( singleBandRenderer = dynamic_cast<QgsSingleBandGrayRenderer *>( rasterRenderer ) ) )
1029  {
1030  ce = singleBandRenderer->contrastEnhancement();
1031  }
1032  else if ( ( multiBandRenderer = dynamic_cast<QgsMultiBandColorRenderer *>( rasterRenderer ) ) )
1033  {
1034  ce = multiBandRenderer->redContrastEnhancement();
1035  }
1036  else if ( ( sbpcr = dynamic_cast<QgsSingleBandPseudoColorRenderer *>( rasterRenderer ) ) )
1037  {
1038  mLastRectangleUsedByRefreshContrastEnhancementIfNeeded = extent;
1039  double min;
1040  double max;
1041  computeMinMax( sbpcr->band(),
1042  rasterRenderer->minMaxOrigin(),
1043  rasterRenderer->minMaxOrigin().limits(), extent,
1044  SAMPLE_SIZE, min, max );
1045  sbpcr->setClassificationMin( min );
1046  sbpcr->setClassificationMax( max );
1047 
1048  if ( sbpcr->shader() )
1049  {
1050  QgsColorRampShader *colorRampShader = dynamic_cast<QgsColorRampShader *>( sbpcr->shader()->rasterShaderFunction() );
1051  if ( colorRampShader )
1052  {
1053  colorRampShader->classifyColorRamp( sbpcr->band(), extent, rasterRenderer->input() );
1054  }
1055  }
1056 
1058  r->setClassificationMin( min );
1059  r->setClassificationMax( max );
1060 
1061  if ( r->shader() )
1062  {
1063  QgsColorRampShader *colorRampShader = dynamic_cast<QgsColorRampShader *>( r->shader()->rasterShaderFunction() );
1064  if ( colorRampShader )
1065  {
1066  colorRampShader->classifyColorRamp( sbpcr->band(), extent, rasterRenderer->input() );
1067  }
1068  }
1069 
1070  emit repaintRequested();
1071  emit styleChanged();
1072  emit rendererChanged();
1073  return;
1074  }
1075 
1076  if ( ce &&
1078  {
1079  mLastRectangleUsedByRefreshContrastEnhancementIfNeeded = extent;
1080 
1082  rasterRenderer->minMaxOrigin().limits(),
1083  extent,
1084  SAMPLE_SIZE,
1085  true,
1086  rasterRenderer );
1087 
1088  // Update main renderer so that the legends get updated
1089  if ( singleBandRenderer )
1090  static_cast<QgsSingleBandGrayRenderer *>( renderer() )->setContrastEnhancement( new QgsContrastEnhancement( * singleBandRenderer->contrastEnhancement() ) );
1091  else if ( multiBandRenderer )
1092  {
1093  if ( multiBandRenderer->redContrastEnhancement() )
1094  {
1095  static_cast<QgsMultiBandColorRenderer *>( renderer() )->setRedContrastEnhancement( new QgsContrastEnhancement( *multiBandRenderer->redContrastEnhancement() ) );
1096  }
1097  if ( multiBandRenderer->greenContrastEnhancement() )
1098  {
1099  static_cast<QgsMultiBandColorRenderer *>( renderer() )->setGreenContrastEnhancement( new QgsContrastEnhancement( *multiBandRenderer->greenContrastEnhancement() ) );
1100  }
1101  if ( multiBandRenderer->blueContrastEnhancement() )
1102  {
1103  static_cast<QgsMultiBandColorRenderer *>( renderer() )->setBlueContrastEnhancement( new QgsContrastEnhancement( *multiBandRenderer->blueContrastEnhancement() ) );
1104  }
1105  }
1106 
1107  emit styleChanged();
1108  emit rendererChanged();
1109  }
1110 }
1111 
1114  QgsRasterMinMaxOrigin::Limits &myLimits ) const
1115 {
1116  QgsSettings mySettings;
1117 
1118  QString key;
1119  QString defaultAlg;
1120  QString defaultLimits;
1121 
1122  // TODO: we should not test renderer class here, move it somehow to renderers
1123  if ( dynamic_cast<QgsSingleBandGrayRenderer *>( renderer() ) )
1124  {
1125  key = QStringLiteral( "singleBand" );
1128  defaultLimits = QgsRasterMinMaxOrigin::limitsString(
1130  }
1131  else if ( dynamic_cast<QgsMultiBandColorRenderer *>( renderer() ) )
1132  {
1133  if ( QgsRasterBlock::typeSize( dataProvider()->sourceDataType( 1 ) ) == 1 )
1134  {
1135  key = QStringLiteral( "multiBandSingleByte" );
1138  defaultLimits = QgsRasterMinMaxOrigin::limitsString(
1140  }
1141  else
1142  {
1143  key = QStringLiteral( "multiBandMultiByte" );
1146  defaultLimits = QgsRasterMinMaxOrigin::limitsString(
1148  }
1149  }
1150 
1151  if ( key.isEmpty() )
1152  {
1153  QgsDebugMsg( "No default contrast enhancement for this drawing style" );
1155  myLimits = QgsRasterMinMaxOrigin::limitsFromString( QString() );
1156  return false;
1157  }
1158  QgsDebugMsgLevel( "key = " + key, 4 );
1159 
1160  QString myAlgorithmString = mySettings.value( "/Raster/defaultContrastEnhancementAlgorithm/" + key, defaultAlg ).toString();
1161  QgsDebugMsgLevel( "myAlgorithmString = " + myAlgorithmString, 4 );
1162 
1163  myAlgorithm = QgsContrastEnhancement::contrastEnhancementAlgorithmFromString( myAlgorithmString );
1164 
1165  QString myLimitsString = mySettings.value( "/Raster/defaultContrastEnhancementLimits/" + key, defaultLimits ).toString();
1166  QgsDebugMsgLevel( "myLimitsString = " + myLimitsString, 4 );
1167  myLimits = QgsRasterMinMaxOrigin::limitsFromString( myLimitsString );
1168 
1169  return true;
1170 }
1171 
1173 {
1174  QgsDebugMsgLevel( "Entered", 4 );
1175 
1178  defaultContrastEnhancementSettings( myAlgorithm, myLimits );
1179 
1180  setContrastEnhancement( myAlgorithm, myLimits );
1181 }
1182 
1183 void QgsRasterLayer::setLayerOrder( QStringList const &layers )
1184 {
1185  QgsDebugMsgLevel( "entered.", 4 );
1186 
1187  if ( mDataProvider )
1188  {
1189  QgsDebugMsgLevel( "About to mDataProvider->setLayerOrder(layers).", 4 );
1190  mDataProvider->setLayerOrder( layers );
1191  }
1192 
1193 }
1194 
1195 void QgsRasterLayer::setSubLayerVisibility( const QString &name, bool vis )
1196 {
1197 
1198  if ( mDataProvider )
1199  {
1200  QgsDebugMsgLevel( "About to mDataProvider->setSubLayerVisibility(name, vis).", 4 );
1201  mDataProvider->setSubLayerVisibility( name, vis );
1202  }
1203 
1204 }
1205 
1206 QDateTime QgsRasterLayer::timestamp() const
1207 {
1208  return mDataProvider->timestamp();
1209 }
1210 
1212 {
1213  QgsDebugMsgLevel( "Entered", 4 );
1214  if ( !renderer )
1215  {
1216  return;
1217  }
1218 
1219  mPipe.set( renderer );
1220  emit rendererChanged();
1221  emit styleChanged();
1222 }
1223 
1224 void QgsRasterLayer::showStatusMessage( QString const &message )
1225 {
1226  // QgsDebugMsg(QString("entered with '%1'.").arg(theMessage));
1227 
1228  // Pass-through
1229  // TODO: See if we can connect signal-to-signal. This is a kludge according to the Qt doc.
1230  emit statusChanged( message );
1231 }
1232 
1233 QStringList QgsRasterLayer::subLayers() const
1234 {
1235  return mDataProvider->subLayers();
1236 }
1237 
1238 // this function should be used when rendering with the MTR engine introduced in 2.3, as QPixmap is not thread safe (see bug #9626)
1239 // note: previewAsImage and previewAsPixmap should use a common low-level fct QgsRasterLayer::previewOnPaintDevice( QSize size, QColor bgColor, QPaintDevice &device )
1240 QImage QgsRasterLayer::previewAsImage( QSize size, const QColor &bgColor, QImage::Format format )
1241 {
1242  QImage myQImage( size, format );
1243 
1244  myQImage.setColor( 0, bgColor.rgba() );
1245  myQImage.fill( 0 ); //defaults to white, set to transparent for rendering on a map
1246 
1247  QgsRasterViewPort *myRasterViewPort = new QgsRasterViewPort();
1248 
1249  double myMapUnitsPerPixel;
1250  double myX = 0.0;
1251  double myY = 0.0;
1252  QgsRectangle myExtent = mDataProvider->extent();
1253  if ( myExtent.width() / myExtent.height() >= static_cast< double >( myQImage.width() ) / myQImage.height() )
1254  {
1255  myMapUnitsPerPixel = myExtent.width() / myQImage.width();
1256  myY = ( myQImage.height() - myExtent.height() / myMapUnitsPerPixel ) / 2;
1257  }
1258  else
1259  {
1260  myMapUnitsPerPixel = myExtent.height() / myQImage.height();
1261  myX = ( myQImage.width() - myExtent.width() / myMapUnitsPerPixel ) / 2;
1262  }
1263 
1264  double myPixelWidth = myExtent.width() / myMapUnitsPerPixel;
1265  double myPixelHeight = myExtent.height() / myMapUnitsPerPixel;
1266 
1267  myRasterViewPort->mTopLeftPoint = QgsPointXY( myX, myY );
1268  myRasterViewPort->mBottomRightPoint = QgsPointXY( myPixelWidth, myPixelHeight );
1269  myRasterViewPort->mWidth = myQImage.width();
1270  myRasterViewPort->mHeight = myQImage.height();
1271 
1272  myRasterViewPort->mDrawnExtent = myExtent;
1273  myRasterViewPort->mSrcCRS = QgsCoordinateReferenceSystem(); // will be invalid
1274  myRasterViewPort->mDestCRS = QgsCoordinateReferenceSystem(); // will be invalid
1275  myRasterViewPort->mSrcDatumTransform = -1;
1276  myRasterViewPort->mDestDatumTransform = -1;
1277 
1278  QgsMapToPixel *myMapToPixel = new QgsMapToPixel( myMapUnitsPerPixel );
1279 
1280  QPainter *myQPainter = new QPainter( &myQImage );
1281  draw( myQPainter, myRasterViewPort, myMapToPixel );
1282  delete myRasterViewPort;
1283  delete myMapToPixel;
1284  myQPainter->end();
1285  delete myQPainter;
1286 
1287  return myQImage;
1288 }
1289 
1291 //
1292 // Protected methods
1293 //
1295 /*
1296  * \param QDomNode node that will contain the symbology definition for this layer.
1297  * \param errorMessage reference to string that will be updated with any error messages
1298  * \return true in case of success.
1299  */
1300 bool QgsRasterLayer::readSymbology( const QDomNode &layer_node, QString &errorMessage, QgsReadWriteContext &context )
1301 {
1302  Q_UNUSED( errorMessage );
1303  QDomElement rasterRendererElem;
1304 
1305  QDomElement layerElement = layer_node.toElement();
1306  readCommonStyle( layerElement, context );
1307 
1308  // pipe element was introduced in the end of 1.9 development when there were
1309  // already many project files in use so we support 1.9 backward compatibility
1310  // even it was never officially released -> use pipe element if present, otherwise
1311  // use layer node
1312  QDomNode pipeNode = layer_node.firstChildElement( QStringLiteral( "pipe" ) );
1313  if ( pipeNode.isNull() ) // old project
1314  {
1315  pipeNode = layer_node;
1316  }
1317 
1318  //rasterlayerproperties element there -> old format (1.8 and early 1.9)
1319  if ( !layer_node.firstChildElement( QStringLiteral( "rasterproperties" ) ).isNull() )
1320  {
1321  //copy node because layer_node is const
1322  QDomNode layerNodeCopy = layer_node.cloneNode();
1323  QDomDocument doc = layerNodeCopy.ownerDocument();
1324  QDomElement rasterPropertiesElem = layerNodeCopy.firstChildElement( QStringLiteral( "rasterproperties" ) );
1325  QgsProjectFileTransform::convertRasterProperties( doc, layerNodeCopy, rasterPropertiesElem,
1326  this );
1327  rasterRendererElem = layerNodeCopy.firstChildElement( QStringLiteral( "rasterrenderer" ) );
1328  QgsDebugMsgLevel( doc.toString(), 4 );
1329  }
1330  else
1331  {
1332  rasterRendererElem = pipeNode.firstChildElement( QStringLiteral( "rasterrenderer" ) );
1333  }
1334 
1335  if ( !rasterRendererElem.isNull() )
1336  {
1337  QString rendererType = rasterRendererElem.attribute( QStringLiteral( "type" ) );
1338  QgsRasterRendererRegistryEntry rendererEntry;
1339  if ( QgsApplication::rasterRendererRegistry()->rendererData( rendererType, rendererEntry ) )
1340  {
1341  QgsRasterRenderer *renderer = rendererEntry.rendererCreateFunction( rasterRendererElem, dataProvider() );
1342  mPipe.set( renderer );
1343  }
1344  }
1345 
1346  //brightness
1348  mPipe.set( brightnessFilter );
1349 
1350  //brightness coefficient
1351  QDomElement brightnessElem = pipeNode.firstChildElement( QStringLiteral( "brightnesscontrast" ) );
1352  if ( !brightnessElem.isNull() )
1353  {
1354  brightnessFilter->readXml( brightnessElem );
1355  }
1356 
1357  //hue/saturation
1359  mPipe.set( hueSaturationFilter );
1360 
1361  //saturation coefficient
1362  QDomElement hueSaturationElem = pipeNode.firstChildElement( QStringLiteral( "huesaturation" ) );
1363  if ( !hueSaturationElem.isNull() )
1364  {
1365  hueSaturationFilter->readXml( hueSaturationElem );
1366  }
1367 
1368  //resampler
1370  mPipe.set( resampleFilter );
1371 
1372  //max oversampling
1373  QDomElement resampleElem = pipeNode.firstChildElement( QStringLiteral( "rasterresampler" ) );
1374  if ( !resampleElem.isNull() )
1375  {
1376  resampleFilter->readXml( resampleElem );
1377  }
1378 
1379  // get and set the blend mode if it exists
1380  QDomNode blendModeNode = layer_node.namedItem( QStringLiteral( "blendMode" ) );
1381  if ( !blendModeNode.isNull() )
1382  {
1383  QDomElement e = blendModeNode.toElement();
1384  setBlendMode( QgsPainting::getCompositionMode( static_cast< QgsPainting::BlendMode >( e.text().toInt() ) ) );
1385  }
1386 
1387  readCustomProperties( layer_node );
1388 
1389  return true;
1390 }
1391 
1392 bool QgsRasterLayer::readStyle( const QDomNode &node, QString &errorMessage, QgsReadWriteContext &context )
1393 {
1394  return readSymbology( node, errorMessage, context );
1395 }
1396 
1397 bool QgsRasterLayer::readXml( const QDomNode &layer_node, QgsReadWriteContext &context )
1398 {
1399  QgsDebugMsgLevel( "Entered", 4 );
1400  // Make sure to read the file first so stats etc are initialized properly!
1401 
1402  //process provider key
1403  QDomNode pkeyNode = layer_node.namedItem( QStringLiteral( "provider" ) );
1404 
1405  if ( pkeyNode.isNull() )
1406  {
1407  mProviderKey = QStringLiteral( "gdal" );
1408  }
1409  else
1410  {
1411  QDomElement pkeyElt = pkeyNode.toElement();
1412  mProviderKey = pkeyElt.text();
1413  if ( mProviderKey.isEmpty() )
1414  {
1415  mProviderKey = QStringLiteral( "gdal" );
1416  }
1417  }
1418 
1419  // Open the raster source based on provider and datasource
1420 
1421  // Go down the raster-data-provider paradigm
1422 
1423  // Collect provider-specific information
1424 
1425  QDomNode rpNode = layer_node.namedItem( QStringLiteral( "rasterproperties" ) );
1426 
1427  if ( mProviderKey == QLatin1String( "wms" ) )
1428  {
1429  // >>> BACKWARD COMPATIBILITY < 1.9
1430  // The old WMS URI format does not contain all the information, we add them here.
1431  if ( !mDataSource.contains( QLatin1String( "crs=" ) ) && !mDataSource.contains( QLatin1String( "format=" ) ) )
1432  {
1433  QgsDebugMsgLevel( "Old WMS URI format detected -> adding params", 4 );
1434  QgsDataSourceUri uri;
1435  uri.setEncodedUri( mDataSource );
1436  QDomElement layerElement = rpNode.firstChildElement( QStringLiteral( "wmsSublayer" ) );
1437  while ( !layerElement.isNull() )
1438  {
1439  // TODO: sublayer visibility - post-0.8 release timeframe
1440 
1441  // collect name for the sublayer
1442  uri.setParam( QStringLiteral( "layers" ), layerElement.namedItem( QStringLiteral( "name" ) ).toElement().text() );
1443 
1444  // collect style for the sublayer
1445  uri.setParam( QStringLiteral( "styles" ), layerElement.namedItem( QStringLiteral( "style" ) ).toElement().text() );
1446 
1447  layerElement = layerElement.nextSiblingElement( QStringLiteral( "wmsSublayer" ) );
1448  }
1449 
1450  // Collect format
1451  QDomNode formatNode = rpNode.namedItem( QStringLiteral( "wmsFormat" ) );
1452  uri.setParam( QStringLiteral( "format" ), rpNode.namedItem( QStringLiteral( "wmsFormat" ) ).toElement().text() );
1453 
1454  // WMS CRS URL param should not be mixed with that assigned to the layer.
1455  // In the old WMS URI version there was no CRS and layer crs().authid() was used.
1456  uri.setParam( QStringLiteral( "crs" ), crs().authid() );
1457  mDataSource = uri.encodedUri();
1458  }
1459  // <<< BACKWARD COMPATIBILITY < 1.9
1460  }
1461 
1462  QgsDataProvider::ProviderOptions providerOptions;
1463  setDataProvider( mProviderKey, providerOptions );
1464  if ( !mValid ) return false;
1465 
1466  QString error;
1467  bool res = readSymbology( layer_node, error, context );
1468 
1469  // old wms settings we need to correct
1470  if ( res && mProviderKey == QLatin1String( "wms" ) && ( !renderer() || renderer()->type() != QLatin1String( "singlebandcolordata" ) ) )
1471  {
1472  setRendererForDrawingStyle( QgsRaster::SingleBandColorDataStyle );
1473  }
1474 
1475  // Check timestamp
1476  // This was probably introduced to reload completely raster if data changed and
1477  // reset completely symbology to reflect new data type etc. It creates however
1478  // problems, because user defined symbology is complete lost if data file time
1479  // changed (the content may be the same). See also 6900.
1480 #if 0
1481  QDomNode stampNode = layer_node.namedItem( "timestamp" );
1482  if ( !stampNode.isNull() )
1483  {
1484  QDateTime stamp = QDateTime::fromString( stampNode.toElement().text(), Qt::ISODate );
1485  // TODO: very bad, we have to load twice!!! Make QgsDataProvider::timestamp() static?
1486  if ( stamp < mDataProvider->dataTimestamp() )
1487  {
1488  QgsDebugMsg( "data changed, reload provider" );
1489  closeDataProvider();
1490  init();
1491  setDataProvider( mProviderKey );
1492  if ( !mValid ) return false;
1493  }
1494  }
1495 #endif
1496 
1497  // Load user no data value
1498  QDomElement noDataElement = layer_node.firstChildElement( QStringLiteral( "noData" ) );
1499 
1500  QDomNodeList noDataBandList = noDataElement.elementsByTagName( QStringLiteral( "noDataList" ) );
1501 
1502  for ( int i = 0; i < noDataBandList.size(); ++i )
1503  {
1504  QDomElement bandElement = noDataBandList.at( i ).toElement();
1505  bool ok;
1506  int bandNo = bandElement.attribute( QStringLiteral( "bandNo" ) ).toInt( &ok );
1507  QgsDebugMsgLevel( QString( "bandNo = %1" ).arg( bandNo ), 4 );
1508  if ( ok && ( bandNo > 0 ) && ( bandNo <= mDataProvider->bandCount() ) )
1509  {
1510  mDataProvider->setUseSourceNoDataValue( bandNo, bandElement.attribute( QStringLiteral( "useSrcNoData" ) ).toInt() );
1511  QgsRasterRangeList myNoDataRangeList;
1512 
1513  QDomNodeList rangeList = bandElement.elementsByTagName( QStringLiteral( "noDataRange" ) );
1514 
1515  myNoDataRangeList.reserve( rangeList.size() );
1516  for ( int j = 0; j < rangeList.size(); ++j )
1517  {
1518  QDomElement rangeElement = rangeList.at( j ).toElement();
1519  QgsRasterRange myNoDataRange( rangeElement.attribute( QStringLiteral( "min" ) ).toDouble(),
1520  rangeElement.attribute( QStringLiteral( "max" ) ).toDouble() );
1521  QgsDebugMsgLevel( QString( "min = %1 %2" ).arg( rangeElement.attribute( "min" ) ).arg( myNoDataRange.min() ), 4 );
1522  myNoDataRangeList << myNoDataRange;
1523  }
1524  mDataProvider->setUserNoDataValue( bandNo, myNoDataRangeList );
1525  }
1526  }
1527 
1528  readStyleManager( layer_node );
1529 
1530  return res;
1531 } // QgsRasterLayer::readXml( QDomNode & layer_node )
1532 
1533 /*
1534  * \param QDomNode the node that will have the style element added to it.
1535  * \param QDomDocument the document that will have the QDomNode added.
1536  * \param errorMessage reference to string that will be updated with any error messages
1537  * \return true in case of success.
1538  */
1539 bool QgsRasterLayer::writeSymbology( QDomNode &layer_node, QDomDocument &document, QString &errorMessage, const QgsReadWriteContext &context ) const
1540 {
1541  Q_UNUSED( errorMessage );
1542 
1543  QDomElement layerElement = layer_node.toElement();
1544  writeCommonStyle( layerElement, document, context );
1545 
1546  // Store pipe members (except provider) into pipe element, in future, it will be
1547  // possible to add custom filters into the pipe
1548  QDomElement pipeElement = document.createElement( QStringLiteral( "pipe" ) );
1549 
1550  for ( int i = 1; i < mPipe.size(); i++ )
1551  {
1552  QgsRasterInterface *interface = mPipe.at( i );
1553  if ( !interface ) continue;
1554  interface->writeXml( document, pipeElement );
1555  }
1556 
1557  layer_node.appendChild( pipeElement );
1558 
1559  // add blend mode node
1560  QDomElement blendModeElement = document.createElement( QStringLiteral( "blendMode" ) );
1561  QDomText blendModeText = document.createTextNode( QString::number( QgsPainting::getBlendModeEnum( blendMode() ) ) );
1562  blendModeElement.appendChild( blendModeText );
1563  layer_node.appendChild( blendModeElement );
1564 
1565  return true;
1566 }
1567 
1568 bool QgsRasterLayer::writeStyle( QDomNode &node, QDomDocument &doc, QString &errorMessage, const QgsReadWriteContext &context ) const
1569 {
1570  return writeSymbology( node, doc, errorMessage, context );
1571 
1572 } // bool QgsRasterLayer::writeSymbology
1573 
1574 /*
1575  * virtual
1576  * \note Called by QgsMapLayer::writeXml().
1577  */
1578 bool QgsRasterLayer::writeXml( QDomNode &layer_node,
1579  QDomDocument &document,
1580  const QgsReadWriteContext &context ) const
1581 {
1582  // first get the layer element so that we can append the type attribute
1583 
1584  QDomElement mapLayerNode = layer_node.toElement();
1585 
1586  if ( mapLayerNode.isNull() || "maplayer" != mapLayerNode.nodeName() )
1587  {
1588  QgsMessageLog::logMessage( tr( "<maplayer> not found." ), tr( "Raster" ) );
1589  return false;
1590  }
1591 
1592  mapLayerNode.setAttribute( QStringLiteral( "type" ), QStringLiteral( "raster" ) );
1593 
1594  // add provider node
1595 
1596  QDomElement provider = document.createElement( QStringLiteral( "provider" ) );
1597  QDomText providerText = document.createTextNode( mProviderKey );
1598  provider.appendChild( providerText );
1599  layer_node.appendChild( provider );
1600 
1601  // User no data
1602  QDomElement noData = document.createElement( QStringLiteral( "noData" ) );
1603 
1604  for ( int bandNo = 1; bandNo <= mDataProvider->bandCount(); bandNo++ )
1605  {
1606  QDomElement noDataRangeList = document.createElement( QStringLiteral( "noDataList" ) );
1607  noDataRangeList.setAttribute( QStringLiteral( "bandNo" ), bandNo );
1608  noDataRangeList.setAttribute( QStringLiteral( "useSrcNoData" ), mDataProvider->useSourceNoDataValue( bandNo ) );
1609 
1610  Q_FOREACH ( QgsRasterRange range, mDataProvider->userNoDataValues( bandNo ) )
1611  {
1612  QDomElement noDataRange = document.createElement( QStringLiteral( "noDataRange" ) );
1613 
1614  noDataRange.setAttribute( QStringLiteral( "min" ), QgsRasterBlock::printValue( range.min() ) );
1615  noDataRange.setAttribute( QStringLiteral( "max" ), QgsRasterBlock::printValue( range.max() ) );
1616  noDataRangeList.appendChild( noDataRange );
1617  }
1618 
1619  noData.appendChild( noDataRangeList );
1620 
1621  }
1622  if ( noData.hasChildNodes() )
1623  {
1624  layer_node.appendChild( noData );
1625  }
1626 
1627  writeStyleManager( layer_node, document );
1628 
1629  //write out the symbology
1630  QString errorMsg;
1631  return writeSymbology( layer_node, document, errorMsg, context );
1632 }
1633 
1634 QString QgsRasterLayer::encodedSource( const QString &source, const QgsReadWriteContext &context ) const
1635 {
1636  QString src( source );
1637  bool handled = false;
1638 
1639  // Update path for subdataset
1640  if ( providerType() == QLatin1String( "gdal" ) )
1641  {
1642  if ( src.startsWith( QLatin1String( "NETCDF:" ) ) )
1643  {
1644  // NETCDF:filename:variable
1645  // filename can be quoted with " as it can contain colons
1646  QRegExp r( "NETCDF:(.+):([^:]+)" );
1647  if ( r.exactMatch( src ) )
1648  {
1649  QString filename = r.cap( 1 );
1650  if ( filename.startsWith( '"' ) && filename.endsWith( '"' ) )
1651  filename = filename.mid( 1, filename.length() - 2 );
1652  src = "NETCDF:\"" + context.pathResolver().writePath( filename ) + "\":" + r.cap( 2 );
1653  handled = true;
1654  }
1655  }
1656  else if ( src.startsWith( QLatin1String( "HDF4_SDS:" ) ) )
1657  {
1658  // HDF4_SDS:subdataset_type:file_name:subdataset_index
1659  // filename can be quoted with " as it can contain colons
1660  QRegExp r( "HDF4_SDS:([^:]+):(.+):([^:]+)" );
1661  if ( r.exactMatch( src ) )
1662  {
1663  QString filename = r.cap( 2 );
1664  if ( filename.startsWith( '"' ) && filename.endsWith( '"' ) )
1665  filename = filename.mid( 1, filename.length() - 2 );
1666  src = "HDF4_SDS:" + r.cap( 1 ) + ":\"" + context.pathResolver().writePath( filename ) + "\":" + r.cap( 3 );
1667  handled = true;
1668  }
1669  }
1670  else if ( src.startsWith( QLatin1String( "HDF5:" ) ) )
1671  {
1672  // HDF5:file_name:subdataset
1673  // filename can be quoted with " as it can contain colons
1674  QRegExp r( "HDF5:(.+):([^:]+)" );
1675  if ( r.exactMatch( src ) )
1676  {
1677  QString filename = r.cap( 1 );
1678  if ( filename.startsWith( '"' ) && filename.endsWith( '"' ) )
1679  filename = filename.mid( 1, filename.length() - 2 );
1680  src = "HDF5:\"" + context.pathResolver().writePath( filename ) + "\":" + r.cap( 2 );
1681  handled = true;
1682  }
1683  }
1684  else if ( src.contains( QRegExp( "^(NITF_IM|RADARSAT_2_CALIB):" ) ) )
1685  {
1686  // NITF_IM:0:filename
1687  // RADARSAT_2_CALIB:?:filename
1688  QRegExp r( "([^:]+):([^:]+):(.+)" );
1689  if ( r.exactMatch( src ) )
1690  {
1691  src = r.cap( 1 ) + ':' + r.cap( 2 ) + ':' + context.pathResolver().writePath( r.cap( 3 ) );
1692  handled = true;
1693  }
1694  }
1695  }
1696 
1697  if ( !handled )
1698  src = context.pathResolver().writePath( src );
1699 
1700  return src;
1701 }
1702 
1703 QString QgsRasterLayer::decodedSource( const QString &source, const QString &provider, const QgsReadWriteContext &context ) const
1704 {
1705  QString src( source );
1706 
1707  if ( provider == QLatin1String( "wms" ) )
1708  {
1709  // >>> BACKWARD COMPATIBILITY < 1.9
1710  // For project file backward compatibility we must support old format:
1711  // 1. mode: <url>
1712  // example: http://example.org/wms?
1713  // 2. mode: tiled=<width>;<height>;<resolution>;<resolution>...,ignoreUrl=GetMap;GetFeatureInfo,featureCount=<count>,username=<name>,password=<password>,url=<url>
1714  // example: tiled=256;256;0.703;0.351,url=http://example.org/tilecache?
1715  // example: featureCount=10,http://example.org/wms?
1716  // example: ignoreUrl=GetMap;GetFeatureInfo,username=cimrman,password=jara,url=http://example.org/wms?
1717  // This is modified version of old QgsWmsProvider::parseUri
1718  // The new format has always params crs,format,layers,styles and that params
1719  // should not appear in old format url -> use them to identify version
1720  // XYZ tile layers do not need to contain crs,format params, but they have type=xyz
1721  if ( !src.contains( QLatin1String( "type=" ) ) &&
1722  !src.contains( QLatin1String( "crs=" ) ) && !src.contains( QLatin1String( "format=" ) ) )
1723  {
1724  QgsDebugMsg( "Old WMS URI format detected -> converting to new format" );
1725  QgsDataSourceUri uri;
1726  if ( !src.startsWith( QLatin1String( "http:" ) ) )
1727  {
1728  QStringList parts = src.split( ',' );
1729  QStringListIterator iter( parts );
1730  while ( iter.hasNext() )
1731  {
1732  QString item = iter.next();
1733  if ( item.startsWith( QLatin1String( "username=" ) ) )
1734  {
1735  uri.setParam( QStringLiteral( "username" ), item.mid( 9 ) );
1736  }
1737  else if ( item.startsWith( QLatin1String( "password=" ) ) )
1738  {
1739  uri.setParam( QStringLiteral( "password" ), item.mid( 9 ) );
1740  }
1741  else if ( item.startsWith( QLatin1String( "tiled=" ) ) )
1742  {
1743  // in < 1.9 tiled= may apper in to variants:
1744  // tiled=width;height - non tiled mode, specifies max width and max height
1745  // tiled=width;height;resolutions-1;resolution2;... - tile mode
1746 
1747  QStringList params = item.mid( 6 ).split( ';' );
1748 
1749  if ( params.size() == 2 ) // non tiled mode
1750  {
1751  uri.setParam( QStringLiteral( "maxWidth" ), params.takeFirst() );
1752  uri.setParam( QStringLiteral( "maxHeight" ), params.takeFirst() );
1753  }
1754  else if ( params.size() > 2 ) // tiled mode
1755  {
1756  // resolutions are no more needed and size limit is not used for tiles
1757  // we have to tell to the provider however that it is tiled
1758  uri.setParam( QStringLiteral( "tileMatrixSet" ), QLatin1String( "" ) );
1759  }
1760  }
1761  else if ( item.startsWith( QLatin1String( "featureCount=" ) ) )
1762  {
1763  uri.setParam( QStringLiteral( "featureCount" ), item.mid( 13 ) );
1764  }
1765  else if ( item.startsWith( QLatin1String( "url=" ) ) )
1766  {
1767  uri.setParam( QStringLiteral( "url" ), item.mid( 4 ) );
1768  }
1769  else if ( item.startsWith( QLatin1String( "ignoreUrl=" ) ) )
1770  {
1771  uri.setParam( QStringLiteral( "ignoreUrl" ), item.mid( 10 ).split( ';' ) );
1772  }
1773  }
1774  }
1775  else
1776  {
1777  uri.setParam( QStringLiteral( "url" ), src );
1778  }
1779  src = uri.encodedUri();
1780  // At this point, the URI is obviously incomplete, we add additional params
1781  // in QgsRasterLayer::readXml
1782  }
1783  // <<< BACKWARD COMPATIBILITY < 1.9
1784  }
1785  else
1786  {
1787  bool handled = false;
1788 
1789  if ( provider == QLatin1String( "gdal" ) )
1790  {
1791  if ( src.startsWith( QLatin1String( "NETCDF:" ) ) )
1792  {
1793  // NETCDF:filename:variable
1794  // filename can be quoted with " as it can contain colons
1795  QRegExp r( "NETCDF:(.+):([^:]+)" );
1796  if ( r.exactMatch( src ) )
1797  {
1798  QString filename = r.cap( 1 );
1799  if ( filename.startsWith( '"' ) && filename.endsWith( '"' ) )
1800  filename = filename.mid( 1, filename.length() - 2 );
1801  src = "NETCDF:\"" + context.pathResolver().readPath( filename ) + "\":" + r.cap( 2 );
1802  handled = true;
1803  }
1804  }
1805  else if ( src.startsWith( QLatin1String( "HDF4_SDS:" ) ) )
1806  {
1807  // HDF4_SDS:subdataset_type:file_name:subdataset_index
1808  // filename can be quoted with " as it can contain colons
1809  QRegExp r( "HDF4_SDS:([^:]+):(.+):([^:]+)" );
1810  if ( r.exactMatch( src ) )
1811  {
1812  QString filename = r.cap( 2 );
1813  if ( filename.startsWith( '"' ) && filename.endsWith( '"' ) )
1814  filename = filename.mid( 1, filename.length() - 2 );
1815  src = "HDF4_SDS:" + r.cap( 1 ) + ":\"" + context.pathResolver().readPath( filename ) + "\":" + r.cap( 3 );
1816  handled = true;
1817  }
1818  }
1819  else if ( src.startsWith( QLatin1String( "HDF5:" ) ) )
1820  {
1821  // HDF5:file_name:subdataset
1822  // filename can be quoted with " as it can contain colons
1823  QRegExp r( "HDF5:(.+):([^:]+)" );
1824  if ( r.exactMatch( src ) )
1825  {
1826  QString filename = r.cap( 1 );
1827  if ( filename.startsWith( '"' ) && filename.endsWith( '"' ) )
1828  filename = filename.mid( 1, filename.length() - 2 );
1829  src = "HDF5:\"" + context.pathResolver().readPath( filename ) + "\":" + r.cap( 2 );
1830  handled = true;
1831  }
1832  }
1833  else if ( src.contains( QRegExp( "^(NITF_IM|RADARSAT_2_CALIB):" ) ) )
1834  {
1835  // NITF_IM:0:filename
1836  // RADARSAT_2_CALIB:?:filename
1837  QRegExp r( "([^:]+):([^:]+):(.+)" );
1838  if ( r.exactMatch( src ) )
1839  {
1840  src = r.cap( 1 ) + ':' + r.cap( 2 ) + ':' + context.pathResolver().readPath( r.cap( 3 ) );
1841  handled = true;
1842  }
1843  }
1844  }
1845 
1846  if ( !handled )
1847  src = context.pathResolver().readPath( src );
1848  }
1849 
1850  return src;
1851 }
1852 
1854 {
1855  if ( !mDataProvider ) return 0;
1856  return mDataProvider->xSize();
1857 }
1858 
1860 {
1861  if ( !mDataProvider ) return 0;
1862  return mDataProvider->ySize();
1863 }
1864 
1866 //
1867 // Private methods
1868 //
1870 bool QgsRasterLayer::update()
1871 {
1872  QgsDebugMsgLevel( "entered.", 4 );
1873  // Check if data changed
1874  if ( mDataProvider->dataTimestamp() > mDataProvider->timestamp() )
1875  {
1876  QgsDebugMsgLevel( "reload data", 4 );
1877  closeDataProvider();
1878  init();
1879  QgsDataProvider::ProviderOptions providerOptions;
1880  setDataProvider( mProviderKey, providerOptions );
1881  emit dataChanged();
1882  }
1883  return mValid;
1884 }
QgsDataProvider * classFactoryFunction_t(const QString *, const QgsDataProvider::ProviderOptions &options)
static void convertRasterProperties(QDomDocument &doc, QDomNode &parentNode, QDomElement &rasterPropertiesElem, QgsRasterLayer *rlayer)
int width() const
Returns the width of the (unclipped) raster.
QgsRasterMinMaxOrigin::Limits limits() const
Returns the raster limits.
void writeCommonStyle(QDomElement &layerElement, QDomDocument &document, const QgsReadWriteContext &context) const
Write style data common to all layer types.
virtual int bandCount() const =0
Gets number of bands.
QgsRasterMinMaxOrigin::Extent extent() const
Returns the raster extent.
virtual void setSubLayerVisibility(const QString &name, bool vis)
Set the visibility of the given sublayer name.
The class is used as a container of context for various read/write operations on other objects...
#define ERR(message)
IdentifyFormat
Definition: qgsraster.h:57
A rectangle specified with double values.
Definition: qgsrectangle.h:40
Base class for all map layer types.
Definition: qgsmaplayer.h:61
Thirty two bit signed integer (qint32)
Definition: qgis.h:98
Interface for all raster shaders.
void setColorRampItemList(const QList< QgsColorRampShader::ColorRampItem > &list)
Sets a custom colormap.
QgsRasterLayer * clone() const override
Returns a new instance equivalent to this one.
QStringList subLayers() const override
Returns the sublayers of this layer.
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)
Sets the source nodata value usage.
virtual QgsMapLayer * clone() const =0
Returns a new instance equivalent to this one except for the id which is still unique.
QString contactsSectionHtml() const
Formats the "Contacts" section according to a metadata object.
QString historySectionHtml() const
Formats the "History" section according to a metadata object.
const QgsContrastEnhancement * blueContrastEnhancement() const
static Q_INVOKABLE QString toString(QgsUnitTypes::DistanceUnit unit)
Returns a translated string representing a distance unit.
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
Returns the number of bands in this layer.
This class is a composition of two QSettings instances:
Definition: qgssettings.h:58
QgsHueSaturationFilter * hueSaturationFilter() const
QString readPath(const QString &filename) const
Turn filename read from the project file to an absolute path.
DrawingStyle
This enumerator describes the different kinds of drawing we can do.
Definition: qgsraster.h:89
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
Gets current status error.
QgsRasterRenderer * renderer() const
QVariant value(const QString &key, const QVariant &defaultValue=QVariant(), Section section=NoSection) const
Returns the value for setting key.
void setRenderer(QgsRasterRenderer *renderer)
Sets raster renderer. Takes ownership of the renderer object.
#define QgsDebugMsg(str)
Definition: qgslogger.h:38
virtual QgsError error() const
Gets current status error.
This class provides qgis with the ability to render raster datasets onto the mapcanvas.
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.
QString accessSectionHtml() const
Formats the "Access" section according to a metadata object.
void readCommonStyle(const QDomElement &layerElement, const QgsReadWriteContext &context)
Read style data common to all layer types.
void willBeDeleted()
Emitted in the destructor when the layer is about to be deleted, but it is still in a perfectly valid...
QgsRasterPipe * pipe()
Returns the raster pipe.
bool writeXml(QDomNode &layer_node, QDomDocument &doc, const QgsReadWriteContext &context) const override
Called by writeLayerXML(), used by children to write state specific to them to project files...
A class to represent a 2D point.
Definition: qgspointxy.h:43
void setDefaultContrastEnhancement()
Sets the default contrast enhancement.
bool qgsDoubleNear(double a, double b, double epsilon=4 *std::numeric_limits< double >::epsilon())
Compare two doubles (but allow some difference)
Definition: qgis.h:251
QString linksSectionHtml() const
Formats the "Links" section according to a metadata object.
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:97
void readCustomProperties(const QDomNode &layerNode, const QString &keyStartsWith=QString())
Read custom properties from project file.
static QgsPainting::BlendMode getBlendModeEnum(QPainter::CompositionMode blendMode)
Returns a BlendMode corresponding to a QPainter::CompositionMode.
Definition: qgspainting.cpp:80
DataType
Raster data types.
Definition: qgis.h:91
QgsRasterInterface * last() const
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.
bool readXml(const QDomNode &layer_node, QgsReadWriteContext &context) override
Called by readLayerXML(), used by children to read state specific to them from project files...
virtual const QgsLayerMetadata & metadata() const
Returns a reference to the layer&#39;s metadata store.
double rasterUnitsPerPixelY() const
Returns the number of raster units per each raster pixel in Y axis.
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...
static QDateTime lastModified(const QString &name)
Returns time stamp for given file name.
double max() const
Returns the maximum value for the range.
static QPainter::CompositionMode getCompositionMode(QgsPainting::BlendMode blendMode)
Returns a QPainter::CompositionMode corresponding to a BlendMode.
Definition: qgspainting.cpp:20
Raster values range container.
Resample filter pipe for rasters.
Abstract base class for spatial data provider implementations.
bool writeSymbology(QDomNode &, QDomDocument &doc, QString &errorMessage, const QgsReadWriteContext &context) const override
Write the symbology for the layer into the docment provided.
const QgsRasterMinMaxOrigin & minMaxOrigin() const
Returns const reference to origin of min/max values.
QgsRasterRenderer * renderer() const
int height() const
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:99
bool isValid() const
Returns the status of the layer.
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.
QgsMapLayer::LayerType type() const
Returns the type of the layer.
QPixmap paletteAsPixmap(int bandNumber=1)
Returns a 100x100 pixmap of the color palette.
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:96
QDateTime timestamp() const override
Time stamp of data source in the moment when data/metadata were loaded by provider.
Complex Int16.
Definition: qgis.h:101
QString mLayerName
Name of the layer - used for display.
Definition: qgsmaplayer.h:1275
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:100
Current extent of the canvas (at the time of computation) is used to compute statistics.
static QString identifyFormatName(QgsRaster::IdentifyFormat format)
virtual QgsRectangle extent() const
Returns the extent of the layer.
void setExtent(QgsRasterMinMaxOrigin::Extent extent)
Sets the extent.
QgsCoordinateReferenceSystem mDestCRS
Target coordinate system.
virtual QgsLayerMetadata layerMetadata() const
Returns layer metadata collected from the provider&#39;s source.
QgsDataProvider * createProvider(const QString &providerKey, const QString &dataSource, const QgsDataProvider::ProviderOptions &options=QgsDataProvider::ProviderOptions())
Creates a new instance of a provider.
QgsBrightnessContrastFilter * brightnessFilter() const
void setCrs(const QgsCoordinateReferenceSystem &srcCRS, const QgsCoordinateReferenceSystem &destCRS, int srcDatumTransform=-1, int destDatumTransform=-1)
Sets the source and destination CRS.
QDateTime timestamp() const override
Time stamp of data source in the moment when data/metadata were loaded by provider.
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
Returns the lower bound of cumulative cut method (between 0 and 1).
Color, alpha, red, green, blue, 4 bytes the same as QImage::Format_ARGB32_Premultiplied.
Definition: qgis.h:106
Perform transforms between map coordinates and device coordinates.
Definition: qgsmaptopixel.h:36
static const QgsRasterMinMaxOrigin::Limits MULTIPLE_BAND_SINGLE_BYTE_MIN_MAX_LIMITS
Default enhancement limits for multiple band raster of type Byte.
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 setContrastEnhancement(QgsContrastEnhancement::ContrastEnhancementAlgorithm algorithm, QgsRasterMinMaxOrigin::Limits limits=QgsRasterMinMaxOrigin::MinMax, const QgsRectangle &extent=QgsRectangle(), int sampleSize=QgsRasterLayer::SAMPLE_SIZE, bool generateLookupTableFlag=true)
Set contrast enhancement algorithm.
void setColorRampType(QgsColorRampShader::Type colorRampType)
Sets the color ramp type.
Alpha (0=transparent, 255=opaque)
Definition: qgsraster.h:43
QgsRasterDataProvider * dataProvider() override
Returns the layer&#39;s data provider.
This class describes the origin of min/max values.
The RasterBandStats struct is a container for statistics about a single raster band.
static QgsProviderRegistry * instance(const QString &pluginPath=QString())
Means of accessing canonical single instance.
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.
Continuous palette, QGIS addition, GRASS.
Definition: qgsraster.h:54
void readStyleManager(const QDomNode &layerNode)
Read style manager&#39;s configuration (if any). To be called by subclasses.
void setRedContrastEnhancement(QgsContrastEnhancement *ce)
Takes ownership.
#define QgsDebugMsgLevel(str, level)
Definition: qgslogger.h:39
bool isEmpty() const
Returns true if the rectangle is empty.
Definition: qgsrectangle.h:419
virtual void setMetadata(const QgsLayerMetadata &metadata)
Sets the layer&#39;s metadata store.
void setCrs(const QgsCoordinateReferenceSystem &srs, bool emitSignal=true)
Sets layer&#39;s spatial reference system.
QgsPointXY mBottomRightPoint
Coordinate (in output device coordinate system) of bottom right corner of the part of the raster that...
virtual int capabilities() const
Returns a bitmask containing the supported capabilities.
QgsRectangle extent() const override=0
Returns the extent of the layer.
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.
static const QgsContrastEnhancement::ContrastEnhancementAlgorithm SINGLE_BAND_ENHANCEMENT_ALGORITHM
Default enhancement algorithm for single band raster.
bool loadDefaultStyle
Sets to true if the default layer style should be loaded.
QgsRasterInterface * at(int idx) const
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:201
QgsRasterShaderFunction * rasterShaderFunction()
virtual void setExtent(const QgsRectangle &rect)
Sets the extent.
QString extentSectionHtml() const
Formats the "Extents" section according to a metadata object.
Complex Float32.
Definition: qgis.h:103
static void logMessage(const QString &message, const QString &tag=QString(), Qgis::MessageLevel level=Qgis::Warning, bool notifyUser=true)
Adds a message to the log instance (and creates it if necessary).
virtual QString dataSourceUri(bool expandAuthConfig=false) const
Gets the data source specification.
double cumulativeCutUpper() const
Returns the upper bound of cumulative cut method (between 0 and 1).
QString bandName(int bandNoInt) const
Returns the name of a band given its number.
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.
QString description() const
Returns the descriptive name of the CRS, e.g., "WGS 84" or "GDA 94 / Vicgrid94".
void setRasterShaderFunction(QgsRasterShaderFunction *function)
A public method that allows the user to set their own shader function.
Range is [ mean - stdDevFactor() * stddev, mean + stdDevFactor() * stddev ].
static QString contrastEnhancementAlgorithmString(ContrastEnhancementAlgorithm algorithm)
Returns 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
Returns default contrast enhancement 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...
QString publicSource() const
Gets a version of the internal layer definition that has sensitive bits removed (for example...
Raster renderer pipe for single band gray.
Complex Int32.
Definition: qgis.h:102
static int typeSize(int dataType)
void setParam(const QString &key, const QString &value)
Set generic param (generic mode)
QgsMapLayerRenderer * createMapRenderer(QgsRenderContext &rendererContext) override
Returns new instance of QgsMapLayerRenderer that will be used for rendering of given context...
Sixteen bit unsigned integer (quint16)
Definition: qgis.h:95
virtual void setLayerOrder(const QStringList &layers)
Reorder the list of layer names to be rendered by this provider (in order from bottom to top) ...
bool readStyle(const QDomNode &node, QString &errorMessage, QgsReadWriteContext &context) override
Read the style for the current layer from the Dom node supplied.
QString decodedSource(const QString &source, const QString &provider, const QgsReadWriteContext &context) const override
Called by readLayerXML(), used by derived classes to decode provider&#39;s specific data source from proj...
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:1269
#define cast_to_fptr(f)
Definition: qgis.h:170
void setName(const QString &name)
Set the display name of the layer.
Q_DECL_DEPRECATED void setDataProvider(const QString &provider)
Set the data provider.
Range is [ min + cumulativeCutLower() * (max - min), min + cumulativeCutUpper() * (max - min) ]...
Base class for processing filters like renderers, reprojector, resampler etc.
As part of the API refactoring and improvements which landed in the Processing API was substantially reworked from the x version This was done in order to allow much of the underlying Processing framework to be ported into allowing algorithms to be written in pure substantial changes are required in order to port existing x Processing algorithms for QGIS x The most significant changes are outlined not GeoAlgorithm For algorithms which operate on features one by consider subclassing the QgsProcessingFeatureBasedAlgorithm class This class allows much of the boilerplate code for looping over features from a vector layer to be bypassed and instead requires implementation of a processFeature method Ensure that your algorithm(or algorithm 's parent class) implements the new pure virtual createInstance(self) call
static const QgsRasterMinMaxOrigin::Limits SINGLE_BAND_MIN_MAX_LIMITS
Default enhancement limits for single band raster.
static QString limitsString(Limits limits)
Returns a string to serialize Limits.
void setSubLayerVisibility(const QString &name, bool vis) override
Set the visibility of the given sublayer name.
bool shade(double value, int *returnRedValue, int *returnGreenValue, int *returnBlueValue, int *returnAlphaValue) override
Generates and new RGB value based on one input value.
virtual QString htmlMetadata()=0
Returns metadata in a format suitable for feeding directly into a subset of the GUI raster properties...
int size() const
static ContrastEnhancementAlgorithm contrastEnhancementAlgorithmFromString(const QString &contrastEnhancementString)
Deserialize ContrastEnhancementAlgorithm.
void classifyColorRamp(int classes=0, int band=-1, const QgsRectangle &extent=QgsRectangle(), QgsRasterInterface *input=nullptr)
Classify color ramp shader.
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.
QString identificationSectionHtml() const
Formats the "Identification" section according to a metadata object.
Limits
This enumerator describes the limits used to compute min/max values.
QgsCoordinateReferenceSystem mSrcCRS
Source coordinate system.
void setLimits(QgsRasterMinMaxOrigin::Limits limits)
Sets the limits.
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.
virtual QgsRasterBandStats bandStatistics(int bandNo, int stats=QgsRasterBandStats::All, const QgsRectangle &extent=QgsRectangle(), int sampleSize=0, QgsRasterBlockFeedback *feedback=nullptr)
Returns the band statistics.
bool readSymbology(const QDomNode &node, QString &errorMessage, QgsReadWriteContext &context) override
Read the symbology for the current layer from the Dom node supplied.
QList< QPair< QString, QColor > > QgsLegendColorList
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.
const QgsPathResolver & pathResolver() const
Returns path resolver for conversion between relative and absolute paths.
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.
Setting options for creating vector data providers.
QString name() const
Returns the display name of the layer.
bool writeStyle(QDomNode &node, QDomDocument &doc, QString &errorMessage, const QgsReadWriteContext &context) const override
Write just the style information for the layer into the document.
static QgsMapLayerLegend * defaultRasterLegend(QgsRasterLayer *rl)
Create new legend implementation for raster layer.
const QgsContrastEnhancement * redContrastEnhancement() const
const QgsContrastEnhancement * greenContrastEnhancement() const
QgsRasterResampleFilter * resampleFilter() const
Sets 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:1272
QString source() const
Returns the source for the layer.
virtual QgsRasterInterface * clone() const =0
Clone itself, create deep copy.
Whole raster is used to compute statistics.
virtual void reloadData()
Reloads the data from the source.
QByteArray encodedUri() const
Returns 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.
void setBlueContrastEnhancement(QgsContrastEnhancement *ce)
Takes ownership.
Provider can read layer metadata from data store. Since QGIS 3.0. See QgsDataProvider::layerMetadata(...
ContrastEnhancementAlgorithm contrastEnhancementAlgorithm() const
Greyscale.
Definition: qgsraster.h:38
bool isvalidrasterfilename_t(QString const &fileNameQString, QString &retErrMsg)
QStringList subLayers() const override
Returns the sublayers of this layer - useful for providers that manage their own layers, such as WMS.
QString writePath(const QString &filename) const
Prepare a filename to save it to the project file.
double minimumValue
The minimum cell value in the raster band.
Class for metadata formatter.
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:1261
virtual QgsRasterRangeList userNoDataValues(int bandNo) const
Returns a 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...
QString encodedSource(const QString &source, const QgsReadWriteContext &context) const override
Called by writeLayerXML(), used by derived classes to encode provider&#39;s specific data source to proje...
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.
~QgsRasterLayer() override
This class provides details of the viewable area that a raster will be rendered into.
QDateTime dataTimestamp() const override
Current time stamp of data source.
virtual bool useSourceNoDataValue(int bandNo) const
Returns the 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
Gets symbology items if provided by renderer.
double min() const
Returns the minimum value for the range.
virtual QString generateBandName(int bandNumber) const
helper function to create zero padded band names
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:104
QgsLegendColorList legendSymbologyItems() const
Returns a list with classification items (Text and color)
virtual QgsRasterDataProvider::ProviderCapabilities providerCapabilities() const
Returns flags containing the supported capabilities of the data provider.
void readXml(const QDomElement &filterElem) override
Sets base class members from xml. Usually called from create() methods of subclasses.
double stdDevFactor() const
Returns the factor f so that the min/max range is [ mean - f * stddev , mean + f * stddev ]...
virtual int xSize() const
Gets 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
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)
Sets error message.
Definition: qgsmaplayer.h:1263
QString authid() const
Returns the authority identifier for the CRS.
Eight bit unsigned integer (quint8)
Definition: qgis.h:94
Qgis::DataType dataType(int bandNo) const override=0
Returns data type for the band specified by number.
Setting options for loading raster layers.
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.
Color, alpha, red, green, blue, 4 bytes the same as QImage::Format_ARGB32.
Definition: qgis.h:105
QPainter::CompositionMode blendMode() const
Returns the current blending mode for a layer.
double height() const
Returns the height of the rectangle.
Definition: qgsrectangle.h:208
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.
QgsPointXY mTopLeftPoint
Coordinate (in output device coordinate system) of top left corner of the part of the raster that is ...
QgsRasterLayer()
Constructor. Provider is not set.