Skip to content

Commit 59bb6ed

Browse files
author
timlinux
committedJan 15, 2007
Ticket #537 applied
Patch for QgsRasterLayer to allow stretching in DrawMultiColorBand, DrawSingleBandGray With thanks to Pete git-svn-id: http://svn.osgeo.org/qgis/trunk/qgis@6435 c8812cc2-4d05-0410-92ff-de0c093fc19c

File tree

2 files changed

+189
-9
lines changed

2 files changed

+189
-9
lines changed
 

‎src/core/raster/qgsrasterlayer.cpp

+177-9
Original file line numberDiff line numberDiff line change
@@ -377,6 +377,10 @@ QgsRasterLayer::QgsRasterLayer(QString const & path, QString const & baseName)
377377
dataProvider(0)
378378

379379
{
380+
userDefinedColorMinMax = false; //defaults needed to bypass stretch
381+
userDefinedGrayMinMax = false;
382+
setColorScalingAlgorithm(QgsRasterLayer::NO_STRETCH); //defaults needed to bypass stretch
383+
380384
// Initialise the affine transform matrix
381385
adfGeoTransform[0] = 0;
382386
adfGeoTransform[1] = 1;
@@ -1335,7 +1339,7 @@ void QgsRasterLayer::draw (QPainter * theQPainter,
13351339
void QgsRasterLayer::drawSingleBandGray(QPainter * theQPainter, QgsRasterViewPort * theRasterViewPort, QgsMapToPixel * theQgsMapToPixel, int theBandNoInt)
13361340
{
13371341
QgsDebugMsg("QgsRasterLayer::drawSingleBandGray called for layer " + QString::number(theBandNoInt));
1338-
QgsRasterBandStats myRasterBandStats = getRasterBandStats(theBandNoInt);
1342+
//QgsRasterBandStats myRasterBandStats = getRasterBandStats(theBandNoInt);
13391343
GDALRasterBand *myGdalBand = gdalDataset->GetRasterBand(theBandNoInt);
13401344
GDALDataType myDataType = myGdalBand->GetRasterDataType();
13411345
void *myGdalScanData = readData ( myGdalBand, theRasterViewPort );
@@ -1345,34 +1349,85 @@ void QgsRasterLayer::drawSingleBandGray(QPainter * theQPainter, QgsRasterViewPor
13451349
myQImage.setAlphaBuffer(true);
13461350
myQImage.fill(qRgba(255,255,255,0 )); // fill transparent
13471351

1348-
double myRangeDouble = myRasterBandStats.rangeDouble;
1352+
//double myRangeDouble = myRasterBandStats.rangeDouble;
1353+
QgsRasterBandStats myGrayBandStats;
1354+
/*
1355+
* If stDevsToPlotDouble is set it will override any user defined Min Max values
1356+
*/
1357+
if(QgsRasterLayer::NO_STRETCH != getColorScalingAlgorithm() && (!userDefinedGrayMinMax || stdDevsToPlotDouble > 0))
1358+
{
1359+
myGrayBandStats = getRasterBandStats(theBandNoInt);
1360+
1361+
/*
1362+
* This may upset some, but these values are set directly so that the userDefinedColorMinMax variable is not set,
1363+
* though it really does not matter by this point.
1364+
*/
1365+
if(stdDevsToPlotDouble > 0)
1366+
{
1367+
minGrayDouble = myGrayBandStats.meanDouble - (stdDevsToPlotDouble * myGrayBandStats.stdDevDouble);
1368+
maxGrayDouble = myGrayBandStats.meanDouble + (stdDevsToPlotDouble * myGrayBandStats.stdDevDouble);
1369+
}
1370+
else
1371+
{
1372+
minGrayDouble = myGrayBandStats.minValDouble;
1373+
maxGrayDouble = myGrayBandStats.maxValDouble;
1374+
}
1375+
}
1376+
1377+
/*
1378+
* Check for invalid min max value based on GDALDataType.
1379+
* Invalid values can happen if the user uses stdDevs to set min and max
1380+
* TODO:Needs to be expanded for all GDALDataTypes
1381+
*/
1382+
if(GDT_Byte == myDataType)
1383+
{
1384+
if(minGrayDouble < 0.0)
1385+
minGrayDouble = 0.0;
1386+
if(maxGrayDouble > 255.0)
1387+
maxGrayDouble = 255.0;
1388+
}
13491389

13501390
// print each point in myGdalScanData with equal parts R, G ,B o make it show as gray
13511391
for (int myColumnInt = 0; myColumnInt < theRasterViewPort->drawableAreaYDimInt; ++myColumnInt)
13521392
{
13531393
for (int myRowInt = 0; myRowInt < theRasterViewPort->drawableAreaXDimInt; ++myRowInt)
13541394
{
1355-
double myGrayValDouble = readValue ( myGdalScanData, myDataType,
1395+
double myGrayValueDouble = readValue ( myGdalScanData, myDataType,
13561396
myColumnInt * theRasterViewPort->drawableAreaXDimInt + myRowInt );
13571397

13581398
// If noDataValueDouble is 'nan', the comparison
13591399
// against myGrayValDouble will always fail ( nan==nan always
13601400
// returns false, by design), hence the slightly odd comparison
13611401
// of myGrayValDouble against itself.
1362-
if ( myGrayValDouble == noDataValueDouble ||
1363-
myGrayValDouble != myGrayValDouble)
1402+
if ( myGrayValueDouble == noDataValueDouble ||
1403+
myGrayValueDouble != myGrayValueDouble)
13641404
{
13651405

13661406
myQImage.setPixel(myRowInt, myColumnInt, qRgba(255,255,255,0 ));
13671407
continue;
13681408
}
13691409

1370-
int myGrayValInt = static_cast < int >( (myGrayValDouble-myRasterBandStats.minValDouble)
1371-
* (255/myRangeDouble));
1410+
if(QgsRasterLayer::NO_STRETCH != getColorScalingAlgorithm())
1411+
{
1412+
if(QgsRasterLayer::CLIP_TO_MINMAX == getColorScalingAlgorithm() || QgsRasterLayer::STRETCH_AND_CLIP_TO_MINMAX == getColorScalingAlgorithm())
1413+
if(myGrayValueDouble < minGrayDouble || myGrayValueDouble > maxGrayDouble) continue;
1414+
1415+
if(QgsRasterLayer::STRETCH_TO_MINMAX == getColorScalingAlgorithm() || QgsRasterLayer::STRETCH_AND_CLIP_TO_MINMAX == getColorScalingAlgorithm())
1416+
myGrayValueDouble = ((myGrayValueDouble - minGrayDouble)/(maxGrayDouble - minGrayDouble))*255;
1417+
1418+
//Check for out of range pixel values
1419+
if(myGrayValueDouble < 0.0)
1420+
myGrayValueDouble = 0.0;
1421+
else if(myGrayValueDouble > 255.0)
1422+
myGrayValueDouble = 255.0;
1423+
}
1424+
1425+
int myGrayValInt = static_cast < int > ( myGrayValueDouble);
1426+
//int myGrayValInt = static_cast < int >( (myGrayValDouble-myRasterBandStats.minValDouble) * (255/myRangeDouble));
13721427

13731428
if (invertHistogramFlag)
13741429
{
1375-
myGrayValDouble = 255 - myGrayValDouble;
1430+
myGrayValInt = 255 - myGrayValInt;
13761431
}
13771432
myQImage.setPixel(myRowInt, myColumnInt, qRgba(myGrayValInt, myGrayValInt, myGrayValInt, mTransparencyLevel));
13781433
}
@@ -2235,6 +2290,80 @@ void QgsRasterLayer::drawMultiBandColor(QPainter * theQPainter, QgsRasterViewPor
22352290
//myQImage.fill(0);
22362291
myQImage.setAlphaBuffer(true);
22372292
myQImage.fill(qRgba(255,255,255,0 )); // fill transparent
2293+
2294+
QgsRasterBandStats myRedBandStats;
2295+
QgsRasterBandStats myGreenBandStats;
2296+
QgsRasterBandStats myBlueBandStats;
2297+
/*
2298+
* If a stetch is requested and there are no user defined Min Max values
2299+
* we need to get these values from the bands themselves.
2300+
* If stDevsToPlotDouble is set it will override any user defined Min Max values
2301+
*
2302+
* NOTE: If the user only set minRedDouble this next block would be skipped
2303+
* and all the other variables could have garbage (they are not initialized in the constructor)
2304+
* This may want to be updated so that each Min Max is check to be sure it was set and if one is missing
2305+
* the get the QgsRasterBandStats for that band.
2306+
*/
2307+
if(QgsRasterLayer::NO_STRETCH != getColorScalingAlgorithm() && (!userDefinedColorMinMax || stdDevsToPlotDouble > 0))
2308+
{
2309+
myRedBandStats = getRasterBandStats(myRedBandNoInt);
2310+
myGreenBandStats = getRasterBandStats(myGreenBandNoInt);
2311+
myBlueBandStats = getRasterBandStats(myBlueBandNoInt);
2312+
2313+
/*
2314+
* This may upset some, but these values are set directly so that the userDefinedColorMinMax variable is not set,
2315+
* though it really does not matter at this point. Also insignificantly faster.
2316+
*/
2317+
if(stdDevsToPlotDouble > 0)
2318+
{
2319+
minRedDouble = myRedBandStats.meanDouble - (stdDevsToPlotDouble * myRedBandStats.stdDevDouble);
2320+
maxRedDouble = myRedBandStats.meanDouble + (stdDevsToPlotDouble * myRedBandStats.stdDevDouble);
2321+
minGreenDouble = myGreenBandStats.meanDouble - (stdDevsToPlotDouble * myGreenBandStats.stdDevDouble);
2322+
maxGreenDouble = myGreenBandStats.meanDouble + (stdDevsToPlotDouble * myGreenBandStats.stdDevDouble);
2323+
minBlueDouble = myBlueBandStats.meanDouble - (stdDevsToPlotDouble * myBlueBandStats.stdDevDouble);
2324+
maxBlueDouble = myBlueBandStats.meanDouble + (stdDevsToPlotDouble * myBlueBandStats.stdDevDouble);
2325+
}
2326+
else
2327+
{
2328+
minRedDouble = myRedBandStats.minValDouble;
2329+
maxRedDouble = myRedBandStats.maxValDouble;
2330+
minGreenDouble = myGreenBandStats.minValDouble;
2331+
maxGreenDouble = myGreenBandStats.maxValDouble;
2332+
minBlueDouble = myBlueBandStats.minValDouble;
2333+
maxBlueDouble = myBlueBandStats.maxValDouble;
2334+
}
2335+
}
2336+
2337+
/*
2338+
* Check for invalid min max value based on GDALDataType.
2339+
* Invalid values can happen if the user uses stdDevs to set min and max
2340+
* TODO:Needs to be expanded for all GDALDataTypes
2341+
*/
2342+
if(GDT_Byte == myRedType)
2343+
{
2344+
if(minRedDouble < 0.0)
2345+
minRedDouble = 0.0;
2346+
if(maxRedDouble > 255.0)
2347+
maxRedDouble = 255.0;
2348+
}
2349+
2350+
if(GDT_Byte == myGreenType)
2351+
{
2352+
if(minGreenDouble < 0.0)
2353+
minGreenDouble = 0.0;
2354+
if(maxGreenDouble > 255.0)
2355+
maxGreenDouble = 255.0;
2356+
}
2357+
2358+
if(GDT_Byte == myBlueType)
2359+
{
2360+
if(minBlueDouble < 0.0)
2361+
minBlueDouble = 0.0;
2362+
if(maxBlueDouble > 255.0)
2363+
maxBlueDouble = 255.0;
2364+
}
2365+
2366+
//Read and display pixels
22382367
for (int myColumnInt = 0; myColumnInt < theRasterViewPort->drawableAreaYDimInt; ++myColumnInt)
22392368
{
22402369
for (int myRowInt = 0; myRowInt < theRasterViewPort->drawableAreaXDimInt; ++myRowInt)
@@ -2263,6 +2392,44 @@ void QgsRasterLayer::drawMultiBandColor(QPainter * theQPainter, QgsRasterViewPor
22632392
continue;
22642393
}
22652394

2395+
/*
2396+
* Stretch RBG values based on selected color scaling algoritm
2397+
* NOTE: NO_STRETCH enum will help eliminte the need to call QgsRasterBandStats when an image is initially loaded
2398+
*/
2399+
2400+
if(QgsRasterLayer::NO_STRETCH != getColorScalingAlgorithm())
2401+
{
2402+
/*
2403+
* Currently if any one band is outside of min max range for the band the pixel is discarded,
2404+
* this can easily be updated so that all band have to be ouside of the min max range
2405+
*/
2406+
if(QgsRasterLayer::CLIP_TO_MINMAX == getColorScalingAlgorithm() || QgsRasterLayer::STRETCH_AND_CLIP_TO_MINMAX == getColorScalingAlgorithm())
2407+
{
2408+
if(myRedValueDouble < minRedDouble || myRedValueDouble > maxRedDouble) continue;
2409+
if(myGreenValueDouble < minRedDouble || myGreenValueDouble > maxRedDouble) continue;
2410+
if(myBlueValueDouble < minBlueDouble || myBlueValueDouble > maxBlueDouble) continue;
2411+
}
2412+
if(QgsRasterLayer::STRETCH_TO_MINMAX == getColorScalingAlgorithm() || QgsRasterLayer::STRETCH_AND_CLIP_TO_MINMAX == getColorScalingAlgorithm())
2413+
{
2414+
myRedValueDouble = ((myRedValueDouble - minRedDouble)/(maxRedDouble - minRedDouble))*255;
2415+
myGreenValueDouble = ((myGreenValueDouble - minGreenDouble)/(maxGreenDouble - minGreenDouble))*255;
2416+
myBlueValueDouble = ((myBlueValueDouble - minBlueDouble)/(maxBlueDouble - minBlueDouble))*255;
2417+
}
2418+
//Check for out of range pixel values
2419+
if(myRedValueDouble < 0.0)
2420+
myRedValueDouble = 0.0;
2421+
else if(myRedValueDouble > 255.0)
2422+
myRedValueDouble = 255.0;
2423+
if(myGreenValueDouble < 0.0)
2424+
myGreenValueDouble = 0.0;
2425+
else if(myGreenValueDouble > 255.0)
2426+
myGreenValueDouble = 255.0;
2427+
if(myBlueValueDouble < 0.0)
2428+
myBlueValueDouble = 0.0;
2429+
else if(myBlueValueDouble > 255.0)
2430+
myBlueValueDouble = 255.0;
2431+
}
2432+
22662433
int myRedValueInt = static_cast < int > ( myRedValueDouble );
22672434
int myGreenValueInt = static_cast < int > ( myGreenValueDouble );
22682435
int myBlueValueInt = static_cast < int > ( myBlueValueDouble );
@@ -2273,6 +2440,7 @@ void QgsRasterLayer::drawMultiBandColor(QPainter * theQPainter, QgsRasterViewPor
22732440
myGreenValueInt = 255 - myGreenValueInt;
22742441
myBlueValueInt = 255 - myBlueValueInt;
22752442
}
2443+
22762444
//set the pixel based on the above color mappings
22772445
myQImage.setPixel ( myRowInt, myColumnInt,
22782446
qRgba(myRedValueInt, myGreenValueInt, myBlueValueInt, mTransparencyLevel) );
@@ -2315,7 +2483,7 @@ void QgsRasterLayer::drawMultiBandColor(QPainter * theQPainter, QgsRasterViewPor
23152483
/ theQgsMapToPixel->mapUnitsPerPixel()
23162484
* fabs(adfGeoTransform[5])
23172485
);
2318-
}
2486+
}
23192487

23202488
QgsDebugMsg("QgsRasterLayer::drawSingleBandGray: painting image to canvas from source NW"\
23212489
+ QString::number(paintXoffset) + ", " + QString::number(paintYoffset)\

‎src/core/raster/qgsrasterlayer.h

+12
Original file line numberDiff line numberDiff line change
@@ -460,6 +460,7 @@ class CORE_EXPORT QgsRasterLayer : public QgsMapLayer
460460
* that falls outside the clipping range.*/
461461
void setMinRedDouble(double theDouble)
462462
{
463+
userDefinedColorMinMax = true;
463464
minRedDouble=theDouble;
464465
};
465466
/** \brief Accessor for maximum clipping range for red.
@@ -478,6 +479,7 @@ class CORE_EXPORT QgsRasterLayer : public QgsMapLayer
478479
* that falls outside the clipping range.*/
479480
void setMaxRedDouble(double theDouble)
480481
{
482+
userDefinedColorMinMax = true;
481483
maxRedDouble=theDouble;
482484
};
483485
//
@@ -499,6 +501,7 @@ class CORE_EXPORT QgsRasterLayer : public QgsMapLayer
499501
* that falls outside the clipping range.*/
500502
void setMinGreenDouble(double theDouble)
501503
{
504+
userDefinedColorMinMax = true;
502505
minGreenDouble=theDouble;
503506
};
504507
/** \brief Accessor for maximum clipping range for green.
@@ -517,6 +520,7 @@ class CORE_EXPORT QgsRasterLayer : public QgsMapLayer
517520
* that falls outside the clipping range.*/
518521
void setMaxGreenDouble(double theDouble)
519522
{
523+
userDefinedColorMinMax = true;
520524
maxGreenDouble=theDouble;
521525
};
522526
//
@@ -539,6 +543,7 @@ class CORE_EXPORT QgsRasterLayer : public QgsMapLayer
539543
* that falls outside the clipping range.*/
540544
void setMinBlueDouble(double theDouble)
541545
{
546+
userDefinedColorMinMax = true;
542547
minBlueDouble=theDouble;
543548
};
544549
/** \brief Accessor for maximum clipping range for blue.
@@ -557,6 +562,7 @@ class CORE_EXPORT QgsRasterLayer : public QgsMapLayer
557562
* that falls outside the clipping range.*/
558563
void setMaxBlueDouble(double theDouble)
559564
{
565+
userDefinedColorMinMax = true;
560566
maxBlueDouble=theDouble;
561567
};
562568
//
@@ -578,6 +584,7 @@ class CORE_EXPORT QgsRasterLayer : public QgsMapLayer
578584
* that falls outside the clipping range.*/
579585
void setMinGrayDouble(double theDouble)
580586
{
587+
userDefinedGrayMinMax = true;
581588
minGrayDouble=theDouble;
582589
};
583590
/** \brief Accessor for maximum clipping range for gray.
@@ -596,12 +603,14 @@ class CORE_EXPORT QgsRasterLayer : public QgsMapLayer
596603
* that falls outside the clipping range.*/
597604
void setMaxGrayDouble(double theDouble)
598605
{
606+
userDefinedGrayMinMax = true;
599607
maxGrayDouble=theDouble;
600608
};
601609
//
602610
/** \brief This enumerator describes the types of histogram scaling algorithms that can be used. */
603611
enum COLOR_SCALING_ALGORITHM
604612
{
613+
NO_STRETCH, //this should be the default color scaling algorithm, will allow for the display of images without calling QgsRasterBandStats unless needed
605614
STRETCH_TO_MINMAX, //linear histogram stretch
606615
STRETCH_AND_CLIP_TO_MINMAX,
607616
CLIP_TO_MINMAX
@@ -998,6 +1007,9 @@ public slots:
9981007
double maxGrayDouble;
9991008
/** \brief Whether this raster has overviews / pyramids or not */
10001009
bool hasPyramidsFlag;
1010+
//Since QgsRasterBandStats deos not set the minRedDouble maxRedDouble etc., it is benificial to know if the user as set these values. Default = false
1011+
bool userDefinedColorMinMax;
1012+
bool userDefinedGrayMinMax;
10011013
/** \brief This list holds a series of RasterPyramid structs
10021014
* which store infomation for each potential pyramid level for this raster.*/
10031015
RasterPyramidList mPyramidList;

0 commit comments

Comments
 (0)
Please sign in to comment.