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