/src/gdal/frmts/mrf/mrf_overview.cpp
Line | Count | Source (jump to first uncovered line) |
1 | | /* |
2 | | * Copyright 2014-2021 Esri |
3 | | * Licensed under the Apache License, Version 2.0 (the "License"); |
4 | | * you may not use this file except in compliance with the License. |
5 | | * You may obtain a copy of the License at |
6 | | * |
7 | | * http://www.apache.org/licenses/LICENSE-2.0 |
8 | | * |
9 | | * Unless required by applicable law or agreed to in writing, software |
10 | | * distributed under the License is distributed on an "AS IS" BASIS, |
11 | | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
12 | | * See the License for the specific language governing permissions and |
13 | | * limitations under the License. |
14 | | */ |
15 | | |
16 | | /****************************************************************************** |
17 | | * |
18 | | * Project: Meta Raster File Format Driver Implementation, overlay support |
19 | | * Purpose: Implementation overlay support for MRF |
20 | | * |
21 | | * Author: Lucian Plesea, Lucian.Plesea jpl.nasa.gov, lplesea esri.com |
22 | | * |
23 | | ****************************************************************************** |
24 | | * This source file contains the non GDAL standard part of the MRF overview |
25 | | *building The PatchOverview method only handles powers of 2 overviews!! |
26 | | ****************************************************************************/ |
27 | | |
28 | | #include "marfa.h" |
29 | | #include <vector> |
30 | | |
31 | | NAMESPACE_MRF_START |
32 | | |
33 | | // |
34 | | // Scales by 2x2 a buffer in place, using Nearest resampling |
35 | | // Always pick the top-left corner |
36 | | // |
37 | | template <typename T> static void NearByFour(T *buff, int xsz, int ysz) |
38 | 0 | { |
39 | 0 | T *obuff = buff; |
40 | 0 | for (int line = 0; line < ysz; line++) |
41 | 0 | { |
42 | | // Copy every other pixel |
43 | 0 | for (int col = 0; col < xsz; col++, buff++) |
44 | 0 | { |
45 | 0 | *obuff++ = *buff++; |
46 | 0 | } |
47 | | // Skip every other line |
48 | 0 | buff += xsz * 2; |
49 | 0 | } |
50 | 0 | } Unexecuted instantiation: mrf_overview.cpp:void GDAL_MRF::NearByFour<unsigned char>(unsigned char*, int, int) Unexecuted instantiation: mrf_overview.cpp:void GDAL_MRF::NearByFour<signed char>(signed char*, int, int) Unexecuted instantiation: mrf_overview.cpp:void GDAL_MRF::NearByFour<unsigned short>(unsigned short*, int, int) Unexecuted instantiation: mrf_overview.cpp:void GDAL_MRF::NearByFour<short>(short*, int, int) Unexecuted instantiation: mrf_overview.cpp:void GDAL_MRF::NearByFour<unsigned int>(unsigned int*, int, int) Unexecuted instantiation: mrf_overview.cpp:void GDAL_MRF::NearByFour<int>(int*, int, int) Unexecuted instantiation: mrf_overview.cpp:void GDAL_MRF::NearByFour<unsigned long long>(unsigned long long*, int, int) Unexecuted instantiation: mrf_overview.cpp:void GDAL_MRF::NearByFour<long long>(long long*, int, int) Unexecuted instantiation: mrf_overview.cpp:void GDAL_MRF::NearByFour<float>(float*, int, int) Unexecuted instantiation: mrf_overview.cpp:void GDAL_MRF::NearByFour<double>(double*, int, int) |
51 | | |
52 | | // |
53 | | // If the NoData value exists, pick a valid pixel if possible |
54 | | // |
55 | | template <typename T> static void NearByFour(T *buff, int xsz, int ysz, T ndv) |
56 | 0 | { |
57 | 0 | T *obuff = buff; |
58 | 0 | T *evenline = buff; |
59 | |
|
60 | 0 | for (int line = 0; line < ysz; line++) |
61 | 0 | { |
62 | 0 | T *oddline = evenline + xsz * 2; |
63 | 0 | for (int col = 0; col < xsz; col++) |
64 | 0 | { |
65 | |
|
66 | 0 | if (evenline[0] != ndv) |
67 | 0 | *obuff++ = evenline[0]; |
68 | 0 | else if (evenline[1] != ndv) |
69 | 0 | *obuff++ = evenline[1]; |
70 | 0 | else if (oddline[0] != ndv) |
71 | 0 | *obuff++ = oddline[0]; |
72 | 0 | else |
73 | 0 | *obuff++ = oddline[1]; |
74 | |
|
75 | 0 | evenline += 2; |
76 | 0 | oddline += 2; |
77 | 0 | } |
78 | 0 | evenline += xsz * 2; // Skips the other input line |
79 | 0 | } |
80 | 0 | } Unexecuted instantiation: mrf_overview.cpp:void GDAL_MRF::NearByFour<unsigned char>(unsigned char*, int, int, unsigned char) Unexecuted instantiation: mrf_overview.cpp:void GDAL_MRF::NearByFour<signed char>(signed char*, int, int, signed char) Unexecuted instantiation: mrf_overview.cpp:void GDAL_MRF::NearByFour<unsigned short>(unsigned short*, int, int, unsigned short) Unexecuted instantiation: mrf_overview.cpp:void GDAL_MRF::NearByFour<short>(short*, int, int, short) Unexecuted instantiation: mrf_overview.cpp:void GDAL_MRF::NearByFour<unsigned int>(unsigned int*, int, int, unsigned int) Unexecuted instantiation: mrf_overview.cpp:void GDAL_MRF::NearByFour<int>(int*, int, int, int) Unexecuted instantiation: mrf_overview.cpp:void GDAL_MRF::NearByFour<unsigned long long>(unsigned long long*, int, int, unsigned long long) Unexecuted instantiation: mrf_overview.cpp:void GDAL_MRF::NearByFour<long long>(long long*, int, int, long long) Unexecuted instantiation: mrf_overview.cpp:void GDAL_MRF::NearByFour<float>(float*, int, int, float) Unexecuted instantiation: mrf_overview.cpp:void GDAL_MRF::NearByFour<double>(double*, int, int, double) |
81 | | |
82 | | // Scales by 2x2 using averaging |
83 | | // There are lots of these AverageByFour templates, because some types have to |
84 | | // be treated slightly different than others. Some could be folded by using |
85 | | // is_integral(), but support is not universal There are two categories, |
86 | | // depending on NoData presence |
87 | | // |
88 | | |
89 | | // Integer data types shorter than 32 bit use integer math safely |
90 | | template <typename T> static void AverageByFour(T *buff, int xsz, int ysz) |
91 | 0 | { |
92 | 0 | T *obuff = buff; |
93 | 0 | T *evenline = buff; |
94 | |
|
95 | 0 | for (int line = 0; line < ysz; line++) |
96 | 0 | { |
97 | 0 | T *oddline = evenline + xsz * 2; |
98 | 0 | for (int col = 0; col < xsz; col++) |
99 | 0 | { |
100 | 0 | *obuff++ = |
101 | 0 | (2 + evenline[0] + evenline[1] + oddline[0] + oddline[1]) / 4; |
102 | 0 | evenline += 2; |
103 | 0 | oddline += 2; |
104 | 0 | } |
105 | 0 | evenline += xsz * 2; // Skips the other line |
106 | 0 | } |
107 | 0 | } Unexecuted instantiation: mrf_overview.cpp:void GDAL_MRF::AverageByFour<unsigned char>(unsigned char*, int, int) Unexecuted instantiation: mrf_overview.cpp:void GDAL_MRF::AverageByFour<signed char>(signed char*, int, int) Unexecuted instantiation: mrf_overview.cpp:void GDAL_MRF::AverageByFour<unsigned short>(unsigned short*, int, int) Unexecuted instantiation: mrf_overview.cpp:void GDAL_MRF::AverageByFour<short>(short*, int, int) Unexecuted instantiation: mrf_overview.cpp:void GDAL_MRF::AverageByFour<unsigned long long>(unsigned long long*, int, int) Unexecuted instantiation: mrf_overview.cpp:void GDAL_MRF::AverageByFour<long long>(long long*, int, int) |
108 | | |
109 | | // 32bit int specialization, avoiding overflow by using 64bit int math |
110 | | template <> void AverageByFour<GInt32>(GInt32 *buff, int xsz, int ysz) |
111 | 0 | { |
112 | 0 | GInt32 *obuff = buff; |
113 | 0 | GInt32 *evenline = buff; |
114 | |
|
115 | 0 | for (int line = 0; line < ysz; line++) |
116 | 0 | { |
117 | 0 | GInt32 *oddline = evenline + xsz * 2; |
118 | 0 | for (int col = 0; col < xsz; col++) |
119 | 0 | { |
120 | 0 | *obuff++ = (GIntBig(2) + evenline[0] + evenline[1] + oddline[0] + |
121 | 0 | oddline[1]) / |
122 | 0 | 4; |
123 | 0 | evenline += 2; |
124 | 0 | oddline += 2; |
125 | 0 | } |
126 | 0 | evenline += xsz * 2; // Skips the other line |
127 | 0 | } |
128 | 0 | } |
129 | | |
130 | | // Same for 32bit unsigned int specialization |
131 | | template <> void AverageByFour<GUInt32>(GUInt32 *buff, int xsz, int ysz) |
132 | 0 | { |
133 | 0 | GUInt32 *obuff = buff; |
134 | 0 | GUInt32 *evenline = buff; |
135 | |
|
136 | 0 | for (int line = 0; line < ysz; line++) |
137 | 0 | { |
138 | 0 | GUInt32 *oddline = evenline + xsz * 2; |
139 | 0 | for (int col = 0; col < xsz; col++) |
140 | 0 | { |
141 | 0 | *obuff++ = (GIntBig(2) + evenline[0] + evenline[1] + oddline[0] + |
142 | 0 | oddline[1]) / |
143 | 0 | 4; |
144 | 0 | evenline += 2; |
145 | 0 | oddline += 2; |
146 | 0 | } |
147 | 0 | evenline += xsz * 2; // Skips the other line |
148 | 0 | } |
149 | 0 | } |
150 | | |
151 | | // float specialization |
152 | | template <> void AverageByFour<float>(float *buff, int xsz, int ysz) |
153 | 0 | { |
154 | 0 | float *obuff = buff; |
155 | 0 | float *evenline = buff; |
156 | |
|
157 | 0 | for (int line = 0; line < ysz; line++) |
158 | 0 | { |
159 | 0 | float *oddline = evenline + xsz * 2; |
160 | 0 | for (int col = 0; col < xsz; col++) |
161 | 0 | { |
162 | 0 | *obuff++ = |
163 | 0 | (evenline[0] + evenline[1] + oddline[0] + oddline[1]) * 0.25f; |
164 | 0 | evenline += 2; |
165 | 0 | oddline += 2; |
166 | 0 | } |
167 | 0 | evenline += xsz * 2; // Skips the other line |
168 | 0 | } |
169 | 0 | } |
170 | | |
171 | | // double specialization |
172 | | template <> void AverageByFour<double>(double *buff, int xsz, int ysz) |
173 | 0 | { |
174 | 0 | double *obuff = buff; |
175 | 0 | double *evenline = buff; |
176 | |
|
177 | 0 | for (int line = 0; line < ysz; line++) |
178 | 0 | { |
179 | 0 | double *oddline = evenline + xsz * 2; |
180 | 0 | for (int col = 0; col < xsz; col++) |
181 | 0 | { |
182 | 0 | *obuff++ = |
183 | 0 | (evenline[0] + evenline[1] + oddline[0] + oddline[1]) * 0.25; |
184 | 0 | evenline += 2; |
185 | 0 | oddline += 2; |
186 | 0 | } |
187 | 0 | evenline += xsz * 2; // Skips the other line |
188 | 0 | } |
189 | 0 | } |
190 | | |
191 | | // |
192 | | // Integer type specialization, with roundup and integer math, avoids overflow |
193 | | // using GIntBig accumulator Speedup by specialization for smaller byte count |
194 | | // int types is probably not worth much since there are so many conditions here |
195 | | // |
196 | | template <typename T> |
197 | | static void AverageByFour(T *buff, int xsz, int ysz, T ndv) |
198 | 0 | { |
199 | 0 | T *obuff = buff; |
200 | 0 | T *evenline = buff; |
201 | |
|
202 | 0 | for (int line = 0; line < ysz; line++) |
203 | 0 | { |
204 | 0 | T *oddline = evenline + xsz * 2; |
205 | 0 | for (int col = 0; col < xsz; col++) |
206 | 0 | { |
207 | 0 | GIntBig acc = 0; |
208 | 0 | int count = 0; |
209 | | |
210 | | // Temporary macro to accumulate the sum, uses the value, increments the pointer |
211 | | // Careful with this one, it has side effects |
212 | 0 | #define use(valp) \ |
213 | 0 | if (*valp != ndv) \ |
214 | 0 | { \ |
215 | 0 | acc += *valp; \ |
216 | 0 | count++; \ |
217 | 0 | }; \ |
218 | 0 | valp++; |
219 | 0 | use(evenline); |
220 | 0 | use(evenline); |
221 | 0 | use(oddline); |
222 | 0 | use(oddline); |
223 | 0 | #undef use |
224 | | // The count/2 is the bias to obtain correct rounding |
225 | 0 | *obuff++ = T((count != 0) ? ((acc + count / 2) / count) : ndv); |
226 | 0 | } |
227 | 0 | evenline += xsz * 2; // Skips every other line |
228 | 0 | } |
229 | 0 | } Unexecuted instantiation: mrf_overview.cpp:void GDAL_MRF::AverageByFour<unsigned char>(unsigned char*, int, int, unsigned char) Unexecuted instantiation: mrf_overview.cpp:void GDAL_MRF::AverageByFour<signed char>(signed char*, int, int, signed char) Unexecuted instantiation: mrf_overview.cpp:void GDAL_MRF::AverageByFour<unsigned short>(unsigned short*, int, int, unsigned short) Unexecuted instantiation: mrf_overview.cpp:void GDAL_MRF::AverageByFour<short>(short*, int, int, short) Unexecuted instantiation: mrf_overview.cpp:void GDAL_MRF::AverageByFour<unsigned int>(unsigned int*, int, int, unsigned int) Unexecuted instantiation: mrf_overview.cpp:void GDAL_MRF::AverageByFour<int>(int*, int, int, int) Unexecuted instantiation: mrf_overview.cpp:void GDAL_MRF::AverageByFour<unsigned long long>(unsigned long long*, int, int, unsigned long long) Unexecuted instantiation: mrf_overview.cpp:void GDAL_MRF::AverageByFour<long long>(long long*, int, int, long long) |
230 | | |
231 | | // float specialization |
232 | | template <> void AverageByFour<float>(float *buff, int xsz, int ysz, float ndv) |
233 | 0 | { |
234 | 0 | float *obuff = buff; |
235 | 0 | float *evenline = buff; |
236 | |
|
237 | 0 | for (int line = 0; line < ysz; line++) |
238 | 0 | { |
239 | 0 | float *oddline = evenline + xsz * 2; |
240 | 0 | for (int col = 0; col < xsz; col++) |
241 | 0 | { |
242 | 0 | double acc = 0; |
243 | 0 | double count = 0; |
244 | | |
245 | | // Temporary macro to accumulate the sum, uses the value, increments the pointer |
246 | | // Careful with this one, it has side effects |
247 | 0 | #define use(valp) \ |
248 | 0 | if (*valp != ndv) \ |
249 | 0 | { \ |
250 | 0 | acc += *valp; \ |
251 | 0 | count += 1.0; \ |
252 | 0 | }; \ |
253 | 0 | valp++; |
254 | 0 | use(evenline); |
255 | 0 | use(evenline); |
256 | 0 | use(oddline); |
257 | 0 | use(oddline); |
258 | 0 | #undef use |
259 | | // Output value is eiher accumulator divided by count or the |
260 | | // NoDataValue |
261 | 0 | *obuff++ = float((count != 0.0) ? acc / count : ndv); |
262 | 0 | } |
263 | 0 | evenline += xsz * 2; // Skips every other line |
264 | 0 | } |
265 | 0 | } |
266 | | |
267 | | // double specialization, same as above |
268 | | template <> |
269 | | void AverageByFour<double>(double *buff, int xsz, int ysz, double ndv) |
270 | 0 | { |
271 | 0 | double *obuff = buff; |
272 | 0 | double *evenline = buff; |
273 | |
|
274 | 0 | for (int line = 0; line < ysz; line++) |
275 | 0 | { |
276 | 0 | double *oddline = evenline + xsz * 2; |
277 | 0 | for (int col = 0; col < xsz; col++) |
278 | 0 | { |
279 | 0 | double acc = 0; |
280 | 0 | double count = 0; |
281 | | |
282 | | // Temporary macro to accumulate the sum, uses the value, increments the pointer |
283 | | // Careful with this one, it has side effects |
284 | 0 | #define use(valp) \ |
285 | 0 | if (*valp != ndv) \ |
286 | 0 | { \ |
287 | 0 | acc += *valp; \ |
288 | 0 | count += 1.0; \ |
289 | 0 | }; \ |
290 | 0 | valp++; |
291 | 0 | use(evenline); |
292 | 0 | use(evenline); |
293 | 0 | use(oddline); |
294 | 0 | use(oddline); |
295 | 0 | #undef use |
296 | | // Output value is eiher accumulator divided by count or the |
297 | | // NoDataValue |
298 | 0 | *obuff++ = ((count != 0.0) ? acc / count : ndv); |
299 | 0 | } |
300 | 0 | evenline += xsz * 2; // Skips every other line |
301 | 0 | } |
302 | 0 | } |
303 | | |
304 | | /* |
305 | | *\brief Patches an overview for the selected area |
306 | | * arguments are in blocks in the source level, if toTheTop is false it only |
307 | | *does the next level It will read adjacent blocks if they are needed, so actual |
308 | | *area read might be padded by one block in either side |
309 | | */ |
310 | | |
311 | | CPLErr MRFDataset::PatchOverview(int BlockX, int BlockY, int Width, int Height, |
312 | | int srcLevel, int recursive, int sampling_mode) |
313 | 0 | { |
314 | 0 | CPLErr status = CE_None; |
315 | 0 | GDALRasterBand *b0 = GetRasterBand(1); |
316 | 0 | if (b0->GetOverviewCount() <= srcLevel) |
317 | 0 | return CE_None; |
318 | | |
319 | 0 | int BlockXOut = BlockX / 2; // Round down |
320 | 0 | Width += BlockX & 1; // Increment width if rounding down |
321 | 0 | int BlockYOut = BlockY / 2; // Round down |
322 | 0 | Height += BlockY & 1; // Increment height if rounding down |
323 | |
|
324 | 0 | int WidthOut = Width / 2 + (Width & 1); // Round up |
325 | 0 | int HeightOut = Height / 2 + (Height & 1); // Round up |
326 | |
|
327 | 0 | int bands = GetRasterCount(); |
328 | 0 | int tsz_x, tsz_y; |
329 | 0 | b0->GetBlockSize(&tsz_x, &tsz_y); |
330 | 0 | GDALDataType eDataType = b0->GetRasterDataType(); |
331 | |
|
332 | 0 | int pixel_size = |
333 | 0 | GDALGetDataTypeSizeBytes(eDataType); // Bytes per pixel per band |
334 | 0 | int line_size = tsz_x * pixel_size; // A line has this many bytes |
335 | 0 | int buffer_size = line_size * tsz_y; // A block size in bytes |
336 | | |
337 | | // Build a vector of input and output bands |
338 | 0 | std::vector<GDALRasterBand *> src_b; |
339 | 0 | std::vector<GDALRasterBand *> dst_b; |
340 | |
|
341 | 0 | for (int band = 1; band <= bands; band++) |
342 | 0 | { |
343 | 0 | if (srcLevel == 0) |
344 | 0 | src_b.push_back(GetRasterBand(band)); |
345 | 0 | else |
346 | 0 | src_b.push_back(GetRasterBand(band)->GetOverview(srcLevel - 1)); |
347 | 0 | dst_b.push_back(GetRasterBand(band)->GetOverview(srcLevel)); |
348 | 0 | } |
349 | | |
350 | | // Allocate input space for four blocks |
351 | 0 | std::vector<GByte> buffer(buffer_size * 4); |
352 | | |
353 | | // If the page is interleaved, we only need to check the page exists |
354 | | // otherwise we need to check each band block |
355 | 0 | int check_bands = (bands == current.pagesize.c) ? 1 : bands; |
356 | | |
357 | | // |
358 | | // The inner loop is the band, so it is efficient for interleaved data. |
359 | | // There is no penalty for separate bands either. |
360 | | // |
361 | 0 | for (int y = 0; y < HeightOut && CE_None == status; y++) |
362 | 0 | { |
363 | 0 | int dst_offset_y = BlockYOut + y; |
364 | 0 | int src_offset_y = dst_offset_y * 2; |
365 | 0 | for (int x = 0; x < WidthOut && CE_None == status; x++) |
366 | 0 | { |
367 | 0 | int dst_offset_x = BlockXOut + x; |
368 | 0 | int src_offset_x = dst_offset_x * 2; |
369 | | |
370 | | // If none of the source blocks exists, there is no need to |
371 | | // read/write the blocks themselves |
372 | 0 | bool has_data = false; |
373 | 0 | for (int band = 0; band < check_bands; band++) |
374 | 0 | { |
375 | 0 | MRFRasterBand *bsrc = |
376 | 0 | reinterpret_cast<MRFRasterBand *>(src_b[band]); |
377 | 0 | has_data |= bsrc->TestBlock(src_offset_x, src_offset_y); |
378 | 0 | has_data |= bsrc->TestBlock(src_offset_x + 1, src_offset_y); |
379 | 0 | has_data |= bsrc->TestBlock(src_offset_x, src_offset_y + 1); |
380 | 0 | has_data |= bsrc->TestBlock(src_offset_x + 1, src_offset_y + 1); |
381 | 0 | } |
382 | | |
383 | | // No data in any of the bands for this output block |
384 | 0 | if (!has_data) |
385 | 0 | { |
386 | | // check that the output is already empty, otherwise force write |
387 | | // an empty block |
388 | 0 | for (int band = 0; band < check_bands; band++) |
389 | 0 | { |
390 | 0 | MRFRasterBand *bdst = |
391 | 0 | reinterpret_cast<MRFRasterBand *>(dst_b[band]); |
392 | 0 | if (bdst->TestBlock(dst_offset_x, dst_offset_y)) |
393 | 0 | { |
394 | | // Output block exists, but it should not, force it |
395 | 0 | ILSize req(dst_offset_x, dst_offset_y, 0, band, |
396 | 0 | bdst->m_l); |
397 | 0 | WriteTile(nullptr, IdxOffset(req, bdst->img)); |
398 | 0 | } |
399 | 0 | } |
400 | | // No blocks in -> No block out |
401 | 0 | continue; |
402 | 0 | } |
403 | | |
404 | | // Do it band at a time so we can work in grayscale |
405 | 0 | for (int band = 0; band < bands; band++) |
406 | 0 | { // Counting from zero in a vector |
407 | |
|
408 | 0 | int sz_x = 2 * tsz_x, sz_y = 2 * tsz_y; |
409 | 0 | MRFRasterBand *bsrc = static_cast<MRFRasterBand *>(src_b[band]); |
410 | 0 | MRFRasterBand *bdst = static_cast<MRFRasterBand *>(dst_b[band]); |
411 | | |
412 | | // |
413 | | // Clip to the size to the input image |
414 | | // This is one of the worst features of GDAL, it doesn't |
415 | | // tolerate any padding |
416 | | // |
417 | 0 | bool adjusted = false; |
418 | 0 | if (bsrc->GetXSize() < (src_offset_x + 2) * tsz_x) |
419 | 0 | { |
420 | 0 | sz_x = bsrc->GetXSize() - src_offset_x * tsz_x; |
421 | 0 | adjusted = true; |
422 | 0 | } |
423 | 0 | if (bsrc->GetYSize() < (src_offset_y + 2) * tsz_y) |
424 | 0 | { |
425 | 0 | sz_y = bsrc->GetYSize() - src_offset_y * tsz_y; |
426 | 0 | adjusted = true; |
427 | 0 | } |
428 | |
|
429 | 0 | if (adjusted) |
430 | 0 | { // Fill with no data for partial buffer, instead of padding |
431 | | // afterwards |
432 | 0 | size_t bsb = bsrc->blockSizeBytes(); |
433 | 0 | auto b = buffer.data(); |
434 | 0 | bsrc->FillBlock(b); |
435 | 0 | bsrc->FillBlock(b + bsb); |
436 | 0 | bsrc->FillBlock(b + 2 * bsb); |
437 | 0 | bsrc->FillBlock(b + 3 * bsb); |
438 | 0 | } |
439 | |
|
440 | 0 | int hasNoData = 0; |
441 | 0 | double ndv = bsrc->GetNoDataValue(&hasNoData); |
442 | |
|
443 | 0 | status = bsrc->RasterIO( |
444 | 0 | GF_Read, src_offset_x * tsz_x, |
445 | 0 | src_offset_y * tsz_y, // offset in input image |
446 | 0 | sz_x, sz_y, // Size in output image |
447 | 0 | buffer.data(), sz_x, sz_y, // Buffer and size in buffer |
448 | 0 | eDataType, pixel_size, 2 * line_size, nullptr); |
449 | |
|
450 | 0 | if (CE_None != status) |
451 | 0 | { |
452 | 0 | CPLError(CE_Failure, CPLE_AppDefined, |
453 | 0 | "MRF: Patch - RasterIO() read failed"); |
454 | 0 | break; // Get out now |
455 | 0 | } |
456 | | |
457 | | // Count the NoData values |
458 | 0 | int count = 0; // Assume all points are data |
459 | 0 | if (sampling_mode == SAMPLING_Avg) |
460 | 0 | { |
461 | | |
462 | | // Dispatch based on data type |
463 | | // Use a temporary macro to make it look easy |
464 | | // Runs the optimized version if the page is full with data |
465 | 0 | #define resample(T) \ |
466 | 0 | if (hasNoData) \ |
467 | 0 | { \ |
468 | 0 | count = MatchCount(reinterpret_cast<T *>(buffer.data()), \ |
469 | 0 | 4 * tsz_x * tsz_y, T(ndv)); \ |
470 | 0 | if (4 * tsz_x * tsz_y == count) \ |
471 | 0 | bdst->FillBlock(buffer.data()); \ |
472 | 0 | else if (0 != count) \ |
473 | 0 | AverageByFour(reinterpret_cast<T *>(buffer.data()), tsz_x, tsz_y, \ |
474 | 0 | T(ndv)); \ |
475 | 0 | } \ |
476 | 0 | if (0 == count) \ |
477 | 0 | AverageByFour(reinterpret_cast<T *>(buffer.data()), tsz_x, tsz_y); \ |
478 | 0 | break; |
479 | |
|
480 | 0 | switch (eDataType) |
481 | 0 | { |
482 | 0 | case GDT_Byte: |
483 | 0 | resample(GByte); |
484 | 0 | case GDT_Int8: |
485 | 0 | resample(GInt8); |
486 | 0 | case GDT_UInt16: |
487 | 0 | resample(GUInt16); |
488 | 0 | case GDT_Int16: |
489 | 0 | resample(GInt16); |
490 | 0 | case GDT_UInt32: |
491 | 0 | resample(GUInt32); |
492 | 0 | case GDT_Int32: |
493 | 0 | resample(GInt32); |
494 | 0 | case GDT_UInt64: |
495 | 0 | resample(GUInt64); |
496 | 0 | case GDT_Int64: |
497 | 0 | resample(GInt64); |
498 | 0 | case GDT_Float32: |
499 | 0 | resample(float); |
500 | 0 | case GDT_Float64: |
501 | 0 | resample(double); |
502 | 0 | default: |
503 | 0 | CPLAssert(false); |
504 | 0 | break; |
505 | 0 | } |
506 | 0 | #undef resample |
507 | 0 | } |
508 | 0 | else if (sampling_mode == SAMPLING_Near) |
509 | 0 | { |
510 | |
|
511 | 0 | #define resample(T) \ |
512 | 0 | if (hasNoData) \ |
513 | 0 | { \ |
514 | 0 | count = MatchCount(reinterpret_cast<T *>(buffer.data()), \ |
515 | 0 | 4 * tsz_x * tsz_y, T(ndv)); \ |
516 | 0 | if (4 * tsz_x * tsz_y == count) \ |
517 | 0 | bdst->FillBlock(buffer.data()); \ |
518 | 0 | else if (0 != count) \ |
519 | 0 | NearByFour(reinterpret_cast<T *>(buffer.data()), tsz_x, tsz_y, \ |
520 | 0 | T(ndv)); \ |
521 | 0 | } \ |
522 | 0 | if (0 == count) \ |
523 | 0 | NearByFour(reinterpret_cast<T *>(buffer.data()), tsz_x, tsz_y); \ |
524 | 0 | break; |
525 | 0 | switch (eDataType) |
526 | 0 | { |
527 | 0 | case GDT_Byte: |
528 | 0 | resample(GByte); |
529 | 0 | case GDT_Int8: |
530 | 0 | resample(GInt8); |
531 | 0 | case GDT_UInt16: |
532 | 0 | resample(GUInt16); |
533 | 0 | case GDT_Int16: |
534 | 0 | resample(GInt16); |
535 | 0 | case GDT_UInt32: |
536 | 0 | resample(GUInt32); |
537 | 0 | case GDT_Int32: |
538 | 0 | resample(GInt32); |
539 | 0 | case GDT_UInt64: |
540 | 0 | resample(GUInt64); |
541 | 0 | case GDT_Int64: |
542 | 0 | resample(GInt64); |
543 | 0 | case GDT_Float32: |
544 | 0 | resample(float); |
545 | 0 | case GDT_Float64: |
546 | 0 | resample(double); |
547 | 0 | default: |
548 | 0 | CPLAssert(false); |
549 | 0 | break; |
550 | 0 | } |
551 | 0 | #undef resample |
552 | 0 | } |
553 | | |
554 | | // Done filling the buffer |
555 | | // Argh, still need to clip the output to the band size on the |
556 | | // right and bottom The offset should be fine, just the size |
557 | | // might need adjustments |
558 | 0 | sz_x = tsz_x; |
559 | 0 | sz_y = tsz_y; |
560 | |
|
561 | 0 | if (bdst->GetXSize() < dst_offset_x * sz_x + sz_x) |
562 | 0 | sz_x = bdst->GetXSize() - dst_offset_x * sz_x; |
563 | 0 | if (bdst->GetYSize() < dst_offset_y * sz_y + sz_y) |
564 | 0 | sz_y = bdst->GetYSize() - dst_offset_y * sz_y; |
565 | |
|
566 | 0 | status = bdst->RasterIO( |
567 | 0 | GF_Write, dst_offset_x * tsz_x, |
568 | 0 | dst_offset_y * tsz_y, // offset in output image |
569 | 0 | sz_x, sz_y, // Size in output image |
570 | 0 | buffer.data(), sz_x, sz_y, // Buffer and size in buffer |
571 | 0 | eDataType, pixel_size, line_size, nullptr); |
572 | |
|
573 | 0 | if (CE_None != status) |
574 | 0 | { |
575 | 0 | CPLError(CE_Failure, CPLE_AppDefined, |
576 | 0 | "MRF: Patch - RasterIO() write failed"); |
577 | 0 | break; |
578 | 0 | } |
579 | 0 | } // Band loop |
580 | | |
581 | | // Mark input data as no longer needed, saves RAM |
582 | 0 | for (int band = 0; band < bands; band++) |
583 | 0 | src_b[band]->FlushCache(false); |
584 | 0 | } |
585 | 0 | } |
586 | | |
587 | 0 | if (CE_None != status) |
588 | 0 | return status; // Report problems |
589 | | |
590 | 0 | for (int band = 0; band < bands; band++) |
591 | 0 | dst_b[band]->FlushCache( |
592 | 0 | false); // Commit destination to disk after each overview |
593 | |
|
594 | 0 | if (!recursive) |
595 | 0 | return CE_None; |
596 | 0 | return PatchOverview(BlockXOut, BlockYOut, WidthOut, HeightOut, |
597 | 0 | srcLevel + 1, true); |
598 | 0 | } |
599 | | |
600 | | NAMESPACE_MRF_END |