• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

OSGeo / gdal / 15992523769

01 Jul 2025 07:16AM UTC coverage: 71.09% (-0.004%) from 71.094%
15992523769

Pull #12682

github

web-flow
Merge 1383a7df3 into f6ed9706f
Pull Request #12682: Bump msys2/setup-msys2 from 2.27.0 to 2.28.0

574092 of 807557 relevant lines covered (71.09%)

250020.23 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

81.23
/frmts/nitf/nitfrasterband.cpp
1
/******************************************************************************
2
 *
3
 * Project:  NITF Read/Write Translator
4
 * Purpose:  NITFRasterBand (and related proxy band) implementations.
5
 * Author:   Frank Warmerdam, warmerdam@pobox.com
6
 *
7
 ******************************************************************************
8
 * Copyright (c) 2002, Frank Warmerdam
9
 * Copyright (c) 2011-2013, Even Rouault <even dot rouault at spatialys.com>
10
 *
11
 * Portions Copyright (c) Her majesty the Queen in right of Canada as
12
 * represented by the Minister of National Defence, 2006, 2020
13
 *
14
 * SPDX-License-Identifier: MIT
15
 ****************************************************************************/
16

17
#include "cpl_port.h"
18
#include "nitfdataset.h"
19

20
#include <climits>
21
#include <cstring>
22
#if HAVE_FCNTL_H
23
#include <fcntl.h>
24
#endif
25
#include <algorithm>
26
#include <map>
27
#include <utility>
28

29
#include "cpl_conv.h"
30
#include "cpl_csv.h"
31
#include "cpl_error.h"
32
#include "cpl_progress.h"
33
#include "cpl_string.h"
34
#include "cpl_vsi.h"
35
#include "gdal.h"
36
#include "gdal_pam.h"
37
#include "gdal_priv.h"
38
#include "nitflib.h"
39

40
/************************************************************************/
41
/*                       NITFMakeColorTable()                           */
42
/************************************************************************/
43

44
static GDALColorTable *NITFMakeColorTable(NITFImage *psImage,
210,943✔
45
                                          NITFBandInfo *psBandInfo)
46
{
47
    GDALColorTable *poColorTable = nullptr;
210,943✔
48

49
    if (psBandInfo->nSignificantLUTEntries > 0)
210,943✔
50
    {
51
        poColorTable = new GDALColorTable();
33✔
52

53
        for (int iColor = 0; iColor < psBandInfo->nSignificantLUTEntries;
5,780✔
54
             iColor++)
55
        {
56
            GDALColorEntry sEntry;
57
            sEntry.c1 = psBandInfo->pabyLUT[0 + iColor];
5,747✔
58
            sEntry.c2 = psBandInfo->pabyLUT[256 + iColor];
5,747✔
59
            sEntry.c3 = psBandInfo->pabyLUT[512 + iColor];
5,747✔
60
            sEntry.c4 = 255;
5,747✔
61

62
            poColorTable->SetColorEntry(iColor, &sEntry);
5,747✔
63
        }
64

65
        if (psImage->bNoDataSet)
33✔
66
        {
67
            GDALColorEntry sEntry = {0, 0, 0, 0};
29✔
68
            poColorTable->SetColorEntry(psImage->nNoDataValue, &sEntry);
29✔
69
        }
70
    }
71

72
    /* -------------------------------------------------------------------- */
73
    /*      We create a color table for 1 bit data too...                   */
74
    /* -------------------------------------------------------------------- */
75
    if (poColorTable == nullptr && psImage->nBitsPerSample == 1)
210,943✔
76
    {
77
        poColorTable = new GDALColorTable();
20✔
78

79
        GDALColorEntry sEntry;
80
        sEntry.c1 = 0;
20✔
81
        sEntry.c2 = 0;
20✔
82
        sEntry.c3 = 0;
20✔
83
        sEntry.c4 = 255;
20✔
84
        poColorTable->SetColorEntry(0, &sEntry);
20✔
85

86
        sEntry.c1 = 255;
20✔
87
        sEntry.c2 = 255;
20✔
88
        sEntry.c3 = 255;
20✔
89
        sEntry.c4 = 255;
20✔
90
        poColorTable->SetColorEntry(1, &sEntry);
20✔
91
    }
92

93
    return poColorTable;
210,943✔
94
}
95

96
/************************************************************************/
97
/* ==================================================================== */
98
/*                        NITFProxyPamRasterBand                        */
99
/* ==================================================================== */
100
/************************************************************************/
101

102
NITFProxyPamRasterBand::~NITFProxyPamRasterBand()
107✔
103
{
104
    std::map<CPLString, char **>::iterator oIter = oMDMap.begin();
107✔
105
    while (oIter != oMDMap.end())
112✔
106
    {
107
        CSLDestroy(oIter->second);
5✔
108
        ++oIter;
5✔
109
    }
110
}
107✔
111

112
char **NITFProxyPamRasterBand::GetMetadata(const char *pszDomain)
6✔
113
{
114
    GDALRasterBand *_poSrcBand = RefUnderlyingRasterBand();
6✔
115
    if (_poSrcBand)
6✔
116
    {
117
        /* Let's merge metadata of PAM and the underlying band */
118
        /* PAM metadata should override underlying band metadata */
119
        char **papszMD = CSLDuplicate(_poSrcBand->GetMetadata(pszDomain));
6✔
120
        papszMD = CSLMerge(papszMD, GDALPamRasterBand::GetMetadata(pszDomain));
6✔
121

122
        if (pszDomain == nullptr)
6✔
123
            pszDomain = "";
×
124

125
        std::map<CPLString, char **>::iterator oIter = oMDMap.find(pszDomain);
6✔
126
        if (oIter != oMDMap.end())
6✔
127
            CSLDestroy(oIter->second);
1✔
128
        oMDMap[pszDomain] = papszMD;
6✔
129
        UnrefUnderlyingRasterBand(_poSrcBand);
6✔
130

131
        return papszMD;
6✔
132
    }
133

134
    return GDALPamRasterBand::GetMetadata(pszDomain);
×
135
}
136

137
const char *NITFProxyPamRasterBand::GetMetadataItem(const char *pszName,
11✔
138
                                                    const char *pszDomain)
139
{
140
    const char *pszRet = GDALPamRasterBand::GetMetadataItem(pszName, pszDomain);
11✔
141
    if (pszRet)
11✔
142
        return pszRet;
×
143

144
    GDALRasterBand *_poSrcBand = RefUnderlyingRasterBand();
11✔
145
    if (_poSrcBand)
11✔
146
    {
147
        if (!m_bEnablePixelTypeSignedByteWarning)
11✔
148
            _poSrcBand->EnablePixelTypeSignedByteWarning(false);
×
149
        pszRet = _poSrcBand->GetMetadataItem(pszName, pszDomain);
11✔
150
        _poSrcBand->EnablePixelTypeSignedByteWarning(true);
11✔
151
        UnrefUnderlyingRasterBand(_poSrcBand);
11✔
152
    }
153

154
    return pszRet;
11✔
155
}
156

157
CPLErr NITFProxyPamRasterBand::GetStatistics(int bApproxOK, int bForce,
2✔
158
                                             double *pdfMin, double *pdfMax,
159
                                             double *pdfMean, double *pdfStdDev)
160
{
161
    /* -------------------------------------------------------------------- */
162
    /*      Do we already have metadata items for the requested values?     */
163
    /* -------------------------------------------------------------------- */
164
    if ((pdfMin == nullptr ||
4✔
165
         GetMetadataItem("STATISTICS_MINIMUM") != nullptr) &&
2✔
166
        (pdfMax == nullptr ||
×
167
         GetMetadataItem("STATISTICS_MAXIMUM") != nullptr) &&
×
168
        (pdfMean == nullptr || GetMetadataItem("STATISTICS_MEAN") != nullptr) &&
4✔
169
        (pdfStdDev == nullptr ||
×
170
         GetMetadataItem("STATISTICS_STDDEV") != nullptr))
×
171
    {
172
        return GDALPamRasterBand::GetStatistics(bApproxOK, bForce, pdfMin,
×
173
                                                pdfMax, pdfMean, pdfStdDev);
×
174
    }
175

176
    GDALRasterBand *_poSrcBand = RefUnderlyingRasterBand();
2✔
177
    if (_poSrcBand)
2✔
178
    {
179
        CPLErr ret = _poSrcBand->GetStatistics(bApproxOK, bForce, pdfMin,
4✔
180
                                               pdfMax, pdfMean, pdfStdDev);
2✔
181
        if (ret == CE_None)
2✔
182
        {
183
            /* Report underlying statistics at PAM level */
184
            SetMetadataItem("STATISTICS_MINIMUM",
2✔
185
                            _poSrcBand->GetMetadataItem("STATISTICS_MINIMUM"));
2✔
186
            SetMetadataItem("STATISTICS_MAXIMUM",
2✔
187
                            _poSrcBand->GetMetadataItem("STATISTICS_MAXIMUM"));
2✔
188
            SetMetadataItem("STATISTICS_MEAN",
2✔
189
                            _poSrcBand->GetMetadataItem("STATISTICS_MEAN"));
2✔
190
            SetMetadataItem("STATISTICS_STDDEV",
2✔
191
                            _poSrcBand->GetMetadataItem("STATISTICS_STDDEV"));
2✔
192
        }
193
        UnrefUnderlyingRasterBand(_poSrcBand);
2✔
194
        return ret;
2✔
195
    }
196

197
    return CE_Failure;
×
198
}
199

200
CPLErr NITFProxyPamRasterBand::ComputeStatistics(
×
201
    int bApproxOK, double *pdfMin, double *pdfMax, double *pdfMean,
202
    double *pdfStdDev, GDALProgressFunc pfn, void *pProgressData)
203
{
204
    GDALRasterBand *_poSrcBand = RefUnderlyingRasterBand();
×
205
    if (_poSrcBand)
×
206
    {
207
        CPLErr ret = _poSrcBand->ComputeStatistics(
×
208
            bApproxOK, pdfMin, pdfMax, pdfMean, pdfStdDev, pfn, pProgressData);
×
209
        if (ret == CE_None)
×
210
        {
211
            /* Report underlying statistics at PAM level */
212
            SetMetadataItem("STATISTICS_MINIMUM",
×
213
                            _poSrcBand->GetMetadataItem("STATISTICS_MINIMUM"));
×
214
            SetMetadataItem("STATISTICS_MAXIMUM",
×
215
                            _poSrcBand->GetMetadataItem("STATISTICS_MAXIMUM"));
×
216
            SetMetadataItem("STATISTICS_MEAN",
×
217
                            _poSrcBand->GetMetadataItem("STATISTICS_MEAN"));
×
218
            SetMetadataItem("STATISTICS_STDDEV",
×
219
                            _poSrcBand->GetMetadataItem("STATISTICS_STDDEV"));
×
220
        }
221
        UnrefUnderlyingRasterBand(_poSrcBand);
×
222
        return ret;
×
223
    }
224

225
    return CE_Failure;
×
226
}
227

228
#define RB_PROXY_METHOD_GET_DBL_WITH_SUCCESS(methodName)                       \
229
    double NITFProxyPamRasterBand::methodName(int *pbSuccess)                  \
230
    {                                                                          \
231
        int bSuccess = FALSE;                                                  \
232
        double dfRet = GDALPamRasterBand::methodName(&bSuccess);               \
233
        if (bSuccess)                                                          \
234
        {                                                                      \
235
            if (pbSuccess)                                                     \
236
                *pbSuccess = TRUE;                                             \
237
            return dfRet;                                                      \
238
        }                                                                      \
239
        GDALRasterBand *_poSrcBand = RefUnderlyingRasterBand();                \
240
        if (_poSrcBand)                                                        \
241
        {                                                                      \
242
            dfRet = _poSrcBand->methodName(pbSuccess);                         \
243
            UnrefUnderlyingRasterBand(_poSrcBand);                             \
244
        }                                                                      \
245
        else                                                                   \
246
        {                                                                      \
247
            dfRet = 0;                                                         \
248
        }                                                                      \
249
        return dfRet;                                                          \
250
    }
251

252
RB_PROXY_METHOD_GET_DBL_WITH_SUCCESS(GetNoDataValue)
15✔
253
RB_PROXY_METHOD_GET_DBL_WITH_SUCCESS(GetMinimum)
×
254
RB_PROXY_METHOD_GET_DBL_WITH_SUCCESS(GetMaximum)
×
255

256
#define RB_PROXY_METHOD_WITH_RET_AND_CALL_OTHER_METHOD(                        \
257
    retType, retErrValue, methodName, underlyingMethodName, argList,           \
258
    argParams)                                                                 \
259
    retType NITFProxyPamRasterBand::methodName argList                         \
260
    {                                                                          \
261
        retType ret;                                                           \
262
        GDALRasterBand *_poSrcBand = RefUnderlyingRasterBand();                \
263
        if (_poSrcBand)                                                        \
264
        {                                                                      \
265
            ret = _poSrcBand->underlyingMethodName argParams;                  \
266
            UnrefUnderlyingRasterBand(_poSrcBand);                             \
267
        }                                                                      \
268
        else                                                                   \
269
        {                                                                      \
270
            ret = retErrValue;                                                 \
271
        }                                                                      \
272
        return ret;                                                            \
273
    }
274

275
RB_PROXY_METHOD_WITH_RET_AND_CALL_OTHER_METHOD(CPLErr, CE_Failure, IReadBlock,
×
276
                                               ReadBlock,
277
                                               (int nXBlockOff, int nYBlockOff,
278
                                                void *pImage),
279
                                               (nXBlockOff, nYBlockOff, pImage))
280
RB_PROXY_METHOD_WITH_RET_AND_CALL_OTHER_METHOD(CPLErr, CE_Failure, IWriteBlock,
×
281
                                               WriteBlock,
282
                                               (int nXBlockOff, int nYBlockOff,
283
                                                void *pImage),
284
                                               (nXBlockOff, nYBlockOff, pImage))
285
RB_PROXY_METHOD_WITH_RET_AND_CALL_OTHER_METHOD(
403✔
286
    CPLErr, CE_Failure, IRasterIO, RasterIO,
287
    (GDALRWFlag eRWFlag, int nXOff, int nYOff, int nXSize, int nYSize,
288
     void *pData, int nBufXSize, int nBufYSize, GDALDataType eBufType,
289
     GSpacing nPixelSpace, GSpacing nLineSpace,
290
     GDALRasterIOExtraArg *psExtraArg),
291
    (eRWFlag, nXOff, nYOff, nXSize, nYSize, pData, nBufXSize, nBufYSize,
292
     eBufType, nPixelSpace, nLineSpace, psExtraArg))
293

294
#define RB_PROXY_METHOD_WITH_RET(retType, retErrValue, methodName, argList,    \
295
                                 argParams)                                    \
296
    retType NITFProxyPamRasterBand::methodName argList                         \
297
    {                                                                          \
298
        retType ret;                                                           \
299
        GDALRasterBand *_poSrcBand = RefUnderlyingRasterBand();                \
300
        if (_poSrcBand)                                                        \
301
        {                                                                      \
302
            ret = _poSrcBand->methodName argParams;                            \
303
            UnrefUnderlyingRasterBand(_poSrcBand);                             \
304
        }                                                                      \
305
        else                                                                   \
306
        {                                                                      \
307
            ret = retErrValue;                                                 \
308
        }                                                                      \
309
        return ret;                                                            \
310
    }
311

312
RB_PROXY_METHOD_WITH_RET(CPLErr, CE_Failure, FlushCache, (bool bAtClosing),
110✔
313
                         (bAtClosing))
314

315
RB_PROXY_METHOD_WITH_RET(GDALColorInterp, GCI_Undefined, GetColorInterpretation,
×
316
                         (), ())
317
RB_PROXY_METHOD_WITH_RET(GDALColorTable *, nullptr, GetColorTable, (), ())
×
318
RB_PROXY_METHOD_WITH_RET(CPLErr, CE_Failure, Fill,
×
319
                         (double dfRealValue, double dfImaginaryValue),
320
                         (dfRealValue, dfImaginaryValue))
321

322
RB_PROXY_METHOD_WITH_RET(CPLErr, CE_Failure, ComputeRasterMinMax,
1✔
323
                         (int arg1, double *arg2), (arg1, arg2))
324

325
RB_PROXY_METHOD_WITH_RET(int, 0, HasArbitraryOverviews, (), ())
×
326
RB_PROXY_METHOD_WITH_RET(int, 0, GetOverviewCount, (), ())
4✔
327
RB_PROXY_METHOD_WITH_RET(GDALRasterBand *, nullptr, GetOverview, (int arg1),
2✔
328
                         (arg1))
329
RB_PROXY_METHOD_WITH_RET(GDALRasterBand *, nullptr, GetRasterSampleOverview,
×
330
                         (GUIntBig arg1), (arg1))
331

332
RB_PROXY_METHOD_WITH_RET(CPLErr, CE_Failure, BuildOverviews,
×
333
                         (const char *arg1, int arg2, const int *arg3,
334
                          GDALProgressFunc arg4, void *arg5,
335
                          CSLConstList papszOptions),
336
                         (arg1, arg2, arg3, arg4, arg5, papszOptions))
337

338
RB_PROXY_METHOD_WITH_RET(CPLErr, CE_Failure, AdviseRead,
4✔
339
                         (int nXOff, int nYOff, int nXSize, int nYSize,
340
                          int nBufXSize, int nBufYSize, GDALDataType eDT,
341
                          char **papszOptions),
342
                         (nXOff, nYOff, nXSize, nYSize, nBufXSize, nBufYSize,
343
                          eDT, papszOptions))
344

345
RB_PROXY_METHOD_WITH_RET(GDALRasterBand *, nullptr, GetMaskBand, (), ())
×
346
RB_PROXY_METHOD_WITH_RET(int, 0, GetMaskFlags, (), ())
16✔
347
RB_PROXY_METHOD_WITH_RET(CPLErr, CE_Failure, CreateMaskBand, (int nFlagsIn),
×
348
                         (nFlagsIn))
349

350
/************************************************************************/
351
/*                 UnrefUnderlyingRasterBand()                        */
352
/************************************************************************/
353

354
void NITFProxyPamRasterBand::UnrefUnderlyingRasterBand(
574✔
355
    CPL_UNUSED GDALRasterBand *poUnderlyingRasterBand)
356
{
357
}
574✔
358

359
/************************************************************************/
360
/* ==================================================================== */
361
/*                            NITFRasterBand                             */
362
/* ==================================================================== */
363
/************************************************************************/
364

365
/************************************************************************/
366
/*                           NITFRasterBand()                           */
367
/************************************************************************/
368

369
NITFRasterBand::NITFRasterBand(NITFDataset *poDSIn, int nBandIn)
210,943✔
370
    : psImage(poDSIn->psImage)
210,943✔
371
{
372
    NITFBandInfo *psBandInfo = poDSIn->psImage->pasBandInfo + nBandIn - 1;
210,943✔
373

374
    poDS = poDSIn;
210,943✔
375
    nBand = nBandIn;
210,943✔
376
    eAccess = poDSIn->eAccess;
210,943✔
377

378
    /* -------------------------------------------------------------------- */
379
    /*      Translate data type(s).                                         */
380
    /* -------------------------------------------------------------------- */
381
    if (psImage->nBitsPerSample <= 8)
210,943✔
382
        eDataType = GDT_Byte;
210,804✔
383
    else if (psImage->nBitsPerSample == 16 && EQUAL(psImage->szPVType, "SI"))
139✔
384
        eDataType = GDT_Int16;
27✔
385
    else if (psImage->nBitsPerSample == 16)
112✔
386
        eDataType = GDT_UInt16;
20✔
387
    else if (psImage->nBitsPerSample == 12)
92✔
388
        eDataType = GDT_UInt16;
16✔
389
    else if (psImage->nBitsPerSample == 32 && EQUAL(psImage->szPVType, "SI"))
76✔
390
        eDataType = GDT_Int32;
12✔
391
    else if (psImage->nBitsPerSample == 32 && EQUAL(psImage->szPVType, "R"))
64✔
392
        eDataType = GDT_Float32;
31✔
393
    else if (psImage->nBitsPerSample == 32)
33✔
394
        eDataType = GDT_UInt32;
12✔
395
    else if (psImage->nBitsPerSample == 64 && EQUAL(psImage->szPVType, "R"))
21✔
396
        eDataType = GDT_Float64;
12✔
397
    else if (psImage->nBitsPerSample == 64 && EQUAL(psImage->szPVType, "C"))
9✔
398
        eDataType = GDT_CFloat32;
9✔
399
    /* ERO : note I'm not sure if CFloat64 can be transmitted as NBPP is only 2
400
     * characters */
401
    else
402
    {
403
        int bOpenUnderlyingDS =
404
            CPLTestBool(CPLGetConfigOption("NITF_OPEN_UNDERLYING_DS", "YES"));
×
405
        if (!bOpenUnderlyingDS && psImage->nBitsPerSample > 8 &&
×
406
            psImage->nBitsPerSample < 16)
×
407
        {
408
            if (EQUAL(psImage->szPVType, "SI"))
×
409
                eDataType = GDT_Int16;
×
410
            else
411
                eDataType = GDT_UInt16;
×
412
        }
413
        else
414
        {
415
            eDataType = GDT_Unknown;
×
416
            CPLError(CE_Warning, CPLE_AppDefined,
×
417
                     "Unsupported combination of PVTYPE(%s) and NBPP(%d).",
418
                     psImage->szPVType, psImage->nBitsPerSample);
×
419
        }
420
    }
421

422
    /* -------------------------------------------------------------------- */
423
    /*      Work out block size. If the image is all one big block we       */
424
    /*      handle via the scanline access API.                             */
425
    /* -------------------------------------------------------------------- */
426
    if (psImage->nBlocksPerRow == 1 && psImage->nBlocksPerColumn == 1 &&
210,943✔
427
        psImage->nBitsPerSample >= 8 && EQUAL(psImage->szIC, "NC"))
210,855✔
428
    {
429
        bScanlineAccess = TRUE;
210,735✔
430
        nBlockXSize = psImage->nBlockWidth;
210,735✔
431
        nBlockYSize = 1;
210,735✔
432
    }
433
    else
434
    {
435
        bScanlineAccess = FALSE;
208✔
436
        nBlockXSize = psImage->nBlockWidth;
208✔
437
        nBlockYSize = psImage->nBlockHeight;
208✔
438
    }
439

440
    /* -------------------------------------------------------------------- */
441
    /*      Do we have a color table?                                       */
442
    /* -------------------------------------------------------------------- */
443
    poColorTable = NITFMakeColorTable(psImage, psBandInfo);
210,943✔
444

445
    if (psImage->nABPP != 8 && psImage->nABPP != 16 && psImage->nABPP != 32 &&
210,943✔
446
        psImage->nABPP != 64)
31✔
447
    {
448
        SetMetadataItem("NBITS", CPLString().Printf("%d", psImage->nABPP),
10✔
449
                        "IMAGE_STRUCTURE");
450
    }
451

452
    if (psImage->nBitsPerSample == 3 || psImage->nBitsPerSample == 5 ||
210,943✔
453
        psImage->nBitsPerSample == 6 || psImage->nBitsPerSample == 7)
210,911✔
454
    {
455
        if (nBlockXSize > (INT_MAX - 7) / nBlockYSize)
64✔
456
        {
457
            eDataType = GDT_Unknown;
×
458
        }
459
        else
460
        {
461
            pUnpackData = static_cast<GByte *>(
64✔
462
                VSI_MALLOC_VERBOSE(((nBlockXSize * nBlockYSize + 7) / 8) * 8));
64✔
463
            if (pUnpackData == nullptr)
64✔
464
                eDataType = GDT_Unknown;
×
465
        }
466
    }
467
}
210,943✔
468

469
/************************************************************************/
470
/*                          ~NITFRasterBand()                           */
471
/************************************************************************/
472

473
NITFRasterBand::~NITFRasterBand()
421,881✔
474

475
{
476
    if (poColorTable != nullptr)
210,943✔
477
        delete poColorTable;
53✔
478

479
    VSIFree(pUnpackData);
210,943✔
480
}
421,881✔
481

482
/************************************************************************/
483
/*                             IReadBlock()                             */
484
/************************************************************************/
485

486
CPLErr NITFRasterBand::IReadBlock(int nBlockXOff, int nBlockYOff, void *pImage)
18,631✔
487

488
{
489
    NITFDataset *poGDS = reinterpret_cast<NITFDataset *>(poDS);
18,631✔
490

491
    /* -------------------------------------------------------------------- */
492
    /*      Special case for JPEG blocks.                                   */
493
    /* -------------------------------------------------------------------- */
494
    if (EQUAL(psImage->szIC, "C3") || EQUAL(psImage->szIC, "M3"))
18,631✔
495
    {
496
        CPLErr eErr = poGDS->ReadJPEGBlock(nBlockXOff, nBlockYOff);
128✔
497
        const int nBlockBandSize = psImage->nBlockWidth *
128✔
498
                                   psImage->nBlockHeight *
128✔
499
                                   GDALGetDataTypeSizeBytes(eDataType);
128✔
500

501
        if (eErr != CE_None)
128✔
502
            return eErr;
×
503

504
        memcpy(pImage, poGDS->pabyJPEGBlock + (nBand - 1) * nBlockBandSize,
128✔
505
               nBlockBandSize);
506

507
        return eErr;
128✔
508
    }
509

510
    /* -------------------------------------------------------------------- */
511
    /*      Read the line/block                                             */
512
    /* -------------------------------------------------------------------- */
513
    int nBlockResult;
514

515
    if (bScanlineAccess)
18,503✔
516
    {
517
        nBlockResult = NITFReadImageLine(psImage, nBlockYOff, nBand, pImage);
15,951✔
518
    }
519
    else
520
    {
521
        nBlockResult =
522
            NITFReadImageBlock(psImage, nBlockXOff, nBlockYOff, nBand, pImage);
2,552✔
523
    }
524

525
    if (nBlockResult == BLKREAD_OK)
18,503✔
526
    {
527
        if (psImage->nBitsPerSample % 8)
18,071✔
528
            Unpack(reinterpret_cast<GByte *>(pImage));
68✔
529

530
        return CE_None;
18,071✔
531
    }
532

533
    if (nBlockResult == BLKREAD_FAIL)
432✔
534
        return CE_Failure;
×
535

536
    /* -------------------------------------------------------------------- */
537
    /*      If we got a null/missing block, try to fill it in with the      */
538
    /*      nodata value.  It seems this only really works properly for     */
539
    /*      8bit.                                                           */
540
    /* -------------------------------------------------------------------- */
541
    if (psImage->bNoDataSet)
432✔
542
        memset(pImage, psImage->nNoDataValue,
432✔
543
               static_cast<size_t>(psImage->nWordSize) * psImage->nBlockWidth *
432✔
544
                   psImage->nBlockHeight);
432✔
545
    else
546
        memset(pImage, 0,
×
547
               static_cast<size_t>(psImage->nWordSize) * psImage->nBlockWidth *
×
548
                   psImage->nBlockHeight);
×
549

550
    return CE_None;
432✔
551
}
552

553
/************************************************************************/
554
/*                            IWriteBlock()                             */
555
/************************************************************************/
556

557
CPLErr NITFRasterBand::IWriteBlock(int nBlockXOff, int nBlockYOff, void *pImage)
16,904✔
558

559
{
560
    /* -------------------------------------------------------------------- */
561
    /*      Write the line/block                                            */
562
    /* -------------------------------------------------------------------- */
563
    int nBlockResult;
564

565
    if (bScanlineAccess)
16,904✔
566
    {
567
        nBlockResult = NITFWriteImageLine(psImage, nBlockYOff, nBand, pImage);
16,260✔
568
    }
569
    else
570
    {
571
        nBlockResult =
572
            NITFWriteImageBlock(psImage, nBlockXOff, nBlockYOff, nBand, pImage);
644✔
573
    }
574

575
    if (nBlockResult == BLKREAD_OK)
16,904✔
576
        return CE_None;
16,904✔
577

578
    return CE_Failure;
×
579
}
580

581
/************************************************************************/
582
/*                           GetNoDataValue()                           */
583
/************************************************************************/
584

585
double NITFRasterBand::GetNoDataValue(int *pbSuccess)
118✔
586

587
{
588
    if (pbSuccess != nullptr)
118✔
589
        *pbSuccess = psImage->bNoDataSet;
117✔
590

591
    if (psImage->bNoDataSet)
118✔
592
        return psImage->nNoDataValue;
22✔
593

594
    return GDALPamRasterBand::GetNoDataValue(pbSuccess);
96✔
595
}
596

597
/************************************************************************/
598
/*                       GetColorInterpretation()                       */
599
/************************************************************************/
600

601
GDALColorInterp NITFRasterBand::GetColorInterpretation()
157✔
602

603
{
604
    NITFBandInfo *psBandInfo = psImage->pasBandInfo + nBand - 1;
157✔
605

606
    if (poColorTable != nullptr)
157✔
607
        return GCI_PaletteIndex;
21✔
608

609
    if (EQUAL(psBandInfo->szIREPBAND, "R"))
136✔
610
        return GCI_RedBand;
20✔
611
    if (EQUAL(psBandInfo->szIREPBAND, "G"))
116✔
612
        return GCI_GreenBand;
20✔
613
    if (EQUAL(psBandInfo->szIREPBAND, "B"))
96✔
614
        return GCI_BlueBand;
20✔
615
    if (EQUAL(psBandInfo->szIREPBAND, "M"))
76✔
616
        return GCI_GrayIndex;
70✔
617
    if (EQUAL(psBandInfo->szIREPBAND, "Y"))
6✔
618
        return GCI_YCbCr_YBand;
2✔
619
    if (EQUAL(psBandInfo->szIREPBAND, "Cb"))
4✔
620
        return GCI_YCbCr_CbBand;
2✔
621
    if (EQUAL(psBandInfo->szIREPBAND, "Cr"))
2✔
622
        return GCI_YCbCr_CrBand;
2✔
623

624
    return GCI_Undefined;
×
625
}
626

627
/************************************************************************/
628
/*                     NITFSetColorInterpretation()                     */
629
/************************************************************************/
630

631
CPLErr NITFSetColorInterpretation(NITFImage *psImage, int nBand,
33✔
632
                                  GDALColorInterp eInterp)
633

634
{
635
    const char *pszREP = nullptr;
33✔
636

637
    if (eInterp == GCI_RedBand)
33✔
638
        pszREP = "R";
11✔
639
    else if (eInterp == GCI_GreenBand)
22✔
640
        pszREP = "G";
11✔
641
    else if (eInterp == GCI_BlueBand)
11✔
642
        pszREP = "B";
11✔
643
    else if (eInterp == GCI_GrayIndex)
×
644
        pszREP = "M";
×
645
    else if (eInterp == GCI_YCbCr_YBand)
×
646
        pszREP = "Y";
×
647
    else if (eInterp == GCI_YCbCr_CbBand)
×
648
        pszREP = "Cb";
×
649
    else if (eInterp == GCI_YCbCr_CrBand)
×
650
        pszREP = "Cr";
×
651
    else if (eInterp == GCI_Undefined)
×
652
        return CE_None;
×
653

654
    if (pszREP == nullptr)
33✔
655
    {
656
        CPLError(CE_Failure, CPLE_NotSupported,
×
657
                 "Requested color interpretation (%s) not supported in NITF.",
658
                 GDALGetColorInterpretationName(eInterp));
659
        return CE_Failure;
×
660
    }
661

662
    /* -------------------------------------------------------------------- */
663
    /*      Where does this go in the file?                                 */
664
    /* -------------------------------------------------------------------- */
665
    NITFBandInfo *psBandInfo = psImage->pasBandInfo + nBand - 1;
33✔
666
    strcpy(psBandInfo->szIREPBAND, pszREP);
33✔
667
    GUIntBig nOffset = NITFIHFieldOffset(psImage, "IREPBAND");
33✔
668

669
    if (nOffset != 0)
33✔
670
        nOffset += (nBand - 1) * 13;
33✔
671

672
    /* -------------------------------------------------------------------- */
673
    /*      write it (space padded).                                        */
674
    /* -------------------------------------------------------------------- */
675
    char szPadded[4];
676
    strcpy(szPadded, pszREP);
33✔
677
    strcat(szPadded, " ");
33✔
678

679
    if (nOffset != 0)
33✔
680
    {
681
        if (VSIFSeekL(psImage->psFile->fp, nOffset, SEEK_SET) != 0 ||
66✔
682
            VSIFWriteL(reinterpret_cast<void *>(szPadded), 1, 2,
33✔
683
                       psImage->psFile->fp) != 2)
33✔
684
        {
685
            CPLError(CE_Failure, CPLE_AppDefined,
×
686
                     "IO failure writing new IREPBAND value to NITF file.");
687
            return CE_Failure;
×
688
        }
689
    }
690

691
    return CE_None;
33✔
692
}
693

694
/************************************************************************/
695
/*                       SetColorInterpretation()                       */
696
/************************************************************************/
697

698
CPLErr NITFRasterBand::SetColorInterpretation(GDALColorInterp eInterp)
30✔
699

700
{
701
    return NITFSetColorInterpretation(psImage, nBand, eInterp);
30✔
702
}
703

704
/************************************************************************/
705
/*                           GetColorTable()                            */
706
/************************************************************************/
707

708
GDALColorTable *NITFRasterBand::GetColorTable()
54✔
709

710
{
711
    return poColorTable;
54✔
712
}
713

714
/************************************************************************/
715
/*                           SetColorTable()                            */
716
/************************************************************************/
717

718
CPLErr NITFRasterBand::SetColorTable(GDALColorTable *poNewCT)
2✔
719

720
{
721
    NITFDataset *poGDS = reinterpret_cast<NITFDataset *>(poDS);
2✔
722
    if (poGDS->bInLoadXML)
2✔
723
        return GDALPamRasterBand::SetColorTable(poNewCT);
×
724

725
    if (poNewCT == nullptr)
2✔
726
        return CE_Failure;
×
727

728
    std::vector<GByte> abyNITFLUT(768);
4✔
729

730
    const int nCount = std::min(256, poNewCT->GetColorEntryCount());
2✔
731
    for (int i = 0; i < nCount; i++)
135✔
732
    {
733
        GDALColorEntry sEntry;
734

735
        poNewCT->GetColorEntryAsRGB(i, &sEntry);
133✔
736
        abyNITFLUT[i + 256 * 0] = static_cast<GByte>(sEntry.c1);
133✔
737
        abyNITFLUT[i + 256 * 1] = static_cast<GByte>(sEntry.c2);
133✔
738
        abyNITFLUT[i + 256 * 2] = static_cast<GByte>(sEntry.c3);
133✔
739
    }
740

741
    if (NITFWriteLUT(psImage, nBand, nCount, abyNITFLUT.data()))
2✔
742
        return CE_None;
2✔
743

744
    return CE_Failure;
×
745
}
746

747
/************************************************************************/
748
/*                           Unpack()                                   */
749
/************************************************************************/
750

751
void NITFRasterBand::Unpack(GByte *pData)
68✔
752
{
753
    const int n = nBlockXSize * nBlockYSize;
68✔
754

755
    GByte abyTempData[7] = {0, 0, 0, 0, 0, 0, 0};
68✔
756
    const GByte *pDataSrc = pData;
68✔
757
    if (n < psImage->nBitsPerSample && psImage->nBitsPerSample < 8)
68✔
758
    {
759
        memcpy(abyTempData, pData, n);
21✔
760
        pDataSrc = abyTempData;
21✔
761
    }
762

763
    switch (psImage->nBitsPerSample)
68✔
764
    {
765
        case 1:
12✔
766
        {
767
            // unpack 1-bit in-place in reverse
768
            // DANGER: Non-standard decrement of counter in the test section of
769
            // for.
770
            for (int i = n; --i >= 0;)
1,050,510✔
771
                pData[i] = (pData[i >> 3] & (0x80 >> (i & 7))) != 0;
1,050,500✔
772

773
            break;
12✔
774
        }
775
        case 2:
8✔
776
        {
777
            constexpr int s_Shift2[] = {6, 4, 2, 0};
8✔
778
            // unpack 2-bit in-place in reverse
779
            // DANGER: Non-standard decrement of counter in the test section of
780
            // for.
781
            for (int i = n; --i >= 0;)
44✔
782
                pData[i] =
36✔
783
                    (pData[i >> 2] >> static_cast<GByte>(s_Shift2[i & 3])) &
36✔
784
                    0x03;
785

786
            break;
8✔
787
        }
788
        case 4:
8✔
789
        {
790
            constexpr int s_Shift4[] = {4, 0};
8✔
791
            // unpack 4-bit in-place in reverse
792
            // DANGER: Non-standard decrement of counter in the test section of
793
            // for.
794
            for (int i = n; --i >= 0;)
44✔
795
                pData[i] =
36✔
796
                    (pData[i >> 1] >> static_cast<GByte>(s_Shift4[i & 1])) &
36✔
797
                    0x0f;
798

799
            break;
8✔
800
        }
801
        case 3:
8✔
802
        {
803
            // unpacks 8 pixels (3 bytes) at time
804
            int i = 0;
8✔
805
            int k = 0;
8✔
806
            for (; i + 7 < n; i += 8, k += 3)
9✔
807
            {
808
                pUnpackData[i + 0] = ((pDataSrc[k + 0] >> 5));
1✔
809
                pUnpackData[i + 1] = ((pDataSrc[k + 0] >> 2) & 0x07);
1✔
810
                pUnpackData[i + 2] =
1✔
811
                    ((pDataSrc[k + 0] << 1) & 0x07) | (pDataSrc[k + 1] >> 7);
1✔
812
                pUnpackData[i + 3] = ((pDataSrc[k + 1] >> 4) & 0x07);
1✔
813
                pUnpackData[i + 4] = ((pDataSrc[k + 1] >> 1) & 0x07);
1✔
814
                pUnpackData[i + 5] =
1✔
815
                    ((pDataSrc[k + 1] << 2) & 0x07) | (pDataSrc[k + 2] >> 6);
1✔
816
                pUnpackData[i + 6] = ((pDataSrc[k + 2] >> 3) & 0x07);
1✔
817
                pUnpackData[i + 7] = ((pDataSrc[k + 2]) & 0x7);
1✔
818
            }
819
            if (i < n)
8✔
820
            {
821
                pUnpackData[i + 0] = ((pDataSrc[k + 0] >> 5));
7✔
822
                if (i + 1 < n)
7✔
823
                    pUnpackData[i + 1] = ((pDataSrc[k + 0] >> 2) & 0x07);
6✔
824
                if (i + 2 < n)
7✔
825
                    pUnpackData[i + 2] = ((pDataSrc[k + 0] << 1) & 0x07) |
5✔
826
                                         (pDataSrc[k + 1] >> 7);
5✔
827
                if (i + 3 < n)
7✔
828
                    pUnpackData[i + 3] = ((pDataSrc[k + 1] >> 4) & 0x07);
4✔
829
                if (i + 4 < n)
7✔
830
                    pUnpackData[i + 4] = ((pDataSrc[k + 1] >> 1) & 0x07);
3✔
831
                if (i + 5 < n)
7✔
832
                    pUnpackData[i + 5] = ((pDataSrc[k + 1] << 2) & 0x07) |
2✔
833
                                         (pDataSrc[k + 2] >> 6);
2✔
834
                if (i + 6 < n)
7✔
835
                    pUnpackData[i + 6] = ((pDataSrc[k + 2] >> 3) & 0x07);
1✔
836
            }
837

838
            memcpy(pData, pUnpackData, n);
8✔
839
            break;
8✔
840
        }
841
        case 5:
8✔
842
        {
843
            // unpacks 8 pixels (5 bytes) at time
844
            int i = 0;
8✔
845
            int k = 0;
8✔
846
            for (; i + 7 < n; i += 8, k += 5)
9✔
847
            {
848
                pUnpackData[i + 0] = ((pDataSrc[k + 0] >> 3));
1✔
849
                pUnpackData[i + 1] =
1✔
850
                    ((pDataSrc[k + 0] << 2) & 0x1f) | (pDataSrc[k + 1] >> 6);
1✔
851
                pUnpackData[i + 2] = ((pDataSrc[k + 1] >> 1) & 0x1f);
1✔
852
                pUnpackData[i + 3] =
1✔
853
                    ((pDataSrc[k + 1] << 4) & 0x1f) | (pDataSrc[k + 2] >> 4);
1✔
854
                pUnpackData[i + 4] =
1✔
855
                    ((pDataSrc[k + 2] << 1) & 0x1f) | (pDataSrc[k + 3] >> 7);
1✔
856
                pUnpackData[i + 5] = ((pDataSrc[k + 3] >> 2) & 0x1f);
1✔
857
                pUnpackData[i + 6] =
1✔
858
                    ((pDataSrc[k + 3] << 3) & 0x1f) | (pDataSrc[k + 4] >> 5);
1✔
859
                pUnpackData[i + 7] = ((pDataSrc[k + 4]) & 0x1f);
1✔
860
            }
861
            if (i < n)
8✔
862
            {
863
                pUnpackData[i + 0] = ((pDataSrc[k + 0] >> 3));
7✔
864
                if (i + 1 < n)
7✔
865
                    pUnpackData[i + 1] = ((pDataSrc[k + 0] << 2) & 0x1f) |
6✔
866
                                         (pDataSrc[k + 1] >> 6);
6✔
867
                if (i + 2 < n)
7✔
868
                    pUnpackData[i + 2] = ((pDataSrc[k + 1] >> 1) & 0x1f);
5✔
869
                if (i + 3 < n)
7✔
870
                    pUnpackData[i + 3] = ((pDataSrc[k + 1] << 4) & 0x1f) |
4✔
871
                                         (pDataSrc[k + 2] >> 4);
4✔
872
                if (i + 4 < n)
7✔
873
                    pUnpackData[i + 4] = ((pDataSrc[k + 2] << 1) & 0x1f) |
3✔
874
                                         (pDataSrc[k + 3] >> 7);
3✔
875
                if (i + 5 < n)
7✔
876
                    pUnpackData[i + 5] = ((pDataSrc[k + 3] >> 2) & 0x1f);
2✔
877
                if (i + 6 < n)
7✔
878
                    pUnpackData[i + 6] = ((pDataSrc[k + 3] << 3) & 0x1f) |
1✔
879
                                         (pDataSrc[k + 4] >> 5);
1✔
880
            }
881

882
            memcpy(pData, pUnpackData, n);
8✔
883
            break;
8✔
884
        }
885
        case 6:
8✔
886
        {
887
            // unpacks 4 pixels (3 bytes) at time
888
            int i = 0;
8✔
889
            int k = 0;
8✔
890
            for (; i + 3 < n; i += 4, k += 3)
14✔
891
            {
892
                pUnpackData[i + 0] = ((pDataSrc[k + 0] >> 2));
6✔
893
                pUnpackData[i + 1] =
6✔
894
                    ((pDataSrc[k + 0] << 4) & 0x3f) | (pDataSrc[k + 1] >> 4);
6✔
895
                pUnpackData[i + 2] =
6✔
896
                    ((pDataSrc[k + 1] << 2) & 0x3f) | (pDataSrc[k + 2] >> 6);
6✔
897
                pUnpackData[i + 3] = ((pDataSrc[k + 2]) & 0x3f);
6✔
898
            }
899
            if (i < n)
8✔
900
            {
901
                pUnpackData[i + 0] = ((pDataSrc[k + 0] >> 2));
6✔
902
                if (i + 1 < n)
6✔
903
                    pUnpackData[i + 1] = ((pDataSrc[k + 0] << 4) & 0x3f) |
4✔
904
                                         (pDataSrc[k + 1] >> 4);
4✔
905
                if (i + 2 < n)
6✔
906
                    pUnpackData[i + 2] = ((pDataSrc[k + 1] << 2) & 0x3f) |
2✔
907
                                         (pDataSrc[k + 2] >> 6);
2✔
908
            }
909

910
            memcpy(pData, pUnpackData, n);
8✔
911
            break;
8✔
912
        }
913
        case 7:
8✔
914
        {
915
            // unpacks 8 pixels (7 bytes) at time
916
            int i = 0;
8✔
917
            int k = 0;
8✔
918
            for (; i + 7 < n; i += 8, k += 7)
9✔
919
            {
920
                pUnpackData[i + 0] = ((pDataSrc[k + 0] >> 1));
1✔
921
                pUnpackData[i + 1] =
1✔
922
                    ((pDataSrc[k + 0] << 6) & 0x7f) | (pDataSrc[k + 1] >> 2);
1✔
923
                pUnpackData[i + 2] =
1✔
924
                    ((pDataSrc[k + 1] << 5) & 0x7f) | (pDataSrc[k + 2] >> 3);
1✔
925
                pUnpackData[i + 3] =
1✔
926
                    ((pDataSrc[k + 2] << 4) & 0x7f) | (pDataSrc[k + 3] >> 4);
1✔
927
                pUnpackData[i + 4] =
1✔
928
                    ((pDataSrc[k + 3] << 3) & 0x7f) | (pDataSrc[k + 4] >> 5);
1✔
929
                pUnpackData[i + 5] =
1✔
930
                    ((pDataSrc[k + 4] << 2) & 0x7f) | (pDataSrc[k + 5] >> 6);
1✔
931
                pUnpackData[i + 6] =
1✔
932
                    ((pDataSrc[k + 5] << 1) & 0x7f) | (pDataSrc[k + 6] >> 7);
1✔
933
                pUnpackData[i + 7] = ((pDataSrc[k + 6]) & 0x7f);
1✔
934
            }
935
            if (i < n)
8✔
936
            {
937
                pUnpackData[i + 0] = ((pDataSrc[k + 0] >> 1));
7✔
938
                if (i + 1 < n)
7✔
939
                    pUnpackData[i + 1] = ((pDataSrc[k + 0] << 6) & 0x7f) |
6✔
940
                                         (pDataSrc[k + 1] >> 2);
6✔
941
                if (i + 2 < n)
7✔
942
                    pUnpackData[i + 2] = ((pDataSrc[k + 1] << 5) & 0x7f) |
5✔
943
                                         (pDataSrc[k + 2] >> 3);
5✔
944
                if (i + 3 < n)
7✔
945
                    pUnpackData[i + 3] = ((pDataSrc[k + 2] << 4) & 0x7f) |
4✔
946
                                         (pDataSrc[k + 3] >> 4);
4✔
947
                if (i + 4 < n)
7✔
948
                    pUnpackData[i + 4] = ((pDataSrc[k + 3] << 3) & 0x7f) |
3✔
949
                                         (pDataSrc[k + 4] >> 5);
3✔
950
                if (i + 5 < n)
7✔
951
                    pUnpackData[i + 5] = ((pDataSrc[k + 4] << 2) & 0x7f) |
2✔
952
                                         (pDataSrc[k + 5] >> 6);
2✔
953
                if (i + 6 < n)
7✔
954
                    pUnpackData[i + 6] = ((pDataSrc[k + 5] << 1) & 0x7f) |
1✔
955
                                         (pDataSrc[k + 6] >> 7);
1✔
956
            }
957

958
            memcpy(pData, pUnpackData, n);
8✔
959
            break;
8✔
960
        }
961
        case 12:
8✔
962
        {
963
            GByte *pabyImage = reinterpret_cast<GByte *>(pData);
8✔
964
            GUInt16 *panImage = reinterpret_cast<GUInt16 *>(pData);
8✔
965
            // DANGER: Non-standard decrement of counter in the test section of
966
            // for.
967
            for (int i = n; --i >= 0;)
44✔
968
            {
969
                const long iOffset = i * 3 / 2;
36✔
970
                if (i % 2 == 0)
36✔
971
                    panImage[i] = pabyImage[iOffset] +
20✔
972
                                  (pabyImage[iOffset + 1] & 0xf0) * 16;
20✔
973
                else
974
                    panImage[i] = (pabyImage[iOffset] & 0x0f) * 16 +
16✔
975
                                  (pabyImage[iOffset + 1] & 0xf0) / 16 +
16✔
976
                                  (pabyImage[iOffset + 1] & 0x0f) * 256;
16✔
977
            }
978

979
            break;
8✔
980
        }
981
    }
982
}
68✔
983

984
/************************************************************************/
985
/* ==================================================================== */
986
/*                       NITFWrapperRasterBand                          */
987
/* ==================================================================== */
988
/************************************************************************/
989

990
/************************************************************************/
991
/*                      NITFWrapperRasterBand()                         */
992
/************************************************************************/
993

994
NITFWrapperRasterBand::NITFWrapperRasterBand(NITFDataset *poDSIn,
107✔
995
                                             GDALRasterBand *poBaseBandIn,
996
                                             int nBandIn)
107✔
997
    : poBaseBand(poBaseBandIn), eInterp(poBaseBandIn->GetColorInterpretation()),
214✔
998
      bIsJPEG(poBaseBandIn->GetDataset() != nullptr &&
321✔
999
              poBaseBandIn->GetDataset()->GetDriver() != nullptr &&
214✔
1000
              EQUAL(poBaseBandIn->GetDataset()->GetDriver()->GetDescription(),
107✔
1001
                    "JPEG"))
107✔
1002
{
1003
    poDS = poDSIn;
107✔
1004
    nBand = nBandIn;
107✔
1005
    poBaseBand->GetBlockSize(&nBlockXSize, &nBlockYSize);
107✔
1006
    eDataType = poBaseBandIn->GetRasterDataType();
107✔
1007
}
107✔
1008

1009
/************************************************************************/
1010
/*                      ~NITFWrapperRasterBand()                        */
1011
/************************************************************************/
1012

1013
NITFWrapperRasterBand::~NITFWrapperRasterBand()
214✔
1014
{
1015
    if (poColorTable != nullptr)
107✔
1016
        delete poColorTable;
×
1017
}
214✔
1018

1019
/************************************************************************/
1020
/*                     RefUnderlyingRasterBand()                        */
1021
/************************************************************************/
1022

1023
/* We don't need ref-counting. Just return the base band */
1024
GDALRasterBand *NITFWrapperRasterBand::RefUnderlyingRasterBand()
574✔
1025
{
1026
    return poBaseBand;
574✔
1027
}
1028

1029
/************************************************************************/
1030
/*                            GetColorTable()                           */
1031
/************************************************************************/
1032

1033
GDALColorTable *NITFWrapperRasterBand::GetColorTable()
16✔
1034
{
1035
    return poColorTable;
16✔
1036
}
1037

1038
/************************************************************************/
1039
/*                 SetColorTableFromNITFBandInfo()                      */
1040
/************************************************************************/
1041

1042
void NITFWrapperRasterBand::SetColorTableFromNITFBandInfo()
×
1043
{
1044
    NITFDataset *poGDS = reinterpret_cast<NITFDataset *>(poDS);
×
1045
    poColorTable = NITFMakeColorTable(poGDS->psImage,
×
1046
                                      poGDS->psImage->pasBandInfo + nBand - 1);
×
1047
}
×
1048

1049
/************************************************************************/
1050
/*                        GetColorInterpretation()                      */
1051
/************************************************************************/
1052

1053
GDALColorInterp NITFWrapperRasterBand::GetColorInterpretation()
60✔
1054
{
1055
    return eInterp;
60✔
1056
}
1057

1058
/************************************************************************/
1059
/*                        SetColorInterpretation()                      */
1060
/************************************************************************/
1061

1062
CPLErr NITFWrapperRasterBand::SetColorInterpretation(GDALColorInterp eInterpIn)
108✔
1063
{
1064
    this->eInterp = eInterpIn;
108✔
1065
    if (poBaseBand->GetDataset() != nullptr &&
108✔
1066
        poBaseBand->GetDataset()->GetDriver() != nullptr &&
216✔
1067
        EQUAL(poBaseBand->GetDataset()->GetDriver()->GetDescription(),
108✔
1068
              "JP2ECW"))
1069
        poBaseBand->SetColorInterpretation(eInterp);
19✔
1070
    return CE_None;
108✔
1071
}
1072

1073
/************************************************************************/
1074
/*                          GetOverviewCount()                          */
1075
/************************************************************************/
1076

1077
int NITFWrapperRasterBand::GetOverviewCount()
6✔
1078
{
1079
    if (bIsJPEG)
6✔
1080
    {
1081
        if ((reinterpret_cast<NITFDataset *>(poDS))
4✔
1082
                ->ExposeUnderlyingJPEGDatasetOverviews())
2✔
1083
            return NITFProxyPamRasterBand::GetOverviewCount();
×
1084

1085
        return GDALPamRasterBand::GetOverviewCount();
2✔
1086
    }
1087

1088
    return NITFProxyPamRasterBand::GetOverviewCount();
4✔
1089
}
1090

1091
/************************************************************************/
1092
/*                             GetOverview()                            */
1093
/************************************************************************/
1094

1095
GDALRasterBand *NITFWrapperRasterBand::GetOverview(int iOverview)
3✔
1096
{
1097
    if (bIsJPEG)
3✔
1098
    {
1099
        if ((reinterpret_cast<NITFDataset *>(poDS))
2✔
1100
                ->ExposeUnderlyingJPEGDatasetOverviews())
1✔
1101
            return NITFProxyPamRasterBand::GetOverview(iOverview);
×
1102

1103
        return GDALPamRasterBand::GetOverview(iOverview);
1✔
1104
    }
1105

1106
    return NITFProxyPamRasterBand::GetOverview(iOverview);
2✔
1107
}
1108

1109
/************************************************************************/
1110
/*                      NITFComplexRasterBand()                         */
1111
/************************************************************************/
1112

1113
NITFComplexRasterBand::NITFComplexRasterBand(NITFDataset *poDSIn,
5✔
1114
                                             GDALRasterBand *poBandI,
1115
                                             GDALRasterBand *poBandQ,
1116
                                             int nIBand, int nQBand)
5✔
1117
    : NITFRasterBand(poDSIn, nIBand)
5✔
1118
{
1119

1120
    CPLAssert(poBandI->GetRasterDataType() == poBandQ->GetRasterDataType());
5✔
1121
    underlyingDataType = poBandI->GetRasterDataType();
5✔
1122

1123
    //add the I and Q bands to an intermediate dataset
1124
    poIntermediateDS = std::make_unique<NITFDataset>();
5✔
1125
    poIntermediateDS->nRasterXSize = poDSIn->nRasterXSize;
5✔
1126
    poIntermediateDS->nRasterYSize = poDSIn->nRasterYSize;
5✔
1127
    poIntermediateDS->eAccess = poDSIn->eAccess;
5✔
1128

1129
    poIntermediateDS->SetBand(nIBand, poBandI);
5✔
1130
    poIntermediateDS->SetBand(nQBand, poBandQ);
5✔
1131

1132
    anBandMap[0] = nIBand;
5✔
1133
    anBandMap[1] = nQBand;
5✔
1134

1135
    //set the new datatype
1136
    switch (underlyingDataType)
5✔
1137
    {
1138
        case GDT_Int16:
×
1139
            eDataType = GDT_CInt16;
×
1140
            break;
×
1141
        case GDT_Int32:
×
1142
            eDataType = GDT_CInt32;
×
1143
            break;
×
1144
        case GDT_Float32:
5✔
1145
            eDataType = GDT_CFloat32;
5✔
1146
            break;
5✔
1147
        case GDT_Float64:
×
1148
            eDataType = GDT_CFloat64;
×
1149
            break;
×
1150
        default:
×
1151
            eDataType = GDT_Unknown;
×
1152
            CPLError(CE_Failure, CPLE_NotSupported,
×
1153
                     "Unsupported complex datatype");
1154
            break;
×
1155
    }
1156

1157
    complexDataTypeSize = GDALGetDataTypeSizeBytes(eDataType);
5✔
1158
    underlyingDataTypeSize = GDALGetDataTypeSizeBytes(underlyingDataType);
5✔
1159
    CPLAssert(underlyingDataTypeSize * 2 == complexDataTypeSize);
5✔
1160

1161
    poBandI->GetBlockSize(&nBlockXSize, &nBlockYSize);
5✔
1162
}
5✔
1163

1164
/************************************************************************/
1165
/*                             IReadBlock()                             */
1166
/************************************************************************/
1167

1168
CPLErr NITFComplexRasterBand::IBlockIO(int nBlockXOff, int nBlockYOff,
40✔
1169
                                       void *pImage, GDALRWFlag rwFlag)
1170

1171
{
1172
    int nRequestYSize;
1173
    int nRequestXSize;
1174
    bool bMemset = false;
40✔
1175

1176
    /* -------------------------------------------------------------------- */
1177
    /*      If the last strip is partial, we need to avoid                  */
1178
    /*      over-requesting.  We also need to initialize the extra part     */
1179
    /*      of the block to zero.                                           */
1180
    /* -------------------------------------------------------------------- */
1181
    if ((nBlockYOff + 1) * nBlockYSize > nRasterYSize)
40✔
1182
    {
1183
        nRequestYSize = nRasterYSize - nBlockYOff * nBlockYSize;
×
1184
        if (rwFlag == GF_Read)
×
1185
            bMemset = true;
×
1186
    }
1187
    else
1188
    {
1189
        nRequestYSize = nBlockYSize;
40✔
1190
    }
1191

1192
    /*-------------------------------------------------------------------- */
1193
    /*      If the input imagery is tiled, also need to avoid over-        */
1194
    /*      requesting in the X-direction.                                 */
1195
    /* ------------------------------------------------------------------- */
1196
    if ((nBlockXOff + 1) * nBlockXSize > nRasterXSize)
40✔
1197
    {
1198
        nRequestXSize = nRasterXSize - nBlockXOff * nBlockXSize;
×
1199
        if (rwFlag == GF_Read)
×
1200
            bMemset = true;
×
1201
    }
1202
    else
1203
    {
1204
        nRequestXSize = nBlockXSize;
40✔
1205
    }
1206

1207
    if (bMemset)
40✔
1208
    {
1209
        memset(pImage, 0,
×
1210
               static_cast<size_t>(GDALGetDataTypeSizeBytes(eDataType)) *
×
1211
                   nBlockXSize * nBlockYSize);
×
1212
    }
1213

1214
    //read/write both bands with interleaved pixels
1215
    return poIntermediateDS->RasterIO(
40✔
1216
        rwFlag, nBlockXOff * nBlockXSize, nBlockYOff * nBlockYSize,
40✔
1217
        nRequestXSize, nRequestYSize, pImage, nRequestXSize, nRequestYSize,
1218
        underlyingDataType, 2, &anBandMap[0], complexDataTypeSize,
40✔
1219
        static_cast<GSpacing>(complexDataTypeSize) * nBlockXSize,
40✔
1220
        underlyingDataTypeSize, nullptr);
80✔
1221
}
1222

1223
/************************************************************************/
1224
/*                             IReadBlock()                             */
1225
/************************************************************************/
1226

1227
CPLErr NITFComplexRasterBand::IReadBlock(int nBlockXOff, int nBlockYOff,
40✔
1228
                                         void *pImage)
1229

1230
{
1231
    return IBlockIO(nBlockXOff, nBlockYOff, pImage, GF_Read);
40✔
1232
}
1233

1234
/************************************************************************/
1235
/*                            IWriteBlock()                             */
1236
/************************************************************************/
1237

1238
CPLErr NITFComplexRasterBand::IWriteBlock(int nBlockXOff, int nBlockYOff,
×
1239
                                          void *pImage)
1240

1241
{
1242
    return IBlockIO(nBlockXOff, nBlockYOff, pImage, GF_Write);
×
1243
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc