Coverage Report

Created: 2025-06-09 07:07

/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