QGIS API Documentation  2.99.0-Master (9f5e33a)
qgsrasterlayer.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  qgsrasterlayer.cpp - description
3  -------------------
4 begin : Sat Jun 22 2002
5 copyright : (C) 2003 by Tim Sutton, Steve Halasz and Gary E.Sherman
6 email : tim at linfiniti.com
7  ***************************************************************************/
8 
9 /***************************************************************************
10  * *
11  * This program is free software; you can redistribute it and/or modify *
12  * it under the terms of the GNU General Public License as published by *
13  * the Free Software Foundation; either version 2 of the License, or *
14  * (at your option) any later version. *
15  * *
16  ***************************************************************************/
17 #include "qgsapplication.h"
19 #include "qgscolorrampshader.h"
21 #include "qgscoordinatetransform.h"
22 #include "qgsdatasourceuri.h"
23 #include "qgshuesaturationfilter.h"
24 #include "qgslogger.h"
25 #include "qgsmaplayerlegend.h"
26 #include "qgsmaptopixel.h"
27 #include "qgsmessagelog.h"
29 #include "qgspainting.h"
32 #include "qgsproviderregistry.h"
33 #include "qgsrasterdataprovider.h"
34 #include "qgsrasterdrawer.h"
35 #include "qgsrasteriterator.h"
36 #include "qgsrasterlayer.h"
37 #include "qgsrasterlayerrenderer.h"
38 #include "qgsrasterprojector.h"
39 #include "qgsrasterrange.h"
42 #include "qgsrastershader.h"
43 #include "qgsrectangle.h"
44 #include "qgsrendercontext.h"
48 #include "qgssettings.h"
49 
50 #include <cmath>
51 #include <cstdio>
52 #include <limits>
53 #include <typeinfo>
54 
55 #include <QApplication>
56 #include <QCursor>
57 #include <QDomElement>
58 #include <QDomNode>
59 #include <QFile>
60 #include <QFileInfo>
61 #include <QFont>
62 #include <QFontMetrics>
63 #include <QFrame>
64 #include <QImage>
65 #include <QLabel>
66 #include <QLibrary>
67 #include <QList>
68 #include <QMatrix>
69 #include <QMessageBox>
70 #include <QPainter>
71 #include <QPixmap>
72 #include <QRegExp>
73 #include <QSlider>
74 #include <QTime>
75 
76 // typedefs for provider plugin functions of interest
77 typedef bool isvalidrasterfilename_t( QString const &fileNameQString, QString &retErrMsg );
78 
79 #define ERR(message) QGS_ERROR_MESSAGE(message,"Raster layer")
80 
81 const double QgsRasterLayer::SAMPLE_SIZE = 250000;
82 
89 
96 
98  : QgsMapLayer( RasterLayer )
99  , QSTRING_NOT_SET( QStringLiteral( "Not Set" ) )
100  , TRSTRING_NOT_SET( tr( "Not Set" ) )
101  , mDataProvider( nullptr )
102 {
103  init();
104  mValid = false;
105 }
106 
107 QgsRasterLayer::QgsRasterLayer( const QString &uri,
108  const QString &baseName,
109  const QString &providerKey,
110  bool loadDefaultStyleFlag )
111  : QgsMapLayer( RasterLayer, baseName, uri )
112  // Constant that signals property not used.
113  , QSTRING_NOT_SET( QStringLiteral( "Not Set" ) )
114  , TRSTRING_NOT_SET( tr( "Not Set" ) )
115  , mDataProvider( nullptr )
116  , mProviderKey( providerKey )
117 {
118  QgsDebugMsgLevel( "Entered", 4 );
119  init();
120  setDataProvider( providerKey );
121  if ( !mValid ) return;
122 
123  // load default style
124  bool defaultLoadedFlag = false;
125  if ( mValid && loadDefaultStyleFlag )
126  {
127  loadDefaultStyle( defaultLoadedFlag );
128  }
129  if ( !defaultLoadedFlag )
130  {
132  }
133 
134  // TODO: Connect signals from the dataprovider to the qgisapp
135 
136  emit statusChanged( tr( "QgsRasterLayer created" ) );
137 } // QgsRasterLayer ctor
138 
140 {
141  emit willBeDeleted();
142 
143  mValid = false;
144  // Note: provider and other interfaces are owned and deleted by pipe
145 }
146 
148 {
149  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  QString myMetadata = QStringLiteral( "<html>\n<body>\n" );
308 
309  // Identification section
310  myMetadata += QLatin1String( "<h1>" ) % tr( "Identification" ) % QLatin1String( "</h1>\n<hr>\n<table class=\"list-view\">\n" );
311 
312  // ID
313  myMetadata += QLatin1String( "<tr><td class=\"highlight\">" ) % tr( "ID" ) % QLatin1String( "</td><td>" ) % id() % QLatin1String( "</td></tr>\n" );
314 
315  // original name
316  myMetadata += QLatin1String( "<tr><td class=\"highlight\">" ) % tr( "Original" ) % QLatin1String( "</td><td>" ) % originalName() % QLatin1String( "</td></tr>\n" );
317 
318  // name
319  myMetadata += QLatin1String( "<tr><td class=\"highlight\">" ) % tr( "Name" ) % QLatin1String( "</td><td>" ) % name() % QLatin1String( "</td></tr>\n" );
320 
321  // short
322  myMetadata += QLatin1String( "<tr><td class=\"highlight\">" ) % tr( "Short" ) % QLatin1String( "</td><td>" ) % shortName() % QLatin1String( "</td></tr>\n" );
323 
324  // title
325  myMetadata += QLatin1String( "<tr><td class=\"highlight\">" ) % tr( "Title" ) % QLatin1String( "</td><td>" ) % title() % QLatin1String( "</td></tr>\n" );
326 
327  // abstract
328  myMetadata += QLatin1String( "<tr><td class=\"highlight\">" ) % tr( "Abstract" ) % QLatin1String( "</td><td>" ) % abstract() % QLatin1String( "</td></tr>\n" );
329 
330  // keywords
331  myMetadata += QLatin1String( "<tr><td class=\"highlight\">" ) % tr( "Keywords" ) % QLatin1String( "</td><td>" ) % keywordList() % QLatin1String( "</td></tr>\n" );
332 
333  // lang, waiting for the proper metadata implementation QEP #91 Work package 2
334  // myMetadata += QLatin1String( "<tr><td class=\"highlight\">" ) % tr( "Language" ) % QLatin1String( "</td><td>en-CA</td></tr>\n" );
335 
336  // comment, not existing for rasters for now
337  // myMetadata += QLatin1String( "<tr><td class=\"highlight\">" ) % tr( "Comment" ) % QLatin1String( "</td><td>" ) % dataComment() % QLatin1String( "</td></tr>\n" );
338 
339  // date, waiting for the proper metadata implementation QEP #91 Work package 2
340  // myMetadata += QLatin1String( "<tr><td class=\"highlight\">" ) % tr( "Date" ) % QLatin1String( "</td><td>28/03/17</td></tr>\n" );
341 
342  // storage type
343  myMetadata += QLatin1String( "<tr><td class=\"highlight\">" ) % tr( "Provider" ) % QLatin1String( "</td><td>" ) % providerType() % QLatin1String( "</td></tr>\n" );
344 
345  // data source
346  myMetadata += QLatin1String( "<tr><td class=\"highlight\">" ) % tr( "Source" ) % QLatin1String( "</td><td>" ) % publicSource() % QLatin1String( "</td></tr>\n" );
347 
348  // Section spatial
349  myMetadata += QLatin1String( "</table>\n<br><br><h1>" ) % tr( "Spatial" ) % QLatin1String( "</h1>\n<hr>\n<table class=\"list-view\">\n" );
350 
351  // EPSG
352  myMetadata += QLatin1String( "<tr><td class=\"highlight\">" ) % tr( "CRS" ) % QLatin1String( "</td><td>" ) % crs().authid() % QLatin1String( " - " );
353  myMetadata += crs().description() % QLatin1String( " - " );
354  if ( crs().isGeographic() )
355  myMetadata += tr( "Geographic" );
356  else
357  myMetadata += tr( "Projected" );
358  myMetadata += QLatin1String( "</td></tr>\n" );
359 
360  // Extent
361  myMetadata += QLatin1String( "<tr><td class=\"highlight\">" ) % tr( "Extent" ) % QLatin1String( "</td><td>" ) % extent().toString() % QLatin1String( "</td></tr>\n" );
362 
363  // unit
364  myMetadata += QLatin1String( "<tr><td class=\"highlight\">" ) % tr( "Unit" ) % QLatin1String( "</td><td>" ) % QgsUnitTypes::toString( crs().mapUnits() ) % QLatin1String( "</td></tr>\n" );
365 
366  // Raster Width
367  myMetadata += QLatin1String( "<tr><td class=\"highlight\">" ) % tr( "Width" ) % QLatin1String( "</td><td>" );
368  if ( dataProvider()->capabilities() & QgsRasterDataProvider::Size )
369  myMetadata += QString::number( width() );
370  else
371  myMetadata += tr( "n/a" );
372  myMetadata += QLatin1String( "</td></tr>\n" );
373 
374  // Raster height
375  myMetadata += QLatin1String( "<tr><td class=\"highlight\">" ) % tr( "Height" ) % QLatin1String( "</td><td>" );
376  if ( dataProvider()->capabilities() & QgsRasterDataProvider::Size )
377  myMetadata += QString::number( height() );
378  else
379  myMetadata += tr( "n/a" );
380  myMetadata += QLatin1String( "</td></tr>\n" );
381 
382  // Data type
383  myMetadata += QLatin1String( "<tr><td class=\"highlight\">" ) % tr( "Data type" ) % QLatin1String( "</td><td>" );
384  // Just use the first band
385  switch ( mDataProvider->sourceDataType( 1 ) )
386  {
387  case Qgis::Byte:
388  myMetadata += tr( "Byte - Eight bit unsigned integer" );
389  break;
390  case Qgis::UInt16:
391  myMetadata += tr( "UInt16 - Sixteen bit unsigned integer " );
392  break;
393  case Qgis::Int16:
394  myMetadata += tr( "Int16 - Sixteen bit signed integer " );
395  break;
396  case Qgis::UInt32:
397  myMetadata += tr( "UInt32 - Thirty two bit unsigned integer " );
398  break;
399  case Qgis::Int32:
400  myMetadata += tr( "Int32 - Thirty two bit signed integer " );
401  break;
402  case Qgis::Float32:
403  myMetadata += tr( "Float32 - Thirty two bit floating point " );
404  break;
405  case Qgis::Float64:
406  myMetadata += tr( "Float64 - Sixty four bit floating point " );
407  break;
408  case Qgis::CInt16:
409  myMetadata += tr( "CInt16 - Complex Int16 " );
410  break;
411  case Qgis::CInt32:
412  myMetadata += tr( "CInt32 - Complex Int32 " );
413  break;
414  case Qgis::CFloat32:
415  myMetadata += tr( "CFloat32 - Complex Float32 " );
416  break;
417  case Qgis::CFloat64:
418  myMetadata += tr( "CFloat64 - Complex Float64 " );
419  break;
420  default:
421  myMetadata += tr( "Could not determine raster data type." );
422  }
423  myMetadata += QLatin1String( "</td></tr>\n" );
424 
425  // Bands section
426  myMetadata += QLatin1String( "</table>\n<br><br><h1>" ) % tr( "Bands" ) % QLatin1String( "</h1>\n<hr>\n<table class=\"list-view\">\n" );
427 
428  // Band count
429  myMetadata += QLatin1String( "<tr><td class=\"highlight\">" ) % tr( "Band count" ) % QLatin1String( "</td><td>" ) % QString::number( bandCount() ) % QLatin1String( "</td></tr>\n" );
430 
431  // Band table
432  myMetadata += "</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 = QString( "" );
439  if ( i % 2 )
440  rowClass = QString( "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 += "</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 += "</tr>\n";
461  }
462 
463  //close previous bands table and start references
464  myMetadata += QLatin1String( "</table>\n<br><br><h1>" ) % tr( "References" ) % QLatin1String( "</h1>\n<hr>\n<table class=\"list-view\">\n" );
465 
466  // data URL
467  myMetadata += QLatin1String( "<tr><td class=\"highlight\">" ) % tr( "Data URL" ) % QLatin1String( "</td><td>" ) % dataUrl() % QLatin1String( "</td></tr>\n" );
468  myMetadata += QLatin1String( "<tr><td class=\"highlight\">" ) % tr( "Data Format" ) % QLatin1String( "</td><td>" ) % dataUrlFormat() % QLatin1String( "</td></tr>\n" );
469 
470  // attribution
471  myMetadata += QLatin1String( "<tr><td class=\"highlight\">" ) % tr( "Attribution" ) % QLatin1String( "</td><td>" ) % attribution() % QLatin1String( "</td></tr>\n" );
472  myMetadata += QLatin1String( "<tr><td class=\"highlight\">" ) % tr( "Attribution URL" ) % QLatin1String( "</td><td>" ) % attributionUrl() % QLatin1String( "</td></tr>\n" );
473 
474  // metadata URL
475  myMetadata += QLatin1String( "<tr><td class=\"highlight\">" ) % tr( "Metadata URL" ) % QLatin1String( "</td><td>" ) % metadataUrl() % QLatin1String( "</td></tr>\n" );
476  myMetadata += QLatin1String( "<tr><td class=\"highlight\">" ) % tr( "Metadata Type" ) % QLatin1String( "</td><td>" ) % metadataUrlType() % QLatin1String( "</td></tr>\n" );
477  myMetadata += QLatin1String( "<tr><td class=\"highlight\">" ) % tr( "Metadata Format" ) % QLatin1String( "</td><td>" ) % metadataUrlFormat() % QLatin1String( "</td></tr>\n" );
478 
479  // legend URL
480  myMetadata += QLatin1String( "<tr><td class=\"highlight\">" ) % tr( "Legend URL" ) % QLatin1String( "</td><td>" ) % legendUrl() % QLatin1String( "</td></tr>\n" );
481  myMetadata += QLatin1String( "<tr><td class=\"highlight\">" ) % tr( "Legend Format" ) % QLatin1String( "</td><td>" ) % legendUrlFormat() % QLatin1String( "</td></tr>\n" );
482 
483  myMetadata += QStringLiteral( "</table>\n</body>\n</html>\n" );
484  return myMetadata;
485 }
486 
487 
492 QPixmap QgsRasterLayer::paletteAsPixmap( int bandNumber )
493 {
494  //TODO: This function should take dimensions
495  QgsDebugMsgLevel( "entered.", 4 );
496 
497  // Only do this for the GDAL provider?
498  // Maybe WMS can do this differently using QImage::numColors and QImage::color()
499  if ( mDataProvider->colorInterpretation( bandNumber ) == QgsRaster::PaletteIndex )
500  {
501  QgsDebugMsgLevel( "....found paletted image", 4 );
502  QgsColorRampShader myShader;
503  QList<QgsColorRampShader::ColorRampItem> myColorRampItemList = mDataProvider->colorTable( bandNumber );
504  if ( !myColorRampItemList.isEmpty() )
505  {
506  QgsDebugMsgLevel( "....got color ramp item list", 4 );
507  myShader.setColorRampItemList( myColorRampItemList );
509  // Draw image
510  int mySize = 100;
511  QPixmap myPalettePixmap( mySize, mySize );
512  QPainter myQPainter( &myPalettePixmap );
513 
514  QImage myQImage = QImage( mySize, mySize, QImage::Format_RGB32 );
515  myQImage.fill( 0 );
516  myPalettePixmap.fill();
517 
518  double myStep = ( static_cast< double >( myColorRampItemList.size() ) - 1 ) / static_cast< double >( mySize * mySize );
519  double myValue = 0.0;
520  for ( int myRow = 0; myRow < mySize; myRow++ )
521  {
522  QRgb *myLineBuffer = reinterpret_cast< QRgb * >( myQImage.scanLine( myRow ) );
523  for ( int myCol = 0; myCol < mySize; myCol++ )
524  {
525  myValue = myStep * static_cast< double >( myCol + myRow * mySize );
526  int c1, c2, c3, c4;
527  myShader.shade( myValue, &c1, &c2, &c3, &c4 );
528  myLineBuffer[ myCol ] = qRgba( c1, c2, c3, c4 );
529  }
530  }
531 
532  myQPainter.drawImage( 0, 0, myQImage );
533  return myPalettePixmap;
534  }
535  QPixmap myNullPixmap;
536  return myNullPixmap;
537  }
538  else
539  {
540  //invalid layer was requested
541  QPixmap myNullPixmap;
542  return myNullPixmap;
543  }
544 }
545 
547 {
548  return mProviderKey;
549 }
550 
555 {
556 // We return one raster pixel per map unit pixel
557 // One raster pixel can have several raster units...
558 
559 // We can only use one of the mGeoTransform[], so go with the
560 // horisontal one.
561 
562  if ( mDataProvider->capabilities() & QgsRasterDataProvider::Size && mDataProvider->xSize() > 0 )
563  {
564  return mDataProvider->extent().width() / mDataProvider->xSize();
565  }
566  return 1;
567 }
568 
570 {
571  if ( mDataProvider->capabilities() & QgsRasterDataProvider::Size && mDataProvider->xSize() > 0 )
572  {
573  return mDataProvider->extent().height() / mDataProvider->ySize();
574  }
575  return 1;
576 }
577 
578 void QgsRasterLayer::init()
579 {
580  mRasterType = QgsRasterLayer::GrayOrUndefined;
581 
583 
584  setRendererForDrawingStyle( QgsRaster::UndefinedDrawingStyle );
585 
586  //Initialize the last view port structure, should really be a class
587  mLastViewPort.mWidth = 0;
588  mLastViewPort.mHeight = 0;
589 }
590 
591 void QgsRasterLayer::setDataProvider( QString const &provider )
592 {
593  QgsDebugMsgLevel( "Entered", 4 );
594  mValid = false; // assume the layer is invalid until we determine otherwise
595 
596  mPipe.remove( mDataProvider ); // deletes if exists
597  mDataProvider = nullptr;
598 
599  // XXX should I check for and possibly delete any pre-existing providers?
600  // XXX How often will that scenario occur?
601 
602  mProviderKey = provider;
603  // set the layer name (uppercase first character)
604  if ( ! mLayerName.isEmpty() ) // XXX shouldn't this happen in parent?
605  {
606  setName( mLayerName );
607  }
608 
609  //mBandCount = 0;
610 
611  mDataProvider = dynamic_cast< QgsRasterDataProvider * >( QgsProviderRegistry::instance()->createProvider( mProviderKey, mDataSource ) );
612  if ( !mDataProvider )
613  {
614  //QgsMessageLog::logMessage( tr( "Cannot instantiate the data provider" ), tr( "Raster" ) );
615  appendError( ERR( tr( "Cannot instantiate the '%1' data provider" ).arg( mProviderKey ) ) );
616  return;
617  }
618  QgsDebugMsgLevel( "Data provider created", 4 );
619 
620  // Set data provider into pipe even if not valid so that it is deleted with pipe (with layer)
621  mPipe.set( mDataProvider );
622  if ( !mDataProvider->isValid() )
623  {
624  setError( mDataProvider->error() );
625  appendError( ERR( tr( "Provider is not valid (provider: %1, URI: %2" ).arg( mProviderKey, mDataSource ) ) );
626  return;
627  }
628 
629  if ( provider == QLatin1String( "gdal" ) )
630  {
631  // make sure that the /vsigzip or /vsizip is added to uri, if applicable
632  mDataSource = mDataProvider->dataSourceUri();
633  }
634 
635  // get the extent
636  QgsRectangle mbr = mDataProvider->extent();
637 
638  // show the extent
639  QgsDebugMsgLevel( "Extent of layer: " + mbr.toString(), 4 );
640  // store the extent
641  setExtent( mbr );
642 
643  // upper case the first letter of the layer name
644  QgsDebugMsgLevel( "mLayerName: " + name(), 4 );
645 
646  // set up the raster drawing style
647  // Do not set any 'sensible' style here, the style is set later
648 
649  // Setup source CRS
650  setCrs( QgsCoordinateReferenceSystem( mDataProvider->crs() ) );
651 
652  QgsDebugMsgLevel( "using wkt:\n" + crs().toWkt(), 4 );
653 
654  //defaults - Needs to be set after the Contrast list has been build
655  //Try to read the default contrast enhancement from the config file
656 
657  //decide what type of layer this is...
658  //TODO Change this to look at the color interp and palette interp to decide which type of layer it is
659  QgsDebugMsgLevel( "bandCount = " + QString::number( mDataProvider->bandCount() ), 4 );
660  QgsDebugMsgLevel( "dataType = " + QString::number( mDataProvider->dataType( 1 ) ), 4 );
661  if ( ( mDataProvider->bandCount() > 1 ) )
662  {
663  // handle singleband gray with alpha
664  if ( mDataProvider->bandCount() == 2
665  && ( ( mDataProvider->colorInterpretation( 1 ) == QgsRaster::GrayIndex
666  && mDataProvider->colorInterpretation( 2 ) == QgsRaster::AlphaBand )
667  || ( mDataProvider->colorInterpretation( 1 ) == QgsRaster::AlphaBand
668  && mDataProvider->colorInterpretation( 2 ) == QgsRaster::GrayIndex ) ) )
669  {
670  mRasterType = GrayOrUndefined;
671  }
672  else
673  {
674  mRasterType = Multiband;
675  }
676  }
677  else if ( mDataProvider->dataType( 1 ) == Qgis::ARGB32
678  || mDataProvider->dataType( 1 ) == Qgis::ARGB32_Premultiplied )
679  {
680  mRasterType = ColorLayer;
681  }
682  else if ( mDataProvider->colorInterpretation( 1 ) == QgsRaster::PaletteIndex )
683  {
684  mRasterType = Palette;
685  }
686  else if ( mDataProvider->colorInterpretation( 1 ) == QgsRaster::ContinuousPalette )
687  {
688  mRasterType = Palette;
689  }
690  else
691  {
692  mRasterType = GrayOrUndefined;
693  }
694 
695  QgsDebugMsgLevel( "mRasterType = " + QString::number( mRasterType ), 4 );
696  if ( mRasterType == ColorLayer )
697  {
698  QgsDebugMsgLevel( "Setting drawing style to SingleBandColorDataStyle " + QString::number( QgsRaster::SingleBandColorDataStyle ), 4 );
699  setRendererForDrawingStyle( QgsRaster::SingleBandColorDataStyle );
700  }
701  else if ( mRasterType == Palette && mDataProvider->colorInterpretation( 1 ) == QgsRaster::PaletteIndex )
702  {
703  setRendererForDrawingStyle( QgsRaster::PalettedColor ); //sensible default
704  }
705  else if ( mRasterType == Palette && mDataProvider->colorInterpretation( 1 ) == QgsRaster::ContinuousPalette )
706  {
707  setRendererForDrawingStyle( QgsRaster::SingleBandPseudoColor );
708  // Load color table
709  QList<QgsColorRampShader::ColorRampItem> colorTable = mDataProvider->colorTable( 1 );
711  if ( r )
712  {
713  // TODO: this should go somewhere else
714  QgsRasterShader *shader = new QgsRasterShader();
715  QgsColorRampShader *colorRampShader = new QgsColorRampShader();
717  colorRampShader->setColorRampItemList( colorTable );
718  shader->setRasterShaderFunction( colorRampShader );
719  r->setShader( shader );
720  }
721  }
722  else if ( mRasterType == Multiband )
723  {
724  setRendererForDrawingStyle( QgsRaster::MultiBandColor ); //sensible default
725  }
726  else //GrayOrUndefined
727  {
728  setRendererForDrawingStyle( QgsRaster::SingleBandGray ); //sensible default
729  }
730 
731  // Auto set alpha band
732  for ( int bandNo = 1; bandNo <= mDataProvider->bandCount(); bandNo++ )
733  {
734  if ( mDataProvider->colorInterpretation( bandNo ) == QgsRaster::AlphaBand )
735  {
736  if ( mPipe.renderer() )
737  {
738  mPipe.renderer()->setAlphaBand( bandNo );
739  }
740  break;
741  }
742  }
743 
744  // brightness filter
746  mPipe.set( brightnessFilter );
747 
748  // hue/saturation filter
750  mPipe.set( hueSaturationFilter );
751 
752  //resampler (must be after renderer)
754  mPipe.set( resampleFilter );
755 
756  // projector (may be anywhere in pipe)
757  QgsRasterProjector *projector = new QgsRasterProjector;
758  mPipe.set( projector );
759 
760  // Set default identify format - use the richest format available
761  int capabilities = mDataProvider->capabilities();
763  if ( capabilities & QgsRasterInterface::IdentifyHtml )
764  {
765  // HTML is usually richest
766  identifyFormat = QgsRaster::IdentifyFormatHtml;
767  }
768  else if ( capabilities & QgsRasterInterface::IdentifyFeature )
769  {
770  identifyFormat = QgsRaster::IdentifyFormatFeature;
771  }
772  else if ( capabilities & QgsRasterInterface::IdentifyText )
773  {
774  identifyFormat = QgsRaster::IdentifyFormatText;
775  }
776  else if ( capabilities & QgsRasterInterface::IdentifyValue )
777  {
778  identifyFormat = QgsRaster::IdentifyFormatValue;
779  }
780  setCustomProperty( QStringLiteral( "identify/format" ), QgsRasterDataProvider::identifyFormatName( identifyFormat ) );
781 
782  // Store timestamp
783  // TODO move to provider
784  mLastModified = lastModified( mDataSource );
785 
786  // Do a passthrough for the status bar text
787  connect( mDataProvider, &QgsRasterDataProvider::statusChanged, this, &QgsRasterLayer::statusChanged );
788 
789  //mark the layer as valid
790  mValid = true;
791 
792  QgsDebugMsgLevel( "exiting.", 4 );
793 } // QgsRasterLayer::setDataProvider
794 
795 void QgsRasterLayer::closeDataProvider()
796 {
797  mValid = false;
798  mPipe.remove( mDataProvider );
799  mDataProvider = nullptr;
800 }
801 
802 void QgsRasterLayer::computeMinMax( int band,
803  const QgsRasterMinMaxOrigin &mmo,
805  const QgsRectangle &extent,
806  int sampleSize,
807  double &min, double &max )
808 {
809 
810  min = std::numeric_limits<double>::quiet_NaN();
811  max = std::numeric_limits<double>::quiet_NaN();
812 
813  if ( limits == QgsRasterMinMaxOrigin::MinMax )
814  {
815  QgsRasterBandStats myRasterBandStats = mDataProvider->bandStatistics( band, QgsRasterBandStats::Min | QgsRasterBandStats::Max, extent, sampleSize );
816  min = myRasterBandStats.minimumValue;
817  max = myRasterBandStats.maximumValue;
818  }
819  else if ( limits == QgsRasterMinMaxOrigin::StdDev )
820  {
821  QgsRasterBandStats myRasterBandStats = mDataProvider->bandStatistics( band, QgsRasterBandStats::Mean | QgsRasterBandStats::StdDev, extent, sampleSize );
822  min = myRasterBandStats.mean - ( mmo.stdDevFactor() * myRasterBandStats.stdDev );
823  max = myRasterBandStats.mean + ( mmo.stdDevFactor() * myRasterBandStats.stdDev );
824  }
825  else if ( limits == QgsRasterMinMaxOrigin::CumulativeCut )
826  {
827  const double myLower = mmo.cumulativeCutLower();
828  const double myUpper = mmo.cumulativeCutUpper();
829  QgsDebugMsgLevel( QString( "myLower = %1 myUpper = %2" ).arg( myLower ).arg( myUpper ), 4 );
830  mDataProvider->cumulativeCut( band, myLower, myUpper, min, max, extent, sampleSize );
831  }
832  QgsDebugMsgLevel( QString( "band = %1 min = %2 max = %3" ).arg( band ).arg( min ).arg( max ), 4 );
833 
834 }
835 
836 
837 void QgsRasterLayer::setContrastEnhancement( QgsContrastEnhancement::ContrastEnhancementAlgorithm algorithm, QgsRasterMinMaxOrigin::Limits limits, const QgsRectangle &extent, int sampleSize, bool generateLookupTableFlag )
838 {
839  setContrastEnhancement( algorithm,
840  limits,
841  extent,
842  sampleSize,
843  generateLookupTableFlag,
844  mPipe.renderer() );
845 }
846 
849  const QgsRectangle &extent,
850  int sampleSize,
851  bool generateLookupTableFlag,
852  QgsRasterRenderer *rasterRenderer )
853 {
854  QgsDebugMsgLevel( QString( "theAlgorithm = %1 limits = %2 extent.isEmpty() = %3" ).arg( algorithm ).arg( limits ).arg( extent.isEmpty() ), 4 );
855  if ( !rasterRenderer || !mDataProvider )
856  {
857  return;
858  }
859 
860  QList<int> myBands;
861  QList<QgsContrastEnhancement *> myEnhancements;
862  QgsRasterMinMaxOrigin myMinMaxOrigin;
863  QgsRasterRenderer *myRasterRenderer = nullptr;
864  QgsSingleBandGrayRenderer *myGrayRenderer = nullptr;
865  QgsSingleBandPseudoColorRenderer *myPseudoColorRenderer = nullptr;
866  QgsMultiBandColorRenderer *myMultiBandRenderer = nullptr;
867  QString rendererType = rasterRenderer->type();
868  if ( rendererType == QLatin1String( "singlebandgray" ) )
869  {
870  myGrayRenderer = dynamic_cast<QgsSingleBandGrayRenderer *>( rasterRenderer );
871  if ( !myGrayRenderer )
872  {
873  return;
874  }
875  myBands << myGrayRenderer->grayBand();
876  myRasterRenderer = myGrayRenderer;
877  myMinMaxOrigin = myGrayRenderer->minMaxOrigin();
878  }
879  else if ( rendererType == QLatin1String( "multibandcolor" ) )
880  {
881  myMultiBandRenderer = dynamic_cast<QgsMultiBandColorRenderer *>( rasterRenderer );
882  if ( !myMultiBandRenderer )
883  {
884  return;
885  }
886  myBands << myMultiBandRenderer->redBand() << myMultiBandRenderer->greenBand() << myMultiBandRenderer->blueBand();
887  myRasterRenderer = myMultiBandRenderer;
888  myMinMaxOrigin = myMultiBandRenderer->minMaxOrigin();
889  }
890  else if ( rendererType == QLatin1String( "singlebandpseudocolor" ) )
891  {
892  myPseudoColorRenderer = dynamic_cast<QgsSingleBandPseudoColorRenderer *>( rasterRenderer );
893  if ( !myPseudoColorRenderer )
894  {
895  return;
896  }
897  myBands << myPseudoColorRenderer->band();
898  myRasterRenderer = myPseudoColorRenderer;
899  myMinMaxOrigin = myPseudoColorRenderer->minMaxOrigin();
900  }
901  else
902  {
903  return;
904  }
905 
906  Q_FOREACH ( int myBand, myBands )
907  {
908  if ( myBand != -1 )
909  {
910  Qgis::DataType myType = static_cast< Qgis::DataType >( mDataProvider->dataType( myBand ) );
911  std::unique_ptr<QgsContrastEnhancement> myEnhancement( new QgsContrastEnhancement( static_cast< Qgis::DataType >( myType ) ) );
912  myEnhancement->setContrastEnhancementAlgorithm( algorithm, generateLookupTableFlag );
913 
914  double min;
915  double max;
916  computeMinMax( myBand, myMinMaxOrigin, limits, extent, sampleSize, min, max );
917 
918  if ( rendererType == QLatin1String( "singlebandpseudocolor" ) )
919  {
920  myPseudoColorRenderer->setClassificationMin( min );
921  myPseudoColorRenderer->setClassificationMax( max );
922  if ( myPseudoColorRenderer->shader() )
923  {
924  QgsColorRampShader *colorRampShader = dynamic_cast<QgsColorRampShader *>( myPseudoColorRenderer->shader()->rasterShaderFunction() );
925  if ( colorRampShader )
926  {
927  colorRampShader->classifyColorRamp( myPseudoColorRenderer->band(), extent, myPseudoColorRenderer->input() );
928  }
929  }
930  }
931  else
932  {
933  myEnhancement->setMinimumValue( min );
934  myEnhancement->setMaximumValue( max );
935  myEnhancements.append( myEnhancement.release() );
936  }
937  }
938  else
939  {
940  myEnhancements.append( nullptr );
941  }
942  }
943 
944  if ( rendererType == QLatin1String( "singlebandgray" ) )
945  {
946  if ( myEnhancements.first() ) myGrayRenderer->setContrastEnhancement( myEnhancements.takeFirst() );
947  }
948  else if ( rendererType == QLatin1String( "multibandcolor" ) )
949  {
950  if ( myEnhancements.first() ) myMultiBandRenderer->setRedContrastEnhancement( myEnhancements.takeFirst() );
951  if ( myEnhancements.first() ) myMultiBandRenderer->setGreenContrastEnhancement( myEnhancements.takeFirst() );
952  if ( myEnhancements.first() ) myMultiBandRenderer->setBlueContrastEnhancement( myEnhancements.takeFirst() );
953  }
954 
955  //delete all remaining unused enhancements
956  qDeleteAll( myEnhancements );
957 
958  myMinMaxOrigin.setLimits( limits );
959  if ( extent != QgsRectangle() &&
960  myMinMaxOrigin.extent() == QgsRasterMinMaxOrigin::WholeRaster )
961  {
963  }
964  if ( myRasterRenderer )
965  {
966  myRasterRenderer->setMinMaxOrigin( myMinMaxOrigin );
967  }
968 
969  if ( rasterRenderer == renderer() )
970  {
971  emit repaintRequested();
972  emit styleChanged();
973  emit rendererChanged();
974  }
975 }
976 
978 {
979  QgsSingleBandGrayRenderer *singleBandRenderer = nullptr;
980  QgsMultiBandColorRenderer *multiBandRenderer = nullptr;
981  const QgsContrastEnhancement *ce = nullptr;
982  if ( ( singleBandRenderer = dynamic_cast<QgsSingleBandGrayRenderer *>( renderer() ) ) )
983  {
984  ce = singleBandRenderer->contrastEnhancement();
985  }
986  else if ( ( multiBandRenderer = dynamic_cast<QgsMultiBandColorRenderer *>( renderer() ) ) )
987  {
988  ce = multiBandRenderer->redContrastEnhancement();
989  }
990 
991  if ( ce )
992  {
997  extent,
998  SAMPLE_SIZE,
999  true,
1000  renderer() );
1001  }
1002  else
1003  {
1006  if ( defaultContrastEnhancementSettings( myAlgorithm, myLimits ) )
1007  {
1009  myLimits,
1010  extent,
1011  SAMPLE_SIZE,
1012  true,
1013  renderer() );
1014  }
1015  }
1016 }
1017 
1019  const QgsRectangle &extent )
1020 {
1021  if ( !( mDataProvider &&
1022  mLastRectangleUsedByRefreshContrastEnhancementIfNeeded != extent &&
1023  rasterRenderer->minMaxOrigin().limits() != QgsRasterMinMaxOrigin::None &&
1024  rasterRenderer->minMaxOrigin().extent() == QgsRasterMinMaxOrigin::UpdatedCanvas ) )
1025  return;
1026 
1027  QgsSingleBandGrayRenderer *singleBandRenderer = nullptr;
1028  QgsMultiBandColorRenderer *multiBandRenderer = nullptr;
1029  QgsSingleBandPseudoColorRenderer *sbpcr = nullptr;
1030  const QgsContrastEnhancement *ce = nullptr;
1031  if ( ( singleBandRenderer = dynamic_cast<QgsSingleBandGrayRenderer *>( rasterRenderer ) ) )
1032  {
1033  ce = singleBandRenderer->contrastEnhancement();
1034  }
1035  else if ( ( multiBandRenderer = dynamic_cast<QgsMultiBandColorRenderer *>( rasterRenderer ) ) )
1036  {
1037  ce = multiBandRenderer->redContrastEnhancement();
1038  }
1039  else if ( ( sbpcr = dynamic_cast<QgsSingleBandPseudoColorRenderer *>( rasterRenderer ) ) )
1040  {
1041  mLastRectangleUsedByRefreshContrastEnhancementIfNeeded = extent;
1042  double min;
1043  double max;
1044  computeMinMax( sbpcr->band(),
1045  rasterRenderer->minMaxOrigin(),
1046  rasterRenderer->minMaxOrigin().limits(), extent,
1047  SAMPLE_SIZE, min, max );
1048  sbpcr->setClassificationMin( min );
1049  sbpcr->setClassificationMax( max );
1050 
1051  if ( sbpcr->shader() )
1052  {
1053  QgsColorRampShader *colorRampShader = dynamic_cast<QgsColorRampShader *>( sbpcr->shader()->rasterShaderFunction() );
1054  if ( colorRampShader )
1055  {
1056  colorRampShader->classifyColorRamp( sbpcr->band(), extent, rasterRenderer->input() );
1057  }
1058  }
1059 
1061  r->setClassificationMin( min );
1062  r->setClassificationMax( max );
1063 
1064  if ( r->shader() )
1065  {
1066  QgsColorRampShader *colorRampShader = dynamic_cast<QgsColorRampShader *>( r->shader()->rasterShaderFunction() );
1067  if ( colorRampShader )
1068  {
1069  colorRampShader->classifyColorRamp( sbpcr->band(), extent, rasterRenderer->input() );
1070  }
1071  }
1072 
1073  emit repaintRequested();
1074  emit styleChanged();
1075  emit rendererChanged();
1076  return;
1077  }
1078 
1079  if ( ce &&
1081  {
1082  mLastRectangleUsedByRefreshContrastEnhancementIfNeeded = extent;
1083 
1085  rasterRenderer->minMaxOrigin().limits(),
1086  extent,
1087  SAMPLE_SIZE,
1088  true,
1089  rasterRenderer );
1090 
1091  // Update main renderer so that the legends get updated
1092  if ( singleBandRenderer )
1093  static_cast<QgsSingleBandGrayRenderer *>( renderer() )->setContrastEnhancement( new QgsContrastEnhancement( * singleBandRenderer->contrastEnhancement() ) );
1094  else if ( multiBandRenderer )
1095  {
1096  if ( multiBandRenderer->redContrastEnhancement() )
1097  {
1098  static_cast<QgsMultiBandColorRenderer *>( renderer() )->setRedContrastEnhancement( new QgsContrastEnhancement( *multiBandRenderer->redContrastEnhancement() ) );
1099  }
1100  if ( multiBandRenderer->greenContrastEnhancement() )
1101  {
1102  static_cast<QgsMultiBandColorRenderer *>( renderer() )->setGreenContrastEnhancement( new QgsContrastEnhancement( *multiBandRenderer->greenContrastEnhancement() ) );
1103  }
1104  if ( multiBandRenderer->blueContrastEnhancement() )
1105  {
1106  static_cast<QgsMultiBandColorRenderer *>( renderer() )->setBlueContrastEnhancement( new QgsContrastEnhancement( *multiBandRenderer->blueContrastEnhancement() ) );
1107  }
1108  }
1109 
1110  emit styleChanged();
1111  emit rendererChanged();
1112  }
1113 }
1114 
1117  QgsRasterMinMaxOrigin::Limits &myLimits ) const
1118 {
1119  QgsSettings mySettings;
1120 
1121  QString key;
1122  QString defaultAlg;
1123  QString defaultLimits;
1124 
1125  // TODO: we should not test renderer class here, move it somehow to renderers
1126  if ( dynamic_cast<QgsSingleBandGrayRenderer *>( renderer() ) )
1127  {
1128  key = QStringLiteral( "singleBand" );
1131  defaultLimits = QgsRasterMinMaxOrigin::limitsString(
1133  }
1134  else if ( dynamic_cast<QgsMultiBandColorRenderer *>( renderer() ) )
1135  {
1136  if ( QgsRasterBlock::typeSize( dataProvider()->sourceDataType( 1 ) ) == 1 )
1137  {
1138  key = QStringLiteral( "multiBandSingleByte" );
1141  defaultLimits = QgsRasterMinMaxOrigin::limitsString(
1143  }
1144  else
1145  {
1146  key = QStringLiteral( "multiBandMultiByte" );
1149  defaultLimits = QgsRasterMinMaxOrigin::limitsString(
1151  }
1152  }
1153 
1154  if ( key.isEmpty() )
1155  {
1156  QgsDebugMsg( "No default contrast enhancement for this drawing style" );
1158  myLimits = QgsRasterMinMaxOrigin::limitsFromString( QString() );
1159  return false;
1160  }
1161  QgsDebugMsgLevel( "key = " + key, 4 );
1162 
1163  QString myAlgorithmString = mySettings.value( "/Raster/defaultContrastEnhancementAlgorithm/" + key, defaultAlg ).toString();
1164  QgsDebugMsgLevel( "myAlgorithmString = " + myAlgorithmString, 4 );
1165 
1166  myAlgorithm = QgsContrastEnhancement::contrastEnhancementAlgorithmFromString( myAlgorithmString );
1167 
1168  QString myLimitsString = mySettings.value( "/Raster/defaultContrastEnhancementLimits/" + key, defaultLimits ).toString();
1169  QgsDebugMsgLevel( "myLimitsString = " + myLimitsString, 4 );
1170  myLimits = QgsRasterMinMaxOrigin::limitsFromString( myLimitsString );
1171 
1172  return true;
1173 }
1174 
1176 {
1177  QgsDebugMsgLevel( "Entered", 4 );
1178 
1181  defaultContrastEnhancementSettings( myAlgorithm, myLimits );
1182 
1183  setContrastEnhancement( myAlgorithm, myLimits );
1184 }
1185 
1186 void QgsRasterLayer::setLayerOrder( QStringList const &layers )
1187 {
1188  QgsDebugMsgLevel( "entered.", 4 );
1189 
1190  if ( mDataProvider )
1191  {
1192  QgsDebugMsgLevel( "About to mDataProvider->setLayerOrder(layers).", 4 );
1193  mDataProvider->setLayerOrder( layers );
1194  }
1195 
1196 }
1197 
1198 void QgsRasterLayer::setSubLayerVisibility( const QString &name, bool vis )
1199 {
1200 
1201  if ( mDataProvider )
1202  {
1203  QgsDebugMsgLevel( "About to mDataProvider->setSubLayerVisibility(name, vis).", 4 );
1204  mDataProvider->setSubLayerVisibility( name, vis );
1205  }
1206 
1207 }
1208 
1209 QDateTime QgsRasterLayer::timestamp() const
1210 {
1211  return mDataProvider->timestamp();
1212 }
1213 
1215 {
1216  QgsDebugMsgLevel( "Entered", 4 );
1217  if ( !renderer )
1218  {
1219  return;
1220  }
1221 
1222  mPipe.set( renderer );
1223  emit rendererChanged();
1224  emit styleChanged();
1225 }
1226 
1227 void QgsRasterLayer::showStatusMessage( QString const &message )
1228 {
1229  // QgsDebugMsg(QString("entered with '%1'.").arg(theMessage));
1230 
1231  // Pass-through
1232  // TODO: See if we can connect signal-to-signal. This is a kludge according to the Qt doc.
1233  emit statusChanged( message );
1234 }
1235 
1236 QStringList QgsRasterLayer::subLayers() const
1237 {
1238  return mDataProvider->subLayers();
1239 }
1240 
1241 // this function should be used when rendering with the MTR engine introduced in 2.3, as QPixmap is not thread safe (see bug #9626)
1242 // note: previewAsImage and previewAsPixmap should use a common low-level fct QgsRasterLayer::previewOnPaintDevice( QSize size, QColor bgColor, QPaintDevice &device )
1243 QImage QgsRasterLayer::previewAsImage( QSize size, const QColor &bgColor, QImage::Format format )
1244 {
1245  QImage myQImage( size, format );
1246 
1247  myQImage.setColor( 0, bgColor.rgba() );
1248  myQImage.fill( 0 ); //defaults to white, set to transparent for rendering on a map
1249 
1250  QgsRasterViewPort *myRasterViewPort = new QgsRasterViewPort();
1251 
1252  double myMapUnitsPerPixel;
1253  double myX = 0.0;
1254  double myY = 0.0;
1255  QgsRectangle myExtent = mDataProvider->extent();
1256  if ( myExtent.width() / myExtent.height() >= static_cast< double >( myQImage.width() ) / myQImage.height() )
1257  {
1258  myMapUnitsPerPixel = myExtent.width() / myQImage.width();
1259  myY = ( myQImage.height() - myExtent.height() / myMapUnitsPerPixel ) / 2;
1260  }
1261  else
1262  {
1263  myMapUnitsPerPixel = myExtent.height() / myQImage.height();
1264  myX = ( myQImage.width() - myExtent.width() / myMapUnitsPerPixel ) / 2;
1265  }
1266 
1267  double myPixelWidth = myExtent.width() / myMapUnitsPerPixel;
1268  double myPixelHeight = myExtent.height() / myMapUnitsPerPixel;
1269 
1270  myRasterViewPort->mTopLeftPoint = QgsPointXY( myX, myY );
1271  myRasterViewPort->mBottomRightPoint = QgsPointXY( myPixelWidth, myPixelHeight );
1272  myRasterViewPort->mWidth = myQImage.width();
1273  myRasterViewPort->mHeight = myQImage.height();
1274 
1275  myRasterViewPort->mDrawnExtent = myExtent;
1276  myRasterViewPort->mSrcCRS = QgsCoordinateReferenceSystem(); // will be invalid
1277  myRasterViewPort->mDestCRS = QgsCoordinateReferenceSystem(); // will be invalid
1278  myRasterViewPort->mSrcDatumTransform = -1;
1279  myRasterViewPort->mDestDatumTransform = -1;
1280 
1281  QgsMapToPixel *myMapToPixel = new QgsMapToPixel( myMapUnitsPerPixel );
1282 
1283  QPainter *myQPainter = new QPainter( &myQImage );
1284  draw( myQPainter, myRasterViewPort, myMapToPixel );
1285  delete myRasterViewPort;
1286  delete myMapToPixel;
1287  myQPainter->end();
1288  delete myQPainter;
1289 
1290  return myQImage;
1291 }
1292 
1294 //
1295 // Protected methods
1296 //
1298 /*
1299  * @param QDomNode node that will contain the symbology definition for this layer.
1300  * @param errorMessage reference to string that will be updated with any error messages
1301  * @return true in case of success.
1302  */
1303 bool QgsRasterLayer::readSymbology( const QDomNode &layer_node, QString &errorMessage, const QgsReadWriteContext &context )
1304 {
1305  Q_UNUSED( errorMessage );
1306  Q_UNUSED( context );
1307  QDomElement rasterRendererElem;
1308 
1309  // pipe element was introduced in the end of 1.9 development when there were
1310  // already many project files in use so we support 1.9 backward compatibility
1311  // even it was never officially released -> use pipe element if present, otherwise
1312  // use layer node
1313  QDomNode pipeNode = layer_node.firstChildElement( QStringLiteral( "pipe" ) );
1314  if ( pipeNode.isNull() ) // old project
1315  {
1316  pipeNode = layer_node;
1317  }
1318 
1319  //rasterlayerproperties element there -> old format (1.8 and early 1.9)
1320  if ( !layer_node.firstChildElement( QStringLiteral( "rasterproperties" ) ).isNull() )
1321  {
1322  //copy node because layer_node is const
1323  QDomNode layerNodeCopy = layer_node.cloneNode();
1324  QDomDocument doc = layerNodeCopy.ownerDocument();
1325  QDomElement rasterPropertiesElem = layerNodeCopy.firstChildElement( QStringLiteral( "rasterproperties" ) );
1326  QgsProjectFileTransform::convertRasterProperties( doc, layerNodeCopy, rasterPropertiesElem,
1327  this );
1328  rasterRendererElem = layerNodeCopy.firstChildElement( QStringLiteral( "rasterrenderer" ) );
1329  QgsDebugMsgLevel( doc.toString(), 4 );
1330  }
1331  else
1332  {
1333  rasterRendererElem = pipeNode.firstChildElement( QStringLiteral( "rasterrenderer" ) );
1334  }
1335 
1336  if ( !rasterRendererElem.isNull() )
1337  {
1338  QString rendererType = rasterRendererElem.attribute( QStringLiteral( "type" ) );
1339  QgsRasterRendererRegistryEntry rendererEntry;
1340  if ( QgsApplication::rasterRendererRegistry()->rendererData( rendererType, rendererEntry ) )
1341  {
1342  QgsRasterRenderer *renderer = rendererEntry.rendererCreateFunction( rasterRendererElem, dataProvider() );
1343  mPipe.set( renderer );
1344  }
1345  }
1346 
1347  //brightness
1349  mPipe.set( brightnessFilter );
1350 
1351  //brightness coefficient
1352  QDomElement brightnessElem = pipeNode.firstChildElement( QStringLiteral( "brightnesscontrast" ) );
1353  if ( !brightnessElem.isNull() )
1354  {
1355  brightnessFilter->readXml( brightnessElem );
1356  }
1357 
1358  //hue/saturation
1360  mPipe.set( hueSaturationFilter );
1361 
1362  //saturation coefficient
1363  QDomElement hueSaturationElem = pipeNode.firstChildElement( QStringLiteral( "huesaturation" ) );
1364  if ( !hueSaturationElem.isNull() )
1365  {
1366  hueSaturationFilter->readXml( hueSaturationElem );
1367  }
1368 
1369  //resampler
1371  mPipe.set( resampleFilter );
1372 
1373  //max oversampling
1374  QDomElement resampleElem = pipeNode.firstChildElement( QStringLiteral( "rasterresampler" ) );
1375  if ( !resampleElem.isNull() )
1376  {
1377  resampleFilter->readXml( resampleElem );
1378  }
1379 
1380  // get and set the blend mode if it exists
1381  QDomNode blendModeNode = layer_node.namedItem( QStringLiteral( "blendMode" ) );
1382  if ( !blendModeNode.isNull() )
1383  {
1384  QDomElement e = blendModeNode.toElement();
1385  setBlendMode( QgsPainting::getCompositionMode( static_cast< QgsPainting::BlendMode >( e.text().toInt() ) ) );
1386  }
1387 
1388  readCustomProperties( layer_node );
1389 
1390  return true;
1391 }
1392 
1393 bool QgsRasterLayer::readStyle( const QDomNode &node, QString &errorMessage, const QgsReadWriteContext &context )
1394 {
1395  return readSymbology( node, errorMessage, context );
1396 } //readSymbology
1397 
1404 bool QgsRasterLayer::readXml( const QDomNode &layer_node, const QgsReadWriteContext &context )
1405 {
1406  QgsDebugMsgLevel( "Entered", 4 );
1407  // Make sure to read the file first so stats etc are initialized properly!
1408 
1409  //process provider key
1410  QDomNode pkeyNode = layer_node.namedItem( QStringLiteral( "provider" ) );
1411 
1412  if ( pkeyNode.isNull() )
1413  {
1414  mProviderKey = QStringLiteral( "gdal" );
1415  }
1416  else
1417  {
1418  QDomElement pkeyElt = pkeyNode.toElement();
1419  mProviderKey = pkeyElt.text();
1420  if ( mProviderKey.isEmpty() )
1421  {
1422  mProviderKey = QStringLiteral( "gdal" );
1423  }
1424  }
1425 
1426  // Open the raster source based on provider and datasource
1427 
1428  // Go down the raster-data-provider paradigm
1429 
1430  // Collect provider-specific information
1431 
1432  QDomNode rpNode = layer_node.namedItem( QStringLiteral( "rasterproperties" ) );
1433 
1434  if ( mProviderKey == QLatin1String( "wms" ) )
1435  {
1436  // >>> BACKWARD COMPATIBILITY < 1.9
1437  // The old WMS URI format does not contain all the information, we add them here.
1438  if ( !mDataSource.contains( QLatin1String( "crs=" ) ) && !mDataSource.contains( QLatin1String( "format=" ) ) )
1439  {
1440  QgsDebugMsgLevel( "Old WMS URI format detected -> adding params", 4 );
1441  QgsDataSourceUri uri;
1442  uri.setEncodedUri( mDataSource );
1443  QDomElement layerElement = rpNode.firstChildElement( QStringLiteral( "wmsSublayer" ) );
1444  while ( !layerElement.isNull() )
1445  {
1446  // TODO: sublayer visibility - post-0.8 release timeframe
1447 
1448  // collect name for the sublayer
1449  uri.setParam( QStringLiteral( "layers" ), layerElement.namedItem( QStringLiteral( "name" ) ).toElement().text() );
1450 
1451  // collect style for the sublayer
1452  uri.setParam( QStringLiteral( "styles" ), layerElement.namedItem( QStringLiteral( "style" ) ).toElement().text() );
1453 
1454  layerElement = layerElement.nextSiblingElement( QStringLiteral( "wmsSublayer" ) );
1455  }
1456 
1457  // Collect format
1458  QDomNode formatNode = rpNode.namedItem( QStringLiteral( "wmsFormat" ) );
1459  uri.setParam( QStringLiteral( "format" ), rpNode.namedItem( QStringLiteral( "wmsFormat" ) ).toElement().text() );
1460 
1461  // WMS CRS URL param should not be mixed with that assigned to the layer.
1462  // In the old WMS URI version there was no CRS and layer crs().authid() was used.
1463  uri.setParam( QStringLiteral( "crs" ), crs().authid() );
1464  mDataSource = uri.encodedUri();
1465  }
1466  // <<< BACKWARD COMPATIBILITY < 1.9
1467  }
1468 
1469  setDataProvider( mProviderKey );
1470  if ( !mValid ) return false;
1471 
1472  QString error;
1473  bool res = readSymbology( layer_node, error, context );
1474 
1475  // old wms settings we need to correct
1476  if ( res && mProviderKey == QLatin1String( "wms" ) && ( !renderer() || renderer()->type() != QLatin1String( "singlebandcolordata" ) ) )
1477  {
1478  setRendererForDrawingStyle( QgsRaster::SingleBandColorDataStyle );
1479  }
1480 
1481  // Check timestamp
1482  // This was probably introduced to reload completely raster if data changed and
1483  // reset completely symbology to reflect new data type etc. It creates however
1484  // problems, because user defined symbology is complete lost if data file time
1485  // changed (the content may be the same). See also 6900.
1486 #if 0
1487  QDomNode stampNode = layer_node.namedItem( "timestamp" );
1488  if ( !stampNode.isNull() )
1489  {
1490  QDateTime stamp = QDateTime::fromString( stampNode.toElement().text(), Qt::ISODate );
1491  // TODO: very bad, we have to load twice!!! Make QgsDataProvider::timestamp() static?
1492  if ( stamp < mDataProvider->dataTimestamp() )
1493  {
1494  QgsDebugMsg( "data changed, reload provider" );
1495  closeDataProvider();
1496  init();
1497  setDataProvider( mProviderKey );
1498  if ( !mValid ) return false;
1499  }
1500  }
1501 #endif
1502 
1503  // Load user no data value
1504  QDomElement noDataElement = layer_node.firstChildElement( QStringLiteral( "noData" ) );
1505 
1506  QDomNodeList noDataBandList = noDataElement.elementsByTagName( QStringLiteral( "noDataList" ) );
1507 
1508  for ( int i = 0; i < noDataBandList.size(); ++i )
1509  {
1510  QDomElement bandElement = noDataBandList.at( i ).toElement();
1511  bool ok;
1512  int bandNo = bandElement.attribute( QStringLiteral( "bandNo" ) ).toInt( &ok );
1513  QgsDebugMsgLevel( QString( "bandNo = %1" ).arg( bandNo ), 4 );
1514  if ( ok && ( bandNo > 0 ) && ( bandNo <= mDataProvider->bandCount() ) )
1515  {
1516  mDataProvider->setUseSourceNoDataValue( bandNo, bandElement.attribute( QStringLiteral( "useSrcNoData" ) ).toInt() );
1517  QgsRasterRangeList myNoDataRangeList;
1518 
1519  QDomNodeList rangeList = bandElement.elementsByTagName( QStringLiteral( "noDataRange" ) );
1520 
1521  myNoDataRangeList.reserve( rangeList.size() );
1522  for ( int j = 0; j < rangeList.size(); ++j )
1523  {
1524  QDomElement rangeElement = rangeList.at( j ).toElement();
1525  QgsRasterRange myNoDataRange( rangeElement.attribute( QStringLiteral( "min" ) ).toDouble(),
1526  rangeElement.attribute( QStringLiteral( "max" ) ).toDouble() );
1527  QgsDebugMsgLevel( QString( "min = %1 %2" ).arg( rangeElement.attribute( "min" ) ).arg( myNoDataRange.min() ), 4 );
1528  myNoDataRangeList << myNoDataRange;
1529  }
1530  mDataProvider->setUserNoDataValue( bandNo, myNoDataRangeList );
1531  }
1532  }
1533 
1534  readStyleManager( layer_node );
1535 
1536  return res;
1537 } // QgsRasterLayer::readXml( QDomNode & layer_node )
1538 
1539 /*
1540  * @param QDomNode the node that will have the style element added to it.
1541  * @param QDomDocument the document that will have the QDomNode added.
1542  * @param errorMessage reference to string that will be updated with any error messages
1543  * @return true in case of success.
1544  */
1545 bool QgsRasterLayer::writeSymbology( QDomNode &layer_node, QDomDocument &document, QString &errorMessage, const QgsReadWriteContext &context ) const
1546 {
1547  Q_UNUSED( errorMessage );
1548  Q_UNUSED( context );
1549 
1550  // Store pipe members (except provider) into pipe element, in future, it will be
1551  // possible to add custom filters into the pipe
1552  QDomElement pipeElement = document.createElement( QStringLiteral( "pipe" ) );
1553 
1554  for ( int i = 1; i < mPipe.size(); i++ )
1555  {
1556  QgsRasterInterface *interface = mPipe.at( i );
1557  if ( !interface ) continue;
1558  interface->writeXml( document, pipeElement );
1559  }
1560 
1561  layer_node.appendChild( pipeElement );
1562 
1563  // add blend mode node
1564  QDomElement blendModeElement = document.createElement( QStringLiteral( "blendMode" ) );
1565  QDomText blendModeText = document.createTextNode( QString::number( QgsPainting::getBlendModeEnum( blendMode() ) ) );
1566  blendModeElement.appendChild( blendModeText );
1567  layer_node.appendChild( blendModeElement );
1568 
1569  return true;
1570 }
1571 
1572 bool QgsRasterLayer::writeStyle( QDomNode &node, QDomDocument &doc, QString &errorMessage, const QgsReadWriteContext &context ) const
1573 {
1574  return writeSymbology( node, doc, errorMessage, context );
1575 
1576 } // bool QgsRasterLayer::writeSymbology
1577 
1578 /*
1579  * virtual
1580  * @note Called by QgsMapLayer::writeXml().
1581  */
1582 bool QgsRasterLayer::writeXml( QDomNode &layer_node,
1583  QDomDocument &document,
1584  const QgsReadWriteContext &context ) const
1585 {
1586  // first get the layer element so that we can append the type attribute
1587 
1588  QDomElement mapLayerNode = layer_node.toElement();
1589 
1590  if ( mapLayerNode.isNull() || "maplayer" != mapLayerNode.nodeName() )
1591  {
1592  QgsMessageLog::logMessage( tr( "<maplayer> not found." ), tr( "Raster" ) );
1593  return false;
1594  }
1595 
1596  mapLayerNode.setAttribute( QStringLiteral( "type" ), QStringLiteral( "raster" ) );
1597 
1598  // add provider node
1599 
1600  QDomElement provider = document.createElement( QStringLiteral( "provider" ) );
1601  QDomText providerText = document.createTextNode( mProviderKey );
1602  provider.appendChild( providerText );
1603  layer_node.appendChild( provider );
1604 
1605  // User no data
1606  QDomElement noData = document.createElement( QStringLiteral( "noData" ) );
1607 
1608  for ( int bandNo = 1; bandNo <= mDataProvider->bandCount(); bandNo++ )
1609  {
1610  QDomElement noDataRangeList = document.createElement( QStringLiteral( "noDataList" ) );
1611  noDataRangeList.setAttribute( QStringLiteral( "bandNo" ), bandNo );
1612  noDataRangeList.setAttribute( QStringLiteral( "useSrcNoData" ), mDataProvider->useSourceNoDataValue( bandNo ) );
1613 
1614  Q_FOREACH ( QgsRasterRange range, mDataProvider->userNoDataValues( bandNo ) )
1615  {
1616  QDomElement noDataRange = document.createElement( QStringLiteral( "noDataRange" ) );
1617 
1618  noDataRange.setAttribute( QStringLiteral( "min" ), QgsRasterBlock::printValue( range.min() ) );
1619  noDataRange.setAttribute( QStringLiteral( "max" ), QgsRasterBlock::printValue( range.max() ) );
1620  noDataRangeList.appendChild( noDataRange );
1621  }
1622 
1623  noData.appendChild( noDataRangeList );
1624 
1625  }
1626  if ( noData.hasChildNodes() )
1627  {
1628  layer_node.appendChild( noData );
1629  }
1630 
1631  writeStyleManager( layer_node, document );
1632 
1633  //write out the symbology
1634  QString errorMsg;
1635  return writeSymbology( layer_node, document, errorMsg, context );
1636 }
1637 
1639 {
1640  if ( !mDataProvider ) return 0;
1641  return mDataProvider->xSize();
1642 }
1643 
1645 {
1646  if ( !mDataProvider ) return 0;
1647  return mDataProvider->ySize();
1648 }
1649 
1651 //
1652 // Private methods
1653 //
1655 bool QgsRasterLayer::update()
1656 {
1657  QgsDebugMsgLevel( "entered.", 4 );
1658  // Check if data changed
1659  if ( mDataProvider->dataTimestamp() > mDataProvider->timestamp() )
1660  {
1661  QgsDebugMsgLevel( "reload data", 4 );
1662  closeDataProvider();
1663  init();
1664  setDataProvider( mProviderKey );
1665  emit dataChanged();
1666  }
1667  return mValid;
1668 }
virtual QgsRectangle extent() const override=0
Returns the extent of the layer.
QString attributionUrl() const
Returns the attribution URL of the layer used by QGIS Server in GetCapabilities request.
Definition: qgsmaplayer.h:279
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)
QString dataUrlFormat() const
Returns the DataUrl format of the layer used by QGIS Server in GetCapabilities request.
Definition: qgsmaplayer.h:245
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.
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
QString shortName() const
Returns the short name of the layer used by QGIS Server to identify the layer.
Definition: qgsmaplayer.h:169
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.
QString dataUrl() const
Returns the DataUrl of the layer used by QGIS Server in GetCapabilities request.
Definition: qgsmaplayer.h:229
virtual void setLayerOrder(const QStringList &layers) override
Reorders the previously selected sublayers of this layer from bottom to top.
double rasterUnitsPerPixelX() const
Returns the number of raster units per each raster pixel in X axis. In a world file, this is normally the first row (without the sign)
void willBeDeleted()
Emitted in the destructor when the layer is about to be deleted, but it is still in a perfectly valid...
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.
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.
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:998
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
QString metadataUrlFormat() const
Returns the metadata format of the layer used by QGIS Server in GetCapabilities request.
Definition: qgsmaplayer.h:329
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
QString id() const
Returns the layer&#39;s unique ID, which is used to access this layer from QgsProject.
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:118
QgsRasterShaderFunction * rasterShaderFunction()
virtual void setExtent(const QgsRectangle &rect)
Set the extent.
Complex Float32.
Definition: qgis.h:86
QString keywordList() const
Returns the keyword list of the layer used by QGIS Server in GetCapabilities request.
Definition: qgsmaplayer.h:211
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 ].
QString legendUrl() const
Returns the URL for the layer&#39;s legend.
Definition: qgsmaplayer.h:651
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) ...
double ANALYSIS_EXPORT min(double x, double y)
Returns the minimum of two doubles or the first argument if both are equal.
Definition: MathUtils.cc:452
void rendererChanged()
Signal emitted when renderer is changed.
void setAlphaBand(int band)
bool mValid
Indicates if the layer is valid and can be drawn.
Definition: qgsmaplayer.h:992
#define cast_to_fptr(f)
Definition: qgis.h:129
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.
double ANALYSIS_EXPORT max(double x, double y)
Returns the maximum of two doubles or the first argument if both are equal.
Definition: MathUtils.cc:437
static const QgsRasterMinMaxOrigin::Limits SINGLE_BAND_MIN_MAX_LIMITS
Default enhancement limits for single band raster.
QString legendUrlFormat() const
Returns the format for a URL based layer legend.
Definition: qgsmaplayer.h:661
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.
QString title() const
Returns the title of the layer used by QGIS Server in GetCapabilities request.
Definition: qgsmaplayer.h:183
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.
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:995
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.
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:984
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...
QString metadataUrl() const
Returns the metadata URL of the layer used by QGIS Server in GetCapabilities request.
Definition: qgsmaplayer.h:297
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:986
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.
QString attribution() const
Returns the attribution of the layer used by QGIS Server in GetCapabilities request.
Definition: qgsmaplayer.h:263
Color, alpha, red, green, blue, 4 bytes the same as QImage::Format_ARGB32.
Definition: qgis.h:88
QString metadataUrlType() const
Returns the metadata type of the layer used by QGIS Server in GetCapabilities request.
Definition: qgsmaplayer.h:313
QPainter::CompositionMode blendMode() const
Returns the current blending mode for a layer.
double height() const
Returns the height of the rectangle.
Definition: qgsrectangle.h:125
virtual int colorInterpretation(int bandNo) const
Returns data type for the band specified by number.
QgsRectangle mDrawnExtent
Intersection of current map extent and layer extent.
Base class for raster data providers.
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.