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