1
|
Index: src/core/raster/qgsrasterlayer.cpp
|
2
|
===================================================================
|
3
|
--- src/core/raster/qgsrasterlayer.cpp (revision 6434)
|
4
|
+++ src/core/raster/qgsrasterlayer.cpp (working copy)
|
5
|
@@ -377,6 +377,10 @@
|
6
|
dataProvider(0)
|
7
|
|
8
|
{
|
9
|
+ userDefinedColorMinMax = false; //defaults needed to bypass stretch
|
10
|
+ userDefinedGrayMinMax = false;
|
11
|
+ setColorScalingAlgorithm(QgsRasterLayer::NO_STRETCH); //defaults needed to bypass stretch
|
12
|
+
|
13
|
// Initialise the affine transform matrix
|
14
|
adfGeoTransform[0] = 0;
|
15
|
adfGeoTransform[1] = 1;
|
16
|
@@ -1335,7 +1339,7 @@
|
17
|
void QgsRasterLayer::drawSingleBandGray(QPainter * theQPainter, QgsRasterViewPort * theRasterViewPort, QgsMapToPixel * theQgsMapToPixel, int theBandNoInt)
|
18
|
{
|
19
|
QgsDebugMsg("QgsRasterLayer::drawSingleBandGray called for layer " + QString::number(theBandNoInt));
|
20
|
- QgsRasterBandStats myRasterBandStats = getRasterBandStats(theBandNoInt);
|
21
|
+ //QgsRasterBandStats myRasterBandStats = getRasterBandStats(theBandNoInt);
|
22
|
GDALRasterBand *myGdalBand = gdalDataset->GetRasterBand(theBandNoInt);
|
23
|
GDALDataType myDataType = myGdalBand->GetRasterDataType();
|
24
|
void *myGdalScanData = readData ( myGdalBand, theRasterViewPort );
|
25
|
@@ -1345,34 +1349,85 @@
|
26
|
myQImage.setAlphaBuffer(true);
|
27
|
myQImage.fill(qRgba(255,255,255,0 )); // fill transparent
|
28
|
|
29
|
- double myRangeDouble = myRasterBandStats.rangeDouble;
|
30
|
+ //double myRangeDouble = myRasterBandStats.rangeDouble;
|
31
|
+ QgsRasterBandStats myGrayBandStats;
|
32
|
+ /*
|
33
|
+ * If stDevsToPlotDouble is set it will override any user defined Min Max values
|
34
|
+ */
|
35
|
+ if(QgsRasterLayer::NO_STRETCH != getColorScalingAlgorithm() && (!userDefinedGrayMinMax || stdDevsToPlotDouble > 0))
|
36
|
+ {
|
37
|
+ myGrayBandStats = getRasterBandStats(theBandNoInt);
|
38
|
|
39
|
+ /*
|
40
|
+ * This may upset some, but these values are set directly so that the userDefinedColorMinMax variable is not set,
|
41
|
+ * though it really does not matter by this point.
|
42
|
+ */
|
43
|
+ if(stdDevsToPlotDouble > 0)
|
44
|
+ {
|
45
|
+ minGrayDouble = myGrayBandStats.meanDouble - (stdDevsToPlotDouble * myGrayBandStats.stdDevDouble);
|
46
|
+ maxGrayDouble = myGrayBandStats.meanDouble + (stdDevsToPlotDouble * myGrayBandStats.stdDevDouble);
|
47
|
+ }
|
48
|
+ else
|
49
|
+ {
|
50
|
+ minGrayDouble = myGrayBandStats.minValDouble;
|
51
|
+ maxGrayDouble = myGrayBandStats.maxValDouble;
|
52
|
+ }
|
53
|
+ }
|
54
|
+
|
55
|
+ /*
|
56
|
+ * Check for invalid min max value based on GDALDataType.
|
57
|
+ * Invalid values can happen if the user uses stdDevs to set min and max
|
58
|
+ * TODO:Needs to be expanded for all GDALDataTypes
|
59
|
+ */
|
60
|
+ if(GDT_Byte == myDataType)
|
61
|
+ {
|
62
|
+ if(minGrayDouble < 0.0)
|
63
|
+ minGrayDouble = 0.0;
|
64
|
+ if(maxGrayDouble > 255.0)
|
65
|
+ maxGrayDouble = 255.0;
|
66
|
+ }
|
67
|
+
|
68
|
// print each point in myGdalScanData with equal parts R, G ,B o make it show as gray
|
69
|
for (int myColumnInt = 0; myColumnInt < theRasterViewPort->drawableAreaYDimInt; ++myColumnInt)
|
70
|
{
|
71
|
for (int myRowInt = 0; myRowInt < theRasterViewPort->drawableAreaXDimInt; ++myRowInt)
|
72
|
{
|
73
|
- double myGrayValDouble = readValue ( myGdalScanData, myDataType,
|
74
|
+ double myGrayValueDouble = readValue ( myGdalScanData, myDataType,
|
75
|
myColumnInt * theRasterViewPort->drawableAreaXDimInt + myRowInt );
|
76
|
|
77
|
// If noDataValueDouble is 'nan', the comparison
|
78
|
// against myGrayValDouble will always fail ( nan==nan always
|
79
|
// returns false, by design), hence the slightly odd comparison
|
80
|
// of myGrayValDouble against itself.
|
81
|
- if ( myGrayValDouble == noDataValueDouble ||
|
82
|
- myGrayValDouble != myGrayValDouble)
|
83
|
+ if ( myGrayValueDouble == noDataValueDouble ||
|
84
|
+ myGrayValueDouble != myGrayValueDouble)
|
85
|
{
|
86
|
|
87
|
myQImage.setPixel(myRowInt, myColumnInt, qRgba(255,255,255,0 ));
|
88
|
continue;
|
89
|
}
|
90
|
|
91
|
- int myGrayValInt = static_cast < int >( (myGrayValDouble-myRasterBandStats.minValDouble)
|
92
|
- * (255/myRangeDouble));
|
93
|
+ if(QgsRasterLayer::NO_STRETCH != getColorScalingAlgorithm())
|
94
|
+ {
|
95
|
+ if(QgsRasterLayer::CLIP_TO_MINMAX == getColorScalingAlgorithm() || QgsRasterLayer::STRETCH_AND_CLIP_TO_MINMAX == getColorScalingAlgorithm())
|
96
|
+ if(myGrayValueDouble < minGrayDouble || myGrayValueDouble > maxGrayDouble) continue;
|
97
|
|
98
|
+ if(QgsRasterLayer::STRETCH_TO_MINMAX == getColorScalingAlgorithm() || QgsRasterLayer::STRETCH_AND_CLIP_TO_MINMAX == getColorScalingAlgorithm())
|
99
|
+ myGrayValueDouble = ((myGrayValueDouble - minGrayDouble)/(maxGrayDouble - minGrayDouble))*255;
|
100
|
+
|
101
|
+ //Check for out of range pixel values
|
102
|
+ if(myGrayValueDouble < 0.0)
|
103
|
+ myGrayValueDouble = 0.0;
|
104
|
+ else if(myGrayValueDouble > 255.0)
|
105
|
+ myGrayValueDouble = 255.0;
|
106
|
+ }
|
107
|
+
|
108
|
+ int myGrayValInt = static_cast < int > ( myGrayValueDouble);
|
109
|
+ //int myGrayValInt = static_cast < int >( (myGrayValDouble-myRasterBandStats.minValDouble) * (255/myRangeDouble));
|
110
|
+
|
111
|
if (invertHistogramFlag)
|
112
|
{
|
113
|
- myGrayValDouble = 255 - myGrayValDouble;
|
114
|
+ myGrayValInt = 255 - myGrayValInt;
|
115
|
}
|
116
|
myQImage.setPixel(myRowInt, myColumnInt, qRgba(myGrayValInt, myGrayValInt, myGrayValInt, mTransparencyLevel));
|
117
|
}
|
118
|
@@ -2235,6 +2290,80 @@
|
119
|
//myQImage.fill(0);
|
120
|
myQImage.setAlphaBuffer(true);
|
121
|
myQImage.fill(qRgba(255,255,255,0 )); // fill transparent
|
122
|
+
|
123
|
+ QgsRasterBandStats myRedBandStats;
|
124
|
+ QgsRasterBandStats myGreenBandStats;
|
125
|
+ QgsRasterBandStats myBlueBandStats;
|
126
|
+ /*
|
127
|
+ * If a stetch is requested and there are no user defined Min Max values
|
128
|
+ * we need to get these values from the bands themselves.
|
129
|
+ * If stDevsToPlotDouble is set it will override any user defined Min Max values
|
130
|
+ *
|
131
|
+ * NOTE: If the user only set minRedDouble this next block would be skipped
|
132
|
+ * and all the other variables could have garbage (they are not initialized in the constructor)
|
133
|
+ * This may want to be updated so that each Min Max is check to be sure it was set and if one is missing
|
134
|
+ * the get the QgsRasterBandStats for that band.
|
135
|
+ */
|
136
|
+ if(QgsRasterLayer::NO_STRETCH != getColorScalingAlgorithm() && (!userDefinedColorMinMax || stdDevsToPlotDouble > 0))
|
137
|
+ {
|
138
|
+ myRedBandStats = getRasterBandStats(myRedBandNoInt);
|
139
|
+ myGreenBandStats = getRasterBandStats(myGreenBandNoInt);
|
140
|
+ myBlueBandStats = getRasterBandStats(myBlueBandNoInt);
|
141
|
+
|
142
|
+ /*
|
143
|
+ * This may upset some, but these values are set directly so that the userDefinedColorMinMax variable is not set,
|
144
|
+ * though it really does not matter at this point. Also insignificantly faster.
|
145
|
+ */
|
146
|
+ if(stdDevsToPlotDouble > 0)
|
147
|
+ {
|
148
|
+ minRedDouble = myRedBandStats.meanDouble - (stdDevsToPlotDouble * myRedBandStats.stdDevDouble);
|
149
|
+ maxRedDouble = myRedBandStats.meanDouble + (stdDevsToPlotDouble * myRedBandStats.stdDevDouble);
|
150
|
+ minGreenDouble = myGreenBandStats.meanDouble - (stdDevsToPlotDouble * myGreenBandStats.stdDevDouble);
|
151
|
+ maxGreenDouble = myGreenBandStats.meanDouble + (stdDevsToPlotDouble * myGreenBandStats.stdDevDouble);
|
152
|
+ minBlueDouble = myBlueBandStats.meanDouble - (stdDevsToPlotDouble * myBlueBandStats.stdDevDouble);
|
153
|
+ maxBlueDouble = myBlueBandStats.meanDouble + (stdDevsToPlotDouble * myBlueBandStats.stdDevDouble);
|
154
|
+ }
|
155
|
+ else
|
156
|
+ {
|
157
|
+ minRedDouble = myRedBandStats.minValDouble;
|
158
|
+ maxRedDouble = myRedBandStats.maxValDouble;
|
159
|
+ minGreenDouble = myGreenBandStats.minValDouble;
|
160
|
+ maxGreenDouble = myGreenBandStats.maxValDouble;
|
161
|
+ minBlueDouble = myBlueBandStats.minValDouble;
|
162
|
+ maxBlueDouble = myBlueBandStats.maxValDouble;
|
163
|
+ }
|
164
|
+ }
|
165
|
+
|
166
|
+ /*
|
167
|
+ * Check for invalid min max value based on GDALDataType.
|
168
|
+ * Invalid values can happen if the user uses stdDevs to set min and max
|
169
|
+ * TODO:Needs to be expanded for all GDALDataTypes
|
170
|
+ */
|
171
|
+ if(GDT_Byte == myRedType)
|
172
|
+ {
|
173
|
+ if(minRedDouble < 0.0)
|
174
|
+ minRedDouble = 0.0;
|
175
|
+ if(maxRedDouble > 255.0)
|
176
|
+ maxRedDouble = 255.0;
|
177
|
+ }
|
178
|
+
|
179
|
+ if(GDT_Byte == myGreenType)
|
180
|
+ {
|
181
|
+ if(minGreenDouble < 0.0)
|
182
|
+ minGreenDouble = 0.0;
|
183
|
+ if(maxGreenDouble > 255.0)
|
184
|
+ maxGreenDouble = 255.0;
|
185
|
+ }
|
186
|
+
|
187
|
+ if(GDT_Byte == myBlueType)
|
188
|
+ {
|
189
|
+ if(minBlueDouble < 0.0)
|
190
|
+ minBlueDouble = 0.0;
|
191
|
+ if(maxBlueDouble > 255.0)
|
192
|
+ maxBlueDouble = 255.0;
|
193
|
+ }
|
194
|
+
|
195
|
+ //Read and display pixels
|
196
|
for (int myColumnInt = 0; myColumnInt < theRasterViewPort->drawableAreaYDimInt; ++myColumnInt)
|
197
|
{
|
198
|
for (int myRowInt = 0; myRowInt < theRasterViewPort->drawableAreaXDimInt; ++myRowInt)
|
199
|
@@ -2263,6 +2392,44 @@
|
200
|
continue;
|
201
|
}
|
202
|
|
203
|
+ /*
|
204
|
+ * Stretch RBG values based on selected color scaling algoritm
|
205
|
+ * NOTE: NO_STRETCH enum will help eliminte the need to call QgsRasterBandStats when an image is initially loaded
|
206
|
+ */
|
207
|
+
|
208
|
+ if(QgsRasterLayer::NO_STRETCH != getColorScalingAlgorithm())
|
209
|
+ {
|
210
|
+ /*
|
211
|
+ * Currently if any one band is outside of min max range for the band the pixel is discarded,
|
212
|
+ * this can easily be updated so that all band have to be ouside of the min max range
|
213
|
+ */
|
214
|
+ if(QgsRasterLayer::CLIP_TO_MINMAX == getColorScalingAlgorithm() || QgsRasterLayer::STRETCH_AND_CLIP_TO_MINMAX == getColorScalingAlgorithm())
|
215
|
+ {
|
216
|
+ if(myRedValueDouble < minRedDouble || myRedValueDouble > maxRedDouble) continue;
|
217
|
+ if(myGreenValueDouble < minRedDouble || myGreenValueDouble > maxRedDouble) continue;
|
218
|
+ if(myBlueValueDouble < minBlueDouble || myBlueValueDouble > maxBlueDouble) continue;
|
219
|
+ }
|
220
|
+ if(QgsRasterLayer::STRETCH_TO_MINMAX == getColorScalingAlgorithm() || QgsRasterLayer::STRETCH_AND_CLIP_TO_MINMAX == getColorScalingAlgorithm())
|
221
|
+ {
|
222
|
+ myRedValueDouble = ((myRedValueDouble - minRedDouble)/(maxRedDouble - minRedDouble))*255;
|
223
|
+ myGreenValueDouble = ((myGreenValueDouble - minGreenDouble)/(maxGreenDouble - minGreenDouble))*255;
|
224
|
+ myBlueValueDouble = ((myBlueValueDouble - minBlueDouble)/(maxBlueDouble - minBlueDouble))*255;
|
225
|
+ }
|
226
|
+ //Check for out of range pixel values
|
227
|
+ if(myRedValueDouble < 0.0)
|
228
|
+ myRedValueDouble = 0.0;
|
229
|
+ else if(myRedValueDouble > 255.0)
|
230
|
+ myRedValueDouble = 255.0;
|
231
|
+ if(myGreenValueDouble < 0.0)
|
232
|
+ myGreenValueDouble = 0.0;
|
233
|
+ else if(myGreenValueDouble > 255.0)
|
234
|
+ myGreenValueDouble = 255.0;
|
235
|
+ if(myBlueValueDouble < 0.0)
|
236
|
+ myBlueValueDouble = 0.0;
|
237
|
+ else if(myBlueValueDouble > 255.0)
|
238
|
+ myBlueValueDouble = 255.0;
|
239
|
+ }
|
240
|
+
|
241
|
int myRedValueInt = static_cast < int > ( myRedValueDouble );
|
242
|
int myGreenValueInt = static_cast < int > ( myGreenValueDouble );
|
243
|
int myBlueValueInt = static_cast < int > ( myBlueValueDouble );
|
244
|
@@ -2273,6 +2440,7 @@
|
245
|
myGreenValueInt = 255 - myGreenValueInt;
|
246
|
myBlueValueInt = 255 - myBlueValueInt;
|
247
|
}
|
248
|
+
|
249
|
//set the pixel based on the above color mappings
|
250
|
myQImage.setPixel ( myRowInt, myColumnInt,
|
251
|
qRgba(myRedValueInt, myGreenValueInt, myBlueValueInt, mTransparencyLevel) );
|
252
|
@@ -2315,7 +2483,7 @@
|
253
|
/ theQgsMapToPixel->mapUnitsPerPixel()
|
254
|
* fabs(adfGeoTransform[5])
|
255
|
);
|
256
|
- }
|
257
|
+ }
|
258
|
|
259
|
QgsDebugMsg("QgsRasterLayer::drawSingleBandGray: painting image to canvas from source NW"\
|
260
|
+ QString::number(paintXoffset) + ", " + QString::number(paintYoffset)\
|
261
|
Index: src/core/raster/qgsrasterlayer.h
|
262
|
===================================================================
|
263
|
--- src/core/raster/qgsrasterlayer.h (revision 6434)
|
264
|
+++ src/core/raster/qgsrasterlayer.h (working copy)
|
265
|
@@ -460,6 +460,7 @@
|
266
|
* that falls outside the clipping range.*/
|
267
|
void setMinRedDouble(double theDouble)
|
268
|
{
|
269
|
+ userDefinedColorMinMax = true;
|
270
|
minRedDouble=theDouble;
|
271
|
};
|
272
|
/** \brief Accessor for maximum clipping range for red.
|
273
|
@@ -478,6 +479,7 @@
|
274
|
* that falls outside the clipping range.*/
|
275
|
void setMaxRedDouble(double theDouble)
|
276
|
{
|
277
|
+ userDefinedColorMinMax = true;
|
278
|
maxRedDouble=theDouble;
|
279
|
};
|
280
|
//
|
281
|
@@ -499,6 +501,7 @@
|
282
|
* that falls outside the clipping range.*/
|
283
|
void setMinGreenDouble(double theDouble)
|
284
|
{
|
285
|
+ userDefinedColorMinMax = true;
|
286
|
minGreenDouble=theDouble;
|
287
|
};
|
288
|
/** \brief Accessor for maximum clipping range for green.
|
289
|
@@ -517,6 +520,7 @@
|
290
|
* that falls outside the clipping range.*/
|
291
|
void setMaxGreenDouble(double theDouble)
|
292
|
{
|
293
|
+ userDefinedColorMinMax = true;
|
294
|
maxGreenDouble=theDouble;
|
295
|
};
|
296
|
//
|
297
|
@@ -539,6 +543,7 @@
|
298
|
* that falls outside the clipping range.*/
|
299
|
void setMinBlueDouble(double theDouble)
|
300
|
{
|
301
|
+ userDefinedColorMinMax = true;
|
302
|
minBlueDouble=theDouble;
|
303
|
};
|
304
|
/** \brief Accessor for maximum clipping range for blue.
|
305
|
@@ -557,6 +562,7 @@
|
306
|
* that falls outside the clipping range.*/
|
307
|
void setMaxBlueDouble(double theDouble)
|
308
|
{
|
309
|
+ userDefinedColorMinMax = true;
|
310
|
maxBlueDouble=theDouble;
|
311
|
};
|
312
|
//
|
313
|
@@ -578,6 +584,7 @@
|
314
|
* that falls outside the clipping range.*/
|
315
|
void setMinGrayDouble(double theDouble)
|
316
|
{
|
317
|
+ userDefinedGrayMinMax = true;
|
318
|
minGrayDouble=theDouble;
|
319
|
};
|
320
|
/** \brief Accessor for maximum clipping range for gray.
|
321
|
@@ -596,12 +603,14 @@
|
322
|
* that falls outside the clipping range.*/
|
323
|
void setMaxGrayDouble(double theDouble)
|
324
|
{
|
325
|
+ userDefinedGrayMinMax = true;
|
326
|
maxGrayDouble=theDouble;
|
327
|
};
|
328
|
//
|
329
|
/** \brief This enumerator describes the types of histogram scaling algorithms that can be used. */
|
330
|
enum COLOR_SCALING_ALGORITHM
|
331
|
{
|
332
|
+ NO_STRETCH, //this should be the default color scaling algorithm, will allow for the display of images without calling QgsRasterBandStats unless needed
|
333
|
STRETCH_TO_MINMAX, //linear histogram stretch
|
334
|
STRETCH_AND_CLIP_TO_MINMAX,
|
335
|
CLIP_TO_MINMAX
|
336
|
@@ -998,6 +1007,9 @@
|
337
|
double maxGrayDouble;
|
338
|
/** \brief Whether this raster has overviews / pyramids or not */
|
339
|
bool hasPyramidsFlag;
|
340
|
+ //Since QgsRasterBandStats deos not set the minRedDouble maxRedDouble etc., it is benificial to know if the user as set these values. Default = false
|
341
|
+ bool userDefinedColorMinMax;
|
342
|
+ bool userDefinedGrayMinMax;
|
343
|
/** \brief This list holds a series of RasterPyramid structs
|
344
|
* which store infomation for each potential pyramid level for this raster.*/
|
345
|
RasterPyramidList mPyramidList;
|