QGIS API Documentation  2.0.1-Dufour
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Groups Pages
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"
18 #include "qgscolorrampshader.h"
20 #include "qgscoordinatetransform.h"
21 #include "qgsdatasourceuri.h"
22 #include "qgslogger.h"
23 #include "qgsmaplayerregistry.h"
24 #include "qgsmaptopixel.h"
25 #include "qgsmessagelog.h"
29 #include "qgsproviderregistry.h"
30 #include "qgspseudocolorshader.h"
31 #include "qgsrasterdrawer.h"
32 #include "qgsrasteriterator.h"
33 #include "qgsrasterlayer.h"
34 #include "qgsrasterprojector.h"
35 #include "qgsrasterrange.h"
37 #include "qgsrectangle.h"
38 #include "qgsrendercontext.h"
42 
43 #include <cmath>
44 #include <cstdio>
45 #include <limits>
46 #include <typeinfo>
47 
48 #include <QApplication>
49 #include <QCursor>
50 #include <QDomElement>
51 #include <QDomNode>
52 #include <QFile>
53 #include <QFileInfo>
54 #include <QFont>
55 #include <QFontMetrics>
56 #include <QFrame>
57 #include <QImage>
58 #include <QLabel>
59 #include <QLibrary>
60 #include <QList>
61 #include <QMatrix>
62 #include <QMessageBox>
63 #include <QPainter>
64 #include <QPixmap>
65 #include <QRegExp>
66 #include <QSettings>
67 #include <QSlider>
68 #include <QTime>
69 
70 // typedefs for provider plugin functions of interest
71 typedef bool isvalidrasterfilename_t( QString const & theFileNameQString, QString & retErrMsg );
72 
73 #define ERR(message) QGS_ERROR_MESSAGE(message,"Raster layer")
74 
75 const double QgsRasterLayer::CUMULATIVE_CUT_LOWER = 0.02;
76 const double QgsRasterLayer::CUMULATIVE_CUT_UPPER = 0.98;
77 const double QgsRasterLayer::SAMPLE_SIZE = 250000;
78 
80  : QgsMapLayer( RasterLayer )
81  , QSTRING_NOT_SET( "Not Set" )
82  , TRSTRING_NOT_SET( tr( "Not Set" ) )
83  , mDataProvider( 0 )
84 {
85  init();
86  mValid = false;
87 }
88 
90  QString const & path,
91  QString const & baseName,
92  bool loadDefaultStyleFlag )
93  : QgsMapLayer( RasterLayer, baseName, path )
94  , QSTRING_NOT_SET( "Not Set" )
95  , TRSTRING_NOT_SET( tr( "Not Set" ) )
96  , mDataProvider( 0 )
97 {
98  QgsDebugMsg( "Entered" );
99 
100  // TODO, call constructor with provider key
101  init();
102  setDataProvider( "gdal" );
103  if ( !mValid ) return;
104 
105  bool defaultLoadedFlag = false;
106  if ( mValid && loadDefaultStyleFlag )
107  {
108  loadDefaultStyle( defaultLoadedFlag );
109  }
110  if ( !defaultLoadedFlag )
111  {
113  }
114  return;
115 } // QgsRasterLayer ctor
116 
121 QgsRasterLayer::QgsRasterLayer( const QString & uri,
122  const QString & baseName,
123  const QString & providerKey,
124  bool loadDefaultStyleFlag )
125  : QgsMapLayer( RasterLayer, baseName, uri )
126  // Constant that signals property not used.
127  , QSTRING_NOT_SET( "Not Set" )
128  , TRSTRING_NOT_SET( tr( "Not Set" ) )
129  , mDataProvider( 0 )
130  , mProviderKey( providerKey )
131 {
132  QgsDebugMsg( "Entered" );
133  init();
134  setDataProvider( providerKey );
135  if ( !mValid ) return;
136 
137  // load default style
138  bool defaultLoadedFlag = false;
139  if ( mValid && loadDefaultStyleFlag )
140  {
141  loadDefaultStyle( defaultLoadedFlag );
142  }
143  if ( !defaultLoadedFlag )
144  {
146  }
147 
148  // TODO: Connect signals from the dataprovider to the qgisapp
149 
150  emit statusChanged( tr( "QgsRasterLayer created" ) );
151 } // QgsRasterLayer ctor
152 
154 {
155  mValid = false;
156  // Note: provider and other interfaces are owned and deleted by pipe
157 }
158 
160 //
161 // Static Methods and members
162 //
164 
168 bool QgsRasterLayer::isValidRasterFileName( QString const & theFileNameQString, QString & retErrMsg )
169 {
170  isvalidrasterfilename_t *pValid = ( isvalidrasterfilename_t * ) cast_to_fptr( QgsProviderRegistry::instance()->function( "gdal", "isValidRasterFileName" ) );
171  if ( ! pValid )
172  {
173  QgsDebugMsg( "Could not resolve isValidRasterFileName in gdal provider library" );
174  return false;
175  }
176 
177  bool myIsValid = pValid( theFileNameQString, retErrMsg );
178  return myIsValid;
179 }
180 
181 bool QgsRasterLayer::isValidRasterFileName( QString const & theFileNameQString )
182 {
183  QString retErrMsg;
184  return isValidRasterFileName( theFileNameQString, retErrMsg );
185 }
186 
187 QDateTime QgsRasterLayer::lastModified( QString const & name )
188 {
189  QgsDebugMsg( "name=" + name );
190  QDateTime t;
191 
192  QFileInfo fi( name );
193 
194  // Is it file?
195  if ( !fi.exists() )
196  return t;
197 
198  t = fi.lastModified();
199 
200  QgsDebugMsg( "last modified = " + t.toString() );
201 
202  return t;
203 }
204 
205 // typedef for the QgsDataProvider class factory
206 typedef QgsDataProvider * classFactoryFunction_t( const QString * );
207 
209 //
210 // Non Static Public methods
211 //
213 
215 {
216  if ( !mDataProvider ) return 0;
217  return mDataProvider->bandCount();
218 }
219 
220 const QString QgsRasterLayer::bandName( int theBandNo )
221 {
222  return dataProvider()->generateBandName( theBandNo );
223 }
224 
226 {
227  setRenderer( QgsRasterRendererRegistry::instance()->defaultRendererForDrawingStyle( theDrawingStyle, mDataProvider ) );
228 }
229 
234 {
235  return mDataProvider;
236 }
237 
242 {
243  return mDataProvider;
244 }
245 
247 {
248  if ( mDataProvider )
249  {
251  }
252 }
253 
254 bool QgsRasterLayer::draw( QgsRenderContext& rendererContext )
255 {
256  QgsDebugMsg( "entered. (renderContext)" );
257 
258  // Don't waste time drawing if transparency is at 0 (completely transparent)
259  if ( mTransparencyLevel == 0 )
260  return true;
261 
262  QgsDebugMsg( "checking timestamp." );
263 
264  // Check timestamp
265  if ( !update() )
266  {
267  return false;
268  }
269 
270  const QgsMapToPixel& theQgsMapToPixel = rendererContext.mapToPixel();
271 
272  QgsRectangle myProjectedViewExtent;
273  QgsRectangle myProjectedLayerExtent;
274 
275  if ( rendererContext.coordinateTransform() )
276  {
277  QgsDebugMsg( "coordinateTransform set -> project extents." );
278  try
279  {
280  myProjectedViewExtent = rendererContext.coordinateTransform()->transformBoundingBox( rendererContext.extent() );
281  }
282  catch ( QgsCsException &cs )
283  {
284  QgsMessageLog::logMessage( tr( "Could not reproject view extent: %1" ).arg( cs.what() ), tr( "Raster" ) );
285  myProjectedViewExtent.setMinimal();
286  }
287 
288  try
289  {
290  myProjectedLayerExtent = rendererContext.coordinateTransform()->transformBoundingBox( extent() );
291  }
292  catch ( QgsCsException &cs )
293  {
294  QgsMessageLog::logMessage( tr( "Could not reproject layer extent: %1" ).arg( cs.what() ), tr( "Raster" ) );
295  myProjectedViewExtent.setMinimal();
296  }
297  }
298  else
299  {
300  QgsDebugMsg( "coordinateTransform not set" );
301  myProjectedViewExtent = rendererContext.extent();
302  myProjectedLayerExtent = extent();
303  }
304 
305  QPainter* theQPainter = rendererContext.painter();
306 
307  if ( !theQPainter )
308  {
309  return false;
310  }
311 
312  // clip raster extent to view extent
313  QgsRectangle myRasterExtent = myProjectedViewExtent.intersect( &myProjectedLayerExtent );
314  if ( myRasterExtent.isEmpty() )
315  {
316  QgsDebugMsg( "draw request outside view extent." );
317  // nothing to do
318  return true;
319  }
320 
321  QgsDebugMsg( "theViewExtent is " + rendererContext.extent().toString() );
322  QgsDebugMsg( "myProjectedViewExtent is " + myProjectedViewExtent.toString() );
323  QgsDebugMsg( "myProjectedLayerExtent is " + myProjectedLayerExtent.toString() );
324  QgsDebugMsg( "myRasterExtent is " + myRasterExtent.toString() );
325 
326  //
327  // The first thing we do is set up the QgsRasterViewPort. This struct stores all the settings
328  // relating to the size (in pixels and coordinate system units) of the raster part that is
329  // in view in the map window. It also stores the origin.
330  //
331  //this is not a class level member because every time the user pans or zooms
332  //the contents of the rasterViewPort will change
333  QgsRasterViewPort *myRasterViewPort = new QgsRasterViewPort();
334 
335  myRasterViewPort->mDrawnExtent = myRasterExtent;
336  if ( rendererContext.coordinateTransform() )
337  {
338  myRasterViewPort->mSrcCRS = crs();
339  myRasterViewPort->mDestCRS = rendererContext.coordinateTransform()->destCRS();
340  }
341  else
342  {
343  myRasterViewPort->mSrcCRS = QgsCoordinateReferenceSystem(); // will be invalid
344  myRasterViewPort->mDestCRS = QgsCoordinateReferenceSystem(); // will be invalid
345  }
346 
347  // get dimensions of clipped raster image in device coordinate space (this is the size of the viewport)
348  myRasterViewPort->mTopLeftPoint = theQgsMapToPixel.transform( myRasterExtent.xMinimum(), myRasterExtent.yMaximum() );
349  myRasterViewPort->mBottomRightPoint = theQgsMapToPixel.transform( myRasterExtent.xMaximum(), myRasterExtent.yMinimum() );
350 
351  // align to output device grid, i.e. floor/ceil to integers
352  // TODO: this should only be done if paint device is raster - screen, image
353  // for other devices (pdf) it can have floating point origin
354  // we could use floating point for raster devices as well, but respecting the
355  // output device grid should make it more effective as the resampling is done in
356  // the provider anyway
357  myRasterViewPort->mTopLeftPoint.setX( floor( myRasterViewPort->mTopLeftPoint.x() ) );
358  myRasterViewPort->mTopLeftPoint.setY( floor( myRasterViewPort->mTopLeftPoint.y() ) );
359  myRasterViewPort->mBottomRightPoint.setX( ceil( myRasterViewPort->mBottomRightPoint.x() ) );
360  myRasterViewPort->mBottomRightPoint.setY( ceil( myRasterViewPort->mBottomRightPoint.y() ) );
361  // recalc myRasterExtent to aligned values
362  myRasterExtent.set(
363  theQgsMapToPixel.toMapCoordinatesF( myRasterViewPort->mTopLeftPoint.x(),
364  myRasterViewPort->mBottomRightPoint.y() ),
365  theQgsMapToPixel.toMapCoordinatesF( myRasterViewPort->mBottomRightPoint.x(),
366  myRasterViewPort->mTopLeftPoint.y() )
367  );
368 
369  //raster viewport top left / bottom right are already rounded to int
370  myRasterViewPort->mWidth = static_cast<int>( myRasterViewPort->mBottomRightPoint.x() - myRasterViewPort->mTopLeftPoint.x() );
371  myRasterViewPort->mHeight = static_cast<int>( myRasterViewPort->mBottomRightPoint.y() - myRasterViewPort->mTopLeftPoint.y() );
372 
373 
374  //the drawable area can start to get very very large when you get down displaying 2x2 or smaller, this is becasue
375  //theQgsMapToPixel.mapUnitsPerPixel() is less then 1,
376  //so we will just get the pixel data and then render these special cases differently in paintImageToCanvas()
377 
378  QgsDebugMsgLevel( QString( "mapUnitsPerPixel = %1" ).arg( theQgsMapToPixel.mapUnitsPerPixel() ), 3 );
379  QgsDebugMsgLevel( QString( "mWidth = %1" ).arg( width() ), 3 );
380  QgsDebugMsgLevel( QString( "mHeight = %1" ).arg( height() ), 3 );
381  QgsDebugMsgLevel( QString( "myRasterExtent.xMinimum() = %1" ).arg( myRasterExtent.xMinimum() ), 3 );
382  QgsDebugMsgLevel( QString( "myRasterExtent.xMaximum() = %1" ).arg( myRasterExtent.xMaximum() ), 3 );
383  QgsDebugMsgLevel( QString( "myRasterExtent.yMinimum() = %1" ).arg( myRasterExtent.yMinimum() ), 3 );
384  QgsDebugMsgLevel( QString( "myRasterExtent.yMaximum() = %1" ).arg( myRasterExtent.yMaximum() ), 3 );
385 
386  QgsDebugMsgLevel( QString( "mTopLeftPoint.x() = %1" ).arg( myRasterViewPort->mTopLeftPoint.x() ), 3 );
387  QgsDebugMsgLevel( QString( "mBottomRightPoint.x() = %1" ).arg( myRasterViewPort->mBottomRightPoint.x() ), 3 );
388  QgsDebugMsgLevel( QString( "mTopLeftPoint.y() = %1" ).arg( myRasterViewPort->mTopLeftPoint.y() ), 3 );
389  QgsDebugMsgLevel( QString( "mBottomRightPoint.y() = %1" ).arg( myRasterViewPort->mBottomRightPoint.y() ), 3 );
390 
391  QgsDebugMsgLevel( QString( "mWidth = %1" ).arg( myRasterViewPort->mWidth ), 3 );
392  QgsDebugMsgLevel( QString( "mHeight = %1" ).arg( myRasterViewPort->mHeight ), 3 );
393 
394  // /\/\/\ - added to handle zoomed-in rasters
395 
396  mLastViewPort = *myRasterViewPort;
397 
398  // TODO: is it necessary? Probably WMS only?
399  mDataProvider->setDpi( rendererContext.rasterScaleFactor() * 25.4 * rendererContext.scaleFactor() );
400 
401  draw( theQPainter, myRasterViewPort, &theQgsMapToPixel );
402 
403  delete myRasterViewPort;
404  QgsDebugMsg( "exiting." );
405 
406  return true;
407 
408 }
409 
410 void QgsRasterLayer::draw( QPainter * theQPainter,
411  QgsRasterViewPort * theRasterViewPort,
412  const QgsMapToPixel* theQgsMapToPixel )
413 {
414  QgsDebugMsg( " 3 arguments" );
415  QTime time;
416  time.start();
417  //
418  //
419  // The goal here is to make as many decisions as possible early on (outside of the rendering loop)
420  // so that we can maximise performance of the rendering process. So now we check which drawing
421  // procedure to use :
422  //
423 
424  QgsRasterProjector *projector = mPipe.projector();
425 
426  // TODO add a method to interface to get provider and get provider
427  // params in QgsRasterProjector
428  if ( projector )
429  {
430  projector->setCRS( theRasterViewPort->mSrcCRS, theRasterViewPort->mDestCRS );
431  }
432 
433  // Drawer to pipe?
434  QgsRasterIterator iterator( mPipe.last() );
435  QgsRasterDrawer drawer( &iterator );
436  drawer.draw( theQPainter, theRasterViewPort, theQgsMapToPixel );
437 
438  QgsDebugMsg( QString( "total raster draw time (ms): %1" ).arg( time.elapsed(), 5 ) );
439 } //end of draw method
440 
442 {
443  return mError;
444 }
445 
447 {
448  return mErrorCaption;
449 }
450 
451 QList< QPair< QString, QColor > > QgsRasterLayer::legendSymbologyItems() const
452 {
453  QList< QPair< QString, QColor > > symbolList;
455  if ( renderer )
456  {
457  renderer->legendSymbologyItems( symbolList );
458  }
459  return symbolList;
460 }
461 
463 {
464  QString myMetadata ;
465  myMetadata += "<p class=\"glossy\">" + tr( "Driver" ) + "</p>\n";
466  myMetadata += "<p>";
467  myMetadata += mDataProvider->description();
468  myMetadata += "</p>\n";
469 
470  // Insert provider-specific (e.g. WMS-specific) metadata
471  // crashing
472  myMetadata += mDataProvider->metadata();
473 
474  myMetadata += "<p class=\"glossy\">";
475  myMetadata += tr( "No Data Value" );
476  myMetadata += "</p>\n";
477  myMetadata += "<p>";
478  // TODO: all bands
479  if ( mDataProvider->srcHasNoDataValue( 1 ) )
480  {
481  myMetadata += QString::number( mDataProvider->srcNoDataValue( 1 ) );
482  }
483  else
484  {
485  myMetadata += "*" + tr( "NoDataValue not set" ) + "*";
486  }
487  myMetadata += "</p>\n";
488 
489  myMetadata += "</p>\n";
490  myMetadata += "<p class=\"glossy\">";
491  myMetadata += tr( "Data Type" );
492  myMetadata += "</p>\n";
493  myMetadata += "<p>";
494  //just use the first band
495  switch ( mDataProvider->srcDataType( 1 ) )
496  {
497  case QGis::Byte:
498  myMetadata += tr( "Byte - Eight bit unsigned integer" );
499  break;
500  case QGis::UInt16:
501  myMetadata += tr( "UInt16 - Sixteen bit unsigned integer " );
502  break;
503  case QGis::Int16:
504  myMetadata += tr( "Int16 - Sixteen bit signed integer " );
505  break;
506  case QGis::UInt32:
507  myMetadata += tr( "UInt32 - Thirty two bit unsigned integer " );
508  break;
509  case QGis::Int32:
510  myMetadata += tr( "Int32 - Thirty two bit signed integer " );
511  break;
512  case QGis::Float32:
513  myMetadata += tr( "Float32 - Thirty two bit floating point " );
514  break;
515  case QGis::Float64:
516  myMetadata += tr( "Float64 - Sixty four bit floating point " );
517  break;
518  case QGis::CInt16:
519  myMetadata += tr( "CInt16 - Complex Int16 " );
520  break;
521  case QGis::CInt32:
522  myMetadata += tr( "CInt32 - Complex Int32 " );
523  break;
524  case QGis::CFloat32:
525  myMetadata += tr( "CFloat32 - Complex Float32 " );
526  break;
527  case QGis::CFloat64:
528  myMetadata += tr( "CFloat64 - Complex Float64 " );
529  break;
530  default:
531  myMetadata += tr( "Could not determine raster data type." );
532  }
533  myMetadata += "</p>\n";
534 
535  myMetadata += "<p class=\"glossy\">";
536  myMetadata += tr( "Pyramid overviews" );
537  myMetadata += "</p>\n";
538  myMetadata += "<p>";
539 
540  myMetadata += "<p class=\"glossy\">";
541  myMetadata += tr( "Layer Spatial Reference System" );
542  myMetadata += "</p>\n";
543  myMetadata += "<p>";
544  myMetadata += crs().toProj4();
545  myMetadata += "</p>\n";
546 
547  myMetadata += "<p class=\"glossy\">";
548  myMetadata += tr( "Layer Extent (layer original source projection)" );
549  myMetadata += "</p>\n";
550  myMetadata += "<p>";
551  myMetadata += mDataProvider->extent().toString();
552  myMetadata += "</p>\n";
553 
554  // output coordinate system
555  // TODO: this is not related to layer, to be removed? [MD]
556 #if 0
557  myMetadata += "<tr><td class=\"glossy\">";
558  myMetadata += tr( "Project Spatial Reference System" );
559  myMetadata += "</p>\n";
560  myMetadata += "<p>";
561  myMetadata += mCoordinateTransform->destCRS().toProj4();
562  myMetadata += "</p>\n";
563 #endif
564 
565  //
566  // Add the stats for each band to the output table
567  //
568  int myBandCountInt = bandCount();
569  for ( int myIteratorInt = 1; myIteratorInt <= myBandCountInt; ++myIteratorInt )
570  {
571  QgsDebugMsg( "Raster properties : checking if band " + QString::number( myIteratorInt ) + " has stats? " );
572  //band name
573  myMetadata += "<p class=\"glossy\">\n";
574  myMetadata += tr( "Band" );
575  myMetadata += "</p>\n";
576  myMetadata += "<p>";
577  myMetadata += bandName( myIteratorInt );
578  myMetadata += "</p>\n";
579  //band number
580  myMetadata += "<p>";
581  myMetadata += tr( "Band No" );
582  myMetadata += "</p>\n";
583  myMetadata += "<p>\n";
584  myMetadata += QString::number( myIteratorInt );
585  myMetadata += "</p>\n";
586 
587  //check if full stats for this layer have already been collected
588  if ( !dataProvider()->hasStatistics( myIteratorInt ) ) //not collected
589  {
590  QgsDebugMsg( ".....no" );
591 
592  myMetadata += "<p>";
593  myMetadata += tr( "No Stats" );
594  myMetadata += "</p>\n";
595  myMetadata += "<p>\n";
596  myMetadata += tr( "No stats collected yet" );
597  myMetadata += "</p>\n";
598  }
599  else // collected - show full detail
600  {
601  QgsDebugMsg( ".....yes" );
602 
603  QgsRasterBandStats myRasterBandStats = dataProvider()->bandStatistics( myIteratorInt );
604  //Min Val
605  myMetadata += "<p>";
606  myMetadata += tr( "Min Val" );
607  myMetadata += "</p>\n";
608  myMetadata += "<p>\n";
609  myMetadata += QString::number( myRasterBandStats.minimumValue, 'f', 10 );
610  myMetadata += "</p>\n";
611 
612  // Max Val
613  myMetadata += "<p>";
614  myMetadata += tr( "Max Val" );
615  myMetadata += "</p>\n";
616  myMetadata += "<p>\n";
617  myMetadata += QString::number( myRasterBandStats.maximumValue, 'f', 10 );
618  myMetadata += "</p>\n";
619 
620  // Range
621  myMetadata += "<p>";
622  myMetadata += tr( "Range" );
623  myMetadata += "</p>\n";
624  myMetadata += "<p>\n";
625  myMetadata += QString::number( myRasterBandStats.range, 'f', 10 );
626  myMetadata += "</p>\n";
627 
628  // Mean
629  myMetadata += "<p>";
630  myMetadata += tr( "Mean" );
631  myMetadata += "</p>\n";
632  myMetadata += "<p>\n";
633  myMetadata += QString::number( myRasterBandStats.mean, 'f', 10 );
634  myMetadata += "</p>\n";
635 
636  //sum of squares
637  myMetadata += "<p>";
638  myMetadata += tr( "Sum of squares" );
639  myMetadata += "</p>\n";
640  myMetadata += "<p>\n";
641  myMetadata += QString::number( myRasterBandStats.sumOfSquares, 'f', 10 );
642  myMetadata += "</p>\n";
643 
644  //standard deviation
645  myMetadata += "<p>";
646  myMetadata += tr( "Standard Deviation" );
647  myMetadata += "</p>\n";
648  myMetadata += "<p>\n";
649  myMetadata += QString::number( myRasterBandStats.stdDev, 'f', 10 );
650  myMetadata += "</p>\n";
651 
652  //sum of all cells
653  myMetadata += "<p>";
654  myMetadata += tr( "Sum of all cells" );
655  myMetadata += "</p>\n";
656  myMetadata += "<p>\n";
657  myMetadata += QString::number( myRasterBandStats.sum, 'f', 10 );
658  myMetadata += "</p>\n";
659 
660  //number of cells
661  myMetadata += "<p>";
662  myMetadata += tr( "Cell Count" );
663  myMetadata += "</p>\n";
664  myMetadata += "<p>\n";
665  myMetadata += QString::number( myRasterBandStats.elementCount );
666  myMetadata += "</p>\n";
667  }
668  }
669 
670  QgsDebugMsg( myMetadata );
671  return myMetadata;
672 }
673 
678 QPixmap QgsRasterLayer::paletteAsPixmap( int theBandNumber )
679 {
680  //TODO: This function should take dimensions
681  QgsDebugMsg( "entered." );
682 
683  // Only do this for the GDAL provider?
684  // Maybe WMS can do this differently using QImage::numColors and QImage::color()
685  if ( mDataProvider->colorInterpretation( theBandNumber ) == QgsRaster::PaletteIndex )
686  {
687  QgsDebugMsg( "....found paletted image" );
688  QgsColorRampShader myShader;
689  QList<QgsColorRampShader::ColorRampItem> myColorRampItemList = mDataProvider->colorTable( theBandNumber );
690  if ( myColorRampItemList.size() > 0 )
691  {
692  QgsDebugMsg( "....got color ramp item list" );
693  myShader.setColorRampItemList( myColorRampItemList );
695  // Draw image
696  int mySize = 100;
697  QPixmap myPalettePixmap( mySize, mySize );
698  QPainter myQPainter( &myPalettePixmap );
699 
700  QImage myQImage = QImage( mySize, mySize, QImage::Format_RGB32 );
701  myQImage.fill( 0 );
702  myPalettePixmap.fill();
703 
704  double myStep = (( double )myColorRampItemList.size() - 1 ) / ( double )( mySize * mySize );
705  double myValue = 0.0;
706  for ( int myRow = 0; myRow < mySize; myRow++ )
707  {
708  QRgb* myLineBuffer = ( QRgb* )myQImage.scanLine( myRow );
709  for ( int myCol = 0; myCol < mySize; myCol++ )
710  {
711  myValue = myStep * ( double )( myCol + myRow * mySize );
712  int c1, c2, c3, c4;
713  myShader.shade( myValue, &c1, &c2, &c3, &c4 );
714  myLineBuffer[ myCol ] = qRgba( c1, c2, c3, c4 );
715  }
716  }
717 
718  myQPainter.drawImage( 0, 0, myQImage );
719  return myPalettePixmap;
720  }
721  QPixmap myNullPixmap;
722  return myNullPixmap;
723  }
724  else
725  {
726  //invalid layer was requested
727  QPixmap myNullPixmap;
728  return myNullPixmap;
729  }
730 }
731 
733 {
734  return mProviderKey;
735 }
736 
741 {
742 // We return one raster pixel per map unit pixel
743 // One raster pixel can have several raster units...
744 
745 // We can only use one of the mGeoTransform[], so go with the
746 // horisontal one.
747 
749  {
750  return mDataProvider->extent().width() / mDataProvider->xSize();
751  }
752  return 1;
753 }
754 
756 {
758  {
759  return mDataProvider->extent().height() / mDataProvider->ySize();
760  }
761  return 1;
762 }
763 
765 {
767 
769 
770  //Initialize the last view port structure, should really be a class
771  mLastViewPort.mWidth = 0;
773 }
774 
775 void QgsRasterLayer::setDataProvider( QString const & provider )
776 {
777  QgsDebugMsg( "Entered" );
778  mValid = false; // assume the layer is invalid until we determine otherwise
779 
780  mPipe.remove( mDataProvider ); // deletes if exists
781  mDataProvider = 0;
782 
783  // XXX should I check for and possibly delete any pre-existing providers?
784  // XXX How often will that scenario occur?
785 
786  mProviderKey = provider;
787  // set the layer name (uppercase first character)
788  if ( ! mLayerName.isEmpty() ) // XXX shouldn't this happen in parent?
789  {
791  }
792 
793  //mBandCount = 0;
794 
796  if ( !mDataProvider )
797  {
798  //QgsMessageLog::logMessage( tr( "Cannot instantiate the data provider" ), tr( "Raster" ) );
799  appendError( ERR( tr( "Cannot instantiate the '%1' data provider" ).arg( mProviderKey ) ) );
800  return;
801  }
802  QgsDebugMsg( "Data provider created" );
803 
804  // Set data provider into pipe even if not valid so that it is deleted with pipe (with layer)
806  if ( !mDataProvider->isValid() )
807  {
809  appendError( ERR( tr( "Provider is not valid (provider: %1, URI: %2" ).arg( mProviderKey ).arg( mDataSource ) ) );
810  return;
811  }
812 
813  if ( provider == "gdal" )
814  {
815  // make sure that the /vsigzip or /vsizip is added to uri, if applicable
817  }
818 
819  // get the extent
821 
822  // show the extent
823  QString s = mbr.toString();
824  QgsDebugMsg( "Extent of layer: " + s );
825  // store the extent
826  setExtent( mbr );
827 
828  // upper case the first letter of the layer name
829  QgsDebugMsg( "mLayerName: " + name() );
830 
831  // set up the raster drawing style
832  // Do not set any 'sensible' style here, the style is set later
833 
834  // Setup source CRS
836 
837  QString mySourceWkt = crs().toWkt();
838 
839  QgsDebugMsg( "using wkt:\n" + mySourceWkt );
840 
841  //defaults - Needs to be set after the Contrast list has been build
842  //Try to read the default contrast enhancement from the config file
843 
844  QSettings myQSettings;
845 
846  //decide what type of layer this is...
847  //TODO Change this to look at the color interp and palette interp to decide which type of layer it is
848  QgsDebugMsg( "bandCount = " + QString::number( mDataProvider->bandCount() ) );
849  QgsDebugMsg( "dataType = " + QString::number( mDataProvider->dataType( 1 ) ) );
850  if (( mDataProvider->bandCount() > 1 ) )
851  {
853  }
854  else if ( mDataProvider->dataType( 1 ) == QGis::ARGB32
856  {
858  }
860  {
862  }
864  {
866  }
867  else
868  {
870  }
871 
872  QgsDebugMsg( "mRasterType = " + QString::number( mRasterType ) );
873  if ( mRasterType == ColorLayer )
874  {
875  QgsDebugMsg( "Setting drawing style to SingleBandColorDataStyle " + QString::number( QgsRaster::SingleBandColorDataStyle ) );
877  }
879  {
881  }
883  {
885  // Load color table
886  QList<QgsColorRampShader::ColorRampItem> colorTable = mDataProvider->colorTable( 1 );
888  if ( r )
889  {
890  // TODO: this should go somewhere else
891  QgsRasterShader* shader = new QgsRasterShader();
892  QgsColorRampShader* colorRampShader = new QgsColorRampShader();
894  colorRampShader->setColorRampItemList( colorTable );
895  shader->setRasterShaderFunction( colorRampShader );
896  r->setShader( shader );
897  }
898  }
899  else if ( mRasterType == Multiband )
900  {
902  }
903  else //GrayOrUndefined
904  {
906  }
907 
908  // Auto set alpha band
909  for ( int bandNo = 1; bandNo <= mDataProvider->bandCount(); bandNo++ )
910  {
912  {
913  if ( mPipe.renderer() )
914  {
915  mPipe.renderer()->setAlphaBand( bandNo );
916  }
917  break;
918  }
919  }
920 
921  // brightness filter
923  mPipe.set( brightnessFilter );
924 
925  // hue/saturation filter
927  mPipe.set( hueSaturationFilter );
928 
929  //resampler (must be after renderer)
931  mPipe.set( resampleFilter );
932 
933  // projector (may be anywhere in pipe)
934  QgsRasterProjector * projector = new QgsRasterProjector;
935  mPipe.set( projector );
936 
937  // Set default identify format - use the richest format available
938  int capabilities = mDataProvider->capabilities();
940  if ( capabilities & QgsRasterInterface::IdentifyHtml )
941  {
942  // HTML is usually richest
943  identifyFormat = QgsRaster::IdentifyFormatHtml;
944  }
945  else if ( capabilities & QgsRasterInterface::IdentifyFeature )
946  {
947  identifyFormat = QgsRaster::IdentifyFormatFeature;
948  }
949  else if ( capabilities & QgsRasterInterface::IdentifyText )
950  {
951  identifyFormat = QgsRaster::IdentifyFormatText;
952  }
953  else if ( capabilities & QgsRasterInterface::IdentifyValue )
954  {
955  identifyFormat = QgsRaster::IdentifyFormatValue;
956  }
957  setCustomProperty( "identify/format", QgsRasterDataProvider::identifyFormatName( identifyFormat ) );
958 
959  // Store timestamp
960  // TODO move to provider
962 
963  // Connect provider signals
964  connect(
965  mDataProvider, SIGNAL( progress( int, double, QString ) ),
966  this, SLOT( onProgress( int, double, QString ) )
967  );
968 
969  // Do a passthrough for the status bar text
970  connect(
971  mDataProvider, SIGNAL( statusChanged( QString ) ),
972  this, SIGNAL( statusChanged( QString ) )
973  );
974 
975  //mark the layer as valid
976  mValid = true;
977 
978  QgsDebugMsg( "exiting." );
979 } // QgsRasterLayer::setDataProvider
980 
982 {
983  mValid = false;
985  mDataProvider = 0;
986 }
987 
988 void QgsRasterLayer::setContrastEnhancement( QgsContrastEnhancement::ContrastEnhancementAlgorithm theAlgorithm, QgsRaster::ContrastEnhancementLimits theLimits, QgsRectangle theExtent, int theSampleSize, bool theGenerateLookupTableFlag )
989 {
990  QgsDebugMsg( QString( "theAlgorithm = %1 theLimits = %2 theExtent.isEmpty() = %3" ).arg( theAlgorithm ).arg( theLimits ).arg( theExtent.isEmpty() ) );
991  if ( !mPipe.renderer() || !mDataProvider )
992  {
993  return;
994  }
995 
996  QList<int> myBands;
997  QList<QgsContrastEnhancement*> myEnhancements;
998  QgsSingleBandGrayRenderer* myGrayRenderer = 0;
999  QgsMultiBandColorRenderer* myMultiBandRenderer = 0;
1000  QString rendererType = mPipe.renderer()->type();
1001  if ( rendererType == "singlebandgray" )
1002  {
1003  myGrayRenderer = dynamic_cast<QgsSingleBandGrayRenderer*>( mPipe.renderer() );
1004  if ( !myGrayRenderer ) return;
1005  myBands << myGrayRenderer->grayBand();
1006  }
1007  else if ( rendererType == "multibandcolor" )
1008  {
1009  myMultiBandRenderer = dynamic_cast<QgsMultiBandColorRenderer*>( mPipe.renderer() );
1010  if ( !myMultiBandRenderer ) return;
1011  myBands << myMultiBandRenderer->redBand() << myMultiBandRenderer->greenBand() << myMultiBandRenderer->blueBand();
1012  }
1013 
1014  foreach ( int myBand, myBands )
1015  {
1016  if ( myBand != -1 )
1017  {
1018  QGis::DataType myType = ( QGis::DataType )mDataProvider->dataType( myBand );
1019  QgsContrastEnhancement* myEnhancement = new QgsContrastEnhancement(( QGis::DataType )myType );
1020  myEnhancement->setContrastEnhancementAlgorithm( theAlgorithm, theGenerateLookupTableFlag );
1021 
1022  double myMin = std::numeric_limits<double>::quiet_NaN();
1023  double myMax = std::numeric_limits<double>::quiet_NaN();
1024 
1025  if ( theLimits == QgsRaster::ContrastEnhancementMinMax )
1026  {
1027  QgsRasterBandStats myRasterBandStats = mDataProvider->bandStatistics( myBand, QgsRasterBandStats::Min | QgsRasterBandStats::Max, theExtent, theSampleSize );
1028  myMin = myRasterBandStats.minimumValue;
1029  myMax = myRasterBandStats.maximumValue;
1030  }
1031  else if ( theLimits == QgsRaster::ContrastEnhancementStdDev )
1032  {
1033  double myStdDev = 1; // make optional?
1034  QgsRasterBandStats myRasterBandStats = mDataProvider->bandStatistics( myBand, QgsRasterBandStats::Mean | QgsRasterBandStats::StdDev, theExtent, theSampleSize );
1035  myMin = myRasterBandStats.mean - ( myStdDev * myRasterBandStats.stdDev );
1036  myMax = myRasterBandStats.mean + ( myStdDev * myRasterBandStats.stdDev );
1037  }
1038  else if ( theLimits == QgsRaster::ContrastEnhancementCumulativeCut )
1039  {
1040  QSettings mySettings;
1041  double myLower = mySettings.value( "/Raster/cumulativeCutLower", QString::number( CUMULATIVE_CUT_LOWER ) ).toDouble();
1042  double myUpper = mySettings.value( "/Raster/cumulativeCutUpper", QString::number( CUMULATIVE_CUT_UPPER ) ).toDouble();
1043  QgsDebugMsg( QString( "myLower = %1 myUpper = %2" ).arg( myLower ).arg( myUpper ) );
1044  mDataProvider->cumulativeCut( myBand, myLower, myUpper, myMin, myMax, theExtent, theSampleSize );
1045  }
1046 
1047  QgsDebugMsg( QString( "myBand = %1 myMin = %2 myMax = %3" ).arg( myBand ).arg( myMin ).arg( myMax ) );
1048  myEnhancement->setMinimumValue( myMin );
1049  myEnhancement->setMaximumValue( myMax );
1050  myEnhancements.append( myEnhancement );
1051  }
1052  else
1053  {
1054  myEnhancements.append( 0 );
1055  }
1056  }
1057 
1058  if ( rendererType == "singlebandgray" )
1059  {
1060  if ( myEnhancements.value( 0 ) ) myGrayRenderer->setContrastEnhancement( myEnhancements.value( 0 ) );
1061  }
1062  else if ( rendererType == "multibandcolor" )
1063  {
1064  if ( myEnhancements.value( 0 ) ) myMultiBandRenderer->setRedContrastEnhancement( myEnhancements.value( 0 ) );
1065  if ( myEnhancements.value( 1 ) ) myMultiBandRenderer->setGreenContrastEnhancement( myEnhancements.value( 1 ) );
1066  if ( myEnhancements.value( 2 ) ) myMultiBandRenderer->setBlueContrastEnhancement( myEnhancements.value( 2 ) );
1067  }
1068 }
1069 
1071 {
1072  QgsDebugMsg( "Entered" );
1073 
1074  QSettings mySettings;
1075 
1076  QString myKey;
1077  QString myDefault;
1078 
1079  // TODO: we should not test renderer class here, move it somehow to renderers
1080  if ( dynamic_cast<QgsSingleBandGrayRenderer*>( renderer() ) )
1081  {
1082  myKey = "singleBand";
1083  myDefault = "StretchToMinimumMaximum";
1084  }
1085  else if ( dynamic_cast<QgsMultiBandColorRenderer*>( renderer() ) )
1086  {
1087  if ( QgsRasterBlock::typeSize( dataProvider()->srcDataType( 1 ) ) == 1 )
1088  {
1089  myKey = "multiBandSingleByte";
1090  myDefault = "NoEnhancement";
1091  }
1092  else
1093  {
1094  myKey = "multiBandMultiByte";
1095  myDefault = "StretchToMinimumMaximum";
1096  }
1097  }
1098 
1099  if ( myKey.isEmpty() )
1100  {
1101  QgsDebugMsg( "No default contrast enhancement for this drawing style" );
1102  }
1103  QgsDebugMsg( "myKey = " + myKey );
1104 
1105  QString myAlgorithmString = mySettings.value( "/Raster/defaultContrastEnhancementAlgorithm/" + myKey, myDefault ).toString();
1106  QgsDebugMsg( "myAlgorithmString = " + myAlgorithmString );
1107 
1109 
1110  if ( myAlgorithm == QgsContrastEnhancement::NoEnhancement )
1111  {
1112  return;
1113  }
1114 
1115  QString myLimitsString = mySettings.value( "/Raster/defaultContrastEnhancementLimits", "CumulativeCut" ).toString();
1117 
1118  setContrastEnhancement( myAlgorithm, myLimits );
1119 }
1120 
1126 void QgsRasterLayer::setDrawingStyle( QString const & theDrawingStyleQString )
1127 {
1128  QgsDebugMsg( "DrawingStyle = " + theDrawingStyleQString );
1129  QgsRaster::DrawingStyle drawingStyle;
1130  if ( theDrawingStyleQString == "SingleBandGray" )//no need to tr() this its not shown in ui
1131  {
1132  drawingStyle = QgsRaster::SingleBandGray;
1133  }
1134  else if ( theDrawingStyleQString == "SingleBandPseudoColor" )//no need to tr() this its not shown in ui
1135  {
1136  drawingStyle = QgsRaster::SingleBandPseudoColor;
1137  }
1138  else if ( theDrawingStyleQString == "PalettedColor" )//no need to tr() this its not shown in ui
1139  {
1140  drawingStyle = QgsRaster::PalettedColor;
1141  }
1142  else if ( theDrawingStyleQString == "PalettedSingleBandGray" )//no need to tr() this its not shown in ui
1143  {
1144  drawingStyle = QgsRaster::PalettedSingleBandGray;
1145  }
1146  else if ( theDrawingStyleQString == "PalettedSingleBandPseudoColor" )//no need to tr() this its not shown in ui
1147  {
1149  }
1150  else if ( theDrawingStyleQString == "PalettedMultiBandColor" )//no need to tr() this its not shown in ui
1151  {
1152  drawingStyle = QgsRaster::PalettedMultiBandColor;
1153  }
1154  else if ( theDrawingStyleQString == "MultiBandSingleBandGray" )//no need to tr() this its not shown in ui
1155  {
1156  drawingStyle = QgsRaster::MultiBandSingleBandGray;
1157  }
1158  else if ( theDrawingStyleQString == "MultiBandSingleBandPseudoColor" )//no need to tr() this its not shown in ui
1159  {
1161  }
1162  else if ( theDrawingStyleQString == "MultiBandColor" )//no need to tr() this its not shown in ui
1163  {
1164  drawingStyle = QgsRaster::MultiBandColor;
1165  }
1166  else if ( theDrawingStyleQString == "SingleBandColorDataStyle" )//no need to tr() this its not shown in ui
1167  {
1168  QgsDebugMsg( "Setting drawingStyle to SingleBandColorDataStyle " + QString::number( QgsRaster::SingleBandColorDataStyle ) );
1169  drawingStyle = QgsRaster::SingleBandColorDataStyle;
1170  QgsDebugMsg( "Setted drawingStyle to " + QString::number( drawingStyle ) );
1171  }
1172  else
1173  {
1174  drawingStyle = QgsRaster::UndefinedDrawingStyle;
1175  }
1176  setRendererForDrawingStyle( drawingStyle );
1177 }
1178 
1179 void QgsRasterLayer::setLayerOrder( QStringList const & layers )
1180 {
1181  QgsDebugMsg( "entered." );
1182 
1183  if ( mDataProvider )
1184  {
1185  QgsDebugMsg( "About to mDataProvider->setLayerOrder(layers)." );
1186  mDataProvider->setLayerOrder( layers );
1187  }
1188 
1189 }
1190 
1191 void QgsRasterLayer::setSubLayerVisibility( QString name, bool vis )
1192 {
1193 
1194  if ( mDataProvider )
1195  {
1196  QgsDebugMsg( "About to mDataProvider->setSubLayerVisibility(name, vis)." );
1197  mDataProvider->setSubLayerVisibility( name, vis );
1198  }
1199 
1200 }
1201 
1203 {
1204  QgsDebugMsg( "Entered" );
1205  if ( !theRenderer ) { return; }
1206  mPipe.set( theRenderer );
1207 }
1208 
1209 void QgsRasterLayer::showProgress( int theValue )
1210 {
1211  emit progressUpdate( theValue );
1212 }
1213 
1214 
1215 void QgsRasterLayer::showStatusMessage( QString const & theMessage )
1216 {
1217  // QgsDebugMsg(QString("entered with '%1'.").arg(theMessage));
1218 
1219  // Pass-through
1220  // TODO: See if we can connect signal-to-signal. This is a kludge according to the Qt doc.
1221  emit statusChanged( theMessage );
1222 }
1223 
1224 QStringList QgsRasterLayer::subLayers() const
1225 {
1226  return mDataProvider->subLayers();
1227 }
1228 
1229 QPixmap QgsRasterLayer::previewAsPixmap( QSize size, QColor bgColor )
1230 {
1231  QPixmap myQPixmap( size );
1232 
1233  myQPixmap.fill( bgColor ); //defaults to white, set to transparent for rendering on a map
1234 
1235  QgsRasterViewPort *myRasterViewPort = new QgsRasterViewPort();
1236 
1237  double myMapUnitsPerPixel;
1238  double myX = 0.0;
1239  double myY = 0.0;
1240  QgsRectangle myExtent = mDataProvider->extent();
1241  if ( myExtent.width() / myExtent.height() >= myQPixmap.width() / myQPixmap.height() )
1242  {
1243  myMapUnitsPerPixel = myExtent.width() / myQPixmap.width();
1244  myY = ( myQPixmap.height() - myExtent.height() / myMapUnitsPerPixel ) / 2;
1245  }
1246  else
1247  {
1248  myMapUnitsPerPixel = myExtent.height() / myQPixmap.height();
1249  myX = ( myQPixmap.width() - myExtent.width() / myMapUnitsPerPixel ) / 2;
1250  }
1251 
1252  double myPixelWidth = myExtent.width() / myMapUnitsPerPixel;
1253  double myPixelHeight = myExtent.height() / myMapUnitsPerPixel;
1254 
1255  myRasterViewPort->mTopLeftPoint = QgsPoint( myX, myY );
1256  myRasterViewPort->mBottomRightPoint = QgsPoint( myPixelWidth, myPixelHeight );
1257  myRasterViewPort->mWidth = myQPixmap.width();
1258  myRasterViewPort->mHeight = myQPixmap.height();
1259 
1260  myRasterViewPort->mDrawnExtent = myExtent;
1261  myRasterViewPort->mSrcCRS = QgsCoordinateReferenceSystem(); // will be invalid
1262  myRasterViewPort->mDestCRS = QgsCoordinateReferenceSystem(); // will be invalid
1263 
1264  QgsMapToPixel *myMapToPixel = new QgsMapToPixel( myMapUnitsPerPixel );
1265 
1266  QPainter * myQPainter = new QPainter( &myQPixmap );
1267  draw( myQPainter, myRasterViewPort, myMapToPixel );
1268  delete myRasterViewPort;
1269  delete myMapToPixel;
1270  myQPainter->end();
1271  delete myQPainter;
1272 
1273  return myQPixmap;
1274 }
1275 
1277 {
1278  emit repaintRequested();
1279 }
1280 
1281 void QgsRasterLayer::updateProgress( int theProgress, int theMax )
1282 {
1283  //simply propogate it on!
1284  emit drawingProgress( theProgress, theMax );
1285 }
1286 
1287 void QgsRasterLayer::onProgress( int theType, double theProgress, QString theMessage )
1288 {
1289  Q_UNUSED( theType );
1290  Q_UNUSED( theMessage );
1291  QgsDebugMsg( QString( "theProgress = %1" ).arg( theProgress ) );
1292  emit progressUpdate(( int )theProgress );
1293 }
1294 
1296 //
1297 // Protected methods
1298 //
1300 /*
1301  * @param QDomNode node that will contain the symbology definition for this layer.
1302  * @param errorMessage reference to string that will be updated with any error messages
1303  * @return true in case of success.
1304  */
1305 bool QgsRasterLayer::readSymbology( const QDomNode& layer_node, QString& errorMessage )
1306 {
1307  Q_UNUSED( errorMessage );
1308  QDomElement rasterRendererElem;
1309 
1310  // pipe element was introduced in the end of 1.9 development when there were
1311  // already many project files in use so we support 1.9 backward compatibility
1312  // even it was never officialy released -> use pipe element if present, otherwise
1313  // use layer node
1314  QDomNode pipeNode = layer_node.firstChildElement( "pipe" );
1315  if ( pipeNode.isNull() ) // old project
1316  {
1317  pipeNode = layer_node;
1318  }
1319 
1320  //rasterlayerproperties element there -> old format (1.8 and early 1.9)
1321  if ( !layer_node.firstChildElement( "rasterproperties" ).isNull() )
1322  {
1323  //copy node because layer_node is const
1324  QDomNode layerNodeCopy = layer_node.cloneNode();
1325  QDomDocument doc = layerNodeCopy.ownerDocument();
1326  QDomElement rasterPropertiesElem = layerNodeCopy.firstChildElement( "rasterproperties" );
1327  QgsProjectFileTransform::convertRasterProperties( doc, layerNodeCopy, rasterPropertiesElem,
1328  this );
1329  rasterRendererElem = layerNodeCopy.firstChildElement( "rasterrenderer" );
1330  QgsDebugMsg( doc.toString() );
1331  }
1332  else
1333  {
1334  rasterRendererElem = pipeNode.firstChildElement( "rasterrenderer" );
1335  }
1336 
1337  if ( !rasterRendererElem.isNull() )
1338  {
1339  QString rendererType = rasterRendererElem.attribute( "type" );
1340  QgsRasterRendererRegistryEntry rendererEntry;
1341  if ( QgsRasterRendererRegistry::instance()->rendererData( rendererType, rendererEntry ) )
1342  {
1343  QgsRasterRenderer *renderer = rendererEntry.rendererCreateFunction( rasterRendererElem, dataProvider() );
1344  mPipe.set( renderer );
1345  }
1346  }
1347 
1348  //brightness
1350  mPipe.set( brightnessFilter );
1351 
1352  //brightness coefficient
1353  QDomElement brightnessElem = pipeNode.firstChildElement( "brightnesscontrast" );
1354  if ( !brightnessElem.isNull() )
1355  {
1356  brightnessFilter->readXML( brightnessElem );
1357  }
1358 
1359  //hue/saturation
1361  mPipe.set( hueSaturationFilter );
1362 
1363  //saturation coefficient
1364  QDomElement hueSaturationElem = pipeNode.firstChildElement( "huesaturation" );
1365  if ( !hueSaturationElem.isNull() )
1366  {
1367  hueSaturationFilter->readXML( hueSaturationElem );
1368  }
1369 
1370  //resampler
1372  mPipe.set( resampleFilter );
1373 
1374  //max oversampling
1375  QDomElement resampleElem = pipeNode.firstChildElement( "rasterresampler" );
1376  if ( !resampleElem.isNull() )
1377  {
1378  resampleFilter->readXML( resampleElem );
1379  }
1380 
1381  // get and set the blend mode if it exists
1382  QDomNode blendModeNode = layer_node.namedItem( "blendMode" );
1383  if ( !blendModeNode.isNull() )
1384  {
1385  QDomElement e = blendModeNode.toElement();
1387  }
1388 
1389  return true;
1390 } //readSymbology
1391 
1398 bool QgsRasterLayer::readXml( const QDomNode& layer_node )
1399 {
1400  QgsDebugMsg( "Entered" );
1402 
1403  //process provider key
1404  QDomNode pkeyNode = layer_node.namedItem( "provider" );
1405 
1406  if ( pkeyNode.isNull() )
1407  {
1408  mProviderKey = "gdal";
1409  }
1410  else
1411  {
1412  QDomElement pkeyElt = pkeyNode.toElement();
1413  mProviderKey = pkeyElt.text();
1414  if ( mProviderKey.isEmpty() )
1415  {
1416  mProviderKey = "gdal";
1417  }
1418  }
1419 
1420  // Open the raster source based on provider and datasource
1421 
1422  // Go down the raster-data-provider paradigm
1423 
1424  // Collect provider-specific information
1425 
1426  QDomNode rpNode = layer_node.namedItem( "rasterproperties" );
1427 
1428  if ( mProviderKey == "wms" )
1429  {
1430  // >>> BACKWARD COMPATIBILITY < 1.9
1431  // The old WMS URI format does not contain all the informations, we add them here.
1432  if ( !mDataSource.contains( "crs=" ) && !mDataSource.contains( "format=" ) )
1433  {
1434  QgsDebugMsg( "Old WMS URI format detected -> adding params" );
1435  QgsDataSourceURI uri;
1436  uri.setEncodedUri( mDataSource );
1437  QDomElement layerElement = rpNode.firstChildElement( "wmsSublayer" );
1438  while ( !layerElement.isNull() )
1439  {
1440  // TODO: sublayer visibility - post-0.8 release timeframe
1441 
1442  // collect name for the sublayer
1443  uri.setParam( "layers", layerElement.namedItem( "name" ).toElement().text() );
1444 
1445  // collect style for the sublayer
1446  uri.setParam( "styles", layerElement.namedItem( "style" ).toElement().text() );
1447 
1448  layerElement = layerElement.nextSiblingElement( "wmsSublayer" );
1449  }
1450 
1451  // Collect format
1452  QDomNode formatNode = rpNode.namedItem( "wmsFormat" );
1453  uri.setParam( "format", rpNode.namedItem( "wmsFormat" ).toElement().text() );
1454 
1455  // WMS CRS URL param should not be mixed with that assigned to the layer.
1456  // In the old WMS URI version there was no CRS and layer crs().authid() was used.
1457  uri.setParam( "crs", crs().authid() );
1458  mDataSource = uri.encodedUri();
1459  }
1460  // <<< BACKWARD COMPATIBILITY < 1.9
1461  }
1462 
1464  if ( !mValid ) return false;
1465 
1466  QString theError;
1467  bool res = readSymbology( layer_node, theError );
1468 
1469  // old wms settings we need to correct
1470  if ( res && mProviderKey == "wms" && ( !renderer() || renderer()->type() != "singlebandcolordata" ) )
1471  {
1473  }
1474 
1475  // Check timestamp
1476  // This was probably introduced to reload completely raster if data changed and
1477  // reset completly symbology to reflect new data type etc. It creates however
1478  // problems, because user defined symbology is complete lost if data file time
1479  // changed (the content may be the same). See also 6900.
1480 #if 0
1481  QDomNode stampNode = layer_node.namedItem( "timestamp" );
1482  if ( !stampNode.isNull() )
1483  {
1484  QDateTime stamp = QDateTime::fromString( stampNode.toElement().text(), Qt::ISODate );
1485  // TODO: very bad, we have to load twice!!! Make QgsDataProvider::timestamp() static?
1486  if ( stamp < mDataProvider->dataTimestamp() )
1487  {
1488  QgsDebugMsg( "data changed, reload provider" );
1490  init();
1492  if ( !mValid ) return false;
1493  }
1494  }
1495 #endif
1496 
1497  // Load user no data value
1498  QDomElement noDataElement = layer_node.firstChildElement( "noData" );
1499 
1500  QDomNodeList noDataBandList = noDataElement.elementsByTagName( "noDataList" );
1501 
1502  for ( int i = 0; i < noDataBandList.size(); ++i )
1503  {
1504  QDomElement bandElement = noDataBandList.at( i ).toElement();
1505  bool ok;
1506  int bandNo = bandElement.attribute( "bandNo" ).toInt( &ok );
1507  QgsDebugMsg( QString( "bandNo = %1" ).arg( bandNo ) );
1508  if ( ok && ( bandNo > 0 ) && ( bandNo <= mDataProvider->bandCount() ) )
1509  {
1510  mDataProvider->setUseSrcNoDataValue( bandNo, bandElement.attribute( "useSrcNoData" ).toInt() );
1511  QgsRasterRangeList myNoDataRangeList;
1512 
1513  QDomNodeList rangeList = bandElement.elementsByTagName( "noDataRange" );
1514 
1515  for ( int j = 0; j < rangeList.size(); ++j )
1516  {
1517  QDomElement rangeElement = rangeList.at( j ).toElement();
1518  QgsRasterRange myNoDataRange( rangeElement.attribute( "min" ).toDouble(),
1519  rangeElement.attribute( "max" ).toDouble() );
1520  QgsDebugMsg( QString( "min = %1 %2" ).arg( rangeElement.attribute( "min" ) ).arg( myNoDataRange.min() ) );
1521  myNoDataRangeList << myNoDataRange;
1522  }
1523  mDataProvider->setUserNoDataValue( bandNo, myNoDataRangeList );
1524  }
1525  }
1526 
1527  return res;
1528 } // QgsRasterLayer::readXml( QDomNode & layer_node )
1529 
1530 /*
1531  * @param QDomNode the node that will have the style element added to it.
1532  * @param QDomDocument the document that will have the QDomNode added.
1533  * @param errorMessage reference to string that will be updated with any error messages
1534  * @return true in case of success.
1535  */
1536 bool QgsRasterLayer::writeSymbology( QDomNode & layer_node, QDomDocument & document, QString& errorMessage ) const
1537 {
1538  Q_UNUSED( errorMessage );
1539  QDomElement layerElem = layer_node.toElement();
1540 
1541  // Store pipe members (except provider) into pipe element, in future, it will be
1542  // possible to add custom filters into the pipe
1543  QDomElement pipeElement = document.createElement( "pipe" );
1544 
1545  for ( int i = 1; i < mPipe.size(); i++ )
1546  {
1547  QgsRasterInterface * interface = mPipe.at( i );
1548  if ( !interface ) continue;
1549  interface->writeXML( document, pipeElement );
1550  }
1551 
1552  layer_node.appendChild( pipeElement );
1553 
1554  // add blend mode node
1555  QDomElement blendModeElement = document.createElement( "blendMode" );
1556  QDomText blendModeText = document.createTextNode( QString::number( QgsMapRenderer::getBlendModeEnum( blendMode() ) ) );
1557  blendModeElement.appendChild( blendModeText );
1558  layer_node.appendChild( blendModeElement );
1559 
1560  return true;
1561 } // bool QgsRasterLayer::writeSymbology
1562 
1563 /*
1564  * virtual
1565  * @note Called by QgsMapLayer::writeXML().
1566  */
1567 bool QgsRasterLayer::writeXml( QDomNode & layer_node,
1568  QDomDocument & document )
1569 {
1570  // first get the layer element so that we can append the type attribute
1571 
1572  QDomElement mapLayerNode = layer_node.toElement();
1573 
1574  if ( mapLayerNode.isNull() || "maplayer" != mapLayerNode.nodeName() )
1575  {
1576  QgsMessageLog::logMessage( tr( "<maplayer> not found." ), tr( "Raster" ) );
1577  return false;
1578  }
1579 
1580  mapLayerNode.setAttribute( "type", "raster" );
1581 
1582  // add provider node
1583 
1584  QDomElement provider = document.createElement( "provider" );
1585  QDomText providerText = document.createTextNode( mProviderKey );
1586  provider.appendChild( providerText );
1587  layer_node.appendChild( provider );
1588 
1589  // User no data
1590  QDomElement noData = document.createElement( "noData" );
1591 
1592  for ( int bandNo = 1; bandNo <= mDataProvider->bandCount(); bandNo++ )
1593  {
1594  if ( mDataProvider->userNoDataValues( bandNo ).isEmpty() ) continue;
1595 
1596  QDomElement noDataRangeList = document.createElement( "noDataList" );
1597  noDataRangeList.setAttribute( "bandNo", bandNo );
1598  noDataRangeList.setAttribute( "useSrcNoData", mDataProvider->useSrcNoDataValue( bandNo ) );
1599 
1600  foreach ( QgsRasterRange range, mDataProvider->userNoDataValues( bandNo ) )
1601  {
1602  QDomElement noDataRange = document.createElement( "noDataRange" );
1603 
1604  noDataRange.setAttribute( "min", range.min() );
1605  noDataRange.setAttribute( "max", range.max() );
1606  noDataRangeList.appendChild( noDataRange );
1607  }
1608 
1609  noData.appendChild( noDataRangeList );
1610 
1611  }
1612  if ( noData.hasChildNodes() )
1613  {
1614  layer_node.appendChild( noData );
1615  }
1616 
1617  //write out the symbology
1618  QString errorMsg;
1619  return writeSymbology( layer_node, document, errorMsg );
1620 }
1621 
1623 {
1624  if ( !mDataProvider ) return 0;
1625  return mDataProvider->xSize();
1626 }
1627 
1629 {
1630  if ( !mDataProvider ) return 0;
1631  return mDataProvider->ySize();
1632 }
1633 
1635 //
1636 // Private methods
1637 //
1640 {
1641  QgsDebugMsg( "entered." );
1642  // Check if data changed
1644  {
1645  QgsDebugMsg( "reload data" );
1647  init();
1649  emit dataChanged();
1650  }
1651  return mValid;
1652 }
QgsDataProvider * classFactoryFunction_t(const QString *)
static void convertRasterProperties(QDomDocument &doc, QDomNode &parentNode, QDomElement &rasterPropertiesElem, QgsRasterLayer *rlayer)
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 setRenderer(QgsRasterRenderer *theRenderer)
Accessor for drawing style.
#define ERR(message)
void setContrastEnhancementAlgorithm(ContrastEnhancementAlgorithm, bool generateTable=true)
Set the contrast enhancement algorithm.
virtual QStringList subLayers() const
Returns the sublayers of this layer - useful for providers that manage their own layers, such as WMS.
IdentifyFormat
Definition: qgsraster.h:52
A rectangle specified with double values.
Definition: qgsrectangle.h:35
Base class for all map layer types.
Definition: qgsmaplayer.h:45
Interface for all raster shaders.
bool isEmpty() const
test if rectangle is empty
double rasterUnitsPerPixelY()
QgsMapLayer::LayerType type() const
Get the type of the layer.
Definition: qgsmaplayer.cpp:89
void setMinimal()
Set a rectangle so that min corner is at max.
double sum
The sum of all cells in the band.
Iterator for sequentially processing raster cells.
static QgsMapRenderer::BlendMode getBlendModeEnum(const QPainter::CompositionMode blendMode)
Returns a BlendMode corresponding to a QPainter::CompositionMode Added in 1.9.
DrawingStyle
This enumerator describes the different kinds of drawing we can do.
Definition: qgsraster.h:93
A ramp shader will color a raster pixel based on a list of values ranges in a ramp.
static QgsProviderRegistry * instance(QString pluginPath=QString::null)
means of accessing canonical single instance
QString lastErrorTitle()
[ data provider interface ] If an operation returns 0 (e.g.
double yMaximum() const
Get the y maximum value (top side of rectangle)
Definition: qgsrectangle.h:185
void setEncodedUri(const QByteArray &uri)
set complete encoded uri (generic mode)
#define QgsDebugMsg(str)
Definition: qgslogger.h:36
virtual QgsCoordinateReferenceSystem crs()=0
static ContrastEnhancementLimits contrastEnhancementLimitsFromString(QString theLimits)
Definition: qgsraster.cpp:39
void setDefaultContrastEnhancement()
Set default contrast enhancement.
void triggerRepaint()
Emit a signal asking for a repaint.
virtual void setUseSrcNoDataValue(int bandNo, bool use)
Set source nodata value usage.
virtual double srcNoDataValue(int bandNo) const
Value representing no data value.
QgsPoint transform(const QgsPoint &p) const
void setCustomProperty(const QString &key, const QVariant &value)
Set a custom property for layer.
virtual void setLayerOrder(const QStringList &layers)
Reorders the previously selected sublayers of this layer from bottom to top.
void drawingProgress(int theProgress, int theTotalSteps)
Emit a signal to notify of a progress event.
double maximumValue
The maximum cell value in the raster band.
int mWidth
Width, number of columns to be rendered.
QgsRasterInterface * last() const
Definition: qgsrasterpipe.h:86
virtual QgsRasterRangeList userNoDataValues(int bandNo) const
Get list of user no data value ranges.
static QDateTime lastModified(const QString &name)
Return time stamp for given file name.
Raster values range container.
const QgsRectangle & extent() const
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.
static QPainter::CompositionMode getCompositionMode(const QgsMapRenderer::BlendMode blendMode)
Returns a QPainter::CompositionMode corresponding to a BlendMode Added in 1.9.
void setColorRampItemList(const QList< QgsColorRampShader::ColorRampItem > &theList)
Set custom colormap.
void readXML(const QDomElement &filterElem)
Sets base class members from xml.
bool draw(QgsRenderContext &rendererContext)
This is called when the view on the raster layer needs to be redrawn.
static const double SAMPLE_SIZE
Default sample size (number of pixels) for estimated statistics/histogram calculation.
double scaleFactor() const
void updateProgress(int, int)
Propagate progress updates from GDAL up to the parent app.
size_t elementCount
The number of not no data cells in the band.
const QgsCoordinateTransform * coordinateTransform() const
void readXML(const QDomElement &filterElem)
Sets base class members from xml.
QString mError
[ data provider interface ]The error message associated with the last error
QString mLayerName
Name of the layer - used for display.
Definition: qgsmaplayer.h:483
void setShader(QgsRasterShader *shader)
Takes ownership of the shader.
BlendMode
Blending modes enum defining the available composition modes that can be used when rendering a layer...
double rasterUnitsPerPixelX()
Returns the number of raster units per each raster pixel.
virtual int ySize() const
void setGreenContrastEnhancement(QgsContrastEnhancement *ce)
Takes ownership.
static QString identifyFormatName(QgsRaster::IdentifyFormat format)
virtual QDateTime dataTimestamp() const
Current time stamp of data source.
static void logMessage(QString message, QString tag=QString::null, MessageLevel level=WARNING)
add a message to the instance (and create it if necessary)
int size() const
Definition: qgsrasterpipe.h:84
QgsCoordinateReferenceSystem mDestCRS
Target coordinate system.
void setDrawingStyle(const QString &theDrawingStyleQString)
Overloaded version of the above function for convenience when restoring from xml. ...
void setRendererForDrawingStyle(const QgsRaster::DrawingStyle &theDrawingStyle)
Sets corresponding renderer for style.
void set(const QgsPoint &p1, const QgsPoint &p2)
Set the rectangle from two QgsPoints. The rectangle is.
void init()
Initialize default values.
virtual bool useSrcNoDataValue(int bandNo) const
Get source nodata value usage.
void setCRS(const QgsCoordinateReferenceSystem &theSrcCRS, const QgsCoordinateReferenceSystem &theDestCRS)
set source and destination CRS
const QString & name() const
Get the display name of the layer.
void onProgress(int, double, QString)
receive progress signal from provider
Perform transforms between map coordinates and device coordinates.
Definition: qgsmaptopixel.h:33
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.
bool readXml(const QDomNode &layer_node)
Reads layer specific state from project file Dom node.
double stdDev
The standard deviation of the cell values.
virtual QStringList subLayers() const
Returns the sublayers of this layer - Useful for providers that manage their own layers, such as WMS.
The RasterBandStats struct is a container for statistics about a single raster band.
static QgsRasterRendererRegistry * instance()
void setError(const QgsError &theError)
Set error message.
Definition: qgsmaplayer.h:468
double mean
The mean cell value for the band.
int height() const
Accessor that returns the height of the (unclipped) raster.
QPainter::CompositionMode blendMode() const
Read blend mode for layer.
void readXML(const QDomElement &filterElem)
Sets base class members from xml.
void setRedContrastEnhancement(QgsContrastEnhancement *ce)
Takes ownership.
double yMinimum() const
Get the y minimum value (bottom side of rectangle)
Definition: qgsrectangle.h:190
QgsRasterRenderer * renderer() const
virtual void setUserNoDataValue(int bandNo, QgsRasterRangeList noData)
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.
double xMaximum() const
Get the x maximum value (right side of rectangle)
Definition: qgsrectangle.h:175
#define QgsDebugMsgLevel(str, level)
Definition: qgslogger.h:37
void setParam(const QString &key, const QString &value)
Set generic param (generic mode)
void setCrs(const QgsCoordinateReferenceSystem &srs, bool emitSignal=true)
Sets layer's spatial reference system.
QgsRasterViewPort mLastViewPort
virtual QGis::DataType srcDataType(int bandNo) const =0
Returns source data type for the band specified by number, source data type may be shorter than dataT...
virtual QgsRectangle extent()=0
Get the extent of the data source.
void statusChanged(QString theStatus)
Emit a signal with status (e.g.
virtual void setExtent(const QgsRectangle &rect)
Set the extent.
bool readSymbology(const QDomNode &node, QString &errorMessage)
Read the symbology for the current layer from the Dom node supplied.
static const double CUMULATIVE_CUT_UPPER
Default cumulative cut upper limit.
~QgsRasterLayer()
The destructor.
ContrastEnhancementLimits
Contrast enhancement limits.
Definition: qgsraster.h:84
void setMinimumValue(double, bool generateTable=true)
Return the minimum value for the contrast enhancement range.
Raster renderer pipe for single band pseudocolor.
void dataChanged()
This is emitted whenever data or metadata (e.g.
virtual QGis::DataType dataType(int bandNo) const =0
Returns data type for the band specified by number.
const QString bandName(int theBandNoInt)
Get the name of a band given its number.
double rasterScaleFactor() const
bool isvalidrasterfilename_t(QString const &theFileNameQString, QString &retErrMsg)
double min() const
Raster renderer pipe for single band gray.
virtual QString generateBandName(int theBandNumber) const
helper function to create zero padded band names
QgsRasterResampleFilter * resampleFilter() const
Set raster resample filter.
double mapUnitsPerPixel() const
Return current map units per pixel.
static int typeSize(int dataType)
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
QString lastError()
[ data provider interface ] If an operation returns 0 (e.g.
void setAlphaBand(int band)
bool mValid
Indicates if the layer is valid and can be drawn.
Definition: qgsmaplayer.h:477
void setContrastEnhancement(QgsContrastEnhancement::ContrastEnhancementAlgorithm theAlgorithm, QgsRaster::ContrastEnhancementLimits theLimits=QgsRaster::ContrastEnhancementMinMax, QgsRectangle theExtent=QgsRectangle(), int theSampleSize=SAMPLE_SIZE, bool theGenerateLookupTableFlag=true)
Set contrast enhancement algorithm.
void setDataProvider(const QString &provider)
[ data provider interface ] Set the data provider
QgsRasterDataProvider * mDataProvider
Pointer to data provider.
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 geometry.
Definition: qgspoint.h:63
void setColorRampType(QgsColorRampShader::ColorRamp_TYPE theColorRampType)
Set the color ramp type.
QPixmap previewAsPixmap(QSize size, QColor bgColor=Qt::white)
Draws a preview of the rasterlayer into a pixmap.
void setBlendMode(const QPainter::CompositionMode blendMode)
Write blend mode for layer.
Class for storing the component parts of a PostgreSQL/RDBMS datasource URI.
QPixmap paletteAsPixmap(int theBandNumber=1)
Get an 100x100 pixmap of the color palette.
bool shade(double, int *, int *, int *, int *)
Generates and new RGB value based on one input value.
void setX(double x)
Definition: qgspoint.h:87
static ContrastEnhancementAlgorithm contrastEnhancementAlgorithmFromString(const QString &contrastEnhancementString)
virtual int capabilities() const
Returns a bitmask containing the supported capabilities.
virtual int colorInterpretation(int theBandNo) const
Returns data type for the band specified by number.
QgsCoordinateReferenceSystem mSrcCRS
Source coordinate system.
QgsPoint toMapCoordinatesF(double x, double y) const
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.
bool writeSymbology(QDomNode &, QDomDocument &doc, QString &errorMessage) const
Write the symbology for the layer into the docment provided.
LayerType mRasterType
QgsPoint mBottomRightPoint
Coordinate (in output device coordinate system) of bottom right corner of the part of the raster that...
void setContrastEnhancement(QgsContrastEnhancement *ce)
Takes ownership.
QString metadata()
Obtain GDAL Metadata for this layer.
ContrastEnhancementAlgorithm
This enumerator describes the types of contrast enhancement algorithms that can be used...
QString what() const
Definition: qgsexception.h:35
QString mProviderKey
[ data provider interface ] Data provider key
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.
QgsRectangle transformBoundingBox(const QgsRectangle theRect, TransformDirection direction=ForwardTransform) const
QPainter * painter()
QDateTime mLastModified
[ data provider interface ] Timestamp, the last modified time of the data source when the layer was c...
bool remove(int idx)
Remove and delete interface at given index if possible.
QList< QgsRasterRange > QgsRasterRangeList
virtual int xSize() const
Get raster size.
unsigned int mTransparencyLevel
Transparency level for this layer should be 0-255 (255 being opaque)
Definition: qgsmaplayer.h:471
QString mDataSource
data source description string, varies by layer type
Definition: qgsmaplayer.h:480
virtual QString loadDefaultStyle(bool &theResultFlag)
Retrieve the default style for this layer if one exists (either as a .qml file on disk or as a record...
virtual QDateTime timestamp() const
Time stamp of data source in the moment when data/metadata were loaded by provider.
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.
QgsRectangle intersect(const QgsRectangle *rect) const
return the intersection with the given rectangle
virtual bool isValid()=0
Returns true if this is a valid layer.
void repaintRequested()
This signal should be connected with the slot QgsMapCanvas::refresh()
int mHeight
Distance in map units from bottom edge to top edge for the part of the raster that is to be rendered...
bool update()
Update the layer if it is outdated.
Brightness/contrast filter pipe for rasters.
Class for storing a coordinate reference system (CRS)
Color and saturation filter pipe for rasters.
static const double CUMULATIVE_CUT_LOWER
Default cumulative cut lower limit.
DataType
Raster data types.
Definition: qgis.h:163
virtual QString description() const =0
return description
double range
The range is the distance between min & max.
void setBlueContrastEnhancement(QgsContrastEnhancement *ce)
Takes ownership.
void closeDataProvider()
Close data provider and clear related members.
QgsHueSaturationFilter * hueSaturationFilter() const
double minimumValue
The minimum cell value in the raster band.
const QgsMapToPixel & mapToPixel() const
Renderer for multiband images with the color components.
void setLayerName(const QString &name)
Set the display name of the layer.
const QgsCoordinateReferenceSystem & crs() const
Returns layer's spatial reference system.
void * function(const QString &providerKey, const QString &functionName)
Get pointer to provider function.
void appendError(const QgsErrorMessage &theMessage)
Add error message.
Definition: qgsmaplayer.h:466
Manipulates raster pixel values so that they enhanceContrast or clip into a specified numerical range...
double max() const
QByteArray encodedUri() const
return complete encoded uri (generic mode)
void(*)() cast_to_fptr(void *p)
Definition: qgis.h:235
QgsRasterDataProvider * dataProvider()
Returns the data provider.
virtual void setSubLayerVisibility(QString name, bool vis)
Set the visibility of the given sublayer name.
Custom exception class for Coordinate Reference System related exceptions.
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 ...
virtual bool srcHasNoDataValue(int bandNo) const
This class provides details of the viewable area that a raster will be rendered into.
QString mErrorCaption
[ data provider interface ] The error caption associated with the last error
double width() const
Width of the rectangle.
Definition: qgsrectangle.h:195
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.
virtual QList< QgsColorRampShader::ColorRampItem > colorTable(int bandNo) const
const QgsCoordinateReferenceSystem & destCRS() const
virtual QgsRectangle extent()
Return the extent of the layer.
double size
Definition: qgssvgcache.cpp:75
QString toString(bool automaticPrecision=false) const
returns string representation of form xmin,ymin xmax,ymax
QgsRasterRenderer * renderer() const
QgsRasterPipe mPipe
bool set(QgsRasterInterface *theInterface)
Insert a new known interface in default place or replace interface of the same role if it already exi...
double xMinimum() const
Get the x minimum value (left side of rectangle)
Definition: qgsrectangle.h:180
virtual QgsError error() const
Get current status error.
QList< QPair< QString, QColor > > legendSymbologyItems() const
Returns a list with classification items (Text and color)
Raster renderer pipe that applies colors to a raster.
QgsRasterRendererCreateFunc rendererCreateFunction
void setDpi(int dpi)
Sets the output device resolution.
virtual QString dataSourceUri() const
Get the data source specification.
void setMaximumValue(double, bool generateTable=true)
Set the maximum value for the contrast enhancement range.
void showStatusMessage(const QString &theMessage)
bool writeXml(QDomNode &layer_node, QDomDocument &doc)
Write layer specific state to project file Dom node.
double height() const
Height of the rectangle.
Definition: qgsrectangle.h:200
QgsBrightnessContrastFilter * brightnessFilter() const
QgsRectangle mDrawnExtent
Intersection of current map extent and layer extent.
QString toProj4() const
Get the Proj Proj4 string representation of this srs.
virtual void reload()
Synchronises with changes in the datasource.
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.
#define tr(sourceText)
QgsRasterLayer()
Constructor.