patch_for_QgsRasterLayer.txt

Text File containing patch for QgsRasterLayer - ersts-amnh-org -, 2007-01-15 10:40 AM

Download (14.3 KB)

 
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;