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