QGIS API Documentation  3.0.2-Girona (307d082)
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  const LayerOptions &options )
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 && options.loadDefaultStyle )
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(), name(), 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  // Begin Provider section
311  myMetadata += QStringLiteral( "<h1>" ) + tr( "Information from provider" ) + QStringLiteral( "</h1>\n<hr>\n" );
312  myMetadata += QLatin1String( "<table class=\"list-view\">\n" );
313 
314  // original name
315  myMetadata += QStringLiteral( "<tr><td class=\"highlight\">" ) + tr( "Original" ) + QStringLiteral( "</td><td>" ) + name() + QStringLiteral( "</td></tr>\n" );
316 
317  // name
318  myMetadata += QStringLiteral( "<tr><td class=\"highlight\">" ) + tr( "Name" ) + QStringLiteral( "</td><td>" ) + name() + QStringLiteral( "</td></tr>\n" );
319 
320  // data source
321  myMetadata += QStringLiteral( "<tr><td class=\"highlight\">" ) + tr( "Source" ) + QStringLiteral( "</td><td>" ) + publicSource() + QStringLiteral( "</td></tr>\n" );
322 
323  // storage type
324  myMetadata += QStringLiteral( "<tr><td class=\"highlight\">" ) + tr( "Provider" ) + QStringLiteral( "</td><td>" ) + providerType() + QStringLiteral( "</td></tr>\n" );
325 
326  // EPSG
327  myMetadata += QStringLiteral( "<tr><td class=\"highlight\">" ) + tr( "CRS" ) + QStringLiteral( "</td><td>" );
328  if ( crs().isValid() )
329  {
330  myMetadata += crs().authid() + QStringLiteral( " - " );
331  myMetadata += crs().description() + QStringLiteral( " - " );
332  if ( crs().isGeographic() )
333  myMetadata += tr( "Geographic" );
334  else
335  myMetadata += tr( "Projected" );
336  }
337  myMetadata += QLatin1String( "</td></tr>\n" );
338 
339  // Extent
340  myMetadata += QStringLiteral( "<tr><td class=\"highlight\">" ) + tr( "Extent" ) + QStringLiteral( "</td><td>" ) + extent().toString() + QStringLiteral( "</td></tr>\n" );
341 
342  // unit
343  myMetadata += QStringLiteral( "<tr><td class=\"highlight\">" ) + tr( "Unit" ) + QStringLiteral( "</td><td>" ) + QgsUnitTypes::toString( crs().mapUnits() ) + QStringLiteral( "</td></tr>\n" );
344 
345  // Raster Width
346  myMetadata += QStringLiteral( "<tr><td class=\"highlight\">" ) + tr( "Width" ) + QStringLiteral( "</td><td>" );
347  if ( dataProvider()->capabilities() & QgsRasterDataProvider::Size )
348  myMetadata += QString::number( width() );
349  else
350  myMetadata += tr( "n/a" );
351  myMetadata += QLatin1String( "</td></tr>\n" );
352 
353  // Raster height
354  myMetadata += QStringLiteral( "<tr><td class=\"highlight\">" ) + tr( "Height" ) + QStringLiteral( "</td><td>" );
355  if ( dataProvider()->capabilities() & QgsRasterDataProvider::Size )
356  myMetadata += QString::number( height() );
357  else
358  myMetadata += tr( "n/a" );
359  myMetadata += QLatin1String( "</td></tr>\n" );
360 
361  // Data type
362  myMetadata += QStringLiteral( "<tr><td class=\"highlight\">" ) + tr( "Data type" ) + QStringLiteral( "</td><td>" );
363  // Just use the first band
364  switch ( mDataProvider->sourceDataType( 1 ) )
365  {
366  case Qgis::Byte:
367  myMetadata += tr( "Byte - Eight bit unsigned integer" );
368  break;
369  case Qgis::UInt16:
370  myMetadata += tr( "UInt16 - Sixteen bit unsigned integer " );
371  break;
372  case Qgis::Int16:
373  myMetadata += tr( "Int16 - Sixteen bit signed integer " );
374  break;
375  case Qgis::UInt32:
376  myMetadata += tr( "UInt32 - Thirty two bit unsigned integer " );
377  break;
378  case Qgis::Int32:
379  myMetadata += tr( "Int32 - Thirty two bit signed integer " );
380  break;
381  case Qgis::Float32:
382  myMetadata += tr( "Float32 - Thirty two bit floating point " );
383  break;
384  case Qgis::Float64:
385  myMetadata += tr( "Float64 - Sixty four bit floating point " );
386  break;
387  case Qgis::CInt16:
388  myMetadata += tr( "CInt16 - Complex Int16 " );
389  break;
390  case Qgis::CInt32:
391  myMetadata += tr( "CInt32 - Complex Int32 " );
392  break;
393  case Qgis::CFloat32:
394  myMetadata += tr( "CFloat32 - Complex Float32 " );
395  break;
396  case Qgis::CFloat64:
397  myMetadata += tr( "CFloat64 - Complex Float64 " );
398  break;
399  default:
400  myMetadata += tr( "Could not determine raster data type." );
401  }
402  myMetadata += QLatin1String( "</td></tr>\n" );
403 
404  // Insert provider-specific (e.g. WMS-specific) metadata
405  myMetadata += mDataProvider->htmlMetadata();
406 
407  // End Provider section
408  myMetadata += QLatin1String( "</table>\n<br><br>" );
409 
410  // Identification section
411  myMetadata += QStringLiteral( "<h1>" ) + tr( "Identification" ) + QStringLiteral( "</h1>\n<hr>\n" );
412  myMetadata += htmlFormatter.identificationSectionHtml();
413  myMetadata += QLatin1String( "<br><br>\n" );
414 
415  // extent section
416  myMetadata += QStringLiteral( "<h1>" ) + tr( "Extent" ) + QStringLiteral( "</h1>\n<hr>\n" );
417  myMetadata += htmlFormatter.extentSectionHtml( );
418  myMetadata += QLatin1String( "<br><br>\n" );
419 
420  // Start the Access section
421  myMetadata += QStringLiteral( "<h1>" ) + tr( "Access" ) + QStringLiteral( "</h1>\n<hr>\n" );
422  myMetadata += htmlFormatter.accessSectionHtml( );
423  myMetadata += QLatin1String( "<br><br>\n" );
424 
425  // Bands section
426  myMetadata += QStringLiteral( "</table>\n<br><br><h1>" ) + tr( "Bands" ) + QStringLiteral( "</h1>\n<hr>\n<table class=\"list-view\">\n" );
427 
428  // Band count
429  myMetadata += QStringLiteral( "<tr><td class=\"highlight\">" ) + tr( "Band count" ) + QStringLiteral( "</td><td>" ) + QString::number( bandCount() ) + QStringLiteral( "</td></tr>\n" );
430 
431  // Band table
432  myMetadata += QLatin1String( "</table>\n<br><table width=\"100%\" class=\"tabular-view\">\n" );
433  myMetadata += "<tr><th>" + tr( "Number" ) + "</th><th>" + tr( "Band" ) + "</th><th>" + tr( "No-Data" ) + "</th><th>" + tr( "Min" ) + "</th><th>" + tr( "Max" ) + "</th></tr>\n";
434 
435  QgsRasterDataProvider *provider = const_cast< QgsRasterDataProvider * >( mDataProvider );
436  for ( int i = 1; i <= bandCount(); i++ )
437  {
438  QString rowClass;
439  if ( i % 2 )
440  rowClass = QStringLiteral( "class=\"odd-row\"" );
441  myMetadata += "<tr " + rowClass + "><td>" + QString::number( i ) + "</td><td>" + bandName( i ) + "</td><td>";
442 
443  if ( dataProvider()->sourceHasNoDataValue( i ) )
444  myMetadata += QString::number( dataProvider()->sourceNoDataValue( i ) );
445  else
446  myMetadata += tr( "n/a" );
447  myMetadata += QLatin1String( "</td>" );
448 
449  if ( provider->hasStatistics( i ) )
450  {
451  QgsRasterBandStats myRasterBandStats = provider->bandStatistics( i );
452  myMetadata += "<td>" + QString::number( myRasterBandStats.minimumValue, 'f', 10 ) + "</td>";
453  myMetadata += "<td>" + QString::number( myRasterBandStats.maximumValue, 'f', 10 ) + "</td>";
454  }
455  else
456  {
457  myMetadata += "<td>" + tr( "n/a" ) + "</td><td>" + tr( "n/a" ) + "</td>";
458  }
459 
460  myMetadata += QLatin1String( "</tr>\n" );
461  }
462 
463  //close previous bands table
464  myMetadata += QLatin1String( "</table>\n<br><br>" );
465 
466  // Start the contacts section
467  myMetadata += QStringLiteral( "<h1>" ) + tr( "Contacts" ) + QStringLiteral( "</h1>\n<hr>\n" );
468  myMetadata += htmlFormatter.contactsSectionHtml( );
469  myMetadata += QLatin1String( "<br><br>\n" );
470 
471  // Start the links section
472  myMetadata += QStringLiteral( "<h1>" ) + tr( "References" ) + QStringLiteral( "</h1>\n<hr>\n" );
473  myMetadata += htmlFormatter.linksSectionHtml( );
474  myMetadata += QLatin1String( "<br><br>\n" );
475 
476  // Start the history section
477  myMetadata += QStringLiteral( "<h1>" ) + tr( "History" ) + QStringLiteral( "</h1>\n<hr>\n" );
478  myMetadata += htmlFormatter.historySectionHtml( );
479  myMetadata += QLatin1String( "<br><br>\n" );
480 
481  myMetadata += QStringLiteral( "\n</body>\n</html>\n" );
482  return myMetadata;
483 }
484 
485 
490 QPixmap QgsRasterLayer::paletteAsPixmap( int bandNumber )
491 {
492  //TODO: This function should take dimensions
493  QgsDebugMsgLevel( "entered.", 4 );
494 
495  // Only do this for the GDAL provider?
496  // Maybe WMS can do this differently using QImage::numColors and QImage::color()
497  if ( mDataProvider->colorInterpretation( bandNumber ) == QgsRaster::PaletteIndex )
498  {
499  QgsDebugMsgLevel( "....found paletted image", 4 );
500  QgsColorRampShader myShader;
501  QList<QgsColorRampShader::ColorRampItem> myColorRampItemList = mDataProvider->colorTable( bandNumber );
502  if ( !myColorRampItemList.isEmpty() )
503  {
504  QgsDebugMsgLevel( "....got color ramp item list", 4 );
505  myShader.setColorRampItemList( myColorRampItemList );
507  // Draw image
508  int mySize = 100;
509  QPixmap myPalettePixmap( mySize, mySize );
510  QPainter myQPainter( &myPalettePixmap );
511 
512  QImage myQImage = QImage( mySize, mySize, QImage::Format_RGB32 );
513  myQImage.fill( 0 );
514  myPalettePixmap.fill();
515 
516  double myStep = ( static_cast< double >( myColorRampItemList.size() ) - 1 ) / static_cast< double >( mySize * mySize );
517  double myValue = 0.0;
518  for ( int myRow = 0; myRow < mySize; myRow++ )
519  {
520  QRgb *myLineBuffer = reinterpret_cast< QRgb * >( myQImage.scanLine( myRow ) );
521  for ( int myCol = 0; myCol < mySize; myCol++ )
522  {
523  myValue = myStep * static_cast< double >( myCol + myRow * mySize );
524  int c1, c2, c3, c4;
525  myShader.shade( myValue, &c1, &c2, &c3, &c4 );
526  myLineBuffer[ myCol ] = qRgba( c1, c2, c3, c4 );
527  }
528  }
529 
530  myQPainter.drawImage( 0, 0, myQImage );
531  return myPalettePixmap;
532  }
533  QPixmap myNullPixmap;
534  return myNullPixmap;
535  }
536  else
537  {
538  //invalid layer was requested
539  QPixmap myNullPixmap;
540  return myNullPixmap;
541  }
542 }
543 
545 {
546  return mProviderKey;
547 }
548 
553 {
554 // We return one raster pixel per map unit pixel
555 // One raster pixel can have several raster units...
556 
557 // We can only use one of the mGeoTransform[], so go with the
558 // horisontal one.
559 
560  if ( mDataProvider->capabilities() & QgsRasterDataProvider::Size && !qgsDoubleNear( mDataProvider->xSize(), 0.0 ) )
561  {
562  return mDataProvider->extent().width() / mDataProvider->xSize();
563  }
564  return 1;
565 }
566 
568 {
569  if ( mDataProvider->capabilities() & QgsRasterDataProvider::Size && !qgsDoubleNear( mDataProvider->ySize(), 0.0 ) )
570  {
571  return mDataProvider->extent().height() / mDataProvider->ySize();
572  }
573  return 1;
574 }
575 
576 void QgsRasterLayer::init()
577 {
578  mRasterType = QgsRasterLayer::GrayOrUndefined;
579 
581 
582  setRendererForDrawingStyle( QgsRaster::UndefinedDrawingStyle );
583 
584  //Initialize the last view port structure, should really be a class
585  mLastViewPort.mWidth = 0;
586  mLastViewPort.mHeight = 0;
587 }
588 
589 void QgsRasterLayer::setDataProvider( QString const &provider )
590 {
591  QgsDebugMsgLevel( "Entered", 4 );
592  mValid = false; // assume the layer is invalid until we determine otherwise
593 
594  mPipe.remove( mDataProvider ); // deletes if exists
595  mDataProvider = nullptr;
596 
597  // XXX should I check for and possibly delete any pre-existing providers?
598  // XXX How often will that scenario occur?
599 
600  mProviderKey = provider;
601  // set the layer name (uppercase first character)
602  if ( ! mLayerName.isEmpty() ) // XXX shouldn't this happen in parent?
603  {
604  setName( mLayerName );
605  }
606 
607  //mBandCount = 0;
608 
609  mDataProvider = dynamic_cast< QgsRasterDataProvider * >( QgsProviderRegistry::instance()->createProvider( mProviderKey, mDataSource ) );
610  if ( !mDataProvider )
611  {
612  //QgsMessageLog::logMessage( tr( "Cannot instantiate the data provider" ), tr( "Raster" ) );
613  appendError( ERR( tr( "Cannot instantiate the '%1' data provider" ).arg( mProviderKey ) ) );
614  return;
615  }
616  QgsDebugMsgLevel( "Data provider created", 4 );
617  mDataProvider->setParent( this );
618 
619  // Set data provider into pipe even if not valid so that it is deleted with pipe (with layer)
620  mPipe.set( mDataProvider );
621  if ( !mDataProvider->isValid() )
622  {
623  setError( mDataProvider->error() );
624  appendError( ERR( tr( "Provider is not valid (provider: %1, URI: %2" ).arg( mProviderKey, mDataSource ) ) );
625  return;
626  }
627 
629  {
630  setMetadata( mDataProvider->layerMetadata() );
631  QgsDebugMsgLevel( QString( "Set Data provider QgsLayerMetadata identifier[%1]" ).arg( metadata().identifier() ), 4 );
632  }
633 
634  if ( provider == QLatin1String( "gdal" ) )
635  {
636  // make sure that the /vsigzip or /vsizip is added to uri, if applicable
637  mDataSource = mDataProvider->dataSourceUri();
638  }
639 
640  // get the extent
641  QgsRectangle mbr = mDataProvider->extent();
642 
643  // show the extent
644  QgsDebugMsgLevel( "Extent of layer: " + mbr.toString(), 4 );
645  // store the extent
646  setExtent( mbr );
647 
648  // upper case the first letter of the layer name
649  QgsDebugMsgLevel( "mLayerName: " + name(), 4 );
650 
651  // set up the raster drawing style
652  // Do not set any 'sensible' style here, the style is set later
653 
654  // Setup source CRS
655  setCrs( QgsCoordinateReferenceSystem( mDataProvider->crs() ) );
656 
657  QgsDebugMsgLevel( "using wkt:\n" + crs().toWkt(), 4 );
658 
659  //defaults - Needs to be set after the Contrast list has been build
660  //Try to read the default contrast enhancement from the config file
661 
662  //decide what type of layer this is...
663  //TODO Change this to look at the color interp and palette interp to decide which type of layer it is
664  QgsDebugMsgLevel( "bandCount = " + QString::number( mDataProvider->bandCount() ), 4 );
665  QgsDebugMsgLevel( "dataType = " + QString::number( mDataProvider->dataType( 1 ) ), 4 );
666  if ( ( mDataProvider->bandCount() > 1 ) )
667  {
668  // handle singleband gray with alpha
669  if ( mDataProvider->bandCount() == 2
670  && ( ( mDataProvider->colorInterpretation( 1 ) == QgsRaster::GrayIndex
671  && mDataProvider->colorInterpretation( 2 ) == QgsRaster::AlphaBand )
672  || ( mDataProvider->colorInterpretation( 1 ) == QgsRaster::AlphaBand
673  && mDataProvider->colorInterpretation( 2 ) == QgsRaster::GrayIndex ) ) )
674  {
675  mRasterType = GrayOrUndefined;
676  }
677  else
678  {
679  mRasterType = Multiband;
680  }
681  }
682  else if ( mDataProvider->dataType( 1 ) == Qgis::ARGB32
683  || mDataProvider->dataType( 1 ) == Qgis::ARGB32_Premultiplied )
684  {
685  mRasterType = ColorLayer;
686  }
687  else if ( mDataProvider->colorInterpretation( 1 ) == QgsRaster::PaletteIndex )
688  {
689  mRasterType = Palette;
690  }
691  else if ( mDataProvider->colorInterpretation( 1 ) == QgsRaster::ContinuousPalette )
692  {
693  mRasterType = Palette;
694  }
695  else
696  {
697  mRasterType = GrayOrUndefined;
698  }
699 
700  QgsDebugMsgLevel( "mRasterType = " + QString::number( mRasterType ), 4 );
701  if ( mRasterType == ColorLayer )
702  {
703  QgsDebugMsgLevel( "Setting drawing style to SingleBandColorDataStyle " + QString::number( QgsRaster::SingleBandColorDataStyle ), 4 );
704  setRendererForDrawingStyle( QgsRaster::SingleBandColorDataStyle );
705  }
706  else if ( mRasterType == Palette && mDataProvider->colorInterpretation( 1 ) == QgsRaster::PaletteIndex )
707  {
708  setRendererForDrawingStyle( QgsRaster::PalettedColor ); //sensible default
709  }
710  else if ( mRasterType == Palette && mDataProvider->colorInterpretation( 1 ) == QgsRaster::ContinuousPalette )
711  {
712  setRendererForDrawingStyle( QgsRaster::SingleBandPseudoColor );
713  // Load color table
714  QList<QgsColorRampShader::ColorRampItem> colorTable = mDataProvider->colorTable( 1 );
716  if ( r )
717  {
718  // TODO: this should go somewhere else
719  QgsRasterShader *shader = new QgsRasterShader();
720  QgsColorRampShader *colorRampShader = new QgsColorRampShader();
722  colorRampShader->setColorRampItemList( colorTable );
723  shader->setRasterShaderFunction( colorRampShader );
724  r->setShader( shader );
725  }
726  }
727  else if ( mRasterType == Multiband )
728  {
729  setRendererForDrawingStyle( QgsRaster::MultiBandColor ); //sensible default
730  }
731  else //GrayOrUndefined
732  {
733  setRendererForDrawingStyle( QgsRaster::SingleBandGray ); //sensible default
734  }
735 
736  // Auto set alpha band
737  for ( int bandNo = 1; bandNo <= mDataProvider->bandCount(); bandNo++ )
738  {
739  if ( mDataProvider->colorInterpretation( bandNo ) == QgsRaster::AlphaBand )
740  {
741  if ( mPipe.renderer() )
742  {
743  mPipe.renderer()->setAlphaBand( bandNo );
744  }
745  break;
746  }
747  }
748 
749  // brightness filter
751  mPipe.set( brightnessFilter );
752 
753  // hue/saturation filter
755  mPipe.set( hueSaturationFilter );
756 
757  //resampler (must be after renderer)
759  mPipe.set( resampleFilter );
760 
761  // projector (may be anywhere in pipe)
762  QgsRasterProjector *projector = new QgsRasterProjector;
763  mPipe.set( projector );
764 
765  // Set default identify format - use the richest format available
766  int capabilities = mDataProvider->capabilities();
768  if ( capabilities & QgsRasterInterface::IdentifyHtml )
769  {
770  // HTML is usually richest
771  identifyFormat = QgsRaster::IdentifyFormatHtml;
772  }
773  else if ( capabilities & QgsRasterInterface::IdentifyFeature )
774  {
775  identifyFormat = QgsRaster::IdentifyFormatFeature;
776  }
777  else if ( capabilities & QgsRasterInterface::IdentifyText )
778  {
779  identifyFormat = QgsRaster::IdentifyFormatText;
780  }
781  else if ( capabilities & QgsRasterInterface::IdentifyValue )
782  {
783  identifyFormat = QgsRaster::IdentifyFormatValue;
784  }
785  setCustomProperty( QStringLiteral( "identify/format" ), QgsRasterDataProvider::identifyFormatName( identifyFormat ) );
786 
787  // Store timestamp
788  // TODO move to provider
789  mLastModified = lastModified( mDataSource );
790 
791  // Do a passthrough for the status bar text
792  connect( mDataProvider, &QgsRasterDataProvider::statusChanged, this, &QgsRasterLayer::statusChanged );
793 
794  //mark the layer as valid
795  mValid = true;
796 
797  QgsDebugMsgLevel( "exiting.", 4 );
798 } // QgsRasterLayer::setDataProvider
799 
800 void QgsRasterLayer::closeDataProvider()
801 {
802  mValid = false;
803  mPipe.remove( mDataProvider );
804  mDataProvider = nullptr;
805 }
806 
807 void QgsRasterLayer::computeMinMax( int band,
808  const QgsRasterMinMaxOrigin &mmo,
810  const QgsRectangle &extent,
811  int sampleSize,
812  double &min, double &max )
813 {
814 
815  min = std::numeric_limits<double>::quiet_NaN();
816  max = std::numeric_limits<double>::quiet_NaN();
817 
818  if ( limits == QgsRasterMinMaxOrigin::MinMax )
819  {
820  QgsRasterBandStats myRasterBandStats = mDataProvider->bandStatistics( band, QgsRasterBandStats::Min | QgsRasterBandStats::Max, extent, sampleSize );
821  min = myRasterBandStats.minimumValue;
822  max = myRasterBandStats.maximumValue;
823  }
824  else if ( limits == QgsRasterMinMaxOrigin::StdDev )
825  {
826  QgsRasterBandStats myRasterBandStats = mDataProvider->bandStatistics( band, QgsRasterBandStats::Mean | QgsRasterBandStats::StdDev, extent, sampleSize );
827  min = myRasterBandStats.mean - ( mmo.stdDevFactor() * myRasterBandStats.stdDev );
828  max = myRasterBandStats.mean + ( mmo.stdDevFactor() * myRasterBandStats.stdDev );
829  }
830  else if ( limits == QgsRasterMinMaxOrigin::CumulativeCut )
831  {
832  const double myLower = mmo.cumulativeCutLower();
833  const double myUpper = mmo.cumulativeCutUpper();
834  QgsDebugMsgLevel( QString( "myLower = %1 myUpper = %2" ).arg( myLower ).arg( myUpper ), 4 );
835  mDataProvider->cumulativeCut( band, myLower, myUpper, min, max, extent, sampleSize );
836  }
837  QgsDebugMsgLevel( QString( "band = %1 min = %2 max = %3" ).arg( band ).arg( min ).arg( max ), 4 );
838 
839 }
840 
841 
842 void QgsRasterLayer::setContrastEnhancement( QgsContrastEnhancement::ContrastEnhancementAlgorithm algorithm, QgsRasterMinMaxOrigin::Limits limits, const QgsRectangle &extent, int sampleSize, bool generateLookupTableFlag )
843 {
844  setContrastEnhancement( algorithm,
845  limits,
846  extent,
847  sampleSize,
848  generateLookupTableFlag,
849  mPipe.renderer() );
850 }
851 
854  const QgsRectangle &extent,
855  int sampleSize,
856  bool generateLookupTableFlag,
857  QgsRasterRenderer *rasterRenderer )
858 {
859  QgsDebugMsgLevel( QString( "theAlgorithm = %1 limits = %2 extent.isEmpty() = %3" ).arg( algorithm ).arg( limits ).arg( extent.isEmpty() ), 4 );
860  if ( !rasterRenderer || !mDataProvider )
861  {
862  return;
863  }
864 
865  QList<int> myBands;
866  QList<QgsContrastEnhancement *> myEnhancements;
867  QgsRasterMinMaxOrigin myMinMaxOrigin;
868  QgsRasterRenderer *myRasterRenderer = nullptr;
869  QgsSingleBandGrayRenderer *myGrayRenderer = nullptr;
870  QgsSingleBandPseudoColorRenderer *myPseudoColorRenderer = nullptr;
871  QgsMultiBandColorRenderer *myMultiBandRenderer = nullptr;
872  QString rendererType = rasterRenderer->type();
873  if ( rendererType == QLatin1String( "singlebandgray" ) )
874  {
875  myGrayRenderer = dynamic_cast<QgsSingleBandGrayRenderer *>( rasterRenderer );
876  if ( !myGrayRenderer )
877  {
878  return;
879  }
880  myBands << myGrayRenderer->grayBand();
881  myRasterRenderer = myGrayRenderer;
882  myMinMaxOrigin = myGrayRenderer->minMaxOrigin();
883  }
884  else if ( rendererType == QLatin1String( "multibandcolor" ) )
885  {
886  myMultiBandRenderer = dynamic_cast<QgsMultiBandColorRenderer *>( rasterRenderer );
887  if ( !myMultiBandRenderer )
888  {
889  return;
890  }
891  myBands << myMultiBandRenderer->redBand() << myMultiBandRenderer->greenBand() << myMultiBandRenderer->blueBand();
892  myRasterRenderer = myMultiBandRenderer;
893  myMinMaxOrigin = myMultiBandRenderer->minMaxOrigin();
894  }
895  else if ( rendererType == QLatin1String( "singlebandpseudocolor" ) )
896  {
897  myPseudoColorRenderer = dynamic_cast<QgsSingleBandPseudoColorRenderer *>( rasterRenderer );
898  if ( !myPseudoColorRenderer )
899  {
900  return;
901  }
902  myBands << myPseudoColorRenderer->band();
903  myRasterRenderer = myPseudoColorRenderer;
904  myMinMaxOrigin = myPseudoColorRenderer->minMaxOrigin();
905  }
906  else
907  {
908  return;
909  }
910 
911  Q_FOREACH ( int myBand, myBands )
912  {
913  if ( myBand != -1 )
914  {
915  Qgis::DataType myType = static_cast< Qgis::DataType >( mDataProvider->dataType( myBand ) );
916  std::unique_ptr<QgsContrastEnhancement> myEnhancement( new QgsContrastEnhancement( static_cast< Qgis::DataType >( myType ) ) );
917  myEnhancement->setContrastEnhancementAlgorithm( algorithm, generateLookupTableFlag );
918 
919  double min;
920  double max;
921  computeMinMax( myBand, myMinMaxOrigin, limits, extent, sampleSize, min, max );
922 
923  if ( rendererType == QLatin1String( "singlebandpseudocolor" ) )
924  {
925  myPseudoColorRenderer->setClassificationMin( min );
926  myPseudoColorRenderer->setClassificationMax( max );
927  if ( myPseudoColorRenderer->shader() )
928  {
929  QgsColorRampShader *colorRampShader = dynamic_cast<QgsColorRampShader *>( myPseudoColorRenderer->shader()->rasterShaderFunction() );
930  if ( colorRampShader )
931  {
932  colorRampShader->classifyColorRamp( myPseudoColorRenderer->band(), extent, myPseudoColorRenderer->input() );
933  }
934  }
935  }
936  else
937  {
938  myEnhancement->setMinimumValue( min );
939  myEnhancement->setMaximumValue( max );
940  myEnhancements.append( myEnhancement.release() );
941  }
942  }
943  else
944  {
945  myEnhancements.append( nullptr );
946  }
947  }
948 
949  if ( rendererType == QLatin1String( "singlebandgray" ) )
950  {
951  if ( myEnhancements.first() ) myGrayRenderer->setContrastEnhancement( myEnhancements.takeFirst() );
952  }
953  else if ( rendererType == QLatin1String( "multibandcolor" ) )
954  {
955  if ( myEnhancements.first() ) myMultiBandRenderer->setRedContrastEnhancement( myEnhancements.takeFirst() );
956  if ( myEnhancements.first() ) myMultiBandRenderer->setGreenContrastEnhancement( myEnhancements.takeFirst() );
957  if ( myEnhancements.first() ) myMultiBandRenderer->setBlueContrastEnhancement( myEnhancements.takeFirst() );
958  }
959 
960  //delete all remaining unused enhancements
961  qDeleteAll( myEnhancements );
962 
963  myMinMaxOrigin.setLimits( limits );
964  if ( extent != QgsRectangle() &&
965  myMinMaxOrigin.extent() == QgsRasterMinMaxOrigin::WholeRaster )
966  {
968  }
969  if ( myRasterRenderer )
970  {
971  myRasterRenderer->setMinMaxOrigin( myMinMaxOrigin );
972  }
973 
974  if ( rasterRenderer == renderer() )
975  {
976  emit repaintRequested();
977  emit styleChanged();
978  emit rendererChanged();
979  }
980 }
981 
983 {
984  QgsSingleBandGrayRenderer *singleBandRenderer = nullptr;
985  QgsMultiBandColorRenderer *multiBandRenderer = nullptr;
986  const QgsContrastEnhancement *ce = nullptr;
987  if ( ( singleBandRenderer = dynamic_cast<QgsSingleBandGrayRenderer *>( renderer() ) ) )
988  {
989  ce = singleBandRenderer->contrastEnhancement();
990  }
991  else if ( ( multiBandRenderer = dynamic_cast<QgsMultiBandColorRenderer *>( renderer() ) ) )
992  {
993  ce = multiBandRenderer->redContrastEnhancement();
994  }
995 
996  if ( ce )
997  {
1002  extent,
1003  SAMPLE_SIZE,
1004  true,
1005  renderer() );
1006  }
1007  else
1008  {
1011  if ( defaultContrastEnhancementSettings( myAlgorithm, myLimits ) )
1012  {
1014  myLimits,
1015  extent,
1016  SAMPLE_SIZE,
1017  true,
1018  renderer() );
1019  }
1020  }
1021 }
1022 
1024  const QgsRectangle &extent )
1025 {
1026  if ( !( mDataProvider &&
1027  mLastRectangleUsedByRefreshContrastEnhancementIfNeeded != extent &&
1028  rasterRenderer->minMaxOrigin().limits() != QgsRasterMinMaxOrigin::None &&
1029  rasterRenderer->minMaxOrigin().extent() == QgsRasterMinMaxOrigin::UpdatedCanvas ) )
1030  return;
1031 
1032  QgsSingleBandGrayRenderer *singleBandRenderer = nullptr;
1033  QgsMultiBandColorRenderer *multiBandRenderer = nullptr;
1034  QgsSingleBandPseudoColorRenderer *sbpcr = nullptr;
1035  const QgsContrastEnhancement *ce = nullptr;
1036  if ( ( singleBandRenderer = dynamic_cast<QgsSingleBandGrayRenderer *>( rasterRenderer ) ) )
1037  {
1038  ce = singleBandRenderer->contrastEnhancement();
1039  }
1040  else if ( ( multiBandRenderer = dynamic_cast<QgsMultiBandColorRenderer *>( rasterRenderer ) ) )
1041  {
1042  ce = multiBandRenderer->redContrastEnhancement();
1043  }
1044  else if ( ( sbpcr = dynamic_cast<QgsSingleBandPseudoColorRenderer *>( rasterRenderer ) ) )
1045  {
1046  mLastRectangleUsedByRefreshContrastEnhancementIfNeeded = extent;
1047  double min;
1048  double max;
1049  computeMinMax( sbpcr->band(),
1050  rasterRenderer->minMaxOrigin(),
1051  rasterRenderer->minMaxOrigin().limits(), extent,
1052  SAMPLE_SIZE, min, max );
1053  sbpcr->setClassificationMin( min );
1054  sbpcr->setClassificationMax( max );
1055 
1056  if ( sbpcr->shader() )
1057  {
1058  QgsColorRampShader *colorRampShader = dynamic_cast<QgsColorRampShader *>( sbpcr->shader()->rasterShaderFunction() );
1059  if ( colorRampShader )
1060  {
1061  colorRampShader->classifyColorRamp( sbpcr->band(), extent, rasterRenderer->input() );
1062  }
1063  }
1064 
1066  r->setClassificationMin( min );
1067  r->setClassificationMax( max );
1068 
1069  if ( r->shader() )
1070  {
1071  QgsColorRampShader *colorRampShader = dynamic_cast<QgsColorRampShader *>( r->shader()->rasterShaderFunction() );
1072  if ( colorRampShader )
1073  {
1074  colorRampShader->classifyColorRamp( sbpcr->band(), extent, rasterRenderer->input() );
1075  }
1076  }
1077 
1078  emit repaintRequested();
1079  emit styleChanged();
1080  emit rendererChanged();
1081  return;
1082  }
1083 
1084  if ( ce &&
1086  {
1087  mLastRectangleUsedByRefreshContrastEnhancementIfNeeded = extent;
1088 
1090  rasterRenderer->minMaxOrigin().limits(),
1091  extent,
1092  SAMPLE_SIZE,
1093  true,
1094  rasterRenderer );
1095 
1096  // Update main renderer so that the legends get updated
1097  if ( singleBandRenderer )
1098  static_cast<QgsSingleBandGrayRenderer *>( renderer() )->setContrastEnhancement( new QgsContrastEnhancement( * singleBandRenderer->contrastEnhancement() ) );
1099  else if ( multiBandRenderer )
1100  {
1101  if ( multiBandRenderer->redContrastEnhancement() )
1102  {
1103  static_cast<QgsMultiBandColorRenderer *>( renderer() )->setRedContrastEnhancement( new QgsContrastEnhancement( *multiBandRenderer->redContrastEnhancement() ) );
1104  }
1105  if ( multiBandRenderer->greenContrastEnhancement() )
1106  {
1107  static_cast<QgsMultiBandColorRenderer *>( renderer() )->setGreenContrastEnhancement( new QgsContrastEnhancement( *multiBandRenderer->greenContrastEnhancement() ) );
1108  }
1109  if ( multiBandRenderer->blueContrastEnhancement() )
1110  {
1111  static_cast<QgsMultiBandColorRenderer *>( renderer() )->setBlueContrastEnhancement( new QgsContrastEnhancement( *multiBandRenderer->blueContrastEnhancement() ) );
1112  }
1113  }
1114 
1115  emit styleChanged();
1116  emit rendererChanged();
1117  }
1118 }
1119 
1122  QgsRasterMinMaxOrigin::Limits &myLimits ) const
1123 {
1124  QgsSettings mySettings;
1125 
1126  QString key;
1127  QString defaultAlg;
1128  QString defaultLimits;
1129 
1130  // TODO: we should not test renderer class here, move it somehow to renderers
1131  if ( dynamic_cast<QgsSingleBandGrayRenderer *>( renderer() ) )
1132  {
1133  key = QStringLiteral( "singleBand" );
1136  defaultLimits = QgsRasterMinMaxOrigin::limitsString(
1138  }
1139  else if ( dynamic_cast<QgsMultiBandColorRenderer *>( renderer() ) )
1140  {
1141  if ( QgsRasterBlock::typeSize( dataProvider()->sourceDataType( 1 ) ) == 1 )
1142  {
1143  key = QStringLiteral( "multiBandSingleByte" );
1146  defaultLimits = QgsRasterMinMaxOrigin::limitsString(
1148  }
1149  else
1150  {
1151  key = QStringLiteral( "multiBandMultiByte" );
1154  defaultLimits = QgsRasterMinMaxOrigin::limitsString(
1156  }
1157  }
1158 
1159  if ( key.isEmpty() )
1160  {
1161  QgsDebugMsg( "No default contrast enhancement for this drawing style" );
1163  myLimits = QgsRasterMinMaxOrigin::limitsFromString( QString() );
1164  return false;
1165  }
1166  QgsDebugMsgLevel( "key = " + key, 4 );
1167 
1168  QString myAlgorithmString = mySettings.value( "/Raster/defaultContrastEnhancementAlgorithm/" + key, defaultAlg ).toString();
1169  QgsDebugMsgLevel( "myAlgorithmString = " + myAlgorithmString, 4 );
1170 
1171  myAlgorithm = QgsContrastEnhancement::contrastEnhancementAlgorithmFromString( myAlgorithmString );
1172 
1173  QString myLimitsString = mySettings.value( "/Raster/defaultContrastEnhancementLimits/" + key, defaultLimits ).toString();
1174  QgsDebugMsgLevel( "myLimitsString = " + myLimitsString, 4 );
1175  myLimits = QgsRasterMinMaxOrigin::limitsFromString( myLimitsString );
1176 
1177  return true;
1178 }
1179 
1181 {
1182  QgsDebugMsgLevel( "Entered", 4 );
1183 
1186  defaultContrastEnhancementSettings( myAlgorithm, myLimits );
1187 
1188  setContrastEnhancement( myAlgorithm, myLimits );
1189 }
1190 
1191 void QgsRasterLayer::setLayerOrder( QStringList const &layers )
1192 {
1193  QgsDebugMsgLevel( "entered.", 4 );
1194 
1195  if ( mDataProvider )
1196  {
1197  QgsDebugMsgLevel( "About to mDataProvider->setLayerOrder(layers).", 4 );
1198  mDataProvider->setLayerOrder( layers );
1199  }
1200 
1201 }
1202 
1203 void QgsRasterLayer::setSubLayerVisibility( const QString &name, bool vis )
1204 {
1205 
1206  if ( mDataProvider )
1207  {
1208  QgsDebugMsgLevel( "About to mDataProvider->setSubLayerVisibility(name, vis).", 4 );
1209  mDataProvider->setSubLayerVisibility( name, vis );
1210  }
1211 
1212 }
1213 
1214 QDateTime QgsRasterLayer::timestamp() const
1215 {
1216  return mDataProvider->timestamp();
1217 }
1218 
1220 {
1221  QgsDebugMsgLevel( "Entered", 4 );
1222  if ( !renderer )
1223  {
1224  return;
1225  }
1226 
1227  mPipe.set( renderer );
1228  emit rendererChanged();
1229  emit styleChanged();
1230 }
1231 
1232 void QgsRasterLayer::showStatusMessage( QString const &message )
1233 {
1234  // QgsDebugMsg(QString("entered with '%1'.").arg(theMessage));
1235 
1236  // Pass-through
1237  // TODO: See if we can connect signal-to-signal. This is a kludge according to the Qt doc.
1238  emit statusChanged( message );
1239 }
1240 
1241 QStringList QgsRasterLayer::subLayers() const
1242 {
1243  return mDataProvider->subLayers();
1244 }
1245 
1246 // this function should be used when rendering with the MTR engine introduced in 2.3, as QPixmap is not thread safe (see bug #9626)
1247 // note: previewAsImage and previewAsPixmap should use a common low-level fct QgsRasterLayer::previewOnPaintDevice( QSize size, QColor bgColor, QPaintDevice &device )
1248 QImage QgsRasterLayer::previewAsImage( QSize size, const QColor &bgColor, QImage::Format format )
1249 {
1250  QImage myQImage( size, format );
1251 
1252  myQImage.setColor( 0, bgColor.rgba() );
1253  myQImage.fill( 0 ); //defaults to white, set to transparent for rendering on a map
1254 
1255  QgsRasterViewPort *myRasterViewPort = new QgsRasterViewPort();
1256 
1257  double myMapUnitsPerPixel;
1258  double myX = 0.0;
1259  double myY = 0.0;
1260  QgsRectangle myExtent = mDataProvider->extent();
1261  if ( myExtent.width() / myExtent.height() >= static_cast< double >( myQImage.width() ) / myQImage.height() )
1262  {
1263  myMapUnitsPerPixel = myExtent.width() / myQImage.width();
1264  myY = ( myQImage.height() - myExtent.height() / myMapUnitsPerPixel ) / 2;
1265  }
1266  else
1267  {
1268  myMapUnitsPerPixel = myExtent.height() / myQImage.height();
1269  myX = ( myQImage.width() - myExtent.width() / myMapUnitsPerPixel ) / 2;
1270  }
1271 
1272  double myPixelWidth = myExtent.width() / myMapUnitsPerPixel;
1273  double myPixelHeight = myExtent.height() / myMapUnitsPerPixel;
1274 
1275  myRasterViewPort->mTopLeftPoint = QgsPointXY( myX, myY );
1276  myRasterViewPort->mBottomRightPoint = QgsPointXY( myPixelWidth, myPixelHeight );
1277  myRasterViewPort->mWidth = myQImage.width();
1278  myRasterViewPort->mHeight = myQImage.height();
1279 
1280  myRasterViewPort->mDrawnExtent = myExtent;
1281  myRasterViewPort->mSrcCRS = QgsCoordinateReferenceSystem(); // will be invalid
1282  myRasterViewPort->mDestCRS = QgsCoordinateReferenceSystem(); // will be invalid
1283  myRasterViewPort->mSrcDatumTransform = -1;
1284  myRasterViewPort->mDestDatumTransform = -1;
1285 
1286  QgsMapToPixel *myMapToPixel = new QgsMapToPixel( myMapUnitsPerPixel );
1287 
1288  QPainter *myQPainter = new QPainter( &myQImage );
1289  draw( myQPainter, myRasterViewPort, myMapToPixel );
1290  delete myRasterViewPort;
1291  delete myMapToPixel;
1292  myQPainter->end();
1293  delete myQPainter;
1294 
1295  return myQImage;
1296 }
1297 
1299 //
1300 // Protected methods
1301 //
1303 /*
1304  * @param QDomNode node that will contain the symbology definition for this layer.
1305  * @param errorMessage reference to string that will be updated with any error messages
1306  * @return true in case of success.
1307  */
1308 bool QgsRasterLayer::readSymbology( const QDomNode &layer_node, QString &errorMessage, const QgsReadWriteContext &context )
1309 {
1310  Q_UNUSED( errorMessage );
1311  QDomElement rasterRendererElem;
1312 
1313  QDomElement layerElement = layer_node.toElement();
1314  readCommonStyle( layerElement, context );
1315 
1316  // pipe element was introduced in the end of 1.9 development when there were
1317  // already many project files in use so we support 1.9 backward compatibility
1318  // even it was never officially released -> use pipe element if present, otherwise
1319  // use layer node
1320  QDomNode pipeNode = layer_node.firstChildElement( QStringLiteral( "pipe" ) );
1321  if ( pipeNode.isNull() ) // old project
1322  {
1323  pipeNode = layer_node;
1324  }
1325 
1326  //rasterlayerproperties element there -> old format (1.8 and early 1.9)
1327  if ( !layer_node.firstChildElement( QStringLiteral( "rasterproperties" ) ).isNull() )
1328  {
1329  //copy node because layer_node is const
1330  QDomNode layerNodeCopy = layer_node.cloneNode();
1331  QDomDocument doc = layerNodeCopy.ownerDocument();
1332  QDomElement rasterPropertiesElem = layerNodeCopy.firstChildElement( QStringLiteral( "rasterproperties" ) );
1333  QgsProjectFileTransform::convertRasterProperties( doc, layerNodeCopy, rasterPropertiesElem,
1334  this );
1335  rasterRendererElem = layerNodeCopy.firstChildElement( QStringLiteral( "rasterrenderer" ) );
1336  QgsDebugMsgLevel( doc.toString(), 4 );
1337  }
1338  else
1339  {
1340  rasterRendererElem = pipeNode.firstChildElement( QStringLiteral( "rasterrenderer" ) );
1341  }
1342 
1343  if ( !rasterRendererElem.isNull() )
1344  {
1345  QString rendererType = rasterRendererElem.attribute( QStringLiteral( "type" ) );
1346  QgsRasterRendererRegistryEntry rendererEntry;
1347  if ( QgsApplication::rasterRendererRegistry()->rendererData( rendererType, rendererEntry ) )
1348  {
1349  QgsRasterRenderer *renderer = rendererEntry.rendererCreateFunction( rasterRendererElem, dataProvider() );
1350  mPipe.set( renderer );
1351  }
1352  }
1353 
1354  //brightness
1356  mPipe.set( brightnessFilter );
1357 
1358  //brightness coefficient
1359  QDomElement brightnessElem = pipeNode.firstChildElement( QStringLiteral( "brightnesscontrast" ) );
1360  if ( !brightnessElem.isNull() )
1361  {
1362  brightnessFilter->readXml( brightnessElem );
1363  }
1364 
1365  //hue/saturation
1367  mPipe.set( hueSaturationFilter );
1368 
1369  //saturation coefficient
1370  QDomElement hueSaturationElem = pipeNode.firstChildElement( QStringLiteral( "huesaturation" ) );
1371  if ( !hueSaturationElem.isNull() )
1372  {
1373  hueSaturationFilter->readXml( hueSaturationElem );
1374  }
1375 
1376  //resampler
1378  mPipe.set( resampleFilter );
1379 
1380  //max oversampling
1381  QDomElement resampleElem = pipeNode.firstChildElement( QStringLiteral( "rasterresampler" ) );
1382  if ( !resampleElem.isNull() )
1383  {
1384  resampleFilter->readXml( resampleElem );
1385  }
1386 
1387  // get and set the blend mode if it exists
1388  QDomNode blendModeNode = layer_node.namedItem( QStringLiteral( "blendMode" ) );
1389  if ( !blendModeNode.isNull() )
1390  {
1391  QDomElement e = blendModeNode.toElement();
1392  setBlendMode( QgsPainting::getCompositionMode( static_cast< QgsPainting::BlendMode >( e.text().toInt() ) ) );
1393  }
1394 
1395  readCustomProperties( layer_node );
1396 
1397  return true;
1398 }
1399 
1400 bool QgsRasterLayer::readStyle( const QDomNode &node, QString &errorMessage, const QgsReadWriteContext &context )
1401 {
1402  return readSymbology( node, errorMessage, context );
1403 } //readSymbology
1404 
1411 bool QgsRasterLayer::readXml( const QDomNode &layer_node, const QgsReadWriteContext &context )
1412 {
1413  QgsDebugMsgLevel( "Entered", 4 );
1414  // Make sure to read the file first so stats etc are initialized properly!
1415 
1416  //process provider key
1417  QDomNode pkeyNode = layer_node.namedItem( QStringLiteral( "provider" ) );
1418 
1419  if ( pkeyNode.isNull() )
1420  {
1421  mProviderKey = QStringLiteral( "gdal" );
1422  }
1423  else
1424  {
1425  QDomElement pkeyElt = pkeyNode.toElement();
1426  mProviderKey = pkeyElt.text();
1427  if ( mProviderKey.isEmpty() )
1428  {
1429  mProviderKey = QStringLiteral( "gdal" );
1430  }
1431  }
1432 
1433  // Open the raster source based on provider and datasource
1434 
1435  // Go down the raster-data-provider paradigm
1436 
1437  // Collect provider-specific information
1438 
1439  QDomNode rpNode = layer_node.namedItem( QStringLiteral( "rasterproperties" ) );
1440 
1441  if ( mProviderKey == QLatin1String( "wms" ) )
1442  {
1443  // >>> BACKWARD COMPATIBILITY < 1.9
1444  // The old WMS URI format does not contain all the information, we add them here.
1445  if ( !mDataSource.contains( QLatin1String( "crs=" ) ) && !mDataSource.contains( QLatin1String( "format=" ) ) )
1446  {
1447  QgsDebugMsgLevel( "Old WMS URI format detected -> adding params", 4 );
1448  QgsDataSourceUri uri;
1449  uri.setEncodedUri( mDataSource );
1450  QDomElement layerElement = rpNode.firstChildElement( QStringLiteral( "wmsSublayer" ) );
1451  while ( !layerElement.isNull() )
1452  {
1453  // TODO: sublayer visibility - post-0.8 release timeframe
1454 
1455  // collect name for the sublayer
1456  uri.setParam( QStringLiteral( "layers" ), layerElement.namedItem( QStringLiteral( "name" ) ).toElement().text() );
1457 
1458  // collect style for the sublayer
1459  uri.setParam( QStringLiteral( "styles" ), layerElement.namedItem( QStringLiteral( "style" ) ).toElement().text() );
1460 
1461  layerElement = layerElement.nextSiblingElement( QStringLiteral( "wmsSublayer" ) );
1462  }
1463 
1464  // Collect format
1465  QDomNode formatNode = rpNode.namedItem( QStringLiteral( "wmsFormat" ) );
1466  uri.setParam( QStringLiteral( "format" ), rpNode.namedItem( QStringLiteral( "wmsFormat" ) ).toElement().text() );
1467 
1468  // WMS CRS URL param should not be mixed with that assigned to the layer.
1469  // In the old WMS URI version there was no CRS and layer crs().authid() was used.
1470  uri.setParam( QStringLiteral( "crs" ), crs().authid() );
1471  mDataSource = uri.encodedUri();
1472  }
1473  // <<< BACKWARD COMPATIBILITY < 1.9
1474  }
1475 
1476  setDataProvider( mProviderKey );
1477  if ( !mValid ) return false;
1478 
1479  QString error;
1480  bool res = readSymbology( layer_node, error, context );
1481 
1482  // old wms settings we need to correct
1483  if ( res && mProviderKey == QLatin1String( "wms" ) && ( !renderer() || renderer()->type() != QLatin1String( "singlebandcolordata" ) ) )
1484  {
1485  setRendererForDrawingStyle( QgsRaster::SingleBandColorDataStyle );
1486  }
1487 
1488  // Check timestamp
1489  // This was probably introduced to reload completely raster if data changed and
1490  // reset completely symbology to reflect new data type etc. It creates however
1491  // problems, because user defined symbology is complete lost if data file time
1492  // changed (the content may be the same). See also 6900.
1493 #if 0
1494  QDomNode stampNode = layer_node.namedItem( "timestamp" );
1495  if ( !stampNode.isNull() )
1496  {
1497  QDateTime stamp = QDateTime::fromString( stampNode.toElement().text(), Qt::ISODate );
1498  // TODO: very bad, we have to load twice!!! Make QgsDataProvider::timestamp() static?
1499  if ( stamp < mDataProvider->dataTimestamp() )
1500  {
1501  QgsDebugMsg( "data changed, reload provider" );
1502  closeDataProvider();
1503  init();
1504  setDataProvider( mProviderKey );
1505  if ( !mValid ) return false;
1506  }
1507  }
1508 #endif
1509 
1510  // Load user no data value
1511  QDomElement noDataElement = layer_node.firstChildElement( QStringLiteral( "noData" ) );
1512 
1513  QDomNodeList noDataBandList = noDataElement.elementsByTagName( QStringLiteral( "noDataList" ) );
1514 
1515  for ( int i = 0; i < noDataBandList.size(); ++i )
1516  {
1517  QDomElement bandElement = noDataBandList.at( i ).toElement();
1518  bool ok;
1519  int bandNo = bandElement.attribute( QStringLiteral( "bandNo" ) ).toInt( &ok );
1520  QgsDebugMsgLevel( QString( "bandNo = %1" ).arg( bandNo ), 4 );
1521  if ( ok && ( bandNo > 0 ) && ( bandNo <= mDataProvider->bandCount() ) )
1522  {
1523  mDataProvider->setUseSourceNoDataValue( bandNo, bandElement.attribute( QStringLiteral( "useSrcNoData" ) ).toInt() );
1524  QgsRasterRangeList myNoDataRangeList;
1525 
1526  QDomNodeList rangeList = bandElement.elementsByTagName( QStringLiteral( "noDataRange" ) );
1527 
1528  myNoDataRangeList.reserve( rangeList.size() );
1529  for ( int j = 0; j < rangeList.size(); ++j )
1530  {
1531  QDomElement rangeElement = rangeList.at( j ).toElement();
1532  QgsRasterRange myNoDataRange( rangeElement.attribute( QStringLiteral( "min" ) ).toDouble(),
1533  rangeElement.attribute( QStringLiteral( "max" ) ).toDouble() );
1534  QgsDebugMsgLevel( QString( "min = %1 %2" ).arg( rangeElement.attribute( "min" ) ).arg( myNoDataRange.min() ), 4 );
1535  myNoDataRangeList << myNoDataRange;
1536  }
1537  mDataProvider->setUserNoDataValue( bandNo, myNoDataRangeList );
1538  }
1539  }
1540 
1541  readStyleManager( layer_node );
1542 
1543  return res;
1544 } // QgsRasterLayer::readXml( QDomNode & layer_node )
1545 
1546 /*
1547  * @param QDomNode the node that will have the style element added to it.
1548  * @param QDomDocument the document that will have the QDomNode added.
1549  * @param errorMessage reference to string that will be updated with any error messages
1550  * @return true in case of success.
1551  */
1552 bool QgsRasterLayer::writeSymbology( QDomNode &layer_node, QDomDocument &document, QString &errorMessage, const QgsReadWriteContext &context ) const
1553 {
1554  Q_UNUSED( errorMessage );
1555 
1556  QDomElement layerElement = layer_node.toElement();
1557  writeCommonStyle( layerElement, document, context );
1558 
1559  // Store pipe members (except provider) into pipe element, in future, it will be
1560  // possible to add custom filters into the pipe
1561  QDomElement pipeElement = document.createElement( QStringLiteral( "pipe" ) );
1562 
1563  for ( int i = 1; i < mPipe.size(); i++ )
1564  {
1565  QgsRasterInterface *interface = mPipe.at( i );
1566  if ( !interface ) continue;
1567  interface->writeXml( document, pipeElement );
1568  }
1569 
1570  layer_node.appendChild( pipeElement );
1571 
1572  // add blend mode node
1573  QDomElement blendModeElement = document.createElement( QStringLiteral( "blendMode" ) );
1574  QDomText blendModeText = document.createTextNode( QString::number( QgsPainting::getBlendModeEnum( blendMode() ) ) );
1575  blendModeElement.appendChild( blendModeText );
1576  layer_node.appendChild( blendModeElement );
1577 
1578  return true;
1579 }
1580 
1581 bool QgsRasterLayer::writeStyle( QDomNode &node, QDomDocument &doc, QString &errorMessage, const QgsReadWriteContext &context ) const
1582 {
1583  return writeSymbology( node, doc, errorMessage, context );
1584 
1585 } // bool QgsRasterLayer::writeSymbology
1586 
1587 /*
1588  * virtual
1589  * \note Called by QgsMapLayer::writeXml().
1590  */
1591 bool QgsRasterLayer::writeXml( QDomNode &layer_node,
1592  QDomDocument &document,
1593  const QgsReadWriteContext &context ) const
1594 {
1595  // first get the layer element so that we can append the type attribute
1596 
1597  QDomElement mapLayerNode = layer_node.toElement();
1598 
1599  if ( mapLayerNode.isNull() || "maplayer" != mapLayerNode.nodeName() )
1600  {
1601  QgsMessageLog::logMessage( tr( "<maplayer> not found." ), tr( "Raster" ) );
1602  return false;
1603  }
1604 
1605  mapLayerNode.setAttribute( QStringLiteral( "type" ), QStringLiteral( "raster" ) );
1606 
1607  // add provider node
1608 
1609  QDomElement provider = document.createElement( QStringLiteral( "provider" ) );
1610  QDomText providerText = document.createTextNode( mProviderKey );
1611  provider.appendChild( providerText );
1612  layer_node.appendChild( provider );
1613 
1614  // User no data
1615  QDomElement noData = document.createElement( QStringLiteral( "noData" ) );
1616 
1617  for ( int bandNo = 1; bandNo <= mDataProvider->bandCount(); bandNo++ )
1618  {
1619  QDomElement noDataRangeList = document.createElement( QStringLiteral( "noDataList" ) );
1620  noDataRangeList.setAttribute( QStringLiteral( "bandNo" ), bandNo );
1621  noDataRangeList.setAttribute( QStringLiteral( "useSrcNoData" ), mDataProvider->useSourceNoDataValue( bandNo ) );
1622 
1623  Q_FOREACH ( QgsRasterRange range, mDataProvider->userNoDataValues( bandNo ) )
1624  {
1625  QDomElement noDataRange = document.createElement( QStringLiteral( "noDataRange" ) );
1626 
1627  noDataRange.setAttribute( QStringLiteral( "min" ), QgsRasterBlock::printValue( range.min() ) );
1628  noDataRange.setAttribute( QStringLiteral( "max" ), QgsRasterBlock::printValue( range.max() ) );
1629  noDataRangeList.appendChild( noDataRange );
1630  }
1631 
1632  noData.appendChild( noDataRangeList );
1633 
1634  }
1635  if ( noData.hasChildNodes() )
1636  {
1637  layer_node.appendChild( noData );
1638  }
1639 
1640  writeStyleManager( layer_node, document );
1641 
1642  //write out the symbology
1643  QString errorMsg;
1644  return writeSymbology( layer_node, document, errorMsg, context );
1645 }
1646 
1648 {
1649  if ( !mDataProvider ) return 0;
1650  return mDataProvider->xSize();
1651 }
1652 
1654 {
1655  if ( !mDataProvider ) return 0;
1656  return mDataProvider->ySize();
1657 }
1658 
1660 //
1661 // Private methods
1662 //
1664 bool QgsRasterLayer::update()
1665 {
1666  QgsDebugMsgLevel( "entered.", 4 );
1667  // Check if data changed
1668  if ( mDataProvider->dataTimestamp() > mDataProvider->timestamp() )
1669  {
1670  QgsDebugMsgLevel( "reload data", 4 );
1671  closeDataProvider();
1672  init();
1673  setDataProvider( mProviderKey );
1674  emit dataChanged();
1675  }
1676  return mValid;
1677 }
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.
void writeCommonStyle(QDomElement &layerElement, QDomDocument &document, const QgsReadWriteContext &context) const
Write style data common to all layer types.
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:57
A rectangle specified with double values.
Definition: qgsrectangle.h:39
Base class for all map layer types.
Definition: qgsmaplayer.h:56
Thirty two bit signed integer (qint32)
Definition: qgis.h:98
Interface for all raster shaders.
void setColorRampItemList(const QList< QgsColorRampShader::ColorRampItem > &list)
Set custom colormap.
QgsRasterLayer * clone() const override
Returns a new instance equivalent to this one.
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:57
QgsHueSaturationFilter * hueSaturationFilter() const
DrawingStyle
This enumerator describes the different kinds of drawing we can do.
Definition: qgsraster.h:89
A ramp shader will color a raster pixel based on a list of values ranges in a ramp.
virtual QList< QgsColorRampShader::ColorRampItem > colorTable(int bandNo) const
virtual QgsError error() const
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:38
virtual QgsError error() const
Get current status error.
This class provides qgis with the ability to render raster datasets onto the mapcanvas.
void setLayerOrder(const QStringList &layers) override
Reorders the previously selected sublayers of this layer from bottom to top.
double rasterUnitsPerPixelX() const
Returns the number of raster units per each raster pixel in X axis. 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 readCommonStyle(const QDomElement &layerElement, const QgsReadWriteContext &context)
Read style data common to all layer types.
void willBeDeleted()
Emitted in the destructor when the layer is about to be deleted, but it is still in a perfectly valid...
QgsRasterPipe * pipe()
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:43
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:97
void readCustomProperties(const QDomNode &layerNode, const QString &keyStartsWith=QString())
Read custom properties from project file.
static QgsPainting::BlendMode getBlendModeEnum(QPainter::CompositionMode blendMode)
Returns a BlendMode corresponding to a QPainter::CompositionMode.
Definition: qgspainting.cpp:80
DataType
Raster data types.
Definition: qgis.h:91
QgsRasterInterface * last() const
double maximumValue
The maximum cell value in the raster band.
static Limits limitsFromString(const QString &limits)
Deserialize Limits.
const QgsContrastEnhancement * contrastEnhancement() const
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)
Qgis::DataType sourceDataType(int bandNo) const override=0
Returns source data type for the band specified by number, source data type may be shorter than dataT...
static QDateTime lastModified(const QString &name)
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:20
Raster values range container.
Resample filter pipe for rasters.
Abstract base class for spatial data provider implementations.
bool writeSymbology(QDomNode &, QDomDocument &doc, QString &errorMessage, const QgsReadWriteContext &context) const override
Write the symbology for the layer into the docment provided.
const QgsRasterMinMaxOrigin & minMaxOrigin() const
Returns const reference to origin of min/max values.
QgsRasterRenderer * renderer() const
int height() const
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:99
bool isValid() const
Return the status of the layer.
Implementation of threaded rendering for raster layers.
void setBlendMode(QPainter::CompositionMode blendMode)
Set the blending mode used for rendering a layer.
QgsRasterShader * shader()
Returns the raster shader.
virtual void cumulativeCut(int bandNo, double lowerCount, double upperCount, double &lowerValue, double &upperValue, const QgsRectangle &extent=QgsRectangle(), int sampleSize=0)
Find values for cumulative pixel count cut.
QgsMapLayer::LayerType type() const
Returns the type of the layer.
QPixmap paletteAsPixmap(int bandNumber=1)
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:96
QDateTime timestamp() const override
Time stamp of data source in the moment when data/metadata were loaded by provider.
Complex Int16.
Definition: qgis.h:101
QString mLayerName
Name of the layer - used for display.
Definition: qgsmaplayer.h:1239
bool qgsDoubleNear(double a, double b, double epsilon=4 *DBL_EPSILON)
Compare two doubles (but allow some difference)
Definition: qgis.h:251
static void logMessage(const QString &message, const QString &tag=QString(), Qgis::MessageLevel level=Qgis::Warning)
add a message to the instance (and create it if necessary)
void setShader(QgsRasterShader *shader)
Takes ownership of the shader.
void styleChanged()
Signal emitted whenever a change affects the layer&#39;s style.
void setGreenContrastEnhancement(QgsContrastEnhancement *ce)
Takes ownership.
void statusChanged(const QString &) const
Emit a message to be displayed on status bar, usually used by network providers (WMS,WCS)
Sixty four bit floating point (double)
Definition: qgis.h:100
Current extent of the canvas (at the time of computation) is used to compute statistics.
static QString identifyFormatName(QgsRaster::IdentifyFormat format)
virtual QgsRectangle extent() const
Returns the extent of the layer.
void setExtent(QgsRasterMinMaxOrigin::Extent extent)
Set extent.
QgsCoordinateReferenceSystem mDestCRS
Target coordinate system.
virtual QgsLayerMetadata layerMetadata() const
Returns layer metadata collected from the provider&#39;s source.
QgsBrightnessContrastFilter * brightnessFilter() const
void setCrs(const QgsCoordinateReferenceSystem &srcCRS, const QgsCoordinateReferenceSystem &destCRS, int srcDatumTransform=-1, int destDatumTransform=-1)
set source and destination CRS
QDateTime timestamp() const override
Time stamp of data source in the moment when data/metadata were loaded by provider.
void statusChanged(const QString &status)
Emit a signal with status (e.g. to be caught by QgisApp and display a msg on status bar) ...
double cumulativeCutLower() const
Return lower bound of cumulative cut method (between 0 and 1).
Color, alpha, red, green, blue, 4 bytes the same as QImage::Format_ARGB32_Premultiplied.
Definition: qgis.h:106
Perform transforms between map coordinates and device coordinates.
Definition: qgsmaptopixel.h:36
static const QgsRasterMinMaxOrigin::Limits MULTIPLE_BAND_SINGLE_BYTE_MIN_MAX_LIMITS
Default enhancement limits for multiple band raster of type Byte.
The drawing pipe for raster layers.
double stdDev
The standard deviation of the cell values.
Paletted (see associated color table)
Definition: qgsraster.h:39
void setContrastEnhancement(QgsContrastEnhancement::ContrastEnhancementAlgorithm algorithm, QgsRasterMinMaxOrigin::Limits limits=QgsRasterMinMaxOrigin::MinMax, const QgsRectangle &extent=QgsRectangle(), int sampleSize=QgsRasterLayer::SAMPLE_SIZE, bool generateLookupTableFlag=true)
Set contrast enhancement algorithm.
void setColorRampType(QgsColorRampShader::Type colorRampType)
Set the color ramp type.
Alpha (0=transparent, 255=opaque)
Definition: qgsraster.h:43
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.
Continuous palette, QGIS addition, GRASS.
Definition: qgsraster.h:54
void readStyleManager(const QDomNode &layerNode)
Read style manager&#39;s configuration (if any). To be called by subclasses.
void setRedContrastEnhancement(QgsContrastEnhancement *ce)
Takes ownership.
#define QgsDebugMsgLevel(str, level)
Definition: qgslogger.h:39
bool isEmpty() const
Returns true if the rectangle is empty.
virtual void setMetadata(const QgsLayerMetadata &metadata)
Sets the layer&#39;s metadata store.
void setCrs(const QgsCoordinateReferenceSystem &srs, bool emitSignal=true)
Sets layer&#39;s spatial reference system.
QgsPointXY mBottomRightPoint
Coordinate (in output device coordinate system) of bottom right corner of the part of the raster that...
virtual int capabilities() const
Returns a bitmask containing the supported capabilities.
QgsRectangle extent() const override=0
Returns the extent of the layer.
virtual bool isValid() const =0
Returns true if this is a valid layer.
virtual QgsCoordinateReferenceSystem crs() const =0
Returns the coordinate system for the data source.
static const QgsContrastEnhancement::ContrastEnhancementAlgorithm SINGLE_BAND_ENHANCEMENT_ALGORITHM
Default enhancement algorithm for single band raster.
bool loadDefaultStyle
Set to true if the default layer style should be loaded.
QgsRasterInterface * at(int idx) const
QString providerType() const
[ data provider interface ] Which provider is being used for this Raster Layer?
double width() const
Returns the width of the rectangle.
Definition: qgsrectangle.h:142
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:103
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:102
static int typeSize(int dataType)
void setParam(const QString &key, const QString &value)
Set generic param (generic mode)
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:95
virtual void setLayerOrder(const QStringList &layers)
Reorder the list of layer names to be rendered by this provider (in order from bottom to top) ...
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:1233
#define cast_to_fptr(f)
Definition: qgis.h:170
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.
void setSubLayerVisibility(const QString &name, bool vis) override
Set the visibility of the given sublayer name.
bool shade(double value, int *returnRedValue, int *returnGreenValue, int *returnBlueValue, int *returnAlphaValue) override
Generates and new RGB value based on one input value.
virtual QString htmlMetadata()=0
Get metadata in a format suitable for feeding directly into a subset of the GUI raster properties "Me...
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.
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:1236
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.
Provider can read layer metadata from data store. Since QGIS 3.0. See QgsDataProvider::layerMetadata(...
ContrastEnhancementAlgorithm contrastEnhancementAlgorithm() const
Greyscale.
Definition: qgsraster.h:38
bool isvalidrasterfilename_t(QString const &fileNameQString, QString &retErrMsg)
QStringList subLayers() const override
Returns the sublayers of this layer - useful for providers that manage their own layers, such as WMS.
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:1225
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.
~QgsRasterLayer() override
This class provides details of the viewable area that a raster will be rendered into.
QDateTime dataTimestamp() const override
Current time stamp of data source.
virtual bool useSourceNoDataValue(int bandNo) const
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
void reload() override
Synchronises with changes in the datasource.
void setLegend(QgsMapLayerLegend *legend)
Assign a legend controller to the map layer.
Class for storing the component parts of a PostgreSQL/RDBMS datasource URI.
virtual void setUserNoDataValue(int bandNo, const QgsRasterRangeList &noData)
Complex Float64.
Definition: qgis.h:104
QgsLegendColorList legendSymbologyItems() const
Returns a list with classification items (Text and color)
virtual QgsRasterDataProvider::ProviderCapabilities providerCapabilities() const
Returns flags containing the supported capabilities of the data provider.
void readXml(const QDomElement &filterElem) override
Sets base class members from xml. Usually called from create() methods of subclasses.
double stdDevFactor() const
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:1227
QString authid() const
Returns the authority identifier for the CRS.
Eight bit unsigned integer (quint8)
Definition: qgis.h:94
Qgis::DataType dataType(int bandNo) const override=0
Returns data type for the band specified by number.
Setting options for loading raster layers.
static const QgsRasterMinMaxOrigin::Limits MULTIPLE_BAND_MULTI_BYTE_MIN_MAX_LIMITS
Default enhancement limits for multiple band raster of type different from Byte.
int band() const
Returns the band used by the renderer.
Color, alpha, red, green, blue, 4 bytes the same as QImage::Format_ARGB32.
Definition: qgis.h:105
QPainter::CompositionMode blendMode() const
Returns the current blending mode for a layer.
double height() const
Returns the height of the rectangle.
Definition: qgsrectangle.h:149
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.