Line data Source code
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 : #include <algorithm>
23 : #include <map>
24 : #include <utility>
25 :
26 : #include "cpl_conv.h"
27 : #include "cpl_csv.h"
28 : #include "cpl_error.h"
29 : #include "cpl_progress.h"
30 : #include "cpl_string.h"
31 : #include "cpl_vsi.h"
32 : #include "gdal.h"
33 : #include "gdal_pam.h"
34 : #include "gdal_priv.h"
35 : #include "nitflib.h"
36 :
37 : /************************************************************************/
38 : /* NITFMakeColorTable() */
39 : /************************************************************************/
40 :
41 140943 : static GDALColorTable *NITFMakeColorTable(NITFImage *psImage,
42 : NITFBandInfo *psBandInfo)
43 : {
44 140943 : GDALColorTable *poColorTable = nullptr;
45 :
46 140943 : if (psBandInfo->nSignificantLUTEntries > 0)
47 : {
48 162 : poColorTable = new GDALColorTable();
49 :
50 34050 : for (int iColor = 0; iColor < psBandInfo->nSignificantLUTEntries;
51 : iColor++)
52 : {
53 : GDALColorEntry sEntry;
54 33888 : sEntry.c1 = psBandInfo->pabyLUT[0 + iColor];
55 33888 : sEntry.c2 = psBandInfo->pabyLUT[256 + iColor];
56 33888 : sEntry.c3 = psBandInfo->pabyLUT[512 + iColor];
57 33888 : sEntry.c4 = 255;
58 :
59 33888 : poColorTable->SetColorEntry(iColor, &sEntry);
60 : }
61 :
62 162 : if (psImage->bNoDataSet)
63 : {
64 138 : GDALColorEntry sEntry = {0, 0, 0, 0};
65 138 : poColorTable->SetColorEntry(psImage->nNoDataValue, &sEntry);
66 : }
67 : }
68 :
69 : /* -------------------------------------------------------------------- */
70 : /* We create a color table for 1 bit data too... */
71 : /* -------------------------------------------------------------------- */
72 140943 : if (poColorTable == nullptr && psImage->nBitsPerSample == 1)
73 : {
74 11 : poColorTable = new GDALColorTable();
75 :
76 : GDALColorEntry sEntry;
77 11 : sEntry.c1 = 0;
78 11 : sEntry.c2 = 0;
79 11 : sEntry.c3 = 0;
80 11 : sEntry.c4 = 255;
81 11 : poColorTable->SetColorEntry(0, &sEntry);
82 :
83 11 : sEntry.c1 = 255;
84 11 : sEntry.c2 = 255;
85 11 : sEntry.c3 = 255;
86 11 : sEntry.c4 = 255;
87 11 : poColorTable->SetColorEntry(1, &sEntry);
88 : }
89 :
90 140943 : return poColorTable;
91 : }
92 :
93 : /************************************************************************/
94 : /* ==================================================================== */
95 : /* NITFProxyPamRasterBand */
96 : /* ==================================================================== */
97 : /************************************************************************/
98 :
99 99 : NITFProxyPamRasterBand::~NITFProxyPamRasterBand()
100 : {
101 99 : std::map<CPLString, char **>::iterator oIter = oMDMap.begin();
102 104 : while (oIter != oMDMap.end())
103 : {
104 5 : CSLDestroy(oIter->second);
105 5 : ++oIter;
106 : }
107 99 : }
108 :
109 6 : CSLConstList NITFProxyPamRasterBand::GetMetadata(const char *pszDomain)
110 : {
111 6 : GDALRasterBand *_poSrcBand = RefUnderlyingRasterBand();
112 6 : if (_poSrcBand)
113 : {
114 : /* Let's merge metadata of PAM and the underlying band */
115 : /* PAM metadata should override underlying band metadata */
116 6 : char **papszMD = CSLDuplicate(_poSrcBand->GetMetadata(pszDomain));
117 6 : papszMD = CSLMerge(papszMD, GDALPamRasterBand::GetMetadata(pszDomain));
118 :
119 6 : if (pszDomain == nullptr)
120 0 : pszDomain = "";
121 :
122 6 : std::map<CPLString, char **>::iterator oIter = oMDMap.find(pszDomain);
123 6 : if (oIter != oMDMap.end())
124 1 : CSLDestroy(oIter->second);
125 6 : oMDMap[pszDomain] = papszMD;
126 6 : UnrefUnderlyingRasterBand(_poSrcBand);
127 :
128 6 : return papszMD;
129 : }
130 :
131 0 : return GDALPamRasterBand::GetMetadata(pszDomain);
132 : }
133 :
134 11 : const char *NITFProxyPamRasterBand::GetMetadataItem(const char *pszName,
135 : const char *pszDomain)
136 : {
137 11 : const char *pszRet = GDALPamRasterBand::GetMetadataItem(pszName, pszDomain);
138 11 : if (pszRet)
139 0 : return pszRet;
140 :
141 11 : GDALRasterBand *_poSrcBand = RefUnderlyingRasterBand();
142 11 : if (_poSrcBand)
143 : {
144 11 : if (!m_bEnablePixelTypeSignedByteWarning)
145 0 : _poSrcBand->EnablePixelTypeSignedByteWarning(false);
146 11 : pszRet = _poSrcBand->GetMetadataItem(pszName, pszDomain);
147 11 : _poSrcBand->EnablePixelTypeSignedByteWarning(true);
148 11 : UnrefUnderlyingRasterBand(_poSrcBand);
149 : }
150 :
151 11 : return pszRet;
152 : }
153 :
154 2 : CPLErr NITFProxyPamRasterBand::GetStatistics(int bApproxOK, int bForce,
155 : double *pdfMin, double *pdfMax,
156 : double *pdfMean, double *pdfStdDev)
157 : {
158 : /* -------------------------------------------------------------------- */
159 : /* Do we already have metadata items for the requested values? */
160 : /* -------------------------------------------------------------------- */
161 4 : if ((pdfMin == nullptr ||
162 2 : GetMetadataItem("STATISTICS_MINIMUM") != nullptr) &&
163 0 : (pdfMax == nullptr ||
164 0 : GetMetadataItem("STATISTICS_MAXIMUM") != nullptr) &&
165 4 : (pdfMean == nullptr || GetMetadataItem("STATISTICS_MEAN") != nullptr) &&
166 0 : (pdfStdDev == nullptr ||
167 0 : GetMetadataItem("STATISTICS_STDDEV") != nullptr))
168 : {
169 0 : return GDALPamRasterBand::GetStatistics(bApproxOK, bForce, pdfMin,
170 0 : pdfMax, pdfMean, pdfStdDev);
171 : }
172 :
173 2 : GDALRasterBand *_poSrcBand = RefUnderlyingRasterBand();
174 2 : if (_poSrcBand)
175 : {
176 4 : CPLErr ret = _poSrcBand->GetStatistics(bApproxOK, bForce, pdfMin,
177 2 : pdfMax, pdfMean, pdfStdDev);
178 2 : if (ret == CE_None)
179 : {
180 : /* Report underlying statistics at PAM level */
181 2 : SetMetadataItem("STATISTICS_MINIMUM",
182 2 : _poSrcBand->GetMetadataItem("STATISTICS_MINIMUM"));
183 2 : SetMetadataItem("STATISTICS_MAXIMUM",
184 2 : _poSrcBand->GetMetadataItem("STATISTICS_MAXIMUM"));
185 2 : SetMetadataItem("STATISTICS_MEAN",
186 2 : _poSrcBand->GetMetadataItem("STATISTICS_MEAN"));
187 2 : SetMetadataItem("STATISTICS_STDDEV",
188 2 : _poSrcBand->GetMetadataItem("STATISTICS_STDDEV"));
189 : }
190 2 : UnrefUnderlyingRasterBand(_poSrcBand);
191 2 : return ret;
192 : }
193 :
194 0 : return CE_Failure;
195 : }
196 :
197 0 : CPLErr NITFProxyPamRasterBand::ComputeStatistics(
198 : int bApproxOK, double *pdfMin, double *pdfMax, double *pdfMean,
199 : double *pdfStdDev, GDALProgressFunc pfn, void *pProgressData,
200 : CSLConstList papszOptions)
201 : {
202 0 : GDALRasterBand *_poSrcBand = RefUnderlyingRasterBand();
203 0 : if (_poSrcBand)
204 : {
205 : const bool bSetStatistics =
206 0 : CPLFetchBool(papszOptions, "SET_STATISTICS", true);
207 0 : CPLErr ret = _poSrcBand->ComputeStatistics(bApproxOK, pdfMin, pdfMax,
208 : pdfMean, pdfStdDev, pfn,
209 0 : pProgressData, papszOptions);
210 0 : if (ret == CE_None && bSetStatistics)
211 : {
212 : /* Report underlying statistics at PAM level */
213 0 : SetMetadataItem("STATISTICS_MINIMUM",
214 0 : _poSrcBand->GetMetadataItem("STATISTICS_MINIMUM"));
215 0 : SetMetadataItem("STATISTICS_MAXIMUM",
216 0 : _poSrcBand->GetMetadataItem("STATISTICS_MAXIMUM"));
217 0 : SetMetadataItem("STATISTICS_MEAN",
218 0 : _poSrcBand->GetMetadataItem("STATISTICS_MEAN"));
219 0 : SetMetadataItem("STATISTICS_STDDEV",
220 0 : _poSrcBand->GetMetadataItem("STATISTICS_STDDEV"));
221 : }
222 0 : UnrefUnderlyingRasterBand(_poSrcBand);
223 0 : return ret;
224 : }
225 :
226 0 : return CE_Failure;
227 : }
228 :
229 : #define RB_PROXY_METHOD_GET_DBL_WITH_SUCCESS(methodName) \
230 : double NITFProxyPamRasterBand::methodName(int *pbSuccess) \
231 : { \
232 : int bSuccess = FALSE; \
233 : double dfRet = GDALPamRasterBand::methodName(&bSuccess); \
234 : if (bSuccess) \
235 : { \
236 : if (pbSuccess) \
237 : *pbSuccess = TRUE; \
238 : return dfRet; \
239 : } \
240 : GDALRasterBand *_poSrcBand = RefUnderlyingRasterBand(); \
241 : if (_poSrcBand) \
242 : { \
243 : dfRet = _poSrcBand->methodName(pbSuccess); \
244 : UnrefUnderlyingRasterBand(_poSrcBand); \
245 : } \
246 : else \
247 : { \
248 : dfRet = 0; \
249 : } \
250 : return dfRet; \
251 : }
252 :
253 15 : RB_PROXY_METHOD_GET_DBL_WITH_SUCCESS(GetNoDataValue)
254 0 : RB_PROXY_METHOD_GET_DBL_WITH_SUCCESS(GetMinimum)
255 0 : RB_PROXY_METHOD_GET_DBL_WITH_SUCCESS(GetMaximum)
256 :
257 : #define RB_PROXY_METHOD_WITH_RET_AND_CALL_OTHER_METHOD( \
258 : retType, retErrValue, methodName, underlyingMethodName, argList, \
259 : argParams) \
260 : retType NITFProxyPamRasterBand::methodName argList \
261 : { \
262 : retType ret; \
263 : GDALRasterBand *_poSrcBand = RefUnderlyingRasterBand(); \
264 : if (_poSrcBand) \
265 : { \
266 : ret = _poSrcBand->underlyingMethodName argParams; \
267 : UnrefUnderlyingRasterBand(_poSrcBand); \
268 : } \
269 : else \
270 : { \
271 : ret = retErrValue; \
272 : } \
273 : return ret; \
274 : }
275 :
276 0 : RB_PROXY_METHOD_WITH_RET_AND_CALL_OTHER_METHOD(CPLErr, CE_Failure, IReadBlock,
277 : ReadBlock,
278 : (int nXBlockOff, int nYBlockOff,
279 : void *pImage),
280 : (nXBlockOff, nYBlockOff, pImage))
281 0 : RB_PROXY_METHOD_WITH_RET_AND_CALL_OTHER_METHOD(CPLErr, CE_Failure, IWriteBlock,
282 : WriteBlock,
283 : (int nXBlockOff, int nYBlockOff,
284 : void *pImage),
285 : (nXBlockOff, nYBlockOff, pImage))
286 403 : RB_PROXY_METHOD_WITH_RET_AND_CALL_OTHER_METHOD(
287 : CPLErr, CE_Failure, IRasterIO, RasterIO,
288 : (GDALRWFlag eRWFlag, int nXOff, int nYOff, int nXSize, int nYSize,
289 : void *pData, int nBufXSize, int nBufYSize, GDALDataType eBufType,
290 : GSpacing nPixelSpace, GSpacing nLineSpace,
291 : GDALRasterIOExtraArg *psExtraArg),
292 : (eRWFlag, nXOff, nYOff, nXSize, nYSize, pData, nBufXSize, nBufYSize,
293 : eBufType, nPixelSpace, nLineSpace, psExtraArg))
294 :
295 : #define RB_PROXY_METHOD_WITH_RET(retType, retErrValue, methodName, argList, \
296 : argParams) \
297 : retType NITFProxyPamRasterBand::methodName argList \
298 : { \
299 : retType ret; \
300 : GDALRasterBand *_poSrcBand = RefUnderlyingRasterBand(); \
301 : if (_poSrcBand) \
302 : { \
303 : ret = _poSrcBand->methodName argParams; \
304 : UnrefUnderlyingRasterBand(_poSrcBand); \
305 : } \
306 : else \
307 : { \
308 : ret = retErrValue; \
309 : } \
310 : return ret; \
311 : }
312 :
313 102 : RB_PROXY_METHOD_WITH_RET(CPLErr, CE_Failure, FlushCache, (bool bAtClosing),
314 : (bAtClosing))
315 :
316 0 : RB_PROXY_METHOD_WITH_RET(GDALColorInterp, GCI_Undefined, GetColorInterpretation,
317 : (), ())
318 0 : RB_PROXY_METHOD_WITH_RET(GDALColorTable *, nullptr, GetColorTable, (), ())
319 0 : RB_PROXY_METHOD_WITH_RET(CPLErr, CE_Failure, Fill,
320 : (double dfRealValue, double dfImaginaryValue),
321 : (dfRealValue, dfImaginaryValue))
322 :
323 1 : RB_PROXY_METHOD_WITH_RET(CPLErr, CE_Failure, ComputeRasterMinMax,
324 : (int arg1, double *arg2), (arg1, arg2))
325 :
326 0 : RB_PROXY_METHOD_WITH_RET(int, 0, HasArbitraryOverviews, (), ())
327 4 : RB_PROXY_METHOD_WITH_RET(int, 0, GetOverviewCount, (), ())
328 2 : RB_PROXY_METHOD_WITH_RET(GDALRasterBand *, nullptr, GetOverview, (int arg1),
329 : (arg1))
330 0 : RB_PROXY_METHOD_WITH_RET(GDALRasterBand *, nullptr, GetRasterSampleOverview,
331 : (GUIntBig arg1), (arg1))
332 :
333 0 : RB_PROXY_METHOD_WITH_RET(CPLErr, CE_Failure, BuildOverviews,
334 : (const char *arg1, int arg2, const int *arg3,
335 : GDALProgressFunc arg4, void *arg5,
336 : CSLConstList papszOptions),
337 : (arg1, arg2, arg3, arg4, arg5, papszOptions))
338 :
339 4 : RB_PROXY_METHOD_WITH_RET(CPLErr, CE_Failure, AdviseRead,
340 : (int nXOff, int nYOff, int nXSize, int nYSize,
341 : int nBufXSize, int nBufYSize, GDALDataType eDT,
342 : CSLConstList papszOptions),
343 : (nXOff, nYOff, nXSize, nYSize, nBufXSize, nBufYSize,
344 : eDT, papszOptions))
345 :
346 0 : RB_PROXY_METHOD_WITH_RET(GDALRasterBand *, nullptr, GetMaskBand, (), ())
347 22 : RB_PROXY_METHOD_WITH_RET(int, 0, GetMaskFlags, (), ())
348 0 : RB_PROXY_METHOD_WITH_RET(CPLErr, CE_Failure, CreateMaskBand, (int nFlagsIn),
349 : (nFlagsIn))
350 :
351 : /************************************************************************/
352 : /* UnrefUnderlyingRasterBand() */
353 : /************************************************************************/
354 :
355 572 : void NITFProxyPamRasterBand::UnrefUnderlyingRasterBand(
356 : CPL_UNUSED GDALRasterBand *poUnderlyingRasterBand)
357 : {
358 572 : }
359 :
360 : /************************************************************************/
361 : /* ==================================================================== */
362 : /* NITFRasterBand */
363 : /* ==================================================================== */
364 : /************************************************************************/
365 :
366 : /************************************************************************/
367 : /* NITFRasterBand() */
368 : /************************************************************************/
369 :
370 140943 : NITFRasterBand::NITFRasterBand(NITFDataset *poDSIn, int nBandIn)
371 140943 : : psImage(poDSIn->psImage)
372 : {
373 140943 : NITFBandInfo *psBandInfo = poDSIn->psImage->pasBandInfo + nBandIn - 1;
374 :
375 140943 : poDS = poDSIn;
376 140943 : nBand = nBandIn;
377 140943 : eAccess = poDSIn->eAccess;
378 :
379 : /* -------------------------------------------------------------------- */
380 : /* Translate data type(s). */
381 : /* -------------------------------------------------------------------- */
382 140943 : if (psImage->nBitsPerSample <= 8)
383 140816 : eDataType = GDT_UInt8;
384 127 : else if (psImage->nBitsPerSample == 16 && EQUAL(psImage->szPVType, "SI"))
385 24 : eDataType = GDT_Int16;
386 103 : else if (psImage->nBitsPerSample == 16)
387 20 : eDataType = GDT_UInt16;
388 83 : else if (psImage->nBitsPerSample == 12)
389 7 : eDataType = GDT_UInt16;
390 76 : else if (psImage->nBitsPerSample == 32 && EQUAL(psImage->szPVType, "SI"))
391 12 : eDataType = GDT_Int32;
392 64 : else if (psImage->nBitsPerSample == 32 && EQUAL(psImage->szPVType, "R"))
393 31 : eDataType = GDT_Float32;
394 33 : else if (psImage->nBitsPerSample == 32)
395 12 : eDataType = GDT_UInt32;
396 21 : else if (psImage->nBitsPerSample == 64 && EQUAL(psImage->szPVType, "R"))
397 12 : eDataType = GDT_Float64;
398 9 : else if (psImage->nBitsPerSample == 64 && EQUAL(psImage->szPVType, "C"))
399 9 : eDataType = GDT_CFloat32;
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 0 : CPLTestBool(CPLGetConfigOption("NITF_OPEN_UNDERLYING_DS", "YES"));
406 0 : if (!bOpenUnderlyingDS && psImage->nBitsPerSample > 8 &&
407 0 : psImage->nBitsPerSample < 16)
408 : {
409 0 : if (EQUAL(psImage->szPVType, "SI"))
410 0 : eDataType = GDT_Int16;
411 : else
412 0 : eDataType = GDT_UInt16;
413 : }
414 : else
415 : {
416 0 : eDataType = GDT_Unknown;
417 0 : CPLError(CE_Warning, CPLE_AppDefined,
418 : "Unsupported combination of PVTYPE(%s) and NBPP(%d).",
419 0 : 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 140943 : if (psImage->nBlocksPerRow == 1 && psImage->nBlocksPerColumn == 1 &&
428 140733 : psImage->nBitsPerSample >= 8 && EQUAL(psImage->szIC, "NC"))
429 : {
430 140676 : bScanlineAccess = TRUE;
431 140676 : nBlockXSize = psImage->nBlockWidth;
432 140676 : nBlockYSize = 1;
433 : }
434 : else
435 : {
436 267 : bScanlineAccess = FALSE;
437 267 : nBlockXSize = psImage->nBlockWidth;
438 267 : nBlockYSize = psImage->nBlockHeight;
439 : }
440 :
441 : /* -------------------------------------------------------------------- */
442 : /* Do we have a color table? */
443 : /* -------------------------------------------------------------------- */
444 140943 : poColorTable = NITFMakeColorTable(psImage, psBandInfo);
445 :
446 140943 : if (psImage->nABPP != 8 && psImage->nABPP != 16 && psImage->nABPP != 32 &&
447 31 : psImage->nABPP != 64)
448 : {
449 10 : SetMetadataItem(GDALMD_NBITS, CPLString().Printf("%d", psImage->nABPP),
450 : GDAL_MDD_IMAGE_STRUCTURE);
451 : }
452 :
453 140943 : if (psImage->nBitsPerSample == 3 || psImage->nBitsPerSample == 5 ||
454 140929 : psImage->nBitsPerSample == 6 || psImage->nBitsPerSample == 7)
455 : {
456 28 : if (nBlockXSize > (INT_MAX - 7) / nBlockYSize)
457 : {
458 0 : eDataType = GDT_Unknown;
459 : }
460 : else
461 : {
462 28 : pUnpackData = static_cast<GByte *>(
463 28 : VSI_MALLOC_VERBOSE(((nBlockXSize * nBlockYSize + 7) / 8) * 8));
464 28 : if (pUnpackData == nullptr)
465 0 : eDataType = GDT_Unknown;
466 : }
467 : }
468 140943 : }
469 :
470 : /************************************************************************/
471 : /* ~NITFRasterBand() */
472 : /************************************************************************/
473 :
474 281881 : NITFRasterBand::~NITFRasterBand()
475 :
476 : {
477 140943 : if (poColorTable != nullptr)
478 173 : delete poColorTable;
479 :
480 140943 : VSIFree(pUnpackData);
481 281881 : }
482 :
483 : /************************************************************************/
484 : /* IReadBlock() */
485 : /************************************************************************/
486 :
487 20124 : CPLErr NITFRasterBand::IReadBlock(int nBlockXOff, int nBlockYOff, void *pImage)
488 :
489 : {
490 20124 : NITFDataset *poGDS = cpl::down_cast<NITFDataset *>(poDS);
491 :
492 : /* -------------------------------------------------------------------- */
493 : /* Special case for JPEG blocks. */
494 : /* -------------------------------------------------------------------- */
495 20124 : if (EQUAL(psImage->szIC, "C3") || EQUAL(psImage->szIC, "M3"))
496 : {
497 128 : CPLErr eErr = poGDS->ReadJPEGBlock(nBlockXOff, nBlockYOff);
498 128 : const int nBlockBandSize = psImage->nBlockWidth *
499 128 : psImage->nBlockHeight *
500 128 : GDALGetDataTypeSizeBytes(eDataType);
501 :
502 128 : if (eErr != CE_None)
503 0 : return eErr;
504 :
505 128 : memcpy(pImage, poGDS->pabyJPEGBlock + (nBand - 1) * nBlockBandSize,
506 : nBlockBandSize);
507 :
508 128 : return eErr;
509 : }
510 :
511 : /* -------------------------------------------------------------------- */
512 : /* Read the line/block */
513 : /* -------------------------------------------------------------------- */
514 : int nBlockResult;
515 :
516 19996 : if (bScanlineAccess)
517 : {
518 16551 : nBlockResult = NITFReadImageLine(psImage, nBlockYOff, nBand, pImage);
519 : }
520 : else
521 : {
522 : nBlockResult =
523 3445 : NITFReadImageBlock(psImage, nBlockXOff, nBlockYOff, nBand, pImage);
524 : }
525 :
526 19996 : if (nBlockResult == BLKREAD_OK)
527 : {
528 19420 : if (psImage->nBitsPerSample % 8)
529 60 : Unpack(reinterpret_cast<GByte *>(pImage));
530 :
531 19420 : return CE_None;
532 : }
533 :
534 576 : if (nBlockResult == BLKREAD_FAIL)
535 0 : 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 576 : if (psImage->bNoDataSet)
543 576 : memset(pImage, psImage->nNoDataValue,
544 576 : static_cast<size_t>(psImage->nWordSize) * psImage->nBlockWidth *
545 576 : psImage->nBlockHeight);
546 : else
547 0 : memset(pImage, 0,
548 0 : static_cast<size_t>(psImage->nWordSize) * psImage->nBlockWidth *
549 0 : psImage->nBlockHeight);
550 :
551 576 : return CE_None;
552 : }
553 :
554 : /************************************************************************/
555 : /* IWriteBlock() */
556 : /************************************************************************/
557 :
558 17525 : CPLErr NITFRasterBand::IWriteBlock(int nBlockXOff, int nBlockYOff, void *pImage)
559 :
560 : {
561 : /* -------------------------------------------------------------------- */
562 : /* Write the line/block */
563 : /* -------------------------------------------------------------------- */
564 : int nBlockResult;
565 :
566 17525 : if (bScanlineAccess)
567 : {
568 16881 : nBlockResult = NITFWriteImageLine(psImage, nBlockYOff, nBand, pImage);
569 : }
570 : else
571 : {
572 : nBlockResult =
573 644 : NITFWriteImageBlock(psImage, nBlockXOff, nBlockYOff, nBand, pImage);
574 : }
575 :
576 17525 : if (nBlockResult == BLKREAD_OK)
577 17525 : return CE_None;
578 :
579 0 : return CE_Failure;
580 : }
581 :
582 : /************************************************************************/
583 : /* GetNoDataValue() */
584 : /************************************************************************/
585 :
586 184 : double NITFRasterBand::GetNoDataValue(int *pbSuccess)
587 :
588 : {
589 184 : if (pbSuccess != nullptr)
590 183 : *pbSuccess = psImage->bNoDataSet;
591 :
592 184 : if (psImage->bNoDataSet)
593 64 : return psImage->nNoDataValue;
594 :
595 120 : return GDALPamRasterBand::GetNoDataValue(pbSuccess);
596 : }
597 :
598 : /************************************************************************/
599 : /* GetColorInterpretation() */
600 : /************************************************************************/
601 :
602 211 : GDALColorInterp NITFRasterBand::GetColorInterpretation()
603 :
604 : {
605 211 : NITFBandInfo *psBandInfo = psImage->pasBandInfo + nBand - 1;
606 :
607 211 : if (poColorTable != nullptr)
608 71 : return GCI_PaletteIndex;
609 :
610 140 : if (EQUAL(psBandInfo->szIREPBAND, "R"))
611 21 : return GCI_RedBand;
612 119 : if (EQUAL(psBandInfo->szIREPBAND, "G"))
613 21 : return GCI_GreenBand;
614 98 : if (EQUAL(psBandInfo->szIREPBAND, "B"))
615 21 : return GCI_BlueBand;
616 77 : if (EQUAL(psBandInfo->szIREPBAND, "M"))
617 71 : return GCI_GrayIndex;
618 6 : if (EQUAL(psBandInfo->szIREPBAND, "Y"))
619 2 : return GCI_YCbCr_YBand;
620 4 : if (EQUAL(psBandInfo->szIREPBAND, "Cb"))
621 2 : return GCI_YCbCr_CbBand;
622 2 : if (EQUAL(psBandInfo->szIREPBAND, "Cr"))
623 2 : return GCI_YCbCr_CrBand;
624 :
625 0 : return GCI_Undefined;
626 : }
627 :
628 : /************************************************************************/
629 : /* NITFSetColorInterpretation() */
630 : /************************************************************************/
631 :
632 33 : CPLErr NITFSetColorInterpretation(NITFImage *psImage, int nBand,
633 : GDALColorInterp eInterp)
634 :
635 : {
636 33 : const char *pszREP = nullptr;
637 :
638 33 : if (eInterp == GCI_RedBand)
639 11 : pszREP = "R";
640 22 : else if (eInterp == GCI_GreenBand)
641 11 : pszREP = "G";
642 11 : else if (eInterp == GCI_BlueBand)
643 11 : pszREP = "B";
644 0 : else if (eInterp == GCI_GrayIndex)
645 0 : pszREP = "M";
646 0 : else if (eInterp == GCI_YCbCr_YBand)
647 0 : pszREP = "Y";
648 0 : else if (eInterp == GCI_YCbCr_CbBand)
649 0 : pszREP = "Cb";
650 0 : else if (eInterp == GCI_YCbCr_CrBand)
651 0 : pszREP = "Cr";
652 0 : else if (eInterp == GCI_Undefined)
653 0 : return CE_None;
654 :
655 33 : if (pszREP == nullptr)
656 : {
657 0 : CPLError(CE_Failure, CPLE_NotSupported,
658 : "Requested color interpretation (%s) not supported in NITF.",
659 : GDALGetColorInterpretationName(eInterp));
660 0 : return CE_Failure;
661 : }
662 :
663 : /* -------------------------------------------------------------------- */
664 : /* Where does this go in the file? */
665 : /* -------------------------------------------------------------------- */
666 33 : NITFBandInfo *psBandInfo = psImage->pasBandInfo + nBand - 1;
667 33 : strcpy(psBandInfo->szIREPBAND, pszREP);
668 33 : GUIntBig nOffset = NITFIHFieldOffset(psImage, "IREPBAND");
669 :
670 33 : if (nOffset != 0)
671 33 : nOffset += (nBand - 1) * 13;
672 :
673 : /* -------------------------------------------------------------------- */
674 : /* write it (space padded). */
675 : /* -------------------------------------------------------------------- */
676 : char szPadded[4];
677 33 : strcpy(szPadded, pszREP);
678 33 : strcat(szPadded, " ");
679 :
680 33 : if (nOffset != 0)
681 : {
682 66 : if (VSIFSeekL(psImage->psFile->fp, nOffset, SEEK_SET) != 0 ||
683 33 : VSIFWriteL(reinterpret_cast<void *>(szPadded), 1, 2,
684 33 : psImage->psFile->fp) != 2)
685 : {
686 0 : CPLError(CE_Failure, CPLE_AppDefined,
687 : "IO failure writing new IREPBAND value to NITF file.");
688 0 : return CE_Failure;
689 : }
690 : }
691 :
692 33 : return CE_None;
693 : }
694 :
695 : /************************************************************************/
696 : /* SetColorInterpretation() */
697 : /************************************************************************/
698 :
699 30 : CPLErr NITFRasterBand::SetColorInterpretation(GDALColorInterp eInterp)
700 :
701 : {
702 30 : return NITFSetColorInterpretation(psImage, nBand, eInterp);
703 : }
704 :
705 : /************************************************************************/
706 : /* GetColorTable() */
707 : /************************************************************************/
708 :
709 4976 : GDALColorTable *NITFRasterBand::GetColorTable()
710 :
711 : {
712 4976 : return poColorTable;
713 : }
714 :
715 : /************************************************************************/
716 : /* SetColorTable() */
717 : /************************************************************************/
718 :
719 34 : CPLErr NITFRasterBand::SetColorTable(GDALColorTable *poNewCT)
720 :
721 : {
722 34 : NITFDataset *poGDS = cpl::down_cast<NITFDataset *>(poDS);
723 34 : if (poGDS->bInLoadXML)
724 0 : return GDALPamRasterBand::SetColorTable(poNewCT);
725 :
726 34 : if (poNewCT == nullptr)
727 0 : return CE_Failure;
728 :
729 68 : std::vector<GByte> abyNITFLUT(768);
730 :
731 34 : const int nCount = std::min(256, poNewCT->GetColorEntryCount());
732 7106 : for (int i = 0; i < nCount; i++)
733 : {
734 : GDALColorEntry sEntry;
735 :
736 7072 : poNewCT->GetColorEntryAsRGB(i, &sEntry);
737 7072 : abyNITFLUT[i + 256 * 0] = static_cast<GByte>(sEntry.c1);
738 7072 : abyNITFLUT[i + 256 * 1] = static_cast<GByte>(sEntry.c2);
739 7072 : abyNITFLUT[i + 256 * 2] = static_cast<GByte>(sEntry.c3);
740 : }
741 :
742 34 : if (NITFWriteLUT(psImage, nBand, nCount, abyNITFLUT.data()))
743 34 : return CE_None;
744 :
745 0 : return CE_Failure;
746 : }
747 :
748 : /************************************************************************/
749 : /* Unpack() */
750 : /************************************************************************/
751 :
752 60 : void NITFRasterBand::Unpack(GByte *pData)
753 : {
754 60 : const int n = nBlockXSize * nBlockYSize;
755 :
756 60 : GByte abyTempData[7] = {0, 0, 0, 0, 0, 0, 0};
757 60 : const GByte *pDataSrc = pData;
758 60 : if (n < psImage->nBitsPerSample && psImage->nBitsPerSample < 8)
759 : {
760 20 : memcpy(abyTempData, pData, n);
761 20 : pDataSrc = abyTempData;
762 : }
763 :
764 60 : switch (psImage->nBitsPerSample)
765 : {
766 11 : case 1:
767 : {
768 : // unpack 1-bit in-place in reverse
769 : // DANGER: Non-standard decrement of counter in the test section of
770 : // for.
771 1050510 : for (int i = n; --i >= 0;)
772 1050500 : pData[i] = (pData[i >> 3] & (0x80 >> (i & 7))) != 0;
773 :
774 11 : break;
775 : }
776 7 : case 2:
777 : {
778 7 : constexpr int s_Shift2[] = {6, 4, 2, 0};
779 : // unpack 2-bit in-place in reverse
780 : // DANGER: Non-standard decrement of counter in the test section of
781 : // for.
782 37 : for (int i = n; --i >= 0;)
783 30 : pData[i] =
784 30 : (pData[i >> 2] >> static_cast<GByte>(s_Shift2[i & 3])) &
785 : 0x03;
786 :
787 7 : break;
788 : }
789 7 : case 4:
790 : {
791 7 : constexpr int s_Shift4[] = {4, 0};
792 : // unpack 4-bit in-place in reverse
793 : // DANGER: Non-standard decrement of counter in the test section of
794 : // for.
795 37 : for (int i = n; --i >= 0;)
796 30 : pData[i] =
797 30 : (pData[i >> 1] >> static_cast<GByte>(s_Shift4[i & 1])) &
798 : 0x0f;
799 :
800 7 : break;
801 : }
802 7 : case 3:
803 : {
804 : // unpacks 8 pixels (3 bytes) at time
805 7 : int i = 0;
806 7 : int k = 0;
807 8 : for (; i + 7 < n; i += 8, k += 3)
808 : {
809 1 : pUnpackData[i + 0] = ((pDataSrc[k + 0] >> 5));
810 1 : pUnpackData[i + 1] = ((pDataSrc[k + 0] >> 2) & 0x07);
811 1 : pUnpackData[i + 2] =
812 1 : ((pDataSrc[k + 0] << 1) & 0x07) | (pDataSrc[k + 1] >> 7);
813 1 : pUnpackData[i + 3] = ((pDataSrc[k + 1] >> 4) & 0x07);
814 1 : pUnpackData[i + 4] = ((pDataSrc[k + 1] >> 1) & 0x07);
815 1 : pUnpackData[i + 5] =
816 1 : ((pDataSrc[k + 1] << 2) & 0x07) | (pDataSrc[k + 2] >> 6);
817 1 : pUnpackData[i + 6] = ((pDataSrc[k + 2] >> 3) & 0x07);
818 1 : pUnpackData[i + 7] = ((pDataSrc[k + 2]) & 0x7);
819 : }
820 7 : if (i < n)
821 : {
822 6 : pUnpackData[i + 0] = ((pDataSrc[k + 0] >> 5));
823 6 : if (i + 1 < n)
824 5 : pUnpackData[i + 1] = ((pDataSrc[k + 0] >> 2) & 0x07);
825 6 : if (i + 2 < n)
826 4 : pUnpackData[i + 2] = ((pDataSrc[k + 0] << 1) & 0x07) |
827 4 : (pDataSrc[k + 1] >> 7);
828 6 : if (i + 3 < n)
829 3 : pUnpackData[i + 3] = ((pDataSrc[k + 1] >> 4) & 0x07);
830 6 : if (i + 4 < n)
831 2 : pUnpackData[i + 4] = ((pDataSrc[k + 1] >> 1) & 0x07);
832 6 : if (i + 5 < n)
833 1 : pUnpackData[i + 5] = ((pDataSrc[k + 1] << 2) & 0x07) |
834 1 : (pDataSrc[k + 2] >> 6);
835 6 : if (i + 6 < n)
836 1 : pUnpackData[i + 6] = ((pDataSrc[k + 2] >> 3) & 0x07);
837 : }
838 :
839 7 : memcpy(pData, pUnpackData, n);
840 7 : break;
841 : }
842 7 : case 5:
843 : {
844 : // unpacks 8 pixels (5 bytes) at time
845 7 : int i = 0;
846 7 : int k = 0;
847 8 : for (; i + 7 < n; i += 8, k += 5)
848 : {
849 1 : pUnpackData[i + 0] = ((pDataSrc[k + 0] >> 3));
850 1 : pUnpackData[i + 1] =
851 1 : ((pDataSrc[k + 0] << 2) & 0x1f) | (pDataSrc[k + 1] >> 6);
852 1 : pUnpackData[i + 2] = ((pDataSrc[k + 1] >> 1) & 0x1f);
853 1 : pUnpackData[i + 3] =
854 1 : ((pDataSrc[k + 1] << 4) & 0x1f) | (pDataSrc[k + 2] >> 4);
855 1 : pUnpackData[i + 4] =
856 1 : ((pDataSrc[k + 2] << 1) & 0x1f) | (pDataSrc[k + 3] >> 7);
857 1 : pUnpackData[i + 5] = ((pDataSrc[k + 3] >> 2) & 0x1f);
858 1 : pUnpackData[i + 6] =
859 1 : ((pDataSrc[k + 3] << 3) & 0x1f) | (pDataSrc[k + 4] >> 5);
860 1 : pUnpackData[i + 7] = ((pDataSrc[k + 4]) & 0x1f);
861 : }
862 7 : if (i < n)
863 : {
864 6 : pUnpackData[i + 0] = ((pDataSrc[k + 0] >> 3));
865 6 : if (i + 1 < n)
866 5 : pUnpackData[i + 1] = ((pDataSrc[k + 0] << 2) & 0x1f) |
867 5 : (pDataSrc[k + 1] >> 6);
868 6 : if (i + 2 < n)
869 4 : pUnpackData[i + 2] = ((pDataSrc[k + 1] >> 1) & 0x1f);
870 6 : if (i + 3 < n)
871 3 : pUnpackData[i + 3] = ((pDataSrc[k + 1] << 4) & 0x1f) |
872 3 : (pDataSrc[k + 2] >> 4);
873 6 : if (i + 4 < n)
874 2 : pUnpackData[i + 4] = ((pDataSrc[k + 2] << 1) & 0x1f) |
875 2 : (pDataSrc[k + 3] >> 7);
876 6 : if (i + 5 < n)
877 1 : pUnpackData[i + 5] = ((pDataSrc[k + 3] >> 2) & 0x1f);
878 6 : if (i + 6 < n)
879 1 : pUnpackData[i + 6] = ((pDataSrc[k + 3] << 3) & 0x1f) |
880 1 : (pDataSrc[k + 4] >> 5);
881 : }
882 :
883 7 : memcpy(pData, pUnpackData, n);
884 7 : break;
885 : }
886 7 : case 6:
887 : {
888 : // unpacks 4 pixels (3 bytes) at time
889 7 : int i = 0;
890 7 : int k = 0;
891 12 : for (; i + 3 < n; i += 4, k += 3)
892 : {
893 5 : pUnpackData[i + 0] = ((pDataSrc[k + 0] >> 2));
894 5 : pUnpackData[i + 1] =
895 5 : ((pDataSrc[k + 0] << 4) & 0x3f) | (pDataSrc[k + 1] >> 4);
896 5 : pUnpackData[i + 2] =
897 5 : ((pDataSrc[k + 1] << 2) & 0x3f) | (pDataSrc[k + 2] >> 6);
898 5 : pUnpackData[i + 3] = ((pDataSrc[k + 2]) & 0x3f);
899 : }
900 7 : if (i < n)
901 : {
902 5 : pUnpackData[i + 0] = ((pDataSrc[k + 0] >> 2));
903 5 : if (i + 1 < n)
904 3 : pUnpackData[i + 1] = ((pDataSrc[k + 0] << 4) & 0x3f) |
905 3 : (pDataSrc[k + 1] >> 4);
906 5 : if (i + 2 < n)
907 2 : pUnpackData[i + 2] = ((pDataSrc[k + 1] << 2) & 0x3f) |
908 2 : (pDataSrc[k + 2] >> 6);
909 : }
910 :
911 7 : memcpy(pData, pUnpackData, n);
912 7 : break;
913 : }
914 7 : case 7:
915 : {
916 : // unpacks 8 pixels (7 bytes) at time
917 7 : int i = 0;
918 7 : int k = 0;
919 8 : for (; i + 7 < n; i += 8, k += 7)
920 : {
921 1 : pUnpackData[i + 0] = ((pDataSrc[k + 0] >> 1));
922 1 : pUnpackData[i + 1] =
923 1 : ((pDataSrc[k + 0] << 6) & 0x7f) | (pDataSrc[k + 1] >> 2);
924 1 : pUnpackData[i + 2] =
925 1 : ((pDataSrc[k + 1] << 5) & 0x7f) | (pDataSrc[k + 2] >> 3);
926 1 : pUnpackData[i + 3] =
927 1 : ((pDataSrc[k + 2] << 4) & 0x7f) | (pDataSrc[k + 3] >> 4);
928 1 : pUnpackData[i + 4] =
929 1 : ((pDataSrc[k + 3] << 3) & 0x7f) | (pDataSrc[k + 4] >> 5);
930 1 : pUnpackData[i + 5] =
931 1 : ((pDataSrc[k + 4] << 2) & 0x7f) | (pDataSrc[k + 5] >> 6);
932 1 : pUnpackData[i + 6] =
933 1 : ((pDataSrc[k + 5] << 1) & 0x7f) | (pDataSrc[k + 6] >> 7);
934 1 : pUnpackData[i + 7] = ((pDataSrc[k + 6]) & 0x7f);
935 : }
936 7 : if (i < n)
937 : {
938 6 : pUnpackData[i + 0] = ((pDataSrc[k + 0] >> 1));
939 6 : if (i + 1 < n)
940 5 : pUnpackData[i + 1] = ((pDataSrc[k + 0] << 6) & 0x7f) |
941 5 : (pDataSrc[k + 1] >> 2);
942 6 : if (i + 2 < n)
943 4 : pUnpackData[i + 2] = ((pDataSrc[k + 1] << 5) & 0x7f) |
944 4 : (pDataSrc[k + 2] >> 3);
945 6 : if (i + 3 < n)
946 3 : pUnpackData[i + 3] = ((pDataSrc[k + 2] << 4) & 0x7f) |
947 3 : (pDataSrc[k + 3] >> 4);
948 6 : if (i + 4 < n)
949 2 : pUnpackData[i + 4] = ((pDataSrc[k + 3] << 3) & 0x7f) |
950 2 : (pDataSrc[k + 4] >> 5);
951 6 : if (i + 5 < n)
952 1 : pUnpackData[i + 5] = ((pDataSrc[k + 4] << 2) & 0x7f) |
953 1 : (pDataSrc[k + 5] >> 6);
954 6 : if (i + 6 < n)
955 1 : pUnpackData[i + 6] = ((pDataSrc[k + 5] << 1) & 0x7f) |
956 1 : (pDataSrc[k + 6] >> 7);
957 : }
958 :
959 7 : memcpy(pData, pUnpackData, n);
960 7 : break;
961 : }
962 7 : case 12:
963 : {
964 7 : GByte *pabyImage = reinterpret_cast<GByte *>(pData);
965 7 : GUInt16 *panImage = reinterpret_cast<GUInt16 *>(pData);
966 : // DANGER: Non-standard decrement of counter in the test section of
967 : // for.
968 37 : for (int i = n; --i >= 0;)
969 : {
970 30 : const long iOffset = i * 3 / 2;
971 30 : if (i % 2 == 0)
972 17 : panImage[i] = pabyImage[iOffset] +
973 17 : (pabyImage[iOffset + 1] & 0xf0) * 16;
974 : else
975 13 : panImage[i] = (pabyImage[iOffset] & 0x0f) * 16 +
976 13 : (pabyImage[iOffset + 1] & 0xf0) / 16 +
977 13 : (pabyImage[iOffset + 1] & 0x0f) * 256;
978 : }
979 :
980 7 : break;
981 : }
982 : }
983 60 : }
984 :
985 : /************************************************************************/
986 : /* ==================================================================== */
987 : /* NITFWrapperRasterBand */
988 : /* ==================================================================== */
989 : /************************************************************************/
990 :
991 : /************************************************************************/
992 : /* NITFWrapperRasterBand() */
993 : /************************************************************************/
994 :
995 99 : NITFWrapperRasterBand::NITFWrapperRasterBand(NITFDataset *poDSIn,
996 : GDALRasterBand *poBaseBandIn,
997 99 : int nBandIn)
998 198 : : poBaseBand(poBaseBandIn), eInterp(poBaseBandIn->GetColorInterpretation()),
999 297 : bIsJPEG(poBaseBandIn->GetDataset() != nullptr &&
1000 198 : poBaseBandIn->GetDataset()->GetDriver() != nullptr &&
1001 99 : EQUAL(poBaseBandIn->GetDataset()->GetDriver()->GetDescription(),
1002 99 : "JPEG"))
1003 : {
1004 99 : poDS = poDSIn;
1005 99 : nBand = nBandIn;
1006 99 : poBaseBand->GetBlockSize(&nBlockXSize, &nBlockYSize);
1007 99 : eDataType = poBaseBandIn->GetRasterDataType();
1008 99 : }
1009 :
1010 : /************************************************************************/
1011 : /* ~NITFWrapperRasterBand() */
1012 : /************************************************************************/
1013 :
1014 198 : NITFWrapperRasterBand::~NITFWrapperRasterBand()
1015 : {
1016 99 : if (poColorTable != nullptr)
1017 0 : delete poColorTable;
1018 198 : }
1019 :
1020 : /************************************************************************/
1021 : /* RefUnderlyingRasterBand() */
1022 : /************************************************************************/
1023 :
1024 : /* We don't need ref-counting. Just return the base band */
1025 572 : GDALRasterBand *NITFWrapperRasterBand::RefUnderlyingRasterBand()
1026 : {
1027 572 : return poBaseBand;
1028 : }
1029 :
1030 : /************************************************************************/
1031 : /* GetColorTable() */
1032 : /************************************************************************/
1033 :
1034 16 : GDALColorTable *NITFWrapperRasterBand::GetColorTable()
1035 : {
1036 16 : return poColorTable;
1037 : }
1038 :
1039 : /************************************************************************/
1040 : /* SetColorTableFromNITFBandInfo() */
1041 : /************************************************************************/
1042 :
1043 0 : void NITFWrapperRasterBand::SetColorTableFromNITFBandInfo()
1044 : {
1045 0 : NITFDataset *poGDS = cpl::down_cast<NITFDataset *>(poDS);
1046 0 : poColorTable = NITFMakeColorTable(poGDS->psImage,
1047 0 : poGDS->psImage->pasBandInfo + nBand - 1);
1048 0 : }
1049 :
1050 : /************************************************************************/
1051 : /* GetColorInterpretation() */
1052 : /************************************************************************/
1053 :
1054 60 : GDALColorInterp NITFWrapperRasterBand::GetColorInterpretation()
1055 : {
1056 60 : return eInterp;
1057 : }
1058 :
1059 : /************************************************************************/
1060 : /* SetColorInterpretation() */
1061 : /************************************************************************/
1062 :
1063 100 : CPLErr NITFWrapperRasterBand::SetColorInterpretation(GDALColorInterp eInterpIn)
1064 : {
1065 100 : this->eInterp = eInterpIn;
1066 100 : if (poBaseBand->GetDataset() != nullptr &&
1067 200 : poBaseBand->GetDataset()->GetDriver() != nullptr &&
1068 100 : EQUAL(poBaseBand->GetDataset()->GetDriver()->GetDescription(),
1069 : "JP2ECW"))
1070 19 : poBaseBand->SetColorInterpretation(eInterp);
1071 100 : return CE_None;
1072 : }
1073 :
1074 : /************************************************************************/
1075 : /* GetOverviewCount() */
1076 : /************************************************************************/
1077 :
1078 6 : int NITFWrapperRasterBand::GetOverviewCount()
1079 : {
1080 6 : if (bIsJPEG)
1081 : {
1082 2 : if ((cpl::down_cast<NITFDataset *>(poDS))
1083 2 : ->ExposeUnderlyingJPEGDatasetOverviews())
1084 0 : return NITFProxyPamRasterBand::GetOverviewCount();
1085 :
1086 2 : return GDALPamRasterBand::GetOverviewCount();
1087 : }
1088 :
1089 4 : return NITFProxyPamRasterBand::GetOverviewCount();
1090 : }
1091 :
1092 : /************************************************************************/
1093 : /* GetOverview() */
1094 : /************************************************************************/
1095 :
1096 3 : GDALRasterBand *NITFWrapperRasterBand::GetOverview(int iOverview)
1097 : {
1098 3 : if (bIsJPEG)
1099 : {
1100 1 : if ((cpl::down_cast<NITFDataset *>(poDS))
1101 1 : ->ExposeUnderlyingJPEGDatasetOverviews())
1102 0 : return NITFProxyPamRasterBand::GetOverview(iOverview);
1103 :
1104 1 : return GDALPamRasterBand::GetOverview(iOverview);
1105 : }
1106 :
1107 2 : return NITFProxyPamRasterBand::GetOverview(iOverview);
1108 : }
1109 :
1110 : /************************************************************************/
1111 : /* NITFComplexRasterBand() */
1112 : /************************************************************************/
1113 :
1114 5 : NITFComplexRasterBand::NITFComplexRasterBand(NITFDataset *poDSIn,
1115 : GDALRasterBand *poBandI,
1116 : GDALRasterBand *poBandQ,
1117 5 : int nIBand, int nQBand)
1118 5 : : NITFRasterBand(poDSIn, nIBand)
1119 : {
1120 :
1121 5 : CPLAssert(poBandI->GetRasterDataType() == poBandQ->GetRasterDataType());
1122 5 : underlyingDataType = poBandI->GetRasterDataType();
1123 :
1124 : //add the I and Q bands to an intermediate dataset
1125 5 : poIntermediateDS = std::make_unique<NITFDataset>();
1126 5 : poIntermediateDS->nRasterXSize = poDSIn->nRasterXSize;
1127 5 : poIntermediateDS->nRasterYSize = poDSIn->nRasterYSize;
1128 5 : poIntermediateDS->eAccess = poDSIn->eAccess;
1129 :
1130 5 : poIntermediateDS->SetBand(nIBand, poBandI);
1131 5 : poIntermediateDS->SetBand(nQBand, poBandQ);
1132 :
1133 5 : anBandMap[0] = nIBand;
1134 5 : anBandMap[1] = nQBand;
1135 :
1136 : //set the new datatype
1137 5 : switch (underlyingDataType)
1138 : {
1139 0 : case GDT_Int16:
1140 0 : eDataType = GDT_CInt16;
1141 0 : break;
1142 0 : case GDT_Int32:
1143 0 : eDataType = GDT_CInt32;
1144 0 : break;
1145 5 : case GDT_Float32:
1146 5 : eDataType = GDT_CFloat32;
1147 5 : break;
1148 0 : case GDT_Float64:
1149 0 : eDataType = GDT_CFloat64;
1150 0 : break;
1151 0 : default:
1152 0 : eDataType = GDT_Unknown;
1153 0 : CPLError(CE_Failure, CPLE_NotSupported,
1154 : "Unsupported complex datatype");
1155 0 : break;
1156 : }
1157 :
1158 5 : complexDataTypeSize = GDALGetDataTypeSizeBytes(eDataType);
1159 5 : underlyingDataTypeSize = GDALGetDataTypeSizeBytes(underlyingDataType);
1160 5 : CPLAssert(underlyingDataTypeSize * 2 == complexDataTypeSize);
1161 :
1162 5 : poBandI->GetBlockSize(&nBlockXSize, &nBlockYSize);
1163 5 : }
1164 :
1165 : /************************************************************************/
1166 : /* IReadBlock() */
1167 : /************************************************************************/
1168 :
1169 40 : CPLErr NITFComplexRasterBand::IBlockIO(int nBlockXOff, int nBlockYOff,
1170 : void *pImage, GDALRWFlag rwFlag)
1171 :
1172 : {
1173 : /* -------------------------------------------------------------------- */
1174 : /* If the last strip is partial, we need to avoid */
1175 : /* over-requesting. We also need to initialize the extra part */
1176 : /* of the block to zero. */
1177 : /* -------------------------------------------------------------------- */
1178 40 : const int nYOff = nBlockYOff * nBlockYSize;
1179 40 : const int nRequestYSize = std::min(nBlockYSize, nRasterYSize - nYOff);
1180 :
1181 : /*-------------------------------------------------------------------- */
1182 : /* If the input imagery is tiled, also need to avoid over- */
1183 : /* requesting in the X-direction. */
1184 : /* ------------------------------------------------------------------- */
1185 40 : const int nXOff = nBlockXOff * nBlockXSize;
1186 40 : const int nRequestXSize = std::min(nBlockXSize, nRasterXSize - nXOff);
1187 :
1188 40 : if (rwFlag == GF_Read &&
1189 40 : (nRequestXSize < nBlockXSize || nRequestYSize < nBlockYSize))
1190 : {
1191 0 : memset(pImage, 0,
1192 0 : static_cast<size_t>(GDALGetDataTypeSizeBytes(eDataType)) *
1193 0 : nBlockXSize * nBlockYSize);
1194 : }
1195 :
1196 : //read/write both bands with interleaved pixels
1197 40 : return poIntermediateDS->RasterIO(
1198 40 : rwFlag, nBlockXOff * nBlockXSize, nBlockYOff * nBlockYSize,
1199 : nRequestXSize, nRequestYSize, pImage, nRequestXSize, nRequestYSize,
1200 40 : underlyingDataType, 2, &anBandMap[0], complexDataTypeSize,
1201 40 : static_cast<GSpacing>(complexDataTypeSize) * nBlockXSize,
1202 80 : underlyingDataTypeSize, nullptr);
1203 : }
1204 :
1205 : /************************************************************************/
1206 : /* IReadBlock() */
1207 : /************************************************************************/
1208 :
1209 40 : CPLErr NITFComplexRasterBand::IReadBlock(int nBlockXOff, int nBlockYOff,
1210 : void *pImage)
1211 :
1212 : {
1213 40 : return IBlockIO(nBlockXOff, nBlockYOff, pImage, GF_Read);
1214 : }
1215 :
1216 : /************************************************************************/
1217 : /* IWriteBlock() */
1218 : /************************************************************************/
1219 :
1220 0 : CPLErr NITFComplexRasterBand::IWriteBlock(int nBlockXOff, int nBlockYOff,
1221 : void *pImage)
1222 :
1223 : {
1224 0 : return IBlockIO(nBlockXOff, nBlockYOff, pImage, GF_Write);
1225 : }
|