@@ -1426,24 +1426,25 @@ bool QgsGdalProvider::hasCachedHistogram( int theBandNo, int theBinCount )
1426
1426
if ( ! myGdalBand )
1427
1427
return false ;
1428
1428
1429
- // get default histo
1429
+ // get default histogram with force=false to see if there is a cached histo
1430
1430
double myMinVal, myMaxVal;
1431
- QgsRasterBandStats theBandStats = bandStatistics ( theBandNo );
1432
- double myerval = ( theBandStats.maximumValue - theBandStats.minimumValue ) / theBinCount;
1433
- myMinVal = theBandStats.minimumValue - 0.1 *myerval;
1434
- myMaxVal = theBandStats.maximumValue + 0.1 *myerval;
1435
- int *myHistogramArray=0 ;
1436
- CPLErr myError = GDALGetDefaultHistogram ( myGdalBand, &myMinVal, &myMaxVal,
1437
- &theBinCount, &myHistogramArray, false ,
1438
- NULL , NULL );
1439
- if ( myHistogramArray )
1431
+ int myBinCount;
1432
+ int *myHistogramArray = 0 ;
1433
+ CPLErr myError = GDALGetDefaultHistogram ( myGdalBand, &myMinVal, &myMaxVal,
1434
+ &myBinCount, &myHistogramArray, false ,
1435
+ NULL , NULL );
1436
+ if ( myHistogramArray )
1440
1437
VSIFree ( myHistogramArray );
1441
1438
1442
1439
// if there was any error/warning assume the histogram is not valid or non-existent
1443
1440
if ( myError != CE_None )
1444
1441
return false ;
1445
- return true ;
1446
1442
1443
+ // make sure the cached histo has the same number of bins than requested
1444
+ if ( myBinCount != theBinCount )
1445
+ return false ;
1446
+
1447
+ return true ;
1447
1448
}
1448
1449
1449
1450
void QgsGdalProvider::populateHistogram ( int theBandNo, QgsRasterBandStats & theBandStats, int theBinCount, bool theIgnoreOutOfRangeFlag, bool theHistogramEstimatedFlag )
@@ -1460,34 +1461,58 @@ void QgsGdalProvider::populateHistogram( int theBandNo, QgsRasterBandStats & the
1460
1461
theIgnoreOutOfRangeFlag != theBandStats.isHistogramOutOfRange ||
1461
1462
theHistogramEstimatedFlag != theBandStats.isHistogramEstimated )
1462
1463
{
1464
+ QgsDebugMsg ( " Computing histogram" );
1463
1465
theBandStats.histogramVector ->clear ();
1464
1466
theBandStats.isHistogramEstimated = theHistogramEstimatedFlag;
1465
1467
theBandStats.isHistogramOutOfRange = theIgnoreOutOfRangeFlag;
1466
1468
int *myHistogramArray = new int [theBinCount];
1467
1469
1468
- #if 0
1469
- CPLErr GDALRasterBand::GetHistogram(
1470
- double dfMin,
1471
- double dfMax,
1472
- int nBuckets,
1473
- int * panHistogram,
1474
- int bIncludeOutOfRange,
1475
- int bApproxOK,
1476
- GDALProgressFunc pfnProgress,
1477
- void * pProgressData
1478
- )
1479
- #endif
1480
-
1481
1470
QgsGdalProgress myProg;
1482
1471
myProg.type = ProgressHistogram;
1483
1472
myProg.provider = this ;
1484
- double myerval = ( theBandStats.maximumValue - theBandStats.minimumValue ) / theBinCount;
1485
1473
1474
+ #if 0 // this is the old method
1475
+
1476
+ double myerval = ( theBandStats.maximumValue - theBandStats.minimumValue ) / theBinCount;
1486
1477
GDALGetRasterHistogram( myGdalBand, theBandStats.minimumValue - 0.1*myerval,
1487
1478
theBandStats.maximumValue + 0.1*myerval, theBinCount, myHistogramArray,
1488
1479
theIgnoreOutOfRangeFlag, theHistogramEstimatedFlag, progressCallback,
1489
1480
&myProg ); //this is the arg for our custom gdal progress callback
1490
1481
1482
+ #else // this is the new method, which gets a "Default" histogram
1483
+
1484
+ // calculate min/max like in GDALRasterBand::GetDefaultHistogram, but don't call it directly
1485
+ // because there is no bApproxOK argument - that is lacking from the API
1486
+ double myMinVal, myMaxVal;
1487
+ const char * pszPixelType = GDALGetMetadataItem ( myGdalBand, " PIXELTYPE" , " IMAGE_STRUCTURE" );
1488
+ int bSignedByte = ( pszPixelType != NULL && EQUAL ( pszPixelType, " SIGNEDBYTE" ) );
1489
+
1490
+ if ( GDALGetRasterDataType ( myGdalBand ) == GDT_Byte && !bSignedByte )
1491
+ {
1492
+ myMinVal = -0.5 ;
1493
+ myMaxVal = 255.5 ;
1494
+ }
1495
+ else
1496
+ {
1497
+ CPLErr eErr = CE_Failure;
1498
+ double dfHalfBucket = 0 ;
1499
+ eErr = GDALGetRasterStatistics ( myGdalBand, TRUE , TRUE , &myMinVal, &myMaxVal, NULL , NULL );
1500
+ if ( eErr != CE_None )
1501
+ return ;
1502
+ dfHalfBucket = ( myMaxVal - myMinVal ) / ( 2 * theBinCount );
1503
+ myMinVal -= dfHalfBucket;
1504
+ myMaxVal += dfHalfBucket;
1505
+ }
1506
+
1507
+ CPLErr myError = GDALGetRasterHistogram ( myGdalBand, myMinVal, myMaxVal,
1508
+ theBinCount, myHistogramArray,
1509
+ theIgnoreOutOfRangeFlag, theHistogramEstimatedFlag, progressCallback,
1510
+ &myProg ); // this is the arg for our custom gdal progress callback
1511
+ if ( myError != CE_None )
1512
+ return ;
1513
+
1514
+ #endif
1515
+
1491
1516
for ( int myBin = 0 ; myBin < theBinCount; myBin++ )
1492
1517
{
1493
1518
if ( myHistogramArray[myBin] < 0 ) // can't have less than 0 pixels of any value
@@ -2063,7 +2088,8 @@ QgsRasterBandStats QgsGdalProvider::bandStatistics( int theBandNo )
2063
2088
{
2064
2089
GDALRasterBandH myGdalBand = GDALGetRasterBand ( mGdalDataset , theBandNo );
2065
2090
QgsRasterBandStats myRasterBandStats;
2066
- int bApproxOK = true ;
2091
+ // int bApproxOK = true;
2092
+ int bApproxOK = false ; // as we asked for stats, don't get approx values
2067
2093
double pdfMin;
2068
2094
double pdfMax;
2069
2095
double pdfMean;
@@ -2072,16 +2098,6 @@ QgsRasterBandStats QgsGdalProvider::bandStatistics( int theBandNo )
2072
2098
myProg.type = ProgressHistogram;
2073
2099
myProg.provider = this ;
2074
2100
2075
- // double myerval =
2076
- // GDALComputeRasterStatistics (
2077
- // myGdalBand, bApproxOK, &pdfMin, &pdfMax, &pdfMean, &pdfStdDev,
2078
- // progressCallback, &myProg ) ;
2079
- // double myerval =
2080
- // GDALGetRasterStatistics ( myGdalBand, bApproxOK, TRUE, &pdfMin, &pdfMax, &pdfMean, &pdfStdDev);
2081
- // double myerval =
2082
- // GDALGetRasterStatisticsProgress ( myGdalBand, bApproxOK, TRUE, &pdfMin, &pdfMax, &pdfMean, &pdfStdDev,
2083
- // progressCallback, &myProg );
2084
-
2085
2101
// try to fetch the cached stats (bForce=FALSE)
2086
2102
CPLErr myerval =
2087
2103
GDALGetRasterStatistics ( myGdalBand, bApproxOK, FALSE , &pdfMin, &pdfMax, &pdfMean, &pdfStdDev );
0 commit comments