Line data Source code
1 : /******************************************************************************
2 : *
3 : * Project: PCRaster Integration
4 : * Purpose: PCRaster raster band implementation.
5 : * Author: Kor de Jong, Oliver Schmitz
6 : *
7 : ******************************************************************************
8 : * Copyright (c) PCRaster owners
9 : *
10 : * Permission is hereby granted, free of charge, to any person obtaining a
11 : * copy of this software and associated documentation files (the "Software"),
12 : * to deal in the Software without restriction, including without limitation
13 : * the rights to use, copy, modify, merge, publish, distribute, sublicense,
14 : * and/or sell copies of the Software, and to permit persons to whom the
15 : * Software is furnished to do so, subject to the following conditions:
16 : *
17 : * The above copyright notice and this permission notice shall be included
18 : * in all copies or substantial portions of the Software.
19 : *
20 : * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
21 : * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
22 : * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
23 : * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
24 : * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
25 : * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
26 : * DEALINGS IN THE SOFTWARE.
27 : ****************************************************************************/
28 :
29 : #include "csf.h"
30 : #include "csfimpl.h"
31 : #include "pcrasterdataset.h"
32 : #include "pcrasterrasterband.h"
33 : #include "pcrasterutil.h"
34 :
35 : /*!
36 : \file
37 : This file contains the implementation of the PCRasterRasterBand class.
38 : */
39 :
40 : //------------------------------------------------------------------------------
41 : // DEFINITION OF PCRRASTERBAND MEMBERS
42 : //------------------------------------------------------------------------------
43 :
44 : //! Constructor.
45 : /*!
46 : \param dataset The dataset we are a part of.
47 : */
48 13 : PCRasterRasterBand::PCRasterRasterBand(PCRasterDataset *dataset)
49 : : GDALPamRasterBand(), d_dataset(dataset), d_noDataValue(),
50 13 : d_defaultNoDataValueOverridden(false), d_create_in(GDT_Unknown)
51 : {
52 13 : poDS = dataset;
53 13 : nBand = 1;
54 13 : eDataType = cellRepresentation2GDALType(dataset->cellRepresentation());
55 13 : nBlockXSize = dataset->GetRasterXSize();
56 13 : nBlockYSize = 1;
57 13 : }
58 :
59 : //! Destructor.
60 : /*!
61 : */
62 26 : PCRasterRasterBand::~PCRasterRasterBand()
63 : {
64 26 : }
65 :
66 455 : double PCRasterRasterBand::GetNoDataValue(int *success)
67 : {
68 455 : if (success)
69 : {
70 12 : *success = 1;
71 : }
72 :
73 455 : return d_defaultNoDataValueOverridden ? d_noDataValue
74 455 : : d_dataset->defaultNoDataValue();
75 : }
76 :
77 0 : double PCRasterRasterBand::GetMinimum(int *success)
78 : {
79 : double result;
80 : bool isValid;
81 :
82 0 : switch (d_dataset->cellRepresentation())
83 : {
84 : // CSF version 2.
85 : // ----------------------------------------------------------
86 0 : case CR_UINT1:
87 : {
88 : UINT1 min;
89 0 : isValid = CPL_TO_BOOL(RgetMinVal(d_dataset->map(), &min));
90 0 : result = static_cast<double>(min);
91 0 : break;
92 : }
93 0 : case CR_INT4:
94 : {
95 : INT4 min;
96 0 : isValid = CPL_TO_BOOL(RgetMinVal(d_dataset->map(), &min));
97 0 : result = static_cast<double>(min);
98 0 : break;
99 : }
100 0 : case CR_REAL4:
101 : {
102 : REAL4 min;
103 0 : isValid = CPL_TO_BOOL(RgetMinVal(d_dataset->map(), &min));
104 0 : result = static_cast<double>(min);
105 0 : break;
106 : }
107 0 : case CR_REAL8:
108 : {
109 : REAL8 min;
110 0 : isValid = CPL_TO_BOOL(RgetMinVal(d_dataset->map(), &min));
111 0 : result = static_cast<double>(min);
112 0 : break;
113 : }
114 : // CSF version 1.
115 : // ----------------------------------------------------------
116 0 : case CR_INT1:
117 : {
118 : INT1 min;
119 0 : isValid = CPL_TO_BOOL(RgetMinVal(d_dataset->map(), &min));
120 0 : result = static_cast<double>(min);
121 0 : break;
122 : }
123 0 : case CR_INT2:
124 : {
125 : INT2 min;
126 0 : isValid = CPL_TO_BOOL(RgetMinVal(d_dataset->map(), &min));
127 0 : result = static_cast<double>(min);
128 0 : break;
129 : }
130 0 : case CR_UINT2:
131 : {
132 : UINT2 min;
133 0 : isValid = CPL_TO_BOOL(RgetMinVal(d_dataset->map(), &min));
134 0 : result = static_cast<double>(min);
135 0 : break;
136 : }
137 0 : case CR_UINT4:
138 : {
139 : UINT4 min;
140 0 : isValid = CPL_TO_BOOL(RgetMinVal(d_dataset->map(), &min));
141 0 : result = static_cast<double>(min);
142 0 : break;
143 : }
144 0 : default:
145 : {
146 0 : result = 0.0;
147 0 : isValid = false;
148 0 : break;
149 : }
150 : }
151 :
152 0 : if (success)
153 : {
154 0 : *success = isValid ? 1 : 0;
155 : }
156 :
157 0 : return result;
158 : }
159 :
160 0 : double PCRasterRasterBand::GetMaximum(int *success)
161 : {
162 : double result;
163 : bool isValid;
164 :
165 0 : switch (d_dataset->cellRepresentation())
166 : {
167 0 : case CR_UINT1:
168 : {
169 : UINT1 max;
170 0 : isValid = CPL_TO_BOOL(RgetMaxVal(d_dataset->map(), &max));
171 0 : result = static_cast<double>(max);
172 0 : break;
173 : }
174 0 : case CR_INT4:
175 : {
176 : INT4 max;
177 0 : isValid = CPL_TO_BOOL(RgetMaxVal(d_dataset->map(), &max));
178 0 : result = static_cast<double>(max);
179 0 : break;
180 : }
181 0 : case CR_REAL4:
182 : {
183 : REAL4 max;
184 0 : isValid = CPL_TO_BOOL(RgetMaxVal(d_dataset->map(), &max));
185 0 : result = static_cast<double>(max);
186 0 : break;
187 : }
188 : // CSF version 1.
189 : // ----------------------------------------------------------
190 0 : case CR_INT1:
191 : {
192 : INT1 max;
193 0 : isValid = CPL_TO_BOOL(RgetMaxVal(d_dataset->map(), &max));
194 0 : result = static_cast<double>(max);
195 0 : break;
196 : }
197 0 : case CR_INT2:
198 : {
199 : INT2 max;
200 0 : isValid = CPL_TO_BOOL(RgetMaxVal(d_dataset->map(), &max));
201 0 : result = static_cast<double>(max);
202 0 : break;
203 : }
204 0 : case CR_UINT2:
205 : {
206 : UINT2 max;
207 0 : isValid = CPL_TO_BOOL(RgetMaxVal(d_dataset->map(), &max));
208 0 : result = static_cast<double>(max);
209 0 : break;
210 : }
211 0 : case CR_UINT4:
212 : {
213 : UINT4 max;
214 0 : isValid = CPL_TO_BOOL(RgetMaxVal(d_dataset->map(), &max));
215 0 : result = static_cast<double>(max);
216 0 : break;
217 : }
218 0 : default:
219 : {
220 0 : result = 0.0;
221 0 : isValid = false;
222 0 : break;
223 : }
224 : }
225 :
226 0 : if (success)
227 : {
228 0 : *success = isValid ? 1 : 0;
229 : }
230 :
231 0 : return result;
232 : }
233 :
234 420 : CPLErr PCRasterRasterBand::IReadBlock(CPL_UNUSED int nBlockXoff, int nBlockYoff,
235 : void *buffer)
236 : {
237 420 : size_t nrCellsRead = RgetRow(d_dataset->map(), nBlockYoff, buffer);
238 :
239 : // Now we have raw values, missing values are set according to the CSF
240 : // conventions. This means that floating points should not be evaluated.
241 : // Since this is done by the GDal library we replace these with valid
242 : // values. Non-MV values are not touched.
243 :
244 : // Replace in-file MV with in-app MV which may be different.
245 420 : alterFromStdMV(buffer, nrCellsRead, d_dataset->cellRepresentation(),
246 : GetNoDataValue());
247 :
248 420 : return CE_None;
249 : }
250 :
251 441 : CPLErr PCRasterRasterBand::IRasterIO(GDALRWFlag eRWFlag, int nXOff, int nYOff,
252 : int nXSize, int nYSize, void *pData,
253 : int nBufXSize, int nBufYSize,
254 : GDALDataType eBufType,
255 : GSpacing nPixelSpace, GSpacing nLineSpace,
256 : GDALRasterIOExtraArg *psExtraArg)
257 : {
258 441 : if (eRWFlag == GF_Read)
259 : {
260 : // read should just be the default
261 440 : return GDALRasterBand::IRasterIO(GF_Read, nXOff, nYOff, nXSize, nYSize,
262 : pData, nBufXSize, nBufYSize, eBufType,
263 440 : nPixelSpace, nLineSpace, psExtraArg);
264 : }
265 : else
266 : {
267 : // the datatype of the incoming data can be of different type than the
268 : // cell representation used in the raster
269 : // 'remember' the GDAL type to distinguish it later on in iWriteBlock
270 1 : d_create_in = eBufType;
271 1 : return GDALRasterBand::IRasterIO(GF_Write, nXOff, nYOff, nXSize, nYSize,
272 : pData, nBufXSize, nBufYSize, eBufType,
273 1 : nPixelSpace, nLineSpace, psExtraArg);
274 : }
275 : }
276 :
277 20 : CPLErr PCRasterRasterBand::IWriteBlock(CPL_UNUSED int nBlockXoff,
278 : int nBlockYoff, void *source)
279 : {
280 20 : CSF_VS valuescale = d_dataset->valueScale();
281 :
282 20 : if (valuescale == VS_LDD)
283 : {
284 0 : if ((d_create_in == GDT_Byte) || (d_create_in == GDT_Float32) ||
285 0 : (d_create_in == GDT_Float64))
286 : {
287 0 : CPLError(CE_Failure, CPLE_NotSupported,
288 : "PCRaster driver: "
289 : "conversion from %s to LDD not supported",
290 : GDALGetDataTypeName(d_create_in));
291 0 : return CE_Failure;
292 : }
293 : }
294 :
295 : // set new location attributes to the header
296 20 : if (d_dataset->location_changed())
297 : {
298 0 : REAL8 west = 0.0;
299 0 : REAL8 north = 0.0;
300 0 : REAL8 cellSize = 1.0;
301 : double transform[6];
302 0 : if (this->poDS->GetGeoTransform(transform) == CE_None)
303 : {
304 0 : if (transform[2] == 0.0 && transform[4] == 0.0)
305 : {
306 0 : west = static_cast<REAL8>(transform[0]);
307 0 : north = static_cast<REAL8>(transform[3]);
308 0 : cellSize = static_cast<REAL8>(transform[1]);
309 : }
310 : }
311 0 : (void)RputXUL(d_dataset->map(), west);
312 0 : (void)RputYUL(d_dataset->map(), north);
313 0 : (void)RputCellSize(d_dataset->map(), cellSize);
314 : }
315 :
316 20 : const int nr_cols = this->poDS->GetRasterXSize();
317 :
318 : // new maps from create() set min/max to MV
319 : // in case of reopening that map the min/max
320 : // value tracking is disabled (MM_WRONGVALUE)
321 : // reactivate it again to ensure that the output will
322 : // get the correct values when values are written to map
323 20 : d_dataset->map()->minMaxStatus = MM_KEEPTRACK;
324 :
325 : // allocate memory for row
326 20 : void *buffer = Rmalloc(d_dataset->map(), nr_cols);
327 20 : memcpy(buffer, source, nr_cols * 4);
328 :
329 : // convert source no_data values to MV in dest
330 20 : switch (valuescale)
331 : {
332 0 : case VS_BOOLEAN:
333 : case VS_LDD:
334 : {
335 0 : alterToStdMV(buffer, nr_cols, CR_UINT1, GetNoDataValue());
336 0 : break;
337 : }
338 0 : case VS_NOMINAL:
339 : case VS_ORDINAL:
340 : {
341 0 : alterToStdMV(buffer, nr_cols, CR_INT4, GetNoDataValue());
342 0 : break;
343 : }
344 20 : case VS_SCALAR:
345 : case VS_DIRECTION:
346 : {
347 20 : alterToStdMV(buffer, nr_cols, CR_REAL4, GetNoDataValue());
348 20 : break;
349 : }
350 0 : default:
351 : {
352 0 : break;
353 : }
354 : }
355 :
356 : // conversion of values according to value scale
357 20 : switch (valuescale)
358 : {
359 0 : case VS_BOOLEAN:
360 : {
361 0 : castValuesToBooleanRange(buffer, nr_cols, CR_UINT1);
362 0 : break;
363 : }
364 0 : case VS_LDD:
365 : {
366 0 : castValuesToLddRange(buffer, nr_cols);
367 0 : break;
368 : }
369 0 : case VS_DIRECTION:
370 : {
371 0 : castValuesToDirectionRange(buffer, nr_cols);
372 0 : break;
373 : }
374 20 : default:
375 : {
376 20 : break;
377 : }
378 : }
379 :
380 20 : RputRow(d_dataset->map(), nBlockYoff, buffer);
381 20 : free(buffer);
382 :
383 20 : return CE_None;
384 : }
385 :
386 0 : CPLErr PCRasterRasterBand::SetNoDataValue(double nodata)
387 : {
388 0 : d_noDataValue = nodata;
389 0 : d_defaultNoDataValueOverridden = true;
390 :
391 0 : return CE_None;
392 : }
|