QGIS API Documentation  2.99.0-Master (0a63d1f)
qgsrasterinterface.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  qgsrasterface.cpp - Internal raster processing modules interface
3  --------------------------------------
4  Date : Jun 21, 2012
5  Copyright : (C) 2012 by Radim Blazek
6  email : radim dot blazek at gmail dot 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 
18 #include <limits>
19 #include <typeinfo>
20 
21 #include <QByteArray>
22 #include <QTime>
23 #include <QStringList>
24 
25 #include <qmath.h>
26 
27 #include "qgslogger.h"
28 #include "qgsrasterbandstats.h"
29 #include "qgsrasterhistogram.h"
30 #include "qgsrasterinterface.h"
31 #include "qgsrectangle.h"
32 
34  : mInput( input )
35  , mOn( true )
36 {
37 }
38 
40  int theBandNo,
41  int theStats,
42  const QgsRectangle & theExtent,
43  int theSampleSize )
44 {
45  QgsDebugMsgLevel( QString( "theBandNo = %1 theSampleSize = %2" ).arg( theBandNo ).arg( theSampleSize ), 4 );
46 
47  theStatistics.bandNumber = theBandNo;
48  theStatistics.statsGathered = theStats;
49 
50  QgsRectangle myExtent;
51  if ( theExtent.isEmpty() )
52  {
53  myExtent = extent();
54  }
55  else
56  {
57  myExtent = extent().intersect( &theExtent );
58  }
59  theStatistics.extent = myExtent;
60 
61  if ( theSampleSize > 0 )
62  {
63  // Calc resolution from theSampleSize
64  double xRes, yRes;
65  xRes = yRes = sqrt(( myExtent.width() * myExtent.height() ) / theSampleSize );
66 
67  // But limit by physical resolution
68  if ( capabilities() & Size )
69  {
70  double srcXRes = extent().width() / xSize();
71  double srcYRes = extent().height() / ySize();
72  if ( xRes < srcXRes ) xRes = srcXRes;
73  if ( yRes < srcYRes ) yRes = srcYRes;
74  }
75  QgsDebugMsgLevel( QString( "xRes = %1 yRes = %2" ).arg( xRes ).arg( yRes ), 4 );
76 
77  theStatistics.width = static_cast <int>( myExtent.width() / xRes );
78  theStatistics.height = static_cast <int>( myExtent.height() / yRes );
79  }
80  else
81  {
82  if ( capabilities() & Size )
83  {
84  theStatistics.width = xSize();
85  theStatistics.height = ySize();
86  }
87  else
88  {
89  theStatistics.width = 1000;
90  theStatistics.height = 1000;
91  }
92  }
93  QgsDebugMsgLevel( QString( "theStatistics.width = %1 theStatistics.height = %2" ).arg( theStatistics.width ).arg( theStatistics.height ), 4 );
94 }
95 
97  int theStats,
98  const QgsRectangle & theExtent,
99  int theSampleSize )
100 {
101  QgsDebugMsgLevel( QString( "theBandNo = %1 theStats = %2 theSampleSize = %3" ).arg( theBandNo ).arg( theStats ).arg( theSampleSize ), 4 );
102  if ( mStatistics.isEmpty() ) return false;
103 
104  QgsRasterBandStats myRasterBandStats;
105  initStatistics( myRasterBandStats, theBandNo, theStats, theExtent, theSampleSize );
106 
107  Q_FOREACH ( const QgsRasterBandStats& stats, mStatistics )
108  {
109  if ( stats.contains( myRasterBandStats ) )
110  {
111  QgsDebugMsgLevel( "Has cached statistics.", 4 );
112  return true;
113  }
114  }
115  return false;
116 }
117 
119  int theStats,
120  const QgsRectangle & theExtent,
121  int theSampleSize )
122 {
123  QgsDebugMsgLevel( QString( "theBandNo = %1 theStats = %2 theSampleSize = %3" ).arg( theBandNo ).arg( theStats ).arg( theSampleSize ), 4 );
124 
125  // TODO: null values set on raster layer!!!
126 
127  QgsRasterBandStats myRasterBandStats;
128  initStatistics( myRasterBandStats, theBandNo, theStats, theExtent, theSampleSize );
129 
130  Q_FOREACH ( const QgsRasterBandStats& stats, mStatistics )
131  {
132  if ( stats.contains( myRasterBandStats ) )
133  {
134  QgsDebugMsgLevel( "Using cached statistics.", 4 );
135  return stats;
136  }
137  }
138 
139  QgsRectangle myExtent = myRasterBandStats.extent;
140  int myWidth = myRasterBandStats.width;
141  int myHeight = myRasterBandStats.height;
142 
143  //int myDataType = dataType( theBandNo );
144 
145  int myXBlockSize = xBlockSize();
146  int myYBlockSize = yBlockSize();
147  if ( myXBlockSize == 0 ) // should not happen, but happens
148  {
149  myXBlockSize = 500;
150  }
151  if ( myYBlockSize == 0 ) // should not happen, but happens
152  {
153  myYBlockSize = 500;
154  }
155 
156  int myNXBlocks = ( myWidth + myXBlockSize - 1 ) / myXBlockSize;
157  int myNYBlocks = ( myHeight + myYBlockSize - 1 ) / myYBlockSize;
158 
159  double myXRes = myExtent.width() / myWidth;
160  double myYRes = myExtent.height() / myHeight;
161  // TODO: progress signals
162 
163  // used by single pass stdev
164  double myMean = 0;
165  double mySumOfSquares = 0;
166 
167  bool myFirstIterationFlag = true;
168  for ( int myYBlock = 0; myYBlock < myNYBlocks; myYBlock++ )
169  {
170  for ( int myXBlock = 0; myXBlock < myNXBlocks; myXBlock++ )
171  {
172  QgsDebugMsgLevel( QString( "myYBlock = %1 myXBlock = %2" ).arg( myYBlock ).arg( myXBlock ), 4 );
173  int myBlockWidth = qMin( myXBlockSize, myWidth - myXBlock * myXBlockSize );
174  int myBlockHeight = qMin( myYBlockSize, myHeight - myYBlock * myYBlockSize );
175 
176  double xmin = myExtent.xMinimum() + myXBlock * myXBlockSize * myXRes;
177  double xmax = xmin + myBlockWidth * myXRes;
178  double ymin = myExtent.yMaximum() - myYBlock * myYBlockSize * myYRes;
179  double ymax = ymin - myBlockHeight * myYRes;
180 
181  QgsRectangle myPartExtent( xmin, ymin, xmax, ymax );
182 
183  QgsRasterBlock* blk = block( theBandNo, myPartExtent, myBlockWidth, myBlockHeight );
184 
185  // Collect the histogram counts.
186  for ( qgssize i = 0; i < ( static_cast< qgssize >( myBlockHeight ) ) * myBlockWidth; i++ )
187  {
188  if ( blk->isNoData( i ) ) continue; // NULL
189 
190  double myValue = blk->value( i );
191 
192  myRasterBandStats.sum += myValue;
193  myRasterBandStats.elementCount++;
194 
195  if ( myFirstIterationFlag )
196  {
197  myFirstIterationFlag = false;
198  myRasterBandStats.minimumValue = myValue;
199  myRasterBandStats.maximumValue = myValue;
200  }
201  else
202  {
203  if ( myValue < myRasterBandStats.minimumValue )
204  {
205  myRasterBandStats.minimumValue = myValue;
206  }
207  if ( myValue > myRasterBandStats.maximumValue )
208  {
209  myRasterBandStats.maximumValue = myValue;
210  }
211  }
212 
213  // Single pass stdev
214  double myDelta = myValue - myMean;
215  myMean += myDelta / myRasterBandStats.elementCount;
216  mySumOfSquares += myDelta * ( myValue - myMean );
217  }
218  delete blk;
219  }
220  }
221 
222  myRasterBandStats.range = myRasterBandStats.maximumValue - myRasterBandStats.minimumValue;
223  myRasterBandStats.mean = myRasterBandStats.sum / myRasterBandStats.elementCount;
224 
225  myRasterBandStats.sumOfSquares = mySumOfSquares; // OK with single pass?
226 
227  // stdDev may differ from GDAL stats, because GDAL is using naive single pass
228  // algorithm which is more error prone (because of rounding errors)
229  // Divide result by sample size - 1 and get square root to get stdev
230  myRasterBandStats.stdDev = sqrt( mySumOfSquares / ( myRasterBandStats.elementCount - 1 ) );
231 
232  QgsDebugMsgLevel( "************ STATS **************", 4 );
233  QgsDebugMsgLevel( QString( "MIN %1" ).arg( myRasterBandStats.minimumValue ), 4 );
234  QgsDebugMsgLevel( QString( "MAX %1" ).arg( myRasterBandStats.maximumValue ), 4 );
235  QgsDebugMsgLevel( QString( "RANGE %1" ).arg( myRasterBandStats.range ), 4 );
236  QgsDebugMsgLevel( QString( "MEAN %1" ).arg( myRasterBandStats.mean ), 4 );
237  QgsDebugMsgLevel( QString( "STDDEV %1" ).arg( myRasterBandStats.stdDev ), 4 );
238 
239  myRasterBandStats.statsGathered = QgsRasterBandStats::All;
240  mStatistics.append( myRasterBandStats );
241 
242  return myRasterBandStats;
243 }
244 
246  int theBandNo,
247  int theBinCount,
248  double theMinimum, double theMaximum,
249  const QgsRectangle & theExtent,
250  int theSampleSize,
251  bool theIncludeOutOfRange )
252 {
253  theHistogram.bandNumber = theBandNo;
254  theHistogram.minimum = theMinimum;
255  theHistogram.maximum = theMaximum;
256  theHistogram.includeOutOfRange = theIncludeOutOfRange;
257 
258  int mySrcDataType = sourceDataType( theBandNo );
259 
260  if ( qIsNaN( theHistogram.minimum ) )
261  {
262  // TODO: this was OK when stats/histogram were calced in provider,
263  // but what TODO in other interfaces? Check for mInput for now.
264  if ( !mInput && mySrcDataType == Qgis::Byte )
265  {
266  theHistogram.minimum = 0; // see histogram() for shift for rounding
267  }
268  else
269  {
270  // We need statistics -> avoid histogramDefaults in hasHistogram if possible
271  // TODO: use approximated statistics if approximated histogram is requested
272  // (theSampleSize > 0)
273  QgsRasterBandStats stats = bandStatistics( theBandNo, QgsRasterBandStats::Min, theExtent, theSampleSize );
274  theHistogram.minimum = stats.minimumValue;
275  }
276  }
277  if ( qIsNaN( theHistogram.maximum ) )
278  {
279  if ( !mInput && mySrcDataType == Qgis::Byte )
280  {
281  theHistogram.maximum = 255;
282  }
283  else
284  {
285  QgsRasterBandStats stats = bandStatistics( theBandNo, QgsRasterBandStats::Max, theExtent, theSampleSize );
286  theHistogram.maximum = stats.maximumValue;
287  }
288  }
289 
290  QgsRectangle myExtent;
291  if ( theExtent.isEmpty() )
292  {
293  myExtent = extent();
294  }
295  else
296  {
297  myExtent = extent().intersect( &theExtent );
298  }
299  theHistogram.extent = myExtent;
300 
301  if ( theSampleSize > 0 )
302  {
303  // Calc resolution from theSampleSize
304  double xRes, yRes;
305  xRes = yRes = sqrt(( myExtent.width() * myExtent.height() ) / theSampleSize );
306 
307  // But limit by physical resolution
308  if ( capabilities() & Size )
309  {
310  double srcXRes = extent().width() / xSize();
311  double srcYRes = extent().height() / ySize();
312  if ( xRes < srcXRes ) xRes = srcXRes;
313  if ( yRes < srcYRes ) yRes = srcYRes;
314  }
315  QgsDebugMsgLevel( QString( "xRes = %1 yRes = %2" ).arg( xRes ).arg( yRes ), 4 );
316 
317  theHistogram.width = static_cast <int>( myExtent.width() / xRes );
318  theHistogram.height = static_cast <int>( myExtent.height() / yRes );
319  }
320  else
321  {
322  if ( capabilities() & Size )
323  {
324  theHistogram.width = xSize();
325  theHistogram.height = ySize();
326  }
327  else
328  {
329  theHistogram.width = 1000;
330  theHistogram.height = 1000;
331  }
332  }
333  QgsDebugMsgLevel( QString( "theHistogram.width = %1 theHistogram.height = %2" ).arg( theHistogram.width ).arg( theHistogram.height ), 4 );
334 
335  int myBinCount = theBinCount;
336  if ( myBinCount == 0 )
337  {
338  // TODO: this was OK when stats/histogram were calced in provider,
339  // but what TODO in other interfaces? Check for mInput for now.
340  if ( !mInput && mySrcDataType == Qgis::Byte )
341  {
342  myBinCount = 256; // Cannot store more values in byte
343  }
344  else
345  {
346  // There is no best default value, to display something reasonable in histogram chart, binCount should be small, OTOH, to get precise data for cumulative cut, the number should be big. Because it is easier to define fixed lower value for the chart, we calc optimum binCount for higher resolution (to avoid calculating that where histogram() is used. In any any case, it does not make sense to use more than width*height;
347  myBinCount = theHistogram.width * theHistogram.height;
348  if ( myBinCount > 1000 ) myBinCount = 1000;
349 
350  // for Int16/Int32 make sure bin count <= actual range, because there is no sense in having
351  // bins at fractional values
352  if ( !mInput && (
353  mySrcDataType == Qgis::Int16 || mySrcDataType == Qgis::Int32 ||
354  mySrcDataType == Qgis::UInt16 || mySrcDataType == Qgis::UInt32 ) )
355  {
356  if ( myBinCount > theHistogram.maximum - theHistogram.minimum + 1 )
357  myBinCount = int( ceil( theHistogram.maximum - theHistogram.minimum + 1 ) );
358  }
359  }
360  }
361  theHistogram.binCount = myBinCount;
362  QgsDebugMsgLevel( QString( "theHistogram.binCount = %1" ).arg( theHistogram.binCount ), 4 );
363 }
364 
365 
367  int theBinCount,
368  double theMinimum, double theMaximum,
369  const QgsRectangle & theExtent,
370  int theSampleSize,
371  bool theIncludeOutOfRange )
372 {
373  QgsDebugMsgLevel( QString( "theBandNo = %1 theBinCount = %2 theMinimum = %3 theMaximum = %4 theSampleSize = %5" ).arg( theBandNo ).arg( theBinCount ).arg( theMinimum ).arg( theMaximum ).arg( theSampleSize ), 4 );
374  // histogramDefaults() needs statistics if theMinimum or theMaximum is NaN ->
375  // do other checks which don't need statistics before histogramDefaults()
376  if ( mHistograms.isEmpty() ) return false;
377 
378  QgsRasterHistogram myHistogram;
379  initHistogram( myHistogram, theBandNo, theBinCount, theMinimum, theMaximum, theExtent, theSampleSize, theIncludeOutOfRange );
380 
381  Q_FOREACH ( const QgsRasterHistogram& histogram, mHistograms )
382  {
383  if ( histogram == myHistogram )
384  {
385  QgsDebugMsgLevel( "Has cached histogram.", 4 );
386  return true;
387  }
388  }
389  return false;
390 }
391 
393  int theBinCount,
394  double theMinimum, double theMaximum,
395  const QgsRectangle & theExtent,
396  int theSampleSize,
397  bool theIncludeOutOfRange )
398 {
399  QgsDebugMsgLevel( QString( "theBandNo = %1 theBinCount = %2 theMinimum = %3 theMaximum = %4 theSampleSize = %5" ).arg( theBandNo ).arg( theBinCount ).arg( theMinimum ).arg( theMaximum ).arg( theSampleSize ), 4 );
400 
401  QgsRasterHistogram myHistogram;
402  initHistogram( myHistogram, theBandNo, theBinCount, theMinimum, theMaximum, theExtent, theSampleSize, theIncludeOutOfRange );
403 
404  // Find cached
405  Q_FOREACH ( const QgsRasterHistogram& histogram, mHistograms )
406  {
407  if ( histogram == myHistogram )
408  {
409  QgsDebugMsgLevel( "Using cached histogram.", 4 );
410  return histogram;
411  }
412  }
413 
414  int myBinCount = myHistogram.binCount;
415  int myWidth = myHistogram.width;
416  int myHeight = myHistogram.height;
417  QgsRectangle myExtent = myHistogram.extent;
418  myHistogram.histogramVector.resize( myBinCount );
419 
420  int myXBlockSize = xBlockSize();
421  int myYBlockSize = yBlockSize();
422  if ( myXBlockSize == 0 ) // should not happen, but happens
423  {
424  myXBlockSize = 500;
425  }
426  if ( myYBlockSize == 0 ) // should not happen, but happens
427  {
428  myYBlockSize = 500;
429  }
430 
431  int myNXBlocks = ( myWidth + myXBlockSize - 1 ) / myXBlockSize;
432  int myNYBlocks = ( myHeight + myYBlockSize - 1 ) / myYBlockSize;
433 
434  double myXRes = myExtent.width() / myWidth;
435  double myYRes = myExtent.height() / myHeight;
436 
437  double myMinimum = myHistogram.minimum;
438  double myMaximum = myHistogram.maximum;
439 
440  // To avoid rounding errors
441  // TODO: check this
442  double myerval = ( myMaximum - myMinimum ) / myHistogram.binCount;
443  myMinimum -= 0.1 * myerval;
444  myMaximum += 0.1 * myerval;
445 
446  QgsDebugMsgLevel( QString( "binCount = %1 myMinimum = %2 myMaximum = %3" ).arg( myHistogram.binCount ).arg( myMinimum ).arg( myMaximum ), 4 );
447 
448  double myBinSize = ( myMaximum - myMinimum ) / myBinCount;
449 
450  // TODO: progress signals
451  for ( int myYBlock = 0; myYBlock < myNYBlocks; myYBlock++ )
452  {
453  for ( int myXBlock = 0; myXBlock < myNXBlocks; myXBlock++ )
454  {
455  int myBlockWidth = qMin( myXBlockSize, myWidth - myXBlock * myXBlockSize );
456  int myBlockHeight = qMin( myYBlockSize, myHeight - myYBlock * myYBlockSize );
457 
458  double xmin = myExtent.xMinimum() + myXBlock * myXBlockSize * myXRes;
459  double xmax = xmin + myBlockWidth * myXRes;
460  double ymin = myExtent.yMaximum() - myYBlock * myYBlockSize * myYRes;
461  double ymax = ymin - myBlockHeight * myYRes;
462 
463  QgsRectangle myPartExtent( xmin, ymin, xmax, ymax );
464 
465  QgsRasterBlock* blk = block( theBandNo, myPartExtent, myBlockWidth, myBlockHeight );
466 
467  // Collect the histogram counts.
468  for ( qgssize i = 0; i < ( static_cast< qgssize >( myBlockHeight ) ) * myBlockWidth; i++ )
469  {
470  if ( blk->isNoData( i ) )
471  {
472  continue; // NULL
473  }
474  double myValue = blk->value( i );
475 
476  int myBinIndex = static_cast <int>( qFloor(( myValue - myMinimum ) / myBinSize ) );
477 
478  if (( myBinIndex < 0 || myBinIndex > ( myBinCount - 1 ) ) && !theIncludeOutOfRange )
479  {
480  continue;
481  }
482  if ( myBinIndex < 0 ) myBinIndex = 0;
483  if ( myBinIndex > ( myBinCount - 1 ) ) myBinIndex = myBinCount - 1;
484 
485  myHistogram.histogramVector[myBinIndex] += 1;
486  myHistogram.nonNullCount++;
487  }
488  delete blk;
489  }
490  }
491 
492  myHistogram.valid = true;
493  mHistograms.append( myHistogram );
494 
495 #ifdef QGISDEBUG
496  QString hist;
497  for ( int i = 0; i < qMin( myHistogram.histogramVector.size(), 500 ); i++ )
498  {
499  hist += QString::number( myHistogram.histogramVector.value( i ) ) + ' ';
500  }
501  QgsDebugMsgLevel( "Histogram (max first 500 bins): " + hist, 4 );
502 #endif
503 
504  return myHistogram;
505 }
506 
508  double theLowerCount, double theUpperCount,
509  double &theLowerValue, double &theUpperValue,
510  const QgsRectangle & theExtent,
511  int theSampleSize )
512 {
513  QgsDebugMsgLevel( QString( "theBandNo = %1 theLowerCount = %2 theUpperCount = %3 theSampleSize = %4" ).arg( theBandNo ).arg( theLowerCount ).arg( theUpperCount ).arg( theSampleSize ), 4 );
514 
515  int mySrcDataType = sourceDataType( theBandNo );
516 
517  // Init to NaN is better than histogram min/max to catch errors
518  theLowerValue = std::numeric_limits<double>::quiet_NaN();
519  theUpperValue = std::numeric_limits<double>::quiet_NaN();
520 
521  //get band stats to specify real histogram min/max (fix #9793 Byte bands)
522  QgsRasterBandStats stats = bandStatistics( theBandNo, QgsRasterBandStats::Min, theExtent, theSampleSize );
523  if ( stats.maximumValue < stats.minimumValue )
524  return;
525 
526  // for byte bands make sure bin count == actual range
527  int myBinCount = ( mySrcDataType == Qgis::Byte ) ? int( ceil( stats.maximumValue - stats.minimumValue + 1 ) ) : 0;
528  QgsRasterHistogram myHistogram = histogram( theBandNo, myBinCount, stats.minimumValue, stats.maximumValue, theExtent, theSampleSize );
529  //QgsRasterHistogram myHistogram = histogram( theBandNo, 0, std::numeric_limits<double>::quiet_NaN(), std::numeric_limits<double>::quiet_NaN(), theExtent, theSampleSize );
530 
531  double myBinXStep = ( myHistogram.maximum - myHistogram.minimum ) / myHistogram.binCount;
532  int myCount = 0;
533  int myMinCount = static_cast< int >( qRound( theLowerCount * myHistogram.nonNullCount ) );
534  int myMaxCount = static_cast< int >( qRound( theUpperCount * myHistogram.nonNullCount ) );
535  bool myLowerFound = false;
536  QgsDebugMsgLevel( QString( "binCount = %1 minimum = %2 maximum = %3 myBinXStep = %4" ).arg( myHistogram.binCount ).arg( myHistogram.minimum ).arg( myHistogram.maximum ).arg( myBinXStep ), 4 );
537  QgsDebugMsgLevel( QString( "myMinCount = %1 myMaxCount = %2" ).arg( myMinCount ).arg( myMaxCount ), 4 );
538 
539  for ( int myBin = 0; myBin < myHistogram.histogramVector.size(); myBin++ )
540  {
541  int myBinValue = myHistogram.histogramVector.value( myBin );
542  myCount += myBinValue;
543  if ( !myLowerFound && myCount > myMinCount )
544  {
545  theLowerValue = myHistogram.minimum + myBin * myBinXStep;
546  myLowerFound = true;
547  QgsDebugMsgLevel( QString( "found lowerValue %1 at bin %2" ).arg( theLowerValue ).arg( myBin ), 4 );
548  }
549  if ( myCount >= myMaxCount )
550  {
551  theUpperValue = myHistogram.minimum + myBin * myBinXStep;
552  QgsDebugMsgLevel( QString( "found upperValue %1 at bin %2" ).arg( theUpperValue ).arg( myBin ), 4 );
553  break;
554  }
555  }
556 
557  // fix integer data - round down/up
558  if ( mySrcDataType == Qgis::Byte ||
559  mySrcDataType == Qgis::Int16 || mySrcDataType == Qgis::Int32 ||
560  mySrcDataType == Qgis::UInt16 || mySrcDataType == Qgis::UInt32 )
561  {
562  if ( theLowerValue != std::numeric_limits<double>::quiet_NaN() )
563  theLowerValue = floor( theLowerValue );
564  if ( theUpperValue != std::numeric_limits<double>::quiet_NaN() )
565  theUpperValue = ceil( theUpperValue );
566  }
567 }
568 
570 {
571  QStringList abilitiesList;
572 
573  int abilities = capabilities();
574 
575  // Not all all capabilities are here (Size, IdentifyValue, IdentifyText,
576  // IdentifyHtml, IdentifyFeature) because those are quite technical and probably
577  // would be confusing for users
578 
579  if ( abilities & QgsRasterInterface::Identify )
580  {
581  abilitiesList += tr( "Identify" );
582  }
583 
584  if ( abilities & QgsRasterInterface::Create )
585  {
586  abilitiesList += tr( "Create Datasources" );
587  }
588 
589  if ( abilities & QgsRasterInterface::Remove )
590  {
591  abilitiesList += tr( "Remove Datasources" );
592  }
593 
594  if ( abilities & QgsRasterInterface::BuildPyramids )
595  {
596  abilitiesList += tr( "Build Pyramids" );
597  }
598 
599  QgsDebugMsgLevel( "Capability: " + abilitiesList.join( ", " ), 4 );
600 
601  return abilitiesList.join( QStringLiteral( ", " ) );
602 }
A rectangle specified with double values.
Definition: qgsrectangle.h:36
Thirty two bit signed integer (qint32)
Definition: qgis.h:68
double sum
The sum of all cells in the band. NO_DATA values are excluded.
void initHistogram(QgsRasterHistogram &theHistogram, int theBandNo, int theBinCount=0, double theMinimum=std::numeric_limits< double >::quiet_NaN(), double theMaximum=std::numeric_limits< double >::quiet_NaN(), const QgsRectangle &theExtent=QgsRectangle(), int theSampleSize=0, bool theIncludeOutOfRange=false)
Fill in histogram defaults if not specified.
virtual QgsRectangle extent() const
Get the extent of the interface.
int bandNumber
The gdal band number (starts at 1)
int width
Number of columns used to calc histogram.
int height
Number of rows used to calc statistics.
int bandNumber
The gdal band number (starts at 1)
double minimum
The minimum histogram value.
Thirty two bit unsigned integer (quint32)
Definition: qgis.h:67
double maximumValue
The maximum cell value in the raster band.
virtual int ySize() const
QgsRectangle intersect(const QgsRectangle *rect) const
return the intersection with the given rectangle
int height
Number of rows used to calc histogram.
Sixteen bit signed integer (qint16)
Definition: qgis.h:66
bool isNoData(int row, int column)
Check if value at position is no data.
bool contains(const QgsRasterBandStats &s) const
Compares region, size etc. not collected statistics.
void initStatistics(QgsRasterBandStats &theStatistics, int theBandNo, int theStats=QgsRasterBandStats::All, const QgsRectangle &theExtent=QgsRectangle(), int theBinCount=0)
Fill in statistics defaults if not specified.
virtual int xBlockSize() const
Get block size.
QgsRectangle extent
Extent used to calc statistics.
virtual QgsRasterBandStats bandStatistics(int theBandNo, int theStats=QgsRasterBandStats::All, const QgsRectangle &theExtent=QgsRectangle(), int theSampleSize=0)
Get band statistics.
double stdDev
The standard deviation of the cell values.
The RasterBandStats struct is a container for statistics about a single raster band.
double mean
The mean cell value for the band. NO_DATA values are excluded.
virtual bool hasHistogram(int theBandNo, int theBinCount, double theMinimum=std::numeric_limits< double >::quiet_NaN(), double theMaximum=std::numeric_limits< double >::quiet_NaN(), const QgsRectangle &theExtent=QgsRectangle(), int theSampleSize=0, bool theIncludeOutOfRange=false)
Returns true if histogram is available (cached, already calculated), the parameters are the same as i...
QgsRasterInterface(QgsRasterInterface *input=nullptr)
Raster data container.
#define QgsDebugMsgLevel(str, level)
Definition: qgslogger.h:37
bool isEmpty() const
test if rectangle is empty.
virtual QgsRasterBlock * block(int bandNo, const QgsRectangle &extent, int width, int height, QgsRasterBlockFeedback *feedback=nullptr)=0
Read block of data using given extent and size.
virtual int capabilities() const
Returns a bitmask containing the supported capabilities.
double width() const
Width of the rectangle.
Definition: qgsrectangle.h:212
QList< QgsRasterHistogram > mHistograms
List of cached histograms, all bands mixed.
qgssize elementCount
The number of not no data cells in the band.
int statsGathered
Collected statistics.
QString capabilitiesString() const
Returns the above in friendly format.
virtual Qgis::DataType sourceDataType(int bandNo) const
Returns source data type for the band specified by number, source data type may be shorter than dataT...
Sixteen bit unsigned integer (quint16)
Definition: qgis.h:65
Base class for processing filters like renderers, reprojector, resampler etc.
unsigned long long qgssize
Qgssize is used instead of size_t, because size_t is stdlib type, unknown by SIP, and it would be har...
Definition: qgis.h:333
virtual QgsRasterHistogram histogram(int theBandNo, int theBinCount=0, double theMinimum=std::numeric_limits< double >::quiet_NaN(), double theMaximum=std::numeric_limits< double >::quiet_NaN(), const QgsRectangle &theExtent=QgsRectangle(), int theSampleSize=0, bool theIncludeOutOfRange=false)
Get histogram.
double maximum
The maximum histogram value.
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).
virtual int yBlockSize() const
double range
The range is the distance between min & max.
double value(int row, int column) const
Read a single value if type of block is numeric.
double xMinimum() const
Get the x minimum value (left side of rectangle)
Definition: qgsrectangle.h:197
double minimumValue
The minimum cell value in the raster band.
The QgsRasterHistogram is a container for histogram of a single raster band.
int binCount
Number of bins (intervals,buckets) in histogram.
double yMaximum() const
Get the y maximum value (top side of rectangle)
Definition: qgsrectangle.h:202
QList< QgsRasterBandStats > mStatistics
List of cached statistics, all bands mixed.
HistogramVector histogramVector
Store the histogram for a given layer.
bool valid
Histogram is valid.
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.
QgsRasterInterface * mInput
QgsRectangle extent
Extent used to calc histogram.
virtual int xSize() const
Get raster size.
Eight bit unsigned integer (quint8)
Definition: qgis.h:64
bool includeOutOfRange
Whether histogram includes out of range values (in first and last bin)
double height() const
Height of the rectangle.
Definition: qgsrectangle.h:217
double sumOfSquares
The sum of the squares. Used to calculate standard deviation.
int width
Number of columns used to calc statistics.
int nonNullCount
The number of non NULL cells used to calculate histogram.