1 : /******************************************************************************
2 : * $Id: gdalnodatavaluesmaskband.cpp 17757 2009-10-05 17:06:20Z rouault $
3 : *
4 : * Project: GDAL Core
5 : * Purpose: Implementation of GDALNoDataValuesMaskBand, a class implementing
6 : * a default band mask based on the NODATA_VALUES metadata item.
7 : * A pixel is considered nodata in all bands if and only if all bands
8 : * match the corresponding value in the NODATA_VALUES tuple
9 : * Author: Even Rouault, <even dot rouault at mines dash paris dot ogr>
10 : *
11 : ******************************************************************************
12 : * Copyright (c) 2008, Even Rouault
13 : *
14 : * Permission is hereby granted, free of charge, to any person obtaining a
15 : * copy of this software and associated documentation files (the "Software"),
16 : * to deal in the Software without restriction, including without limitation
17 : * the rights to use, copy, modify, merge, publish, distribute, sublicense,
18 : * and/or sell copies of the Software, and to permit persons to whom the
19 : * Software is furnished to do so, subject to the following conditions:
20 : *
21 : * The above copyright notice and this permission notice shall be included
22 : * in all copies or substantial portions of the Software.
23 : *
24 : * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
25 : * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
26 : * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
27 : * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
28 : * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
29 : * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
30 : * DEALINGS IN THE SOFTWARE.
31 : ****************************************************************************/
32 :
33 : #include "gdal_priv.h"
34 :
35 : CPL_CVSID("$Id: gdalnodatavaluesmaskband.cpp 17757 2009-10-05 17:06:20Z rouault $");
36 :
37 : /************************************************************************/
38 : /* GDALNoDataValuesMaskBand() */
39 : /************************************************************************/
40 :
41 41 : GDALNoDataValuesMaskBand::GDALNoDataValuesMaskBand( GDALDataset* poDS )
42 :
43 : {
44 41 : const char* pszNoDataValues = poDS->GetMetadataItem("NODATA_VALUES");
45 41 : char** papszNoDataValues = CSLTokenizeStringComplex(pszNoDataValues, " ", FALSE, FALSE);
46 :
47 : int i;
48 41 : padfNodataValues = (double*)CPLMalloc(sizeof(double) * poDS->GetRasterCount());
49 164 : for(i=0;i<poDS->GetRasterCount();i++)
50 : {
51 123 : padfNodataValues[i] = atof(papszNoDataValues[i]);
52 : }
53 :
54 41 : CSLDestroy(papszNoDataValues);
55 :
56 41 : this->poDS = poDS;
57 41 : nBand = 0;
58 :
59 41 : nRasterXSize = poDS->GetRasterXSize();
60 41 : nRasterYSize = poDS->GetRasterYSize();
61 :
62 41 : eDataType = GDT_Byte;
63 41 : poDS->GetRasterBand(1)->GetBlockSize( &nBlockXSize, &nBlockYSize );
64 41 : }
65 :
66 : /************************************************************************/
67 : /* ~GDALNoDataValuesMaskBand() */
68 : /************************************************************************/
69 :
70 82 : GDALNoDataValuesMaskBand::~GDALNoDataValuesMaskBand()
71 :
72 : {
73 41 : CPLFree(padfNodataValues);
74 82 : }
75 :
76 : /************************************************************************/
77 : /* IReadBlock() */
78 : /************************************************************************/
79 :
80 20 : CPLErr GDALNoDataValuesMaskBand::IReadBlock( int nXBlockOff, int nYBlockOff,
81 : void * pImage )
82 :
83 : {
84 : int iBand;
85 : GDALDataType eWrkDT;
86 :
87 : /* -------------------------------------------------------------------- */
88 : /* Decide on a working type. */
89 : /* -------------------------------------------------------------------- */
90 20 : switch( poDS->GetRasterBand(1)->GetRasterDataType() )
91 : {
92 : case GDT_Byte:
93 12 : eWrkDT = GDT_Byte;
94 12 : break;
95 :
96 : case GDT_UInt16:
97 : case GDT_UInt32:
98 2 : eWrkDT = GDT_UInt32;
99 2 : break;
100 :
101 : case GDT_Int16:
102 : case GDT_Int32:
103 : case GDT_CInt16:
104 : case GDT_CInt32:
105 2 : eWrkDT = GDT_Int32;
106 2 : break;
107 :
108 : case GDT_Float32:
109 : case GDT_CFloat32:
110 2 : eWrkDT = GDT_Float32;
111 2 : break;
112 :
113 : case GDT_Float64:
114 : case GDT_CFloat64:
115 2 : eWrkDT = GDT_Float64;
116 2 : break;
117 :
118 : default:
119 : CPLAssert( FALSE );
120 0 : eWrkDT = GDT_Float64;
121 : break;
122 : }
123 :
124 : /* -------------------------------------------------------------------- */
125 : /* Read the image data. */
126 : /* -------------------------------------------------------------------- */
127 : GByte *pabySrc;
128 : CPLErr eErr;
129 :
130 20 : int nBands = poDS->GetRasterCount();
131 20 : pabySrc = (GByte *) VSIMalloc3( nBands * GDALGetDataTypeSize(eWrkDT)/8, nBlockXSize, nBlockYSize );
132 20 : if (pabySrc == NULL)
133 : {
134 : CPLError( CE_Failure, CPLE_OutOfMemory,
135 0 : "GDALNoDataValuesMaskBand::IReadBlock: Out of memory for buffer." );
136 0 : return CE_Failure;
137 : }
138 :
139 20 : int nXSizeRequest = nBlockXSize;
140 20 : if (nXBlockOff * nBlockXSize + nBlockXSize > nRasterXSize)
141 0 : nXSizeRequest = nRasterXSize - nXBlockOff * nBlockXSize;
142 20 : int nYSizeRequest = nBlockYSize;
143 20 : if (nYBlockOff * nBlockYSize + nBlockYSize > nRasterYSize)
144 0 : nYSizeRequest = nRasterYSize - nYBlockOff * nBlockYSize;
145 :
146 20 : if (nXSizeRequest != nBlockXSize || nYSizeRequest != nBlockYSize)
147 : {
148 : /* memset the whole buffer to avoid Valgrind warnings in case we can't */
149 : /* fetch a full block */
150 0 : memset(pabySrc, 0, nBands * GDALGetDataTypeSize(eWrkDT)/8 * nBlockXSize * nBlockYSize );
151 : }
152 :
153 20 : int nBlockOffsetPixels = nBlockXSize * nBlockYSize;
154 20 : int nBandOffsetByte = (GDALGetDataTypeSize(eWrkDT)/8) * nBlockXSize * nBlockYSize;
155 80 : for(iBand=0;iBand<nBands;iBand++)
156 : {
157 : eErr = poDS->GetRasterBand(iBand + 1)->RasterIO(
158 : GF_Read,
159 : nXBlockOff * nBlockXSize, nYBlockOff * nBlockYSize,
160 : nXSizeRequest, nYSizeRequest,
161 : pabySrc + iBand * nBandOffsetByte, nXSizeRequest, nYSizeRequest,
162 60 : eWrkDT, 0, nBlockXSize * (GDALGetDataTypeSize(eWrkDT)/8) );
163 60 : if( eErr != CE_None )
164 0 : return eErr;
165 : }
166 :
167 : /* -------------------------------------------------------------------- */
168 : /* Process different cases. */
169 : /* -------------------------------------------------------------------- */
170 : int i;
171 20 : switch( eWrkDT )
172 : {
173 : case GDT_Byte:
174 : {
175 12 : GByte* pabyNoData = (GByte*) CPLMalloc(nBands * sizeof(GByte));
176 48 : for(iBand=0;iBand<nBands;iBand++)
177 : {
178 36 : pabyNoData[iBand] = (GByte)padfNodataValues[iBand];
179 : }
180 :
181 27513 : for( i = nBlockXSize * nBlockYSize - 1; i >= 0; i-- )
182 : {
183 27501 : int nCountNoData = 0;
184 110004 : for(iBand=0;iBand<nBands;iBand++)
185 : {
186 82503 : if( pabySrc[i + iBand * nBlockOffsetPixels] == pabyNoData[iBand] )
187 62703 : nCountNoData ++;
188 : }
189 27501 : if (nCountNoData == nBands)
190 17601 : ((GByte *) pImage)[i] = 0;
191 : else
192 9900 : ((GByte *) pImage)[i] = 255;
193 : }
194 :
195 12 : CPLFree(pabyNoData);
196 : }
197 12 : break;
198 :
199 : case GDT_UInt32:
200 : {
201 2 : GUInt32* panNoData = (GUInt32*) CPLMalloc(nBands * sizeof(GUInt32));
202 8 : for(iBand=0;iBand<nBands;iBand++)
203 : {
204 6 : panNoData[iBand] = (GUInt32)padfNodataValues[iBand];
205 : }
206 :
207 4 : for( i = nBlockXSize * nBlockYSize - 1; i >= 0; i-- )
208 : {
209 2 : int nCountNoData = 0;
210 8 : for(iBand=0;iBand<nBands;iBand++)
211 : {
212 6 : if( ((GUInt32 *)pabySrc)[i + iBand * nBlockOffsetPixels] == panNoData[iBand] )
213 6 : nCountNoData ++;
214 : }
215 2 : if (nCountNoData == nBands)
216 2 : ((GByte *) pImage)[i] = 0;
217 : else
218 0 : ((GByte *) pImage)[i] = 255;
219 : }
220 :
221 2 : CPLFree(panNoData);
222 : }
223 2 : break;
224 :
225 : case GDT_Int32:
226 : {
227 2 : GInt32* panNoData = (GInt32*) CPLMalloc(nBands * sizeof(GInt32));
228 8 : for(iBand=0;iBand<nBands;iBand++)
229 : {
230 6 : panNoData[iBand] = (GInt32)padfNodataValues[iBand];
231 : }
232 :
233 4 : for( i = nBlockXSize * nBlockYSize - 1; i >= 0; i-- )
234 : {
235 2 : int nCountNoData = 0;
236 8 : for(iBand=0;iBand<nBands;iBand++)
237 : {
238 6 : if( ((GInt32 *)pabySrc)[i + iBand * nBlockOffsetPixels] == panNoData[iBand] )
239 6 : nCountNoData ++;
240 : }
241 2 : if (nCountNoData == nBands)
242 2 : ((GByte *) pImage)[i] = 0;
243 : else
244 0 : ((GByte *) pImage)[i] = 255;
245 : }
246 :
247 2 : CPLFree(panNoData);
248 : }
249 2 : break;
250 :
251 : case GDT_Float32:
252 : {
253 2 : float* pafNoData = (float*) CPLMalloc(nBands * sizeof(float));
254 8 : for(iBand=0;iBand<nBands;iBand++)
255 : {
256 6 : pafNoData[iBand] = (float)padfNodataValues[iBand];
257 : }
258 :
259 4 : for( i = nBlockXSize * nBlockYSize - 1; i >= 0; i-- )
260 : {
261 2 : int nCountNoData = 0;
262 8 : for(iBand=0;iBand<nBands;iBand++)
263 : {
264 6 : if( ((float *)pabySrc)[i + iBand * nBlockOffsetPixels] == pafNoData[iBand] )
265 6 : nCountNoData ++;
266 : }
267 2 : if (nCountNoData == nBands)
268 2 : ((GByte *) pImage)[i] = 0;
269 : else
270 0 : ((GByte *) pImage)[i] = 255;
271 : }
272 :
273 2 : CPLFree(pafNoData);
274 : }
275 2 : break;
276 :
277 : case GDT_Float64:
278 : {
279 2 : double* padfNoData = (double*) CPLMalloc(nBands * sizeof(double));
280 8 : for(iBand=0;iBand<nBands;iBand++)
281 : {
282 6 : padfNoData[iBand] = (double)padfNodataValues[iBand];
283 : }
284 :
285 4 : for( i = nBlockXSize * nBlockYSize - 1; i >= 0; i-- )
286 : {
287 2 : int nCountNoData = 0;
288 8 : for(iBand=0;iBand<nBands;iBand++)
289 : {
290 6 : if( ((double *)pabySrc)[i + iBand * nBlockOffsetPixels] == padfNoData[iBand] )
291 6 : nCountNoData ++;
292 : }
293 2 : if (nCountNoData == nBands)
294 2 : ((GByte *) pImage)[i] = 0;
295 : else
296 0 : ((GByte *) pImage)[i] = 255;
297 : }
298 :
299 2 : CPLFree(padfNoData);
300 : }
301 : break;
302 :
303 : default:
304 : CPLAssert( FALSE );
305 : break;
306 : }
307 :
308 20 : CPLFree( pabySrc );
309 :
310 20 : return CE_None;
311 : }
|