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

OSGeo / gdal / 13813968540

12 Mar 2025 02:33PM UTC coverage: 70.43% (-0.02%) from 70.446%
13813968540

Pull #11951

github

web-flow
Merge 0560ed8f8 into 5ab779ac6
Pull Request #11951: Doc: Build docs using CMake

553276 of 785573 relevant lines covered (70.43%)

222076.27 hits per line

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

81.2
/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,942✔
45
                                          NITFBandInfo *psBandInfo)
46
{
47
    GDALColorTable *poColorTable = nullptr;
210,942✔
48

49
    if (psBandInfo->nSignificantLUTEntries > 0)
210,942✔
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,942✔
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,942✔
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,942✔
370
    : psImage(poDSIn->psImage), poColorTable(nullptr), pUnpackData(nullptr),
210,942✔
371
      bScanlineAccess(FALSE)
210,942✔
372
{
373
    NITFBandInfo *psBandInfo = poDSIn->psImage->pasBandInfo + nBandIn - 1;
210,942✔
374

375
    poDS = poDSIn;
210,942✔
376
    nBand = nBandIn;
210,942✔
377
    eAccess = poDSIn->eAccess;
210,942✔
378

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

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

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

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

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

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

474
NITFRasterBand::~NITFRasterBand()
421,879✔
475

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

480
    VSIFree(pUnpackData);
210,942✔
481
}
421,879✔
482

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

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

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

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

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

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

508
        return eErr;
128✔
509
    }
510

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

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

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

531
        return CE_None;
18,071✔
532
    }
533

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

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

551
    return CE_None;
432✔
552
}
553

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

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

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

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

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

579
    return CE_Failure;
×
580
}
581

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

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

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

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

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

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

602
GDALColorInterp NITFRasterBand::GetColorInterpretation()
157✔
603

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

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

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

625
    return GCI_Undefined;
×
626
}
627

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

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

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

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

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

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

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

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

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

692
    return CE_None;
33✔
693
}
694

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

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

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

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

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

711
{
712
    return poColorTable;
54✔
713
}
714

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

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

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

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

729
    GByte abyNITFLUT[768];
730
    memset(abyNITFLUT, 0, 768);
2✔
731

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

737
        poNewCT->GetColorEntryAsRGB(i, &sEntry);
133✔
738
        abyNITFLUT[i] = (GByte)sEntry.c1;
133✔
739
        abyNITFLUT[i + 256] = (GByte)sEntry.c2;
133✔
740
        abyNITFLUT[i + 512] = (GByte)sEntry.c3;
133✔
741
    }
742

743
    if (NITFWriteLUT(psImage, nBand, nCount, abyNITFLUT))
2✔
744
        return CE_None;
2✔
745

746
    return CE_Failure;
×
747
}
748

749
/************************************************************************/
750
/*                           Unpack()                                   */
751
/************************************************************************/
752

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

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

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

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

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

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

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

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

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

977
            break;
8✔
978
        }
979
    }
980
}
68✔
981

982
/************************************************************************/
983
/* ==================================================================== */
984
/*                       NITFWrapperRasterBand                          */
985
/* ==================================================================== */
986
/************************************************************************/
987

988
/************************************************************************/
989
/*                      NITFWrapperRasterBand()                         */
990
/************************************************************************/
991

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

1240
{
1241
    return IBlockIO(nBlockXOff, nBlockYOff, pImage, GF_Write);
×
1242
}
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