@@ -387,6 +387,8 @@ QgsRasterBlock* QgsGdalProvider::block( int theBandNo, const QgsRectangle &theEx
387
387
block->setIsNoDataExcept ( subRect );
388
388
}
389
389
readBlock ( theBandNo, theExtent, theWidth, theHeight, block->bits () );
390
+ // apply scale and offset
391
+ block->applyScaleOffset ( bandScale ( theBandNo ), bandOffset ( theBandNo ) );
390
392
block->applyNoDataValues ( userNoDataValues ( theBandNo ) );
391
393
return block;
392
394
}
@@ -1067,55 +1069,45 @@ int QgsGdalProvider::capabilities() const
1067
1069
return capability;
1068
1070
}
1069
1071
1070
- QGis::DataType QgsGdalProvider::dataTypeFormGdal ( int theGdalDataType ) const
1071
- {
1072
- switch ( theGdalDataType )
1073
- {
1074
- case GDT_Unknown:
1075
- return QGis::UnknownDataType;
1076
- break ;
1077
- case GDT_Byte:
1078
- return QGis::Byte ;
1079
- break ;
1080
- case GDT_UInt16:
1081
- return QGis::UInt16 ;
1082
- break ;
1083
- case GDT_Int16:
1084
- return QGis::Int16;
1085
- break ;
1086
- case GDT_UInt32:
1087
- return QGis::UInt32 ;
1088
- break ;
1089
- case GDT_Int32:
1090
- return QGis::Int32;
1091
- break ;
1092
- case GDT_Float32:
1093
- return QGis::Float32 ;
1094
- break ;
1095
- case GDT_Float64:
1096
- return QGis::Float64 ;
1097
- break ;
1098
- case GDT_CInt16:
1099
- return QGis::CInt16;
1100
- break ;
1101
- case GDT_CInt32:
1102
- return QGis::CInt32;
1103
- break ;
1104
- case GDT_CFloat32:
1105
- return QGis::CFloat32;
1106
- break ;
1107
- case GDT_CFloat64:
1108
- return QGis::CFloat64;
1109
- break ;
1110
- }
1111
- return QGis::UnknownDataType;
1112
- }
1113
-
1114
1072
QGis::DataType QgsGdalProvider::srcDataType ( int bandNo ) const
1115
1073
{
1116
1074
GDALRasterBandH myGdalBand = GDALGetRasterBand ( mGdalDataset , bandNo );
1117
1075
GDALDataType myGdalDataType = GDALGetRasterDataType ( myGdalBand );
1118
- return dataTypeFromGdal ( myGdalDataType );
1076
+ QGis::DataType myDataType = dataTypeFromGdal ( myGdalDataType );
1077
+
1078
+ // define if the band has scale and offset to apply
1079
+ double myScale = bandScale ( bandNo );
1080
+ double myOffset = bandOffset ( bandNo );
1081
+ if ( myScale != 1.0 && myOffset != 0.0 )
1082
+ {
1083
+ // if the band has scale and offset to apply change dataType
1084
+ switch ( myDataType )
1085
+ {
1086
+ case QGis::UnknownDataType:
1087
+ case QGis::ARGB32:
1088
+ case QGis::ARGB32_Premultiplied:
1089
+ return myDataType;
1090
+ break ;
1091
+ case QGis::Byte :
1092
+ case QGis::UInt16 :
1093
+ case QGis::Int16:
1094
+ case QGis::UInt32 :
1095
+ case QGis::Int32:
1096
+ case QGis::Float32 :
1097
+ case QGis::CInt16:
1098
+ myDataType = QGis::Float32 ;
1099
+ break ;
1100
+ case QGis::Float64 :
1101
+ case QGis::CInt32:
1102
+ case QGis::CFloat32:
1103
+ myDataType = QGis::Float64 ;
1104
+ break ;
1105
+ case QGis::CFloat64:
1106
+ return myDataType;
1107
+ break ;
1108
+ }
1109
+ }
1110
+ return myDataType;
1119
1111
}
1120
1112
1121
1113
QGis::DataType QgsGdalProvider::dataType ( int bandNo ) const
@@ -1125,6 +1117,38 @@ QGis::DataType QgsGdalProvider::dataType( int bandNo ) const
1125
1117
return dataTypeFromGdal ( mGdalDataType [bandNo-1 ] );
1126
1118
}
1127
1119
1120
+ double QgsGdalProvider::bandScale ( int bandNo ) const
1121
+ {
1122
+ #if GDAL_VERSION_NUM >= 1800
1123
+ GDALRasterBandH myGdalBand = GDALGetRasterBand ( mGdalDataset , bandNo );
1124
+ int bGotScale;
1125
+ double myScale = GDALGetRasterScale ( myGdalBand, &bGotScale );
1126
+ if ( bGotScale )
1127
+ return myScale;
1128
+ else
1129
+ return 1.0 ;
1130
+ #else
1131
+ Q_UNUSED ( bandNo );
1132
+ return 1.0 ;
1133
+ #endif
1134
+ }
1135
+
1136
+ double QgsGdalProvider::bandOffset ( int bandNo ) const
1137
+ {
1138
+ #if GDAL_VERSION_NUM >= 1800
1139
+ GDALRasterBandH myGdalBand = GDALGetRasterBand ( mGdalDataset , bandNo );
1140
+ int bGotOffset;
1141
+ double myOffset = GDALGetRasterOffset ( myGdalBand, &bGotOffset );
1142
+ if ( bGotOffset )
1143
+ return myOffset;
1144
+ else
1145
+ return 0.0 ;
1146
+ #else
1147
+ Q_UNUSED ( bandNo );
1148
+ return 0.0 ;
1149
+ #endif
1150
+ }
1151
+
1128
1152
int QgsGdalProvider::bandCount () const
1129
1153
{
1130
1154
if ( mGdalDataset )
@@ -1355,10 +1379,19 @@ QgsRasterHistogram QgsGdalProvider::histogram( int theBandNo,
1355
1379
1356
1380
// Min/max, if not specified, are set by histogramDefaults, it does not
1357
1381
// set however min/max shifted to avoid rounding errors
1358
-
1382
+
1359
1383
double myMinVal = myHistogram.minimum ;
1360
1384
double myMaxVal = myHistogram.maximum ;
1361
1385
1386
+ // unapply scale anf offset for min and max
1387
+ double myScale = bandScale ( theBandNo );
1388
+ double myOffset = bandOffset ( theBandNo );
1389
+ if ( myScale != 1.0 || myOffset != 0 . )
1390
+ {
1391
+ myMinVal = (myHistogram.minimum - myOffset) / myScale;
1392
+ myMaxVal = (myHistogram.maximum - myOffset) / myScale;
1393
+ }
1394
+
1362
1395
double dfHalfBucket = ( myMaxVal - myMinVal ) / ( 2 * myHistogram.binCount );
1363
1396
myMinVal -= dfHalfBucket;
1364
1397
myMaxVal += dfHalfBucket;
@@ -2352,6 +2385,35 @@ QgsRasterBandStats QgsGdalProvider::bandStatistics( int theBandNo, int theStats,
2352
2385
myRasterBandStats.statsGathered = QgsRasterBandStats::Min | QgsRasterBandStats::Max
2353
2386
| QgsRasterBandStats::Range | QgsRasterBandStats::Mean
2354
2387
| QgsRasterBandStats::StdDev;
2388
+
2389
+ // define if the band has scale and offset to apply
2390
+ double myScale = bandScale ( theBandNo );
2391
+ double myOffset = bandOffset ( theBandNo );
2392
+ if ( myScale != 1.0 || myOffset != 0.0 )
2393
+ {
2394
+ if ( myScale < 0.0 )
2395
+ {
2396
+ // update Min and Max value
2397
+ myRasterBandStats.minimumValue = pdfMax * myScale + myOffset;
2398
+ myRasterBandStats.maximumValue = pdfMin * myScale + myOffset;
2399
+ // update the range
2400
+ myRasterBandStats.range = (pdfMin - pdfMax) * myScale;
2401
+ // update standard deviation
2402
+ myRasterBandStats.stdDev = -1.0 * pdfStdDev * myScale;
2403
+ }
2404
+ else
2405
+ {
2406
+ // update Min and Max value
2407
+ myRasterBandStats.minimumValue = pdfMin * myScale + myOffset;
2408
+ myRasterBandStats.maximumValue = pdfMax * myScale + myOffset;
2409
+ // update the range
2410
+ myRasterBandStats.range = (pdfMax - pdfMin) * myScale;
2411
+ // update standard deviation
2412
+ myRasterBandStats.stdDev = pdfStdDev * myScale;
2413
+ }
2414
+ // update the mean
2415
+ myRasterBandStats.mean = pdfMean * myScale + myOffset;
2416
+ }
2355
2417
2356
2418
#ifdef QGISDEBUG
2357
2419
QgsDebugMsg ( " ************ STATS **************" );
@@ -2562,6 +2624,36 @@ void QgsGdalProvider::initBaseDataset()
2562
2624
#endif
2563
2625
// mGdalDataType.append( myInternalGdalDataType );
2564
2626
2627
+ // define if the band has scale and offset to apply
2628
+ double myScale = bandScale ( i );
2629
+ double myOffset = bandOffset ( i );
2630
+ if ( myScale != 1.0 && myOffset != 0.0 )
2631
+ {
2632
+ // if the band has scale and offset to apply change dataType
2633
+ switch ( myGdalDataType )
2634
+ {
2635
+ case GDT_Unknown:
2636
+ case GDT_TypeCount:
2637
+ break ;
2638
+ case GDT_Byte:
2639
+ case GDT_UInt16:
2640
+ case GDT_Int16:
2641
+ case GDT_UInt32:
2642
+ case GDT_Int32:
2643
+ case GDT_Float32:
2644
+ case GDT_CInt16:
2645
+ myGdalDataType = GDT_Float32;
2646
+ break ;
2647
+ case GDT_Float64:
2648
+ case GDT_CInt32:
2649
+ case GDT_CFloat32:
2650
+ myGdalDataType = GDT_Float64;
2651
+ break ;
2652
+ case GDT_CFloat64:
2653
+ break ;
2654
+ }
2655
+ }
2656
+
2565
2657
mGdalDataType .append ( myGdalDataType );
2566
2658
// mInternalNoDataValue.append( myInternalNoDataValue );
2567
2659
// QgsDebugMsg( QString( "mInternalNoDataValue[%1] = %2" ).arg( i - 1 ).arg( mInternalNoDataValue[i-1] ) );
0 commit comments