QGIS API Documentation  2.99.0-Master (53aba61)
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"
33 #include "qgsproviderregistry.h"
34 #include "qgsrasterdataprovider.h"
35 #include "qgsrasterdrawer.h"
36 #include "qgsrasteriterator.h"
37 #include "qgsrasterlayer.h"
38 #include "qgsrasterlayerrenderer.h"
39 #include "qgsrasterprojector.h"
40 #include "qgsrasterrange.h"
43 #include "qgsrastershader.h"
44 #include "qgsrectangle.h"
45 #include "qgsrendercontext.h"
49 #include "qgssettings.h"
50 
51 #include <cmath>
52 #include <cstdio>
53 #include <limits>
54 #include <typeinfo>
55 
56 #include <QApplication>
57 #include <QCursor>
58 #include <QDomElement>
59 #include <QDomNode>
60 #include <QFile>
61 #include <QFileInfo>
62 #include <QFont>
63 #include <QFontMetrics>
64 #include <QFrame>
65 #include <QImage>
66 #include <QLabel>
67 #include <QLibrary>
68 #include <QList>
69 #include <QMatrix>
70 #include <QMessageBox>
71 #include <QPainter>
72 #include <QPixmap>
73 #include <QRegExp>
74 #include <QSlider>
75 #include <QTime>
76 
77 // typedefs for provider plugin functions of interest
78 typedef bool isvalidrasterfilename_t( QString const &fileNameQString, QString &retErrMsg );
79 
80 #define ERR(message) QGS_ERROR_MESSAGE(message,"Raster layer")
81 
82 const double QgsRasterLayer::SAMPLE_SIZE = 250000;
83 
90 
97 
99  : QgsMapLayer( RasterLayer )
100  , QSTRING_NOT_SET( QStringLiteral( "Not Set" ) )
101  , TRSTRING_NOT_SET( tr( "Not Set" ) )
102 
103 {
104  init();
105  mValid = false;
106 }
107 
108 QgsRasterLayer::QgsRasterLayer( const QString &uri,
109  const QString &baseName,
110  const QString &providerKey,
111  bool loadDefaultStyleFlag )
112  : QgsMapLayer( RasterLayer, baseName, uri )
113  // Constant that signals property not used.
114  , QSTRING_NOT_SET( QStringLiteral( "Not Set" ) )
115  , TRSTRING_NOT_SET( tr( "Not Set" ) )
116  , mProviderKey( providerKey )
117 {
118  QgsDebugMsgLevel( "Entered", 4 );
119  init();
120  setDataProvider( providerKey );
121  if ( !mValid ) return;
122 
123  // load default style
124  bool defaultLoadedFlag = false;
125  if ( mValid && loadDefaultStyleFlag )
126  {
127  loadDefaultStyle( defaultLoadedFlag );
128  }
129  if ( !defaultLoadedFlag )
130  {
132  }
133 
134  // TODO: Connect signals from the dataprovider to the qgisapp
135 
136  emit statusChanged( tr( "QgsRasterLayer created" ) );
137 } // QgsRasterLayer ctor
138 
140 {
141  emit willBeDeleted();
142 
143  mValid = false;
144  // Note: provider and other interfaces are owned and deleted by pipe
145 }
146 
148 {
149  QgsRasterLayer *layer = new QgsRasterLayer( source(), originalName(), mProviderKey );
150  QgsMapLayer::clone( layer );
151 
152  // do not clone data provider which is the first element in pipe
153  for ( int i = 1; i < mPipe.size(); i++ )
154  {
155  if ( mPipe.at( i ) )
156  layer->pipe()->set( mPipe.at( i )->clone() );
157  }
158 
159  return layer;
160 }
161 
163 //
164 // Static Methods and members
165 //
167 
171 bool QgsRasterLayer::isValidRasterFileName( const QString &fileNameQString, QString &retErrMsg )
172 {
173  isvalidrasterfilename_t *pValid = reinterpret_cast< isvalidrasterfilename_t * >( cast_to_fptr( QgsProviderRegistry::instance()->function( "gdal", "isValidRasterFileName" ) ) );
174  if ( ! pValid )
175  {
176  QgsDebugMsg( "Could not resolve isValidRasterFileName in gdal provider library" );
177  return false;
178  }
179 
180  bool myIsValid = pValid( fileNameQString, retErrMsg );
181  return myIsValid;
182 }
183 
184 bool QgsRasterLayer::isValidRasterFileName( QString const &fileNameQString )
185 {
186  QString retErrMsg;
187  return isValidRasterFileName( fileNameQString, retErrMsg );
188 }
189 
190 QDateTime QgsRasterLayer::lastModified( QString const &name )
191 {
192  QgsDebugMsgLevel( "name=" + name, 4 );
193  QDateTime t;
194 
195  QFileInfo fi( name );
196 
197  // Is it file?
198  if ( !fi.exists() )
199  return t;
200 
201  t = fi.lastModified();
202 
203  QgsDebugMsgLevel( "last modified = " + t.toString(), 4 );
204 
205  return t;
206 }
207 
208 // typedef for the QgsDataProvider class factory
209 typedef QgsDataProvider *classFactoryFunction_t( const QString * );
210 
212 //
213 // Non Static Public methods
214 //
216 
218 {
219  if ( !mDataProvider ) return 0;
220  return mDataProvider->bandCount();
221 }
222 
223 QString QgsRasterLayer::bandName( int bandNo ) const
224 {
225  return dataProvider()->generateBandName( bandNo );
226 }
227 
228 void QgsRasterLayer::setRendererForDrawingStyle( QgsRaster::DrawingStyle drawingStyle )
229 {
230  setRenderer( QgsApplication::rasterRendererRegistry()->defaultRendererForDrawingStyle( drawingStyle, mDataProvider ) );
231 }
232 
237 {
238  return mDataProvider;
239 }
240 
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  // Identification section
311  myMetadata += QLatin1String( "<h1>" ) + tr( "Identification" ) + QLatin1String( "</h1>\n<hr>\n" );
312  myMetadata += htmlFormatter.identificationSectionHtml();
313  myMetadata += QLatin1String( "<br><br>\n" );
314 
315  // Begin Provider section
316  myMetadata += QLatin1String( "<h1>" ) + tr( "Information from provider" ) + QLatin1String( "</h1>\n<hr>\n" );
317  myMetadata += QLatin1String( "<table class=\"list-view\">\n" );
318 
319  // original name
320  myMetadata += QLatin1String( "<tr><td class=\"highlight\">" ) + tr( "Original" ) + QLatin1String( "</td><td>" ) + originalName() + QLatin1String( "</td></tr>\n" );
321 
322  // name
323  myMetadata += QLatin1String( "<tr><td class=\"highlight\">" ) + tr( "Name" ) + QLatin1String( "</td><td>" ) + name() + QLatin1String( "</td></tr>\n" );
324 
325  // data source
326  myMetadata += QLatin1String( "<tr><td class=\"highlight\">" ) + tr( "Source" ) + QLatin1String( "</td><td>" ) + publicSource() + QLatin1String( "</td></tr>\n" );
327 
328  // storage type
329  myMetadata += QLatin1String( "<tr><td class=\"highlight\">" ) + tr( "Provider" ) + QLatin1String( "</td><td>" ) + providerType() + QLatin1String( "</td></tr>\n" );
330 
331  // EPSG
332  myMetadata += QLatin1String( "<tr><td class=\"highlight\">" ) + tr( "CRS" ) + QLatin1String( "</td><td>" ) + crs().authid() + QLatin1String( " - " );
333  myMetadata += crs().description() + QLatin1String( " - " );
334  if ( crs().isGeographic() )
335  myMetadata += tr( "Geographic" );
336  else
337  myMetadata += tr( "Projected" );
338  myMetadata += QLatin1String( "</td></tr>\n" );
339 
340  // Extent
341  myMetadata += QLatin1String( "<tr><td class=\"highlight\">" ) + tr( "Extent" ) + QLatin1String( "</td><td>" ) + extent().toString() + QLatin1String( "</td></tr>\n" );
342 
343  // unit
344  myMetadata += QLatin1String( "<tr><td class=\"highlight\">" ) + tr( "Unit" ) + QLatin1String( "</td><td>" ) + QgsUnitTypes::toString( crs().mapUnits() ) + QLatin1String( "</td></tr>\n" );
345 
346  // Raster Width
347  myMetadata += QLatin1String( "<tr><td class=\"highlight\">" ) + tr( "Width" ) + QLatin1String( "</td><td>" );
348  if ( dataProvider()->capabilities() & QgsRasterDataProvider::Size )
349  myMetadata += QString::number( width() );
350  else
351  myMetadata += tr( "n/a" );
352  myMetadata += QLatin1String( "</td></tr>\n" );
353 
354  // Raster height
355  myMetadata += QLatin1String( "<tr><td class=\"highlight\">" ) + tr( "Height" ) + QLatin1String( "</td><td>" );
356  if ( dataProvider()->capabilities() & QgsRasterDataProvider::Size )
357  myMetadata += QString::number( height() );
358  else
359  myMetadata += tr( "n/a" );
360  myMetadata += QLatin1String( "</td></tr>\n" );
361 
362  // Data type
363  myMetadata += QLatin1String( "<tr><td class=\"highlight\">" ) + tr( "Data type" ) + QLatin1String( "</td><td>" );
364  // Just use the first band
365  switch ( mDataProvider->sourceDataType( 1 ) )
366  {
367  case Qgis::Byte:
368  myMetadata += tr( "Byte - Eight bit unsigned integer" );
369  break;
370  case Qgis::UInt16:
371  myMetadata += tr( "UInt16 - Sixteen bit unsigned integer " );
372  break;
373  case Qgis::Int16:
374  myMetadata += tr( "Int16 - Sixteen bit signed integer " );
375  break;
376  case Qgis::UInt32:
377  myMetadata += tr( "UInt32 - Thirty two bit unsigned integer " );
378  break;
379  case Qgis::Int32:
380  myMetadata += tr( "Int32 - Thirty two bit signed integer " );
381  break;
382  case Qgis::Float32:
383  myMetadata += tr( "Float32 - Thirty two bit floating point " );
384  break;
385  case Qgis::Float64:
386  myMetadata += tr( "Float64 - Sixty four bit floating point " );
387  break;
388  case Qgis::CInt16:
389  myMetadata += tr( "CInt16 - Complex Int16 " );
390  break;
391  case Qgis::CInt32:
392  myMetadata += tr( "CInt32 - Complex Int32 " );
393  break;
394  case Qgis::CFloat32:
395  myMetadata += tr( "CFloat32 - Complex Float32 " );
396  break;
397  case Qgis::CFloat64:
398  myMetadata += tr( "CFloat64 - Complex Float64 " );
399  break;
400  default:
401  myMetadata += tr( "Could not determine raster data type." );
402  }
403  myMetadata += QLatin1String( "</td></tr>\n" );
404 
405  // End Provider section
406  myMetadata += QLatin1String( "</table>\n<br><br>" );
407 
408  // extent section
409  myMetadata += QLatin1String( "<h1>" ) + tr( "Extent" ) + QLatin1String( "</h1>\n<hr>\n" );
410  myMetadata += htmlFormatter.extentSectionHtml( );
411  myMetadata += QLatin1String( "<br><br>\n" );
412 
413  // Start the Access section
414  myMetadata += QLatin1String( "<h1>" ) + tr( "Access" ) + QLatin1String( "</h1>\n<hr>\n" );
415  myMetadata += htmlFormatter.accessSectionHtml( );
416  myMetadata += QLatin1String( "<br><br>\n" );
417 
418  // Bands section
419  myMetadata += QLatin1String( "</table>\n<br><br><h1>" ) + tr( "Bands" ) + QLatin1String( "</h1>\n<hr>\n<table class=\"list-view\">\n" );
420 
421  // Band count
422  myMetadata += QLatin1String( "<tr><td class=\"highlight\">" ) + tr( "Band count" ) + QLatin1String( "</td><td>" ) + QString::number( bandCount() ) + QLatin1String( "</td></tr>\n" );
423 
424  // Band table
425  myMetadata += "</table>\n<br><table width=\"100%\" class=\"tabular-view\">\n";
426  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";
427 
428  QgsRasterDataProvider *provider = const_cast< QgsRasterDataProvider * >( mDataProvider );
429  for ( int i = 1; i <= bandCount(); i++ )
430  {
431  QString rowClass = QString( "" );
432  if ( i % 2 )
433  rowClass = QString( "class=\"odd-row\"" );
434  myMetadata += "<tr " + rowClass + "><td>" + QString::number( i ) + "</td><td>" + bandName( i ) + "</td><td>";
435 
436  if ( dataProvider()->sourceHasNoDataValue( i ) )
437  myMetadata += QString::number( dataProvider()->sourceNoDataValue( i ) );
438  else
439  myMetadata += tr( "n/a" );
440  myMetadata += "</td>";
441 
442  if ( provider->hasStatistics( i ) )
443  {
444  QgsRasterBandStats myRasterBandStats = provider->bandStatistics( i );
445  myMetadata += "<td>" + QString::number( myRasterBandStats.minimumValue, 'f', 10 ) + "</td>";
446  myMetadata += "<td>" + QString::number( myRasterBandStats.maximumValue, 'f', 10 ) + "</td>";
447  }
448  else
449  {
450  myMetadata += "<td>" + tr( "n/a" ) + "</td><td>" + tr( "n/a" ) + "</td>";
451  }
452 
453  myMetadata += "</tr>\n";
454  }
455 
456  //close previous bands table
457  myMetadata += QLatin1String( "</table>\n<br><br>" );
458 
459  // Start the contacts section
460  myMetadata += QLatin1String( "<h1>" ) + tr( "Contacts" ) + QLatin1String( "</h1>\n<hr>\n" );
461  myMetadata += htmlFormatter.contactsSectionHtml( );
462  myMetadata += QLatin1String( "<br><br>\n" );
463 
464  // Start the links section
465  myMetadata += QLatin1String( "<h1>" ) + tr( "References" ) + QLatin1String( "</h1>\n<hr>\n" );
466  myMetadata += htmlFormatter.linksSectionHtml( );
467  myMetadata += QLatin1String( "<br><br>\n" );
468 
469  // Start the history section
470  myMetadata += QLatin1String( "<h1>" ) + tr( "History" ) + QLatin1String( "</h1>\n<hr>\n" );
471  myMetadata += htmlFormatter.historySectionHtml( );
472  myMetadata += QLatin1String( "<br><br>\n" );
473 
474  myMetadata += QStringLiteral( "\n</body>\n</html>\n" );
475  return myMetadata;
476 }
477 
478 
483 QPixmap QgsRasterLayer::paletteAsPixmap( int bandNumber )
484 {
485  //TODO: This function should take dimensions
486  QgsDebugMsgLevel( "entered.", 4 );
487 
488  // Only do this for the GDAL provider?
489  // Maybe WMS can do this differently using QImage::numColors and QImage::color()
490  if ( mDataProvider->colorInterpretation( bandNumber ) == QgsRaster::PaletteIndex )
491  {
492  QgsDebugMsgLevel( "....found paletted image", 4 );
493  QgsColorRampShader myShader;
494  QList<QgsColorRampShader::ColorRampItem> myColorRampItemList = mDataProvider->colorTable( bandNumber );
495  if ( !myColorRampItemList.isEmpty() )
496  {
497  QgsDebugMsgLevel( "....got color ramp item list", 4 );
498  myShader.setColorRampItemList( myColorRampItemList );
500  // Draw image
501  int mySize = 100;
502  QPixmap myPalettePixmap( mySize, mySize );
503  QPainter myQPainter( &myPalettePixmap );
504 
505  QImage myQImage = QImage( mySize, mySize, QImage::Format_RGB32 );
506  myQImage.fill( 0 );
507  myPalettePixmap.fill();
508 
509  double myStep = ( static_cast< double >( myColorRampItemList.size() ) - 1 ) / static_cast< double >( mySize * mySize );
510  double myValue = 0.0;
511  for ( int myRow = 0; myRow < mySize; myRow++ )
512  {
513  QRgb *myLineBuffer = reinterpret_cast< QRgb * >( myQImage.scanLine( myRow ) );
514  for ( int myCol = 0; myCol < mySize; myCol++ )
515  {
516  myValue = myStep * static_cast< double >( myCol + myRow * mySize );
517  int c1, c2, c3, c4;
518  myShader.shade( myValue, &c1, &c2, &c3, &c4 );
519  myLineBuffer[ myCol ] = qRgba( c1, c2, c3, c4 );
520  }
521  }
522 
523  myQPainter.drawImage( 0, 0, myQImage );
524  return myPalettePixmap;
525  }
526  QPixmap myNullPixmap;
527  return myNullPixmap;
528  }
529  else
530  {
531  //invalid layer was requested
532  QPixmap myNullPixmap;
533  return myNullPixmap;
534  }
535 }
536 
538 {
539  return mProviderKey;
540 }
541 
546 {
547 // We return one raster pixel per map unit pixel
548 // One raster pixel can have several raster units...
549 
550 // We can only use one of the mGeoTransform[], so go with the
551 // horisontal one.
552 
553  if ( mDataProvider->capabilities() & QgsRasterDataProvider::Size && mDataProvider->xSize() > 0 )
554  {
555  return mDataProvider->extent().width() / mDataProvider->xSize();
556  }
557  return 1;
558 }
559 
561 {
562  if ( mDataProvider->capabilities() & QgsRasterDataProvider::Size && mDataProvider->xSize() > 0 )
563  {
564  return mDataProvider->extent().height() / mDataProvider->ySize();
565  }
566  return 1;
567 }
568 
569 void QgsRasterLayer::init()
570 {
571  mRasterType = QgsRasterLayer::GrayOrUndefined;
572 
574 
575  setRendererForDrawingStyle( QgsRaster::UndefinedDrawingStyle );
576 
577  //Initialize the last view port structure, should really be a class
578  mLastViewPort.mWidth = 0;
579  mLastViewPort.mHeight = 0;
580 }
581 
582 void QgsRasterLayer::setDataProvider( QString const &provider )
583 {
584  QgsDebugMsgLevel( "Entered", 4 );
585  mValid = false; // assume the layer is invalid until we determine otherwise
586 
587  mPipe.remove( mDataProvider ); // deletes if exists
588  mDataProvider = nullptr;
589 
590  // XXX should I check for and possibly delete any pre-existing providers?
591  // XXX How often will that scenario occur?
592 
593  mProviderKey = provider;
594  // set the layer name (uppercase first character)
595  if ( ! mLayerName.isEmpty() ) // XXX shouldn't this happen in parent?
596  {
597  setName( mLayerName );
598  }
599 
600  //mBandCount = 0;
601 
602  mDataProvider = dynamic_cast< QgsRasterDataProvider * >( QgsProviderRegistry::instance()->createProvider( mProviderKey, mDataSource ) );
603  if ( !mDataProvider )
604  {
605  //QgsMessageLog::logMessage( tr( "Cannot instantiate the data provider" ), tr( "Raster" ) );
606  appendError( ERR( tr( "Cannot instantiate the '%1' data provider" ).arg( mProviderKey ) ) );
607  return;
608  }
609  QgsDebugMsgLevel( "Data provider created", 4 );
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 
620  if ( provider == QLatin1String( "gdal" ) )
621  {
622  // make sure that the /vsigzip or /vsizip is added to uri, if applicable
623  mDataSource = mDataProvider->dataSourceUri();
624  }
625 
626  // get the extent
627  QgsRectangle mbr = mDataProvider->extent();
628 
629  // show the extent
630  QgsDebugMsgLevel( "Extent of layer: " + mbr.toString(), 4 );
631  // store the extent
632  setExtent( mbr );
633 
634  // upper case the first letter of the layer name
635  QgsDebugMsgLevel( "mLayerName: " + name(), 4 );
636 
637  // set up the raster drawing style
638  // Do not set any 'sensible' style here, the style is set later
639 
640  // Setup source CRS
641  setCrs( QgsCoordinateReferenceSystem( mDataProvider->crs() ) );
642 
643  QgsDebugMsgLevel( "using wkt:\n" + crs().toWkt(), 4 );
644 
645  //defaults - Needs to be set after the Contrast list has been build
646  //Try to read the default contrast enhancement from the config file
647 
648  //decide what type of layer this is...
649  //TODO Change this to look at the color interp and palette interp to decide which type of layer it is
650  QgsDebugMsgLevel( "bandCount = " + QString::number( mDataProvider->bandCount() ), 4 );
651  QgsDebugMsgLevel( "dataType = " + QString::number( mDataProvider->dataType( 1 ) ), 4 );
652  if ( ( mDataProvider->bandCount() > 1 ) )
653  {
654  // handle singleband gray with alpha
655  if ( mDataProvider->bandCount() == 2
656  && ( ( mDataProvider->colorInterpretation( 1 ) == QgsRaster::GrayIndex
657  && mDataProvider->colorInterpretation( 2 ) == QgsRaster::AlphaBand )
658  || ( mDataProvider->colorInterpretation( 1 ) == QgsRaster::AlphaBand
659  && mDataProvider->colorInterpretation( 2 ) == QgsRaster::GrayIndex ) ) )
660  {
661  mRasterType = GrayOrUndefined;
662  }
663  else
664  {
665  mRasterType = Multiband;
666  }
667  }
668  else if ( mDataProvider->dataType( 1 ) == Qgis::ARGB32
669  || mDataProvider->dataType( 1 ) == Qgis::ARGB32_Premultiplied )
670  {
671  mRasterType = ColorLayer;
672  }
673  else if ( mDataProvider->colorInterpretation( 1 ) == QgsRaster::PaletteIndex )
674  {
675  mRasterType = Palette;
676  }
677  else if ( mDataProvider->colorInterpretation( 1 ) == QgsRaster::ContinuousPalette )
678  {
679  mRasterType = Palette;
680  }
681  else
682  {
683  mRasterType = GrayOrUndefined;
684  }
685 
686  QgsDebugMsgLevel( "mRasterType = " + QString::number( mRasterType ), 4 );
687  if ( mRasterType == ColorLayer )
688  {
689  QgsDebugMsgLevel( "Setting drawing style to SingleBandColorDataStyle " + QString::number( QgsRaster::SingleBandColorDataStyle ), 4 );
690  setRendererForDrawingStyle( QgsRaster::SingleBandColorDataStyle );
691  }
692  else if ( mRasterType == Palette && mDataProvider->colorInterpretation( 1 ) == QgsRaster::PaletteIndex )
693  {
694  setRendererForDrawingStyle( QgsRaster::PalettedColor ); //sensible default
695  }
696  else if ( mRasterType == Palette && mDataProvider->colorInterpretation( 1 ) == QgsRaster::ContinuousPalette )
697  {
698  setRendererForDrawingStyle( QgsRaster::SingleBandPseudoColor );
699  // Load color table
700  QList<QgsColorRampShader::ColorRampItem> colorTable = mDataProvider->colorTable( 1 );
702  if ( r )
703  {
704  // TODO: this should go somewhere else
705  QgsRasterShader *shader = new QgsRasterShader();
706  QgsColorRampShader *colorRampShader = new QgsColorRampShader();
708  colorRampShader->setColorRampItemList( colorTable );
709  shader->setRasterShaderFunction( colorRampShader );
710  r->setShader( shader );
711  }
712  }
713  else if ( mRasterType == Multiband )
714  {
715  setRendererForDrawingStyle( QgsRaster::MultiBandColor ); //sensible default
716  }
717  else //GrayOrUndefined
718  {
719  setRendererForDrawingStyle( QgsRaster::SingleBandGray ); //sensible default
720  }
721 
722  // Auto set alpha band
723  for ( int bandNo = 1; bandNo <= mDataProvider->bandCount(); bandNo++ )
724  {
725  if ( mDataProvider->colorInterpretation( bandNo ) == QgsRaster::AlphaBand )
726  {
727  if ( mPipe.renderer() )
728  {
729  mPipe.renderer()->setAlphaBand( bandNo );
730  }
731  break;
732  }
733  }
734 
735  // brightness filter
737  mPipe.set( brightnessFilter );
738 
739  // hue/saturation filter
741  mPipe.set( hueSaturationFilter );
742 
743  //resampler (must be after renderer)
745  mPipe.set( resampleFilter );
746 
747  // projector (may be anywhere in pipe)
748  QgsRasterProjector *projector = new QgsRasterProjector;
749  mPipe.set( projector );
750 
751  // Set default identify format - use the richest format available
752  int capabilities = mDataProvider->capabilities();
754  if ( capabilities & QgsRasterInterface::IdentifyHtml )
755  {
756  // HTML is usually richest
757  identifyFormat = QgsRaster::IdentifyFormatHtml;
758  }
759  else if ( capabilities & QgsRasterInterface::IdentifyFeature )
760  {
761  identifyFormat = QgsRaster::IdentifyFormatFeature;
762  }
763  else if ( capabilities & QgsRasterInterface::IdentifyText )
764  {
765  identifyFormat = QgsRaster::IdentifyFormatText;
766  }
767  else if ( capabilities & QgsRasterInterface::IdentifyValue )
768  {
769  identifyFormat = QgsRaster::IdentifyFormatValue;
770  }
771  setCustomProperty( QStringLiteral( "identify/format" ), QgsRasterDataProvider::identifyFormatName( identifyFormat ) );
772 
773  // Store timestamp
774  // TODO move to provider
775  mLastModified = lastModified( mDataSource );
776 
777  // Do a passthrough for the status bar text
778  connect( mDataProvider, &QgsRasterDataProvider::statusChanged, this, &QgsRasterLayer::statusChanged );
779 
780  //mark the layer as valid
781  mValid = true;
782 
783  QgsDebugMsgLevel( "exiting.", 4 );
784 } // QgsRasterLayer::setDataProvider
785 
786 void QgsRasterLayer::closeDataProvider()
787 {
788  mValid = false;
789  mPipe.remove( mDataProvider );
790  mDataProvider = nullptr;
791 }
792 
793 void QgsRasterLayer::computeMinMax( int band,
794  const QgsRasterMinMaxOrigin &mmo,
796  const QgsRectangle &extent,
797  int sampleSize,
798  double &min, double &max )
799 {
800 
801  min = std::numeric_limits<double>::quiet_NaN();
802  max = std::numeric_limits<double>::quiet_NaN();
803 
804  if ( limits == QgsRasterMinMaxOrigin::MinMax )
805  {
806  QgsRasterBandStats myRasterBandStats = mDataProvider->bandStatistics( band, QgsRasterBandStats::Min | QgsRasterBandStats::Max, extent, sampleSize );
807  min = myRasterBandStats.minimumValue;
808  max = myRasterBandStats.maximumValue;
809  }
810  else if ( limits == QgsRasterMinMaxOrigin::StdDev )
811  {
812  QgsRasterBandStats myRasterBandStats = mDataProvider->bandStatistics( band, QgsRasterBandStats::Mean | QgsRasterBandStats::StdDev, extent, sampleSize );
813  min = myRasterBandStats.mean - ( mmo.stdDevFactor() * myRasterBandStats.stdDev );
814  max = myRasterBandStats.mean + ( mmo.stdDevFactor() * myRasterBandStats.stdDev );
815  }
816  else if ( limits == QgsRasterMinMaxOrigin::CumulativeCut )
817  {
818  const double myLower = mmo.cumulativeCutLower();
819  const double myUpper = mmo.cumulativeCutUpper();
820  QgsDebugMsgLevel( QString( "myLower = %1 myUpper = %2" ).arg( myLower ).arg( myUpper ), 4 );
821  mDataProvider->cumulativeCut( band, myLower, myUpper, min, max, extent, sampleSize );
822  }
823  QgsDebugMsgLevel( QString( "band = %1 min = %2 max = %3" ).arg( band ).arg( min ).arg( max ), 4 );
824 
825 }
826 
827 
828 void QgsRasterLayer::setContrastEnhancement( QgsContrastEnhancement::ContrastEnhancementAlgorithm algorithm, QgsRasterMinMaxOrigin::Limits limits, const QgsRectangle &extent, int sampleSize, bool generateLookupTableFlag )
829 {
830  setContrastEnhancement( algorithm,
831  limits,
832  extent,
833  sampleSize,
834  generateLookupTableFlag,
835  mPipe.renderer() );
836 }
837 
840  const QgsRectangle &extent,
841  int sampleSize,
842  bool generateLookupTableFlag,
843  QgsRasterRenderer *rasterRenderer )
844 {
845  QgsDebugMsgLevel( QString( "theAlgorithm = %1 limits = %2 extent.isEmpty() = %3" ).arg( algorithm ).arg( limits ).arg( extent.isEmpty() ), 4 );
846  if ( !rasterRenderer || !mDataProvider )
847  {
848  return;
849  }
850 
851  QList<int> myBands;
852  QList<QgsContrastEnhancement *> myEnhancements;
853  QgsRasterMinMaxOrigin myMinMaxOrigin;
854  QgsRasterRenderer *myRasterRenderer = nullptr;
855  QgsSingleBandGrayRenderer *myGrayRenderer = nullptr;
856  QgsSingleBandPseudoColorRenderer *myPseudoColorRenderer = nullptr;
857  QgsMultiBandColorRenderer *myMultiBandRenderer = nullptr;
858  QString rendererType = rasterRenderer->type();
859  if ( rendererType == QLatin1String( "singlebandgray" ) )
860  {
861  myGrayRenderer = dynamic_cast<QgsSingleBandGrayRenderer *>( rasterRenderer );
862  if ( !myGrayRenderer )
863  {
864  return;
865  }
866  myBands << myGrayRenderer->grayBand();
867  myRasterRenderer = myGrayRenderer;
868  myMinMaxOrigin = myGrayRenderer->minMaxOrigin();
869  }
870  else if ( rendererType == QLatin1String( "multibandcolor" ) )
871  {
872  myMultiBandRenderer = dynamic_cast<QgsMultiBandColorRenderer *>( rasterRenderer );
873  if ( !myMultiBandRenderer )
874  {
875  return;
876  }
877  myBands << myMultiBandRenderer->redBand() << myMultiBandRenderer->greenBand() << myMultiBandRenderer->blueBand();
878  myRasterRenderer = myMultiBandRenderer;
879  myMinMaxOrigin = myMultiBandRenderer->minMaxOrigin();
880  }
881  else if ( rendererType == QLatin1String( "singlebandpseudocolor" ) )
882  {
883  myPseudoColorRenderer = dynamic_cast<QgsSingleBandPseudoColorRenderer *>( rasterRenderer );
884  if ( !myPseudoColorRenderer )
885  {
886  return;
887  }
888  myBands << myPseudoColorRenderer->band();
889  myRasterRenderer = myPseudoColorRenderer;
890  myMinMaxOrigin = myPseudoColorRenderer->minMaxOrigin();
891  }
892  else
893  {
894  return;
895  }
896 
897  Q_FOREACH ( int myBand, myBands )
898  {
899  if ( myBand != -1 )
900  {
901  Qgis::DataType myType = static_cast< Qgis::DataType >( mDataProvider->dataType( myBand ) );
902  std::unique_ptr<QgsContrastEnhancement> myEnhancement( new QgsContrastEnhancement( static_cast< Qgis::DataType >( myType ) ) );
903  myEnhancement->setContrastEnhancementAlgorithm( algorithm, generateLookupTableFlag );
904 
905  double min;
906  double max;
907  computeMinMax( myBand, myMinMaxOrigin, limits, extent, sampleSize, min, max );
908 
909  if ( rendererType == QLatin1String( "singlebandpseudocolor" ) )
910  {
911  myPseudoColorRenderer->setClassificationMin( min );
912  myPseudoColorRenderer->setClassificationMax( max );
913  if ( myPseudoColorRenderer->shader() )
914  {
915  QgsColorRampShader *colorRampShader = dynamic_cast<QgsColorRampShader *>( myPseudoColorRenderer->shader()->rasterShaderFunction() );
916  if ( colorRampShader )
917  {
918  colorRampShader->classifyColorRamp( myPseudoColorRenderer->band(), extent, myPseudoColorRenderer->input() );
919  }
920  }
921  }
922  else
923  {
924  myEnhancement->setMinimumValue( min );
925  myEnhancement->setMaximumValue( max );
926  myEnhancements.append( myEnhancement.release() );
927  }
928  }
929  else
930  {
931  myEnhancements.append( nullptr );
932  }
933  }
934 
935  if ( rendererType == QLatin1String( "singlebandgray" ) )
936  {
937  if ( myEnhancements.first() ) myGrayRenderer->setContrastEnhancement( myEnhancements.takeFirst() );
938  }
939  else if ( rendererType == QLatin1String( "multibandcolor" ) )
940  {
941  if ( myEnhancements.first() ) myMultiBandRenderer->setRedContrastEnhancement( myEnhancements.takeFirst() );
942  if ( myEnhancements.first() ) myMultiBandRenderer->setGreenContrastEnhancement( myEnhancements.takeFirst() );
943  if ( myEnhancements.first() ) myMultiBandRenderer->setBlueContrastEnhancement( myEnhancements.takeFirst() );
944  }
945 
946  //delete all remaining unused enhancements
947  qDeleteAll( myEnhancements );
948 
949  myMinMaxOrigin.setLimits( limits );
950  if ( extent != QgsRectangle() &&
951  myMinMaxOrigin.extent() == QgsRasterMinMaxOrigin::WholeRaster )
952  {
954  }
955  if ( myRasterRenderer )
956  {
957  myRasterRenderer->setMinMaxOrigin( myMinMaxOrigin );
958  }
959 
960  if ( rasterRenderer == renderer() )
961  {
962  emit repaintRequested();
963  emit styleChanged();
964  emit rendererChanged();
965  }
966 }
967 
969 {
970  QgsSingleBandGrayRenderer *singleBandRenderer = nullptr;
971  QgsMultiBandColorRenderer *multiBandRenderer = nullptr;
972  const QgsContrastEnhancement *ce = nullptr;
973  if ( ( singleBandRenderer = dynamic_cast<QgsSingleBandGrayRenderer *>( renderer() ) ) )
974  {
975  ce = singleBandRenderer->contrastEnhancement();
976  }
977  else if ( ( multiBandRenderer = dynamic_cast<QgsMultiBandColorRenderer *>( renderer() ) ) )
978  {
979  ce = multiBandRenderer->redContrastEnhancement();
980  }
981 
982  if ( ce )
983  {
988  extent,
989  SAMPLE_SIZE,
990  true,
991  renderer() );
992  }
993  else
994  {
997  if ( defaultContrastEnhancementSettings( myAlgorithm, myLimits ) )
998  {
1000  myLimits,
1001  extent,
1002  SAMPLE_SIZE,
1003  true,
1004  renderer() );
1005  }
1006  }
1007 }
1008 
1010  const QgsRectangle &extent )
1011 {
1012  if ( !( mDataProvider &&
1013  mLastRectangleUsedByRefreshContrastEnhancementIfNeeded != extent &&
1014  rasterRenderer->minMaxOrigin().limits() != QgsRasterMinMaxOrigin::None &&
1015  rasterRenderer->minMaxOrigin().extent() == QgsRasterMinMaxOrigin::UpdatedCanvas ) )
1016  return;
1017 
1018  QgsSingleBandGrayRenderer *singleBandRenderer = nullptr;
1019  QgsMultiBandColorRenderer *multiBandRenderer = nullptr;
1020  QgsSingleBandPseudoColorRenderer *sbpcr = nullptr;
1021  const QgsContrastEnhancement *ce = nullptr;
1022  if ( ( singleBandRenderer = dynamic_cast<QgsSingleBandGrayRenderer *>( rasterRenderer ) ) )
1023  {
1024  ce = singleBandRenderer->contrastEnhancement();
1025  }
1026  else if ( ( multiBandRenderer = dynamic_cast<QgsMultiBandColorRenderer *>( rasterRenderer ) ) )
1027  {
1028  ce = multiBandRenderer->redContrastEnhancement();
1029  }
1030  else if ( ( sbpcr = dynamic_cast<QgsSingleBandPseudoColorRenderer *>( rasterRenderer ) ) )
1031  {
1032  mLastRectangleUsedByRefreshContrastEnhancementIfNeeded = extent;
1033  double min;
1034  double max;
1035  computeMinMax( sbpcr->band(),
1036  rasterRenderer->minMaxOrigin(),
1037  rasterRenderer->minMaxOrigin().limits(), extent,
1038  SAMPLE_SIZE, min, max );
1039  sbpcr->setClassificationMin( min );
1040  sbpcr->setClassificationMax( max );
1041 
1042  if ( sbpcr->shader() )
1043  {
1044  QgsColorRampShader *colorRampShader = dynamic_cast<QgsColorRampShader *>( sbpcr->shader()->rasterShaderFunction() );
1045  if ( colorRampShader )
1046  {
1047  colorRampShader->classifyColorRamp( sbpcr->band(), extent, rasterRenderer->input() );
1048  }
1049  }
1050 
1052  r->setClassificationMin( min );
1053  r->setClassificationMax( max );
1054 
1055  if ( r->shader() )
1056  {
1057  QgsColorRampShader *colorRampShader = dynamic_cast<QgsColorRampShader *>( r->shader()->rasterShaderFunction() );
1058  if ( colorRampShader )
1059  {
1060  colorRampShader->classifyColorRamp( sbpcr->band(), extent, rasterRenderer->input() );
1061  }
1062  }
1063 
1064  emit repaintRequested();
1065  emit styleChanged();
1066  emit rendererChanged();
1067  return;
1068  }
1069 
1070  if ( ce &&
1072  {
1073  mLastRectangleUsedByRefreshContrastEnhancementIfNeeded = extent;
1074 
1076  rasterRenderer->minMaxOrigin().limits(),
1077  extent,
1078  SAMPLE_SIZE,
1079  true,
1080  rasterRenderer );
1081 
1082  // Update main renderer so that the legends get updated
1083  if ( singleBandRenderer )
1084  static_cast<QgsSingleBandGrayRenderer *>( renderer() )->setContrastEnhancement( new QgsContrastEnhancement( * singleBandRenderer->contrastEnhancement() ) );
1085  else if ( multiBandRenderer )
1086  {
1087  if ( multiBandRenderer->redContrastEnhancement() )
1088  {
1089  static_cast<QgsMultiBandColorRenderer *>( renderer() )->setRedContrastEnhancement( new QgsContrastEnhancement( *multiBandRenderer->redContrastEnhancement() ) );
1090  }
1091  if ( multiBandRenderer->greenContrastEnhancement() )
1092  {
1093  static_cast<QgsMultiBandColorRenderer *>( renderer() )->setGreenContrastEnhancement( new QgsContrastEnhancement( *multiBandRenderer->greenContrastEnhancement() ) );
1094  }
1095  if ( multiBandRenderer->blueContrastEnhancement() )
1096  {
1097  static_cast<QgsMultiBandColorRenderer *>( renderer() )->setBlueContrastEnhancement( new QgsContrastEnhancement( *multiBandRenderer->blueContrastEnhancement() ) );
1098  }
1099  }
1100 
1101  emit styleChanged();
1102  emit rendererChanged();
1103  }
1104 }
1105 
1108  QgsRasterMinMaxOrigin::Limits &myLimits ) const
1109 {
1110  QgsSettings mySettings;
1111 
1112  QString key;
1113  QString defaultAlg;
1114  QString defaultLimits;
1115 
1116  // TODO: we should not test renderer class here, move it somehow to renderers
1117  if ( dynamic_cast<QgsSingleBandGrayRenderer *>( renderer() ) )
1118  {
1119  key = QStringLiteral( "singleBand" );
1122  defaultLimits = QgsRasterMinMaxOrigin::limitsString(
1124  }
1125  else if ( dynamic_cast<QgsMultiBandColorRenderer *>( renderer() ) )
1126  {
1127  if ( QgsRasterBlock::typeSize( dataProvider()->sourceDataType( 1 ) ) == 1 )
1128  {
1129  key = QStringLiteral( "multiBandSingleByte" );
1132  defaultLimits = QgsRasterMinMaxOrigin::limitsString(
1134  }
1135  else
1136  {
1137  key = QStringLiteral( "multiBandMultiByte" );
1140  defaultLimits = QgsRasterMinMaxOrigin::limitsString(
1142  }
1143  }
1144 
1145  if ( key.isEmpty() )
1146  {
1147  QgsDebugMsg( "No default contrast enhancement for this drawing style" );
1149  myLimits = QgsRasterMinMaxOrigin::limitsFromString( QString() );
1150  return false;
1151  }
1152  QgsDebugMsgLevel( "key = " + key, 4 );
1153 
1154  QString myAlgorithmString = mySettings.value( "/Raster/defaultContrastEnhancementAlgorithm/" + key, defaultAlg ).toString();
1155  QgsDebugMsgLevel( "myAlgorithmString = " + myAlgorithmString, 4 );
1156 
1157  myAlgorithm = QgsContrastEnhancement::contrastEnhancementAlgorithmFromString( myAlgorithmString );
1158 
1159  QString myLimitsString = mySettings.value( "/Raster/defaultContrastEnhancementLimits/" + key, defaultLimits ).toString();
1160  QgsDebugMsgLevel( "myLimitsString = " + myLimitsString, 4 );
1161  myLimits = QgsRasterMinMaxOrigin::limitsFromString( myLimitsString );
1162 
1163  return true;
1164 }
1165 
1167 {
1168  QgsDebugMsgLevel( "Entered", 4 );
1169 
1172  defaultContrastEnhancementSettings( myAlgorithm, myLimits );
1173 
1174  setContrastEnhancement( myAlgorithm, myLimits );
1175 }
1176 
1177 void QgsRasterLayer::setLayerOrder( QStringList const &layers )
1178 {
1179  QgsDebugMsgLevel( "entered.", 4 );
1180 
1181  if ( mDataProvider )
1182  {
1183  QgsDebugMsgLevel( "About to mDataProvider->setLayerOrder(layers).", 4 );
1184  mDataProvider->setLayerOrder( layers );
1185  }
1186 
1187 }
1188 
1189 void QgsRasterLayer::setSubLayerVisibility( const QString &name, bool vis )
1190 {
1191 
1192  if ( mDataProvider )
1193  {
1194  QgsDebugMsgLevel( "About to mDataProvider->setSubLayerVisibility(name, vis).", 4 );
1195  mDataProvider->setSubLayerVisibility( name, vis );
1196  }
1197 
1198 }
1199 
1200 QDateTime QgsRasterLayer::timestamp() const
1201 {
1202  return mDataProvider->timestamp();
1203 }
1204 
1206 {
1207  QgsDebugMsgLevel( "Entered", 4 );
1208  if ( !renderer )
1209  {
1210  return;
1211  }
1212 
1213  mPipe.set( renderer );
1214  emit rendererChanged();
1215  emit styleChanged();
1216 }
1217 
1218 void QgsRasterLayer::showStatusMessage( QString const &message )
1219 {
1220  // QgsDebugMsg(QString("entered with '%1'.").arg(theMessage));
1221 
1222  // Pass-through
1223  // TODO: See if we can connect signal-to-signal. This is a kludge according to the Qt doc.
1224  emit statusChanged( message );
1225 }
1226 
1227 QStringList QgsRasterLayer::subLayers() const
1228 {
1229  return mDataProvider->subLayers();
1230 }
1231 
1232 // this function should be used when rendering with the MTR engine introduced in 2.3, as QPixmap is not thread safe (see bug #9626)
1233 // note: previewAsImage and previewAsPixmap should use a common low-level fct QgsRasterLayer::previewOnPaintDevice( QSize size, QColor bgColor, QPaintDevice &device )
1234 QImage QgsRasterLayer::previewAsImage( QSize size, const QColor &bgColor, QImage::Format format )
1235 {
1236  QImage myQImage( size, format );
1237 
1238  myQImage.setColor( 0, bgColor.rgba() );
1239  myQImage.fill( 0 ); //defaults to white, set to transparent for rendering on a map
1240 
1241  QgsRasterViewPort *myRasterViewPort = new QgsRasterViewPort();
1242 
1243  double myMapUnitsPerPixel;
1244  double myX = 0.0;
1245  double myY = 0.0;
1246  QgsRectangle myExtent = mDataProvider->extent();
1247  if ( myExtent.width() / myExtent.height() >= static_cast< double >( myQImage.width() ) / myQImage.height() )
1248  {
1249  myMapUnitsPerPixel = myExtent.width() / myQImage.width();
1250  myY = ( myQImage.height() - myExtent.height() / myMapUnitsPerPixel ) / 2;
1251  }
1252  else
1253  {
1254  myMapUnitsPerPixel = myExtent.height() / myQImage.height();
1255  myX = ( myQImage.width() - myExtent.width() / myMapUnitsPerPixel ) / 2;
1256  }
1257 
1258  double myPixelWidth = myExtent.width() / myMapUnitsPerPixel;
1259  double myPixelHeight = myExtent.height() / myMapUnitsPerPixel;
1260 
1261  myRasterViewPort->mTopLeftPoint = QgsPointXY( myX, myY );
1262  myRasterViewPort->mBottomRightPoint = QgsPointXY( myPixelWidth, myPixelHeight );
1263  myRasterViewPort->mWidth = myQImage.width();
1264  myRasterViewPort->mHeight = myQImage.height();
1265 
1266  myRasterViewPort->mDrawnExtent = myExtent;
1267  myRasterViewPort->mSrcCRS = QgsCoordinateReferenceSystem(); // will be invalid
1268  myRasterViewPort->mDestCRS = QgsCoordinateReferenceSystem(); // will be invalid
1269  myRasterViewPort->mSrcDatumTransform = -1;
1270  myRasterViewPort->mDestDatumTransform = -1;
1271 
1272  QgsMapToPixel *myMapToPixel = new QgsMapToPixel( myMapUnitsPerPixel );
1273 
1274  QPainter *myQPainter = new QPainter( &myQImage );
1275  draw( myQPainter, myRasterViewPort, myMapToPixel );
1276  delete myRasterViewPort;
1277  delete myMapToPixel;
1278  myQPainter->end();
1279  delete myQPainter;
1280 
1281  return myQImage;
1282 }
1283 
1285 //
1286 // Protected methods
1287 //
1289 /*
1290  * @param QDomNode node that will contain the symbology definition for this layer.
1291  * @param errorMessage reference to string that will be updated with any error messages
1292  * @return true in case of success.
1293  */
1294 bool QgsRasterLayer::readSymbology( const QDomNode &layer_node, QString &errorMessage, const QgsReadWriteContext &context )
1295 {
1296  Q_UNUSED( errorMessage );
1297  Q_UNUSED( context );
1298  QDomElement rasterRendererElem;
1299 
1300  // pipe element was introduced in the end of 1.9 development when there were
1301  // already many project files in use so we support 1.9 backward compatibility
1302  // even it was never officially released -> use pipe element if present, otherwise
1303  // use layer node
1304  QDomNode pipeNode = layer_node.firstChildElement( QStringLiteral( "pipe" ) );
1305  if ( pipeNode.isNull() ) // old project
1306  {
1307  pipeNode = layer_node;
1308  }
1309 
1310  //rasterlayerproperties element there -> old format (1.8 and early 1.9)
1311  if ( !layer_node.firstChildElement( QStringLiteral( "rasterproperties" ) ).isNull() )
1312  {
1313  //copy node because layer_node is const
1314  QDomNode layerNodeCopy = layer_node.cloneNode();
1315  QDomDocument doc = layerNodeCopy.ownerDocument();
1316  QDomElement rasterPropertiesElem = layerNodeCopy.firstChildElement( QStringLiteral( "rasterproperties" ) );
1317  QgsProjectFileTransform::convertRasterProperties( doc, layerNodeCopy, rasterPropertiesElem,
1318  this );
1319  rasterRendererElem = layerNodeCopy.firstChildElement( QStringLiteral( "rasterrenderer" ) );
1320  QgsDebugMsgLevel( doc.toString(), 4 );
1321  }
1322  else
1323  {
1324  rasterRendererElem = pipeNode.firstChildElement( QStringLiteral( "rasterrenderer" ) );
1325  }
1326 
1327  if ( !rasterRendererElem.isNull() )
1328  {
1329  QString rendererType = rasterRendererElem.attribute( QStringLiteral( "type" ) );
1330  QgsRasterRendererRegistryEntry rendererEntry;
1331  if ( QgsApplication::rasterRendererRegistry()->rendererData( rendererType, rendererEntry ) )
1332  {
1333  QgsRasterRenderer *renderer = rendererEntry.rendererCreateFunction( rasterRendererElem, dataProvider() );
1334  mPipe.set( renderer );
1335  }
1336  }
1337 
1338  //brightness
1340  mPipe.set( brightnessFilter );
1341 
1342  //brightness coefficient
1343  QDomElement brightnessElem = pipeNode.firstChildElement( QStringLiteral( "brightnesscontrast" ) );
1344  if ( !brightnessElem.isNull() )
1345  {
1346  brightnessFilter->readXml( brightnessElem );
1347  }
1348 
1349  //hue/saturation
1351  mPipe.set( hueSaturationFilter );
1352 
1353  //saturation coefficient
1354  QDomElement hueSaturationElem = pipeNode.firstChildElement( QStringLiteral( "huesaturation" ) );
1355  if ( !hueSaturationElem.isNull() )
1356  {
1357  hueSaturationFilter->readXml( hueSaturationElem );
1358  }
1359 
1360  //resampler
1362  mPipe.set( resampleFilter );
1363 
1364  //max oversampling
1365  QDomElement resampleElem = pipeNode.firstChildElement( QStringLiteral( "rasterresampler" ) );
1366  if ( !resampleElem.isNull() )
1367  {
1368  resampleFilter->readXml( resampleElem );
1369  }
1370 
1371  // get and set the blend mode if it exists
1372  QDomNode blendModeNode = layer_node.namedItem( QStringLiteral( "blendMode" ) );
1373  if ( !blendModeNode.isNull() )
1374  {
1375  QDomElement e = blendModeNode.toElement();
1376  setBlendMode( QgsPainting::getCompositionMode( static_cast< QgsPainting::BlendMode >( e.text().toInt() ) ) );
1377  }
1378 
1379  readCustomProperties( layer_node );
1380 
1381  return true;
1382 }
1383 
1384 bool QgsRasterLayer::readStyle( const QDomNode &node, QString &errorMessage, const QgsReadWriteContext &context )
1385 {
1386  return readSymbology( node, errorMessage, context );
1387 } //readSymbology
1388 
1395 bool QgsRasterLayer::readXml( const QDomNode &layer_node, const QgsReadWriteContext &context )
1396 {
1397  QgsDebugMsgLevel( "Entered", 4 );
1398  // Make sure to read the file first so stats etc are initialized properly!
1399 
1400  //process provider key
1401  QDomNode pkeyNode = layer_node.namedItem( QStringLiteral( "provider" ) );
1402 
1403  if ( pkeyNode.isNull() )
1404  {
1405  mProviderKey = QStringLiteral( "gdal" );
1406  }
1407  else
1408  {
1409  QDomElement pkeyElt = pkeyNode.toElement();
1410  mProviderKey = pkeyElt.text();
1411  if ( mProviderKey.isEmpty() )
1412  {
1413  mProviderKey = QStringLiteral( "gdal" );
1414  }
1415  }
1416 
1417  // Open the raster source based on provider and datasource
1418 
1419  // Go down the raster-data-provider paradigm
1420 
1421  // Collect provider-specific information
1422 
1423  QDomNode rpNode = layer_node.namedItem( QStringLiteral( "rasterproperties" ) );
1424 
1425  if ( mProviderKey == QLatin1String( "wms" ) )
1426  {
1427  // >>> BACKWARD COMPATIBILITY < 1.9
1428  // The old WMS URI format does not contain all the information, we add them here.
1429  if ( !mDataSource.contains( QLatin1String( "crs=" ) ) && !mDataSource.contains( QLatin1String( "format=" ) ) )
1430  {
1431  QgsDebugMsgLevel( "Old WMS URI format detected -> adding params", 4 );
1432  QgsDataSourceUri uri;
1433  uri.setEncodedUri( mDataSource );
1434  QDomElement layerElement = rpNode.firstChildElement( QStringLiteral( "wmsSublayer" ) );
1435  while ( !layerElement.isNull() )
1436  {
1437  // TODO: sublayer visibility - post-0.8 release timeframe
1438 
1439  // collect name for the sublayer
1440  uri.setParam( QStringLiteral( "layers" ), layerElement.namedItem( QStringLiteral( "name" ) ).toElement().text() );
1441 
1442  // collect style for the sublayer
1443  uri.setParam( QStringLiteral( "styles" ), layerElement.namedItem( QStringLiteral( "style" ) ).toElement().text() );
1444 
1445  layerElement = layerElement.nextSiblingElement( QStringLiteral( "wmsSublayer" ) );
1446  }
1447 
1448  // Collect format
1449  QDomNode formatNode = rpNode.namedItem( QStringLiteral( "wmsFormat" ) );
1450  uri.setParam( QStringLiteral( "format" ), rpNode.namedItem( QStringLiteral( "wmsFormat" ) ).toElement().text() );
1451 
1452  // WMS CRS URL param should not be mixed with that assigned to the layer.
1453  // In the old WMS URI version there was no CRS and layer crs().authid() was used.
1454  uri.setParam( QStringLiteral( "crs" ), crs().authid() );
1455  mDataSource = uri.encodedUri();
1456  }
1457  // <<< BACKWARD COMPATIBILITY < 1.9
1458  }
1459 
1460  setDataProvider( mProviderKey );
1461  if ( !mValid ) return false;
1462 
1463  QString error;
1464  bool res = readSymbology( layer_node, error, context );
1465 
1466  // old wms settings we need to correct
1467  if ( res && mProviderKey == QLatin1String( "wms" ) && ( !renderer() || renderer()->type() != QLatin1String( "singlebandcolordata" ) ) )
1468  {
1469  setRendererForDrawingStyle( QgsRaster::SingleBandColorDataStyle );
1470  }
1471 
1472  // Check timestamp
1473  // This was probably introduced to reload completely raster if data changed and
1474  // reset completely symbology to reflect new data type etc. It creates however
1475  // problems, because user defined symbology is complete lost if data file time
1476  // changed (the content may be the same). See also 6900.
1477 #if 0
1478  QDomNode stampNode = layer_node.namedItem( "timestamp" );
1479  if ( !stampNode.isNull() )
1480  {
1481  QDateTime stamp = QDateTime::fromString( stampNode.toElement().text(), Qt::ISODate );
1482  // TODO: very bad, we have to load twice!!! Make QgsDataProvider::timestamp() static?
1483  if ( stamp < mDataProvider->dataTimestamp() )
1484  {
1485  QgsDebugMsg( "data changed, reload provider" );
1486  closeDataProvider();
1487  init();
1488  setDataProvider( mProviderKey );
1489  if ( !mValid ) return false;
1490  }
1491  }
1492 #endif
1493 
1494  // Load user no data value
1495  QDomElement noDataElement = layer_node.firstChildElement( QStringLiteral( "noData" ) );
1496 
1497  QDomNodeList noDataBandList = noDataElement.elementsByTagName( QStringLiteral( "noDataList" ) );
1498 
1499  for ( int i = 0; i < noDataBandList.size(); ++i )
1500  {
1501  QDomElement bandElement = noDataBandList.at( i ).toElement();
1502  bool ok;
1503  int bandNo = bandElement.attribute( QStringLiteral( "bandNo" ) ).toInt( &ok );
1504  QgsDebugMsgLevel( QString( "bandNo = %1" ).arg( bandNo ), 4 );
1505  if ( ok && ( bandNo > 0 ) && ( bandNo <= mDataProvider->bandCount() ) )
1506  {
1507  mDataProvider->setUseSourceNoDataValue( bandNo, bandElement.attribute( QStringLiteral( "useSrcNoData" ) ).toInt() );
1508  QgsRasterRangeList myNoDataRangeList;
1509 
1510  QDomNodeList rangeList = bandElement.elementsByTagName( QStringLiteral( "noDataRange" ) );
1511 
1512  myNoDataRangeList.reserve( rangeList.size() );
1513  for ( int j = 0; j < rangeList.size(); ++j )
1514  {
1515  QDomElement rangeElement = rangeList.at( j ).toElement();
1516  QgsRasterRange myNoDataRange( rangeElement.attribute( QStringLiteral( "min" ) ).toDouble(),
1517  rangeElement.attribute( QStringLiteral( "max" ) ).toDouble() );
1518  QgsDebugMsgLevel( QString( "min = %1 %2" ).arg( rangeElement.attribute( "min" ) ).arg( myNoDataRange.min() ), 4 );
1519  myNoDataRangeList << myNoDataRange;
1520  }
1521  mDataProvider->setUserNoDataValue( bandNo, myNoDataRangeList );
1522  }
1523  }
1524 
1525  readStyleManager( layer_node );
1526 
1527  return res;
1528 } // QgsRasterLayer::readXml( QDomNode & layer_node )
1529 
1530 /*
1531  * @param QDomNode the node that will have the style element added to it.
1532  * @param QDomDocument the document that will have the QDomNode added.
1533  * @param errorMessage reference to string that will be updated with any error messages
1534  * @return true in case of success.
1535  */
1536 bool QgsRasterLayer::writeSymbology( QDomNode &layer_node, QDomDocument &document, QString &errorMessage, const QgsReadWriteContext &context ) const
1537 {
1538  Q_UNUSED( errorMessage );
1539  Q_UNUSED( context );
1540 
1541  // Store pipe members (except provider) into pipe element, in future, it will be
1542  // possible to add custom filters into the pipe
1543  QDomElement pipeElement = document.createElement( QStringLiteral( "pipe" ) );
1544 
1545  for ( int i = 1; i < mPipe.size(); i++ )
1546  {
1547  QgsRasterInterface *interface = mPipe.at( i );
1548  if ( !interface ) continue;
1549  interface->writeXml( document, pipeElement );
1550  }
1551 
1552  layer_node.appendChild( pipeElement );
1553 
1554  // add blend mode node
1555  QDomElement blendModeElement = document.createElement( QStringLiteral( "blendMode" ) );
1556  QDomText blendModeText = document.createTextNode( QString::number( QgsPainting::getBlendModeEnum( blendMode() ) ) );
1557  blendModeElement.appendChild( blendModeText );
1558  layer_node.appendChild( blendModeElement );
1559 
1560  return true;
1561 }
1562 
1563 bool QgsRasterLayer::writeStyle( QDomNode &node, QDomDocument &doc, QString &errorMessage, const QgsReadWriteContext &context ) const
1564 {
1565  return writeSymbology( node, doc, errorMessage, context );
1566 
1567 } // bool QgsRasterLayer::writeSymbology
1568 
1569 /*
1570  * virtual
1571  * @note Called by QgsMapLayer::writeXml().
1572  */
1573 bool QgsRasterLayer::writeXml( QDomNode &layer_node,
1574  QDomDocument &document,
1575  const QgsReadWriteContext &context ) const
1576 {
1577  // first get the layer element so that we can append the type attribute
1578 
1579  QDomElement mapLayerNode = layer_node.toElement();
1580 
1581  if ( mapLayerNode.isNull() || "maplayer" != mapLayerNode.nodeName() )
1582  {
1583  QgsMessageLog::logMessage( tr( "<maplayer> not found." ), tr( "Raster" ) );
1584  return false;
1585  }
1586 
1587  mapLayerNode.setAttribute( QStringLiteral( "type" ), QStringLiteral( "raster" ) );
1588 
1589  // add provider node
1590 
1591  QDomElement provider = document.createElement( QStringLiteral( "provider" ) );
1592  QDomText providerText = document.createTextNode( mProviderKey );
1593  provider.appendChild( providerText );
1594  layer_node.appendChild( provider );
1595 
1596  // User no data
1597  QDomElement noData = document.createElement( QStringLiteral( "noData" ) );
1598 
1599  for ( int bandNo = 1; bandNo <= mDataProvider->bandCount(); bandNo++ )
1600  {
1601  QDomElement noDataRangeList = document.createElement( QStringLiteral( "noDataList" ) );
1602  noDataRangeList.setAttribute( QStringLiteral( "bandNo" ), bandNo );
1603  noDataRangeList.setAttribute( QStringLiteral( "useSrcNoData" ), mDataProvider->useSourceNoDataValue( bandNo ) );
1604 
1605  Q_FOREACH ( QgsRasterRange range, mDataProvider->userNoDataValues( bandNo ) )
1606  {
1607  QDomElement noDataRange = document.createElement( QStringLiteral( "noDataRange" ) );
1608 
1609  noDataRange.setAttribute( QStringLiteral( "min" ), QgsRasterBlock::printValue( range.min() ) );
1610  noDataRange.setAttribute( QStringLiteral( "max" ), QgsRasterBlock::printValue( range.max() ) );
1611  noDataRangeList.appendChild( noDataRange );
1612  }
1613 
1614  noData.appendChild( noDataRangeList );
1615 
1616  }
1617  if ( noData.hasChildNodes() )
1618  {
1619  layer_node.appendChild( noData );
1620  }
1621 
1622  writeStyleManager( layer_node, document );
1623 
1624  //write out the symbology
1625  QString errorMsg;
1626  return writeSymbology( layer_node, document, errorMsg, context );
1627 }
1628 
1630 {
1631  if ( !mDataProvider ) return 0;
1632  return mDataProvider->xSize();
1633 }
1634 
1636 {
1637  if ( !mDataProvider ) return 0;
1638  return mDataProvider->ySize();
1639 }
1640 
1642 //
1643 // Private methods
1644 //
1646 bool QgsRasterLayer::update()
1647 {
1648  QgsDebugMsgLevel( "entered.", 4 );
1649  // Check if data changed
1650  if ( mDataProvider->dataTimestamp() > mDataProvider->timestamp() )
1651  {
1652  QgsDebugMsgLevel( "reload data", 4 );
1653  closeDataProvider();
1654  init();
1655  setDataProvider( mProviderKey );
1656  emit dataChanged();
1657  }
1658  return mValid;
1659 }
virtual QgsRectangle extent() const override=0
Returns the extent of the layer.
QgsDataProvider * classFactoryFunction_t(const QString *)
static void convertRasterProperties(QDomDocument &doc, QDomNode &parentNode, QDomElement &rasterPropertiesElem, QgsRasterLayer *rlayer)
int width() const
Accessor that returns the width of the (unclipped) raster.
QgsRasterMinMaxOrigin::Limits limits() const
Return limits.
virtual int bandCount() const =0
Get number of bands.
QgsRasterMinMaxOrigin::Extent extent() const
Return 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:56
A rectangle specified with double values.
Definition: qgsrectangle.h:38
Base class for all map layer types.
Definition: qgsmaplayer.h:54
Thirty two bit signed integer (qint32)
Definition: qgis.h:81
Interface for all raster shaders.
virtual QDateTime timestamp() const override
Time stamp of data source in the moment when data/metadata were loaded by provider.
void setColorRampItemList(const QList< QgsColorRampShader::ColorRampItem > &list)
Set custom colormap.
virtual QgsRasterLayer * clone() const override
Returns a new instance equivalent to this one.
virtual QStringList subLayers() const override
Returns the sublayers of this layer - Useful for providers that manage their own layers, such as WMS.
static QString printValue(double value)
Print double value with all necessary significant digits.
void refreshContrastEnhancement(const QgsRectangle &extent)
Refresh contrast enhancement with new extent.
virtual void setUseSourceNoDataValue(int bandNo, bool use)
Set source nodata value usage.
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
Get the number of bands in this layer.
This class is a composition of two QSettings instances:
Definition: qgssettings.h:54
QgsHueSaturationFilter * hueSaturationFilter() const
DrawingStyle
This enumerator describes the different kinds of drawing we can do.
Definition: qgsraster.h:88
A ramp shader will color a raster pixel based on a list of values ranges in a ramp.
virtual QList< QgsColorRampShader::ColorRampItem > colorTable(int bandNo) const
virtual QgsError error() const
Get current status error.
QgsRasterRenderer * renderer() const
void setRenderer(QgsRasterRenderer *renderer)
Set raster renderer. Takes ownership of the renderer object.
#define QgsDebugMsg(str)
Definition: qgslogger.h:37
virtual QgsError error() const
Get current status error.
This class provides qgis with the ability to render raster datasets onto the mapcanvas.
virtual void setLayerOrder(const QStringList &layers) override
Reorders the previously selected sublayers of this layer from bottom to top.
double rasterUnitsPerPixelX() const
Returns the number of raster units per each raster pixel in X axis. In a world file, this is normally the first row (without the sign)
QString accessSectionHtml() const
Formats the "Access" section according to a metadata object.
void willBeDeleted()
Emitted in the destructor when the layer is about to be deleted, but it is still in a perfectly valid...
QgsRasterPipe * pipe()
Get raster pipe.
bool writeXml(QDomNode &layer_node, QDomDocument &doc, const QgsReadWriteContext &context) const override
Write layer specific state to project file Dom node.
A class to represent a 2D point.
Definition: qgspointxy.h:42
void setDefaultContrastEnhancement()
Set default contrast enhancement.
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:80
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:66
DataType
Raster data types.
Definition: qgis.h:74
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
QgsDataProvider * createProvider(const QString &providerKey, const QString &dataSource)
Creates a new instance of a provider.
virtual int ySize() const
int mWidth
Width, number of columns to be rendered.
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. In a world file, this is normally the first row (without the sign)
static QDateTime lastModified(const QString &name)
Return time stamp for given file name.
double max() const
static QPainter::CompositionMode getCompositionMode(QgsPainting::BlendMode blendMode)
Returns a QPainter::CompositionMode corresponding to a BlendMode.
Definition: qgspainting.cpp:6
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
Accessor that returns the height of the (unclipped) raster.
static const double SAMPLE_SIZE
Default sample size (number of pixels) for estimated statistics/histogram calculation.
Thirty two bit floating point (float)
Definition: qgis.h:82
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)
Get an 100x100 pixmap of the color palette. If the layer has no palette a white pixmap will be return...
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:79
virtual QDateTime timestamp() const override
Time stamp of data source in the moment when data/metadata were loaded by provider.
Complex Int16.
Definition: qgis.h:84
QString mLayerName
Name of the layer - used for display.
Definition: qgsmaplayer.h:1029
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:83
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)
Set extent.
QgsCoordinateReferenceSystem mDestCRS
Target coordinate system.
QgsBrightnessContrastFilter * brightnessFilter() const
void setCrs(const QgsCoordinateReferenceSystem &srcCRS, const QgsCoordinateReferenceSystem &destCRS, int srcDatumTransform=-1, int destDatumTransform=-1)
set source and destination CRS
void statusChanged(const QString &status)
Emit a signal with status (e.g. to be caught by QgisApp and display a msg on status bar) ...
double cumulativeCutLower() const
Return lower bound of cumulative cut method (between 0 and 1).
virtual Qgis::DataType sourceDataType(int bandNo) const override=0
Returns source data type for the band specified by number, source data type may be shorter than dataT...
Color, alpha, red, green, blue, 4 bytes the same as QImage::Format_ARGB32_Premultiplied.
Definition: qgis.h:89
Perform transforms between map coordinates and device coordinates.
Definition: qgsmaptopixel.h:35
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:38
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)
Set the color ramp type.
Alpha (0=transparent, 255=opaque)
Definition: qgsraster.h:42
QgsRasterDataProvider * dataProvider() override
This class describes the origin of min/max values.
The RasterBandStats struct is a container for statistics about a single raster band.
static 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.
virtual Qgis::DataType dataType(int bandNo) const override=0
Returns data type for the band specified by number.
Continuous palette, QGIS addition, GRASS.
Definition: qgsraster.h:53
void readStyleManager(const QDomNode &layerNode)
Read style manager&#39;s configuration (if any). To be called by subclasses.
void setRedContrastEnhancement(QgsContrastEnhancement *ce)
Takes ownership.
QString originalName() const
Returns the original name of the layer.
#define QgsDebugMsgLevel(str, level)
Definition: qgslogger.h:38
bool isEmpty() const
Returns true if the rectangle is empty.
void setCrs(const QgsCoordinateReferenceSystem &srs, bool emitSignal=true)
Sets layer&#39;s spatial reference system.
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.
virtual bool isValid() const =0
Returns true if this is a valid layer.
virtual QgsCoordinateReferenceSystem crs() const =0
Returns the coordinate system for the data source.
virtual QStringList subLayers() const override
Returns the sublayers of this layer - useful for providers that manage their own layers, such as WMS.
static const QgsContrastEnhancement::ContrastEnhancementAlgorithm SINGLE_BAND_ENHANCEMENT_ALGORITHM
Default enhancement algorithm for single band raster.
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:123
QgsRasterShaderFunction * rasterShaderFunction()
virtual void setExtent(const QgsRectangle &rect)
Set the extent.
QString extentSectionHtml() const
Formats the "Extents" section according to a metadata object.
Complex Float32.
Definition: qgis.h:86
virtual QString dataSourceUri(bool expandAuthConfig=false) const
Get the data source specification.
double cumulativeCutUpper() const
Return upper bound of cumulative cut method (between 0 and 1).
QString bandName(int bandNoInt) const
Get the name of a band given its number.
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)
Return a string to serialize ContrastEnhancementAlgorithm.
QgsCoordinateReferenceSystem crs() const
Returns the layer&#39;s spatial reference system.
bool defaultContrastEnhancementSettings(QgsContrastEnhancement::ContrastEnhancementAlgorithm &myAlgorithm, QgsRasterMinMaxOrigin::Limits &myLimits) const
Return default contrast enhancemnt settings for that type of raster.
void draw(QPainter *theQPainter, QgsRasterViewPort *myRasterViewPort, const QgsMapToPixel *qgsMapToPixel=nullptr)
This is an overloaded version of the draw() function that is called by both draw() and thumbnailAsPix...
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:85
static int typeSize(int dataType)
void setParam(const QString &key, const QString &value)
Set generic param (generic mode)
virtual QgsMapLayerRenderer * createMapRenderer(QgsRenderContext &rendererContext) override
Return new instance of QgsMapLayerRenderer that will be used for rendering of given context...
Sixteen bit unsigned integer (quint16)
Definition: qgis.h:78
virtual void setLayerOrder(const QStringList &layers)
Reorder the list of layer names to be rendered by this provider (in order from bottom to top) ...
void rendererChanged()
Signal emitted when renderer is changed.
void setAlphaBand(int band)
bool mValid
Indicates if the layer is valid and can be drawn.
Definition: qgsmaplayer.h:1023
#define cast_to_fptr(f)
Definition: qgis.h:136
void setName(const QString &name)
Set the display name of the layer.
void setDataProvider(const QString &provider)
[ data provider interface ] Set the data provider
Range is [ min + cumulativeCutLower() * (max - min), min + cumulativeCutUpper() * (max - min) ]...
Base class for processing filters like renderers, reprojector, resampler etc.
static const QgsRasterMinMaxOrigin::Limits SINGLE_BAND_MIN_MAX_LIMITS
Default enhancement limits for single band raster.
static QString limitsString(Limits limits)
Return a string to serialize Limits.
virtual void setSubLayerVisibility(const QString &name, bool vis) override
Set the visibility of the given sublayer name.
bool shade(double value, int *returnRedValue, int *returnGreenValue, int *returnBlueValue, int *returnAlphaValue) override
Generates and new RGB value based on one input value.
int size() const
static ContrastEnhancementAlgorithm contrastEnhancementAlgorithmFromString(const QString &contrastEnhancementString)
Deserialize ContrastEnhancementAlgorithm.
void repaintRequested(bool deferredUpdate=false)
By emitting this signal the layer tells that either appearance or content have been changed and any v...
void setMinMaxOrigin(const QgsRasterMinMaxOrigin &origin)
Sets origin of min/max values.
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)
Set 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)
Get band statistics.
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.
static void logMessage(const QString &message, const QString &tag=QString(), MessageLevel level=QgsMessageLog::WARNING)
add a message to the instance (and create it if necessary)
ContrastEnhancementAlgorithm
This enumerator describes the types of contrast enhancement algorithms that can be used...
virtual QString loadDefaultStyle(bool &resultFlag)
Retrieve the default style for this layer if one exists (either as a .qml file on disk or as a record...
Contains information about the context of a rendering operation.
QString name() const
Returns the display name of the layer.
bool writeStyle(QDomNode &node, QDomDocument &doc, QString &errorMessage, const QgsReadWriteContext &context) const override
Write the style for the layer into the docment provided.
static QgsMapLayerLegend * defaultRasterLegend(QgsRasterLayer *rl)
Create new legend implementation for raster layer.
const QgsContrastEnhancement * redContrastEnhancement() const
const QgsContrastEnhancement * greenContrastEnhancement() const
void classifyColorRamp(const int classes=0, const int band=-1, const QgsRectangle &extent=QgsRectangle(), QgsRasterInterface *input=nullptr)
Classify color ramp shader.
QgsRasterResampleFilter * resampleFilter() const
Set raster resample filter. Takes ownership of the resample filter object.
bool remove(int idx)
Remove and delete interface at given index if possible.
QList< QgsRasterRange > QgsRasterRangeList
QString mDataSource
Data source description string, varies by layer type.
Definition: qgsmaplayer.h:1026
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.
QVariant value(const QString &key, const QVariant &defaultValue=QVariant(), const Section section=NoSection) const
Returns the value for setting key.
virtual void reloadData()
Reloads the data from the source.
QByteArray encodedUri() const
return complete encoded uri (generic mode)
int mHeight
Distance in map units from bottom edge to top edge for the part of the raster that is to be rendered...
Brightness/contrast filter pipe for rasters.
This class represents a coordinate reference system (CRS).
Color and saturation filter pipe for rasters.
void setBlueContrastEnhancement(QgsContrastEnhancement *ce)
Takes ownership.
ContrastEnhancementAlgorithm contrastEnhancementAlgorithm() const
Greyscale.
Definition: qgsraster.h:37
bool isvalidrasterfilename_t(QString const &fileNameQString, QString &retErrMsg)
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:1015
virtual QgsRasterRangeList userNoDataValues(int bandNo) const
Get list of user no data value ranges.
Base class for utility classes that encapsulate information necessary for rendering of map layers...
bool readXml(const QDomNode &layer_node, const QgsReadWriteContext &context) override
Reads layer specific state from project file Dom node.
Interpolates the color between two class breaks linearly.
Manipulates raster pixel values so that they enhanceContrast or clip into a specified numerical range...
void readXml(const QDomElement &filterElem) override
Sets base class members from xml. Usually called from create() methods of subclasses.
bool readSymbology(const QDomNode &node, QString &errorMessage, const QgsReadWriteContext &context) override
Read the symbology for the current layer from the Dom node supplied.
void refreshRendererIfNeeded(QgsRasterRenderer *rasterRenderer, const QgsRectangle &extent)
Refresh renderer with new extent, if needed.
This class provides details of the viewable area that a raster will be rendered into.
virtual bool useSourceNoDataValue(int bandNo) const
Get source nodata value usage.
Assigns the color of the higher class for every pixel between two class breaks.
virtual void legendSymbologyItems(QList< QPair< QString, QColor > > &symbolItems) const
Get symbology items if provided by renderer.
bool readStyle(const QDomNode &node, QString &errorMessage, const QgsReadWriteContext &context) override
Read the style information for the current layer from the Dom node supplied.
double min() const
virtual QString generateBandName(int bandNumber) const
helper function to create zero padded band names
virtual void reload() override
Synchronises with changes in the datasource.
void setLegend(QgsMapLayerLegend *legend)
Assign a legend controller to the map layer.
Class for storing the component parts of a PostgreSQL/RDBMS datasource URI.
virtual void setUserNoDataValue(int bandNo, const QgsRasterRangeList &noData)
Complex Float64.
Definition: qgis.h:87
QgsLegendColorList legendSymbologyItems() const
Returns a list with classification items (Text and color)
void readXml(const QDomElement &filterElem) override
Sets base class members from xml. Usually called from create() methods of subclasses.
double stdDevFactor() const
Return factor f so that the min/max range is [ mean - f * stddev , mean + f * stddev ]...
virtual int xSize() const
Get raster size.
static QgsRasterRendererRegistry * rasterRendererRegistry()
Returns the application&#39;s raster renderer registry, used for managing raster layer renderers...
Raster renderer pipe that applies colors to a raster.
QgsRasterRendererCreateFunc rendererCreateFunction
static const QgsContrastEnhancement::ContrastEnhancementAlgorithm MULTIPLE_BAND_SINGLE_BYTE_ENHANCEMENT_ALGORITHM
Default enhancement algorithm for multiple band raster of type Byte.
void setError(const QgsError &error)
Set error message.
Definition: qgsmaplayer.h:1017
QString authid() const
Returns the authority identifier for the CRS.
Eight bit unsigned integer (quint8)
Definition: qgis.h:77
static const QgsRasterMinMaxOrigin::Limits MULTIPLE_BAND_MULTI_BYTE_MIN_MAX_LIMITS
Default enhancement limits for multiple band raster of type different from Byte.
int band() const
Returns the band used by the renderer.
virtual QDateTime dataTimestamp() const override
Current time stamp of data source.
Color, alpha, red, green, blue, 4 bytes the same as QImage::Format_ARGB32.
Definition: qgis.h:88
QPainter::CompositionMode blendMode() const
Returns the current blending mode for a layer.
double height() const
Returns the height of the rectangle.
Definition: qgsrectangle.h:130
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.