1 : /******************************************************************************
2 : * $Id: nitfrasterband.cpp 22851 2011-08-01 19:01:18Z rouault $
3 : *
4 : * Project: NITF Read/Write Translator
5 : * Purpose: NITFRasterBand (and related proxy band) implementations.
6 : * Author: Frank Warmerdam, warmerdam@pobox.com
7 : *
8 : ******************************************************************************
9 : * Copyright (c) 2002, Frank Warmerdam
10 : *
11 : * Portions Copyright (c) Her majesty the Queen in right of Canada as
12 : * represented by the Minister of National Defence, 2006.
13 : *
14 : * Permission is hereby granted, free of charge, to any person obtaining a
15 : * copy of this software and associated documentation files (the "Software"),
16 : * to deal in the Software without restriction, including without limitation
17 : * the rights to use, copy, modify, merge, publish, distribute, sublicense,
18 : * and/or sell copies of the Software, and to permit persons to whom the
19 : * Software is furnished to do so, subject to the following conditions:
20 : *
21 : * The above copyright notice and this permission notice shall be included
22 : * in all copies or substantial portions of the Software.
23 : *
24 : * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
25 : * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
26 : * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
27 : * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
28 : * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
29 : * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
30 : * DEALINGS IN THE SOFTWARE.
31 : ****************************************************************************/
32 :
33 : #include "nitfdataset.h"
34 : #include "cpl_string.h"
35 : #include "cpl_csv.h"
36 :
37 : CPL_CVSID("$Id: nitfrasterband.cpp 22851 2011-08-01 19:01:18Z rouault $");
38 :
39 : /************************************************************************/
40 : /* NITFMakeColorTable() */
41 : /************************************************************************/
42 :
43 421444 : static GDALColorTable* NITFMakeColorTable(NITFImage* psImage, NITFBandInfo *psBandInfo)
44 : {
45 421444 : GDALColorTable* poColorTable = NULL;
46 :
47 421444 : if( psBandInfo->nSignificantLUTEntries > 0 )
48 : {
49 : int iColor;
50 :
51 82 : poColorTable = new GDALColorTable();
52 :
53 16528 : for( iColor = 0; iColor < psBandInfo->nSignificantLUTEntries; iColor++)
54 : {
55 : GDALColorEntry sEntry;
56 :
57 16446 : sEntry.c1 = psBandInfo->pabyLUT[ 0 + iColor];
58 16446 : sEntry.c2 = psBandInfo->pabyLUT[256 + iColor];
59 16446 : sEntry.c3 = psBandInfo->pabyLUT[512 + iColor];
60 16446 : sEntry.c4 = 255;
61 :
62 16446 : poColorTable->SetColorEntry( iColor, &sEntry );
63 : }
64 :
65 82 : if (psImage->bNoDataSet)
66 : {
67 : GDALColorEntry sEntry;
68 62 : sEntry.c1 = sEntry.c2 = sEntry.c3 = sEntry.c4 = 0;
69 62 : poColorTable->SetColorEntry( psImage->nNoDataValue, &sEntry );
70 : }
71 : }
72 :
73 : /* -------------------------------------------------------------------- */
74 : /* We create a color table for 1 bit data too... */
75 : /* -------------------------------------------------------------------- */
76 421444 : if( poColorTable == NULL && psImage->nBitsPerSample == 1 )
77 : {
78 : GDALColorEntry sEntry;
79 :
80 36 : poColorTable = new GDALColorTable();
81 :
82 36 : sEntry.c1 = 0;
83 36 : sEntry.c2 = 0;
84 36 : sEntry.c3 = 0;
85 36 : sEntry.c4 = 255;
86 36 : poColorTable->SetColorEntry( 0, &sEntry );
87 :
88 36 : sEntry.c1 = 255;
89 36 : sEntry.c2 = 255;
90 36 : sEntry.c3 = 255;
91 36 : sEntry.c4 = 255;
92 36 : poColorTable->SetColorEntry( 1, &sEntry );
93 : }
94 :
95 421444 : return poColorTable;
96 : }
97 :
98 : /************************************************************************/
99 : /* ==================================================================== */
100 : /* NITFProxyPamRasterBand */
101 : /* ==================================================================== */
102 : /************************************************************************/
103 :
104 112 : NITFProxyPamRasterBand::~NITFProxyPamRasterBand()
105 : {
106 112 : std::map<CPLString, char**>::iterator oIter = oMDMap.begin();
107 232 : while(oIter != oMDMap.end())
108 : {
109 8 : CSLDestroy(oIter->second);
110 8 : oIter ++;
111 : }
112 112 : }
113 :
114 :
115 : #define RB_PROXY_METHOD_WITH_RET(retType, retErrValue, methodName, argList, argParams) \
116 : retType NITFProxyPamRasterBand::methodName argList \
117 : { \
118 : retType ret; \
119 : GDALRasterBand* _poSrcBand = RefUnderlyingRasterBand(); \
120 : if (_poSrcBand) \
121 : { \
122 : ret = _poSrcBand->methodName argParams; \
123 : UnrefUnderlyingRasterBand(_poSrcBand); \
124 : } \
125 : else \
126 : { \
127 : ret = retErrValue; \
128 : } \
129 : return ret; \
130 : }
131 :
132 :
133 : #define RB_PROXY_METHOD_WITH_RET_AND_CALL_OTHER_METHOD(retType, retErrValue, methodName, underlyingMethodName, argList, argParams) \
134 : retType NITFProxyPamRasterBand::methodName argList \
135 : { \
136 : retType ret; \
137 : GDALRasterBand* _poSrcBand = RefUnderlyingRasterBand(); \
138 : if (_poSrcBand) \
139 : { \
140 : ret = _poSrcBand->underlyingMethodName argParams; \
141 : UnrefUnderlyingRasterBand(_poSrcBand); \
142 : } \
143 : else \
144 : { \
145 : ret = retErrValue; \
146 : } \
147 : return ret; \
148 : }
149 :
150 8 : char **NITFProxyPamRasterBand::GetMetadata( const char * pszDomain )
151 : {
152 8 : GDALRasterBand* _poSrcBand = RefUnderlyingRasterBand();
153 8 : if (_poSrcBand)
154 : {
155 : /* Let's merge metadata of PAM and the underlying band */
156 : /* PAM metadata should override underlying band metadata */
157 8 : char** papszMD = CSLDuplicate(_poSrcBand->GetMetadata( pszDomain ));
158 8 : papszMD = CSLMerge( papszMD, GDALPamRasterBand::GetMetadata(pszDomain) );
159 :
160 8 : if (pszDomain == NULL)
161 0 : pszDomain = "";
162 :
163 8 : std::map<CPLString, char**>::iterator oIter = oMDMap.find(pszDomain);
164 8 : if (oIter != oMDMap.end())
165 0 : CSLDestroy(oIter->second);
166 8 : oMDMap[pszDomain] = papszMD;
167 8 : UnrefUnderlyingRasterBand(_poSrcBand);
168 :
169 8 : return papszMD;
170 : }
171 :
172 0 : return GDALPamRasterBand::GetMetadata(pszDomain);
173 : }
174 :
175 :
176 8 : const char *NITFProxyPamRasterBand::GetMetadataItem( const char * pszName,
177 : const char * pszDomain )
178 : {
179 8 : const char* pszRet = GDALPamRasterBand::GetMetadataItem(pszName, pszDomain);
180 8 : if (pszRet)
181 0 : return pszRet;
182 :
183 8 : GDALRasterBand* _poSrcBand = RefUnderlyingRasterBand();
184 8 : if (_poSrcBand)
185 : {
186 8 : pszRet = _poSrcBand->GetMetadataItem( pszName, pszDomain );
187 8 : UnrefUnderlyingRasterBand(_poSrcBand);
188 : }
189 :
190 8 : return pszRet;
191 : }
192 :
193 4 : CPLErr NITFProxyPamRasterBand::GetStatistics( int bApproxOK, int bForce,
194 : double *pdfMin, double *pdfMax,
195 : double *pdfMean, double *pdfStdDev )
196 : {
197 : CPLErr ret;
198 :
199 : /* -------------------------------------------------------------------- */
200 : /* Do we already have metadata items for the requested values? */
201 : /* -------------------------------------------------------------------- */
202 4 : if( (pdfMin == NULL || GetMetadataItem("STATISTICS_MINIMUM") != NULL)
203 0 : && (pdfMax == NULL || GetMetadataItem("STATISTICS_MAXIMUM") != NULL)
204 0 : && (pdfMean == NULL || GetMetadataItem("STATISTICS_MEAN") != NULL)
205 0 : && (pdfStdDev == NULL || GetMetadataItem("STATISTICS_STDDEV") != NULL) )
206 : {
207 : return GDALPamRasterBand::GetStatistics( bApproxOK, bForce,
208 : pdfMin, pdfMax,
209 0 : pdfMean, pdfStdDev);
210 : }
211 :
212 4 : GDALRasterBand* _poSrcBand = RefUnderlyingRasterBand();
213 4 : if (_poSrcBand)
214 : {
215 : ret = _poSrcBand->GetStatistics( bApproxOK, bForce,
216 4 : pdfMin, pdfMax, pdfMean, pdfStdDev);
217 4 : if (ret == CE_None)
218 : {
219 : /* Report underlying statistics at PAM level */
220 : SetMetadataItem("STATISTICS_MINIMUM",
221 4 : _poSrcBand->GetMetadataItem("STATISTICS_MINIMUM"));
222 : SetMetadataItem("STATISTICS_MAXIMUM",
223 4 : _poSrcBand->GetMetadataItem("STATISTICS_MAXIMUM"));
224 : SetMetadataItem("STATISTICS_MEAN",
225 4 : _poSrcBand->GetMetadataItem("STATISTICS_MEAN"));
226 : SetMetadataItem("STATISTICS_STDDEV",
227 4 : _poSrcBand->GetMetadataItem("STATISTICS_STDDEV"));
228 : }
229 4 : UnrefUnderlyingRasterBand(_poSrcBand);
230 : }
231 : else
232 : {
233 0 : ret = CE_Failure;
234 : }
235 4 : return ret;
236 : }
237 :
238 0 : CPLErr NITFProxyPamRasterBand::ComputeStatistics( int bApproxOK,
239 : double *pdfMin, double *pdfMax,
240 : double *pdfMean, double *pdfStdDev,
241 : GDALProgressFunc pfn, void *pProgressData )
242 : {
243 : CPLErr ret;
244 0 : GDALRasterBand* _poSrcBand = RefUnderlyingRasterBand();
245 0 : if (_poSrcBand)
246 : {
247 : ret = _poSrcBand->ComputeStatistics( bApproxOK, pdfMin, pdfMax,
248 : pdfMean, pdfStdDev,
249 0 : pfn, pProgressData);
250 0 : if (ret == CE_None)
251 : {
252 : /* Report underlying statistics at PAM level */
253 : SetMetadataItem("STATISTICS_MINIMUM",
254 0 : _poSrcBand->GetMetadataItem("STATISTICS_MINIMUM"));
255 : SetMetadataItem("STATISTICS_MAXIMUM",
256 0 : _poSrcBand->GetMetadataItem("STATISTICS_MAXIMUM"));
257 : SetMetadataItem("STATISTICS_MEAN",
258 0 : _poSrcBand->GetMetadataItem("STATISTICS_MEAN"));
259 : SetMetadataItem("STATISTICS_STDDEV",
260 0 : _poSrcBand->GetMetadataItem("STATISTICS_STDDEV"));
261 : }
262 0 : UnrefUnderlyingRasterBand(_poSrcBand);
263 : }
264 : else
265 : {
266 0 : ret = CE_Failure;
267 : }
268 0 : return ret;
269 : }
270 :
271 :
272 : #define RB_PROXY_METHOD_GET_DBL_WITH_SUCCESS(methodName) \
273 : double NITFProxyPamRasterBand::methodName( int *pbSuccess ) \
274 : { \
275 : int bSuccess = FALSE; \
276 : double dfRet = GDALPamRasterBand::methodName(&bSuccess); \
277 : if (bSuccess) \
278 : { \
279 : if (pbSuccess) \
280 : *pbSuccess = TRUE; \
281 : return dfRet; \
282 : } \
283 : GDALRasterBand* _poSrcBand = RefUnderlyingRasterBand(); \
284 : if (_poSrcBand) \
285 : { \
286 : dfRet = _poSrcBand->methodName( pbSuccess ); \
287 : UnrefUnderlyingRasterBand(_poSrcBand); \
288 : } \
289 : else \
290 : { \
291 : dfRet = 0; \
292 : } \
293 : return dfRet; \
294 : }
295 :
296 12 : RB_PROXY_METHOD_GET_DBL_WITH_SUCCESS(GetNoDataValue)
297 0 : RB_PROXY_METHOD_GET_DBL_WITH_SUCCESS(GetMinimum)
298 0 : RB_PROXY_METHOD_GET_DBL_WITH_SUCCESS(GetMaximum)
299 :
300 0 : RB_PROXY_METHOD_WITH_RET_AND_CALL_OTHER_METHOD(CPLErr, CE_Failure, IReadBlock, ReadBlock,
301 : ( int nXBlockOff, int nYBlockOff, void* pImage),
302 : (nXBlockOff, nYBlockOff, pImage) )
303 0 : RB_PROXY_METHOD_WITH_RET_AND_CALL_OTHER_METHOD(CPLErr, CE_Failure, IWriteBlock, WriteBlock,
304 : ( int nXBlockOff, int nYBlockOff, void* pImage),
305 : (nXBlockOff, nYBlockOff, pImage) )
306 21466 : RB_PROXY_METHOD_WITH_RET_AND_CALL_OTHER_METHOD(CPLErr, CE_Failure, IRasterIO, RasterIO,
307 : ( GDALRWFlag eRWFlag,
308 : int nXOff, int nYOff, int nXSize, int nYSize,
309 : void * pData, int nBufXSize, int nBufYSize,
310 : GDALDataType eBufType,
311 : int nPixelSpace,
312 : int nLineSpace ),
313 : (eRWFlag, nXOff, nYOff, nXSize, nYSize,
314 : pData, nBufXSize, nBufYSize, eBufType,
315 : nPixelSpace, nLineSpace ) )
316 :
317 112 : RB_PROXY_METHOD_WITH_RET(CPLErr, CE_Failure, FlushCache, (), ())
318 :
319 0 : RB_PROXY_METHOD_WITH_RET(GDALColorInterp, GCI_Undefined, GetColorInterpretation, (), ())
320 0 : RB_PROXY_METHOD_WITH_RET(GDALColorTable*, NULL, GetColorTable, (), ())
321 0 : RB_PROXY_METHOD_WITH_RET(CPLErr, CE_Failure, Fill,
322 : (double dfRealValue, double dfImaginaryValue),
323 : (dfRealValue, dfImaginaryValue))
324 :
325 2 : RB_PROXY_METHOD_WITH_RET(CPLErr, CE_Failure, ComputeRasterMinMax,
326 : ( int arg1, double* arg2 ), (arg1, arg2))
327 :
328 0 : RB_PROXY_METHOD_WITH_RET(int, 0, HasArbitraryOverviews, (), ())
329 8 : RB_PROXY_METHOD_WITH_RET(int, 0, GetOverviewCount, (), ())
330 6 : RB_PROXY_METHOD_WITH_RET(GDALRasterBand*, NULL, GetOverview, (int arg1), (arg1))
331 0 : RB_PROXY_METHOD_WITH_RET(GDALRasterBand*, NULL, GetRasterSampleOverview,
332 : (int arg1), (arg1))
333 :
334 0 : RB_PROXY_METHOD_WITH_RET(CPLErr, CE_Failure, BuildOverviews,
335 : (const char * arg1, int arg2, int *arg3,
336 : GDALProgressFunc arg4, void * arg5),
337 : (arg1, arg2, arg3, arg4, arg5))
338 :
339 0 : RB_PROXY_METHOD_WITH_RET(CPLErr, CE_Failure, AdviseRead,
340 : ( int nXOff, int nYOff, int nXSize, int nYSize,
341 : int nBufXSize, int nBufYSize,
342 : GDALDataType eDT, char **papszOptions ),
343 : (nXOff, nYOff, nXSize, nYSize, nBufXSize, nBufYSize, eDT, papszOptions))
344 :
345 0 : RB_PROXY_METHOD_WITH_RET(GDALRasterBand*, NULL, GetMaskBand, (), ())
346 12 : RB_PROXY_METHOD_WITH_RET(int, 0, GetMaskFlags, (), ())
347 0 : RB_PROXY_METHOD_WITH_RET(CPLErr, CE_Failure, CreateMaskBand, ( int nFlags ), (nFlags))
348 :
349 :
350 : /************************************************************************/
351 : /* UnrefUnderlyingRasterBand() */
352 : /************************************************************************/
353 :
354 21638 : void NITFProxyPamRasterBand::UnrefUnderlyingRasterBand(GDALRasterBand* poUnderlyingRasterBand)
355 : {
356 21638 : }
357 :
358 :
359 : /************************************************************************/
360 : /* ==================================================================== */
361 : /* NITFRasterBand */
362 : /* ==================================================================== */
363 : /************************************************************************/
364 :
365 : /************************************************************************/
366 : /* NITFRasterBand() */
367 : /************************************************************************/
368 :
369 421436 : NITFRasterBand::NITFRasterBand( NITFDataset *poDS, int nBand )
370 :
371 : {
372 421436 : NITFBandInfo *psBandInfo = poDS->psImage->pasBandInfo + nBand - 1;
373 :
374 421436 : this->poDS = poDS;
375 421436 : this->nBand = nBand;
376 :
377 421436 : this->eAccess = poDS->eAccess;
378 421436 : this->psImage = poDS->psImage;
379 :
380 : /* -------------------------------------------------------------------- */
381 : /* Translate data type(s). */
382 : /* -------------------------------------------------------------------- */
383 421436 : if( psImage->nBitsPerSample <= 8 )
384 421204 : eDataType = GDT_Byte;
385 286 : else if( psImage->nBitsPerSample == 16
386 : && EQUAL(psImage->szPVType,"SI") )
387 54 : eDataType = GDT_Int16;
388 178 : else if( psImage->nBitsPerSample == 16 )
389 24 : eDataType = GDT_UInt16;
390 154 : else if( psImage->nBitsPerSample == 12 )
391 36 : eDataType = GDT_UInt16;
392 142 : else if( psImage->nBitsPerSample == 32
393 : && EQUAL(psImage->szPVType,"SI") )
394 24 : eDataType = GDT_Int32;
395 122 : else if( psImage->nBitsPerSample == 32
396 : && EQUAL(psImage->szPVType,"R") )
397 28 : eDataType = GDT_Float32;
398 66 : else if( psImage->nBitsPerSample == 32 )
399 24 : eDataType = GDT_UInt32;
400 66 : else if( psImage->nBitsPerSample == 64
401 : && EQUAL(psImage->szPVType,"R") )
402 24 : eDataType = GDT_Float64;
403 36 : else if( psImage->nBitsPerSample == 64
404 : && EQUAL(psImage->szPVType,"C") )
405 18 : eDataType = GDT_CFloat32;
406 : /* ERO : note I'm not sure if CFloat64 can be transmitted as NBPP is only 2 characters */
407 : else
408 : {
409 : int bOpenUnderlyingDS = CSLTestBoolean(
410 0 : CPLGetConfigOption("NITF_OPEN_UNDERLYING_DS", "YES"));
411 0 : if (!bOpenUnderlyingDS && psImage->nBitsPerSample > 8 && psImage->nBitsPerSample < 16)
412 : {
413 0 : if (EQUAL(psImage->szPVType,"SI"))
414 0 : eDataType = GDT_Int16;
415 : else
416 0 : eDataType = GDT_UInt16;
417 : }
418 : else
419 : {
420 0 : eDataType = GDT_Unknown;
421 : CPLError( CE_Warning, CPLE_AppDefined,
422 : "Unsupported combination of PVTYPE(%s) and NBPP(%d).",
423 0 : psImage->szPVType, psImage->nBitsPerSample );
424 : }
425 : }
426 :
427 : /* -------------------------------------------------------------------- */
428 : /* Work out block size. If the image is all one big block we */
429 : /* handle via the scanline access API. */
430 : /* -------------------------------------------------------------------- */
431 842444 : if( psImage->nBlocksPerRow == 1
432 : && psImage->nBlocksPerColumn == 1
433 : && psImage->nBitsPerSample >= 8
434 : && EQUAL(psImage->szIC,"NC") )
435 : {
436 421008 : bScanlineAccess = TRUE;
437 421008 : nBlockXSize = psImage->nBlockWidth;
438 421008 : nBlockYSize = 1;
439 : }
440 : else
441 : {
442 428 : bScanlineAccess = FALSE;
443 428 : nBlockXSize = psImage->nBlockWidth;
444 428 : nBlockYSize = psImage->nBlockHeight;
445 : }
446 :
447 : /* -------------------------------------------------------------------- */
448 : /* Do we have a color table? */
449 : /* -------------------------------------------------------------------- */
450 : poColorTable = NITFMakeColorTable(psImage,
451 421436 : psBandInfo);
452 :
453 421436 : if( psImage->nBitsPerSample == 1
454 : || psImage->nBitsPerSample == 3
455 : || psImage->nBitsPerSample == 5
456 : || psImage->nBitsPerSample == 6
457 : || psImage->nBitsPerSample == 7
458 : || psImage->nBitsPerSample == 12 )
459 204 : SetMetadataItem( "NBITS", CPLString().Printf("%d", psImage->nBitsPerSample), "IMAGE_STRUCTURE" );
460 :
461 421436 : pUnpackData = 0;
462 421436 : if (psImage->nBitsPerSample == 3
463 : || psImage->nBitsPerSample == 5
464 : || psImage->nBitsPerSample == 6
465 : || psImage->nBitsPerSample == 7)
466 128 : pUnpackData = new GByte[((nBlockXSize*nBlockYSize+7)/8)*8];
467 421436 : }
468 :
469 : /************************************************************************/
470 : /* ~NITFRasterBand() */
471 : /************************************************************************/
472 :
473 421436 : NITFRasterBand::~NITFRasterBand()
474 :
475 : {
476 421436 : if( poColorTable != NULL )
477 110 : delete poColorTable;
478 :
479 421436 : delete[] pUnpackData;
480 421436 : }
481 :
482 : /************************************************************************/
483 : /* IReadBlock() */
484 : /************************************************************************/
485 :
486 46254 : CPLErr NITFRasterBand::IReadBlock( int nBlockXOff, int nBlockYOff,
487 : void * pImage )
488 :
489 : {
490 : int nBlockResult;
491 46254 : NITFDataset *poGDS = (NITFDataset *) poDS;
492 :
493 : /* -------------------------------------------------------------------- */
494 : /* Special case for JPEG blocks. */
495 : /* -------------------------------------------------------------------- */
496 46254 : if( EQUAL(psImage->szIC,"C3") || EQUAL(psImage->szIC,"M3") )
497 : {
498 110 : CPLErr eErr = poGDS->ReadJPEGBlock( nBlockXOff, nBlockYOff );
499 : int nBlockBandSize = psImage->nBlockWidth*psImage->nBlockHeight*
500 110 : (GDALGetDataTypeSize(eDataType)/8);
501 :
502 110 : if( eErr != CE_None )
503 0 : return eErr;
504 :
505 : memcpy( pImage,
506 : poGDS->pabyJPEGBlock + (nBand - 1) * nBlockBandSize,
507 110 : nBlockBandSize );
508 :
509 110 : return eErr;
510 : }
511 :
512 : /* -------------------------------------------------------------------- */
513 : /* Read the line/block */
514 : /* -------------------------------------------------------------------- */
515 46144 : if( bScanlineAccess )
516 : {
517 : nBlockResult =
518 42094 : NITFReadImageLine(psImage, nBlockYOff, nBand, pImage);
519 : }
520 : else
521 : {
522 : nBlockResult =
523 4050 : NITFReadImageBlock(psImage, nBlockXOff, nBlockYOff, nBand, pImage);
524 : }
525 :
526 46144 : if( nBlockResult == BLKREAD_OK )
527 : {
528 45706 : if( psImage->nBitsPerSample % 8 )
529 144 : Unpack((GByte*)pImage);
530 :
531 45706 : return CE_None;
532 : }
533 :
534 438 : 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 438 : if( psImage->bNoDataSet )
543 : memset( pImage, psImage->nNoDataValue,
544 438 : psImage->nWordSize*psImage->nBlockWidth*psImage->nBlockHeight);
545 : else
546 : memset( pImage, 0,
547 0 : psImage->nWordSize*psImage->nBlockWidth*psImage->nBlockHeight);
548 :
549 438 : return CE_None;
550 : }
551 :
552 : /************************************************************************/
553 : /* IWriteBlock() */
554 : /************************************************************************/
555 :
556 13308 : CPLErr NITFRasterBand::IWriteBlock( int nBlockXOff, int nBlockYOff,
557 : void * pImage )
558 :
559 : {
560 : int nBlockResult;
561 :
562 : /* -------------------------------------------------------------------- */
563 : /* Write the line/block */
564 : /* -------------------------------------------------------------------- */
565 13308 : if( bScanlineAccess )
566 : {
567 : nBlockResult =
568 12018 : NITFWriteImageLine(psImage, nBlockYOff, nBand, pImage);
569 : }
570 : else
571 : {
572 : nBlockResult =
573 1290 : NITFWriteImageBlock(psImage, nBlockXOff, nBlockYOff, nBand,pImage);
574 : }
575 :
576 13308 : if( nBlockResult == BLKREAD_OK )
577 13308 : return CE_None;
578 : else
579 0 : return CE_Failure;
580 : }
581 :
582 : /************************************************************************/
583 : /* GetNoDataValue() */
584 : /************************************************************************/
585 :
586 152 : double NITFRasterBand::GetNoDataValue( int *pbSuccess )
587 :
588 : {
589 152 : if( pbSuccess != NULL )
590 150 : *pbSuccess = psImage->bNoDataSet;
591 :
592 152 : if( psImage->bNoDataSet )
593 38 : return psImage->nNoDataValue;
594 : else
595 114 : return GDALPamRasterBand::GetNoDataValue( pbSuccess );
596 : }
597 :
598 : /************************************************************************/
599 : /* GetColorInterpretation() */
600 : /************************************************************************/
601 :
602 246 : GDALColorInterp NITFRasterBand::GetColorInterpretation()
603 :
604 : {
605 246 : NITFBandInfo *psBandInfo = psImage->pasBandInfo + nBand - 1;
606 :
607 246 : if( poColorTable != NULL )
608 34 : return GCI_PaletteIndex;
609 :
610 212 : if( EQUAL(psBandInfo->szIREPBAND,"R") )
611 32 : return GCI_RedBand;
612 180 : if( EQUAL(psBandInfo->szIREPBAND,"G") )
613 32 : return GCI_GreenBand;
614 148 : if( EQUAL(psBandInfo->szIREPBAND,"B") )
615 32 : return GCI_BlueBand;
616 116 : if( EQUAL(psBandInfo->szIREPBAND,"M") )
617 80 : return GCI_GrayIndex;
618 36 : if( EQUAL(psBandInfo->szIREPBAND,"Y") )
619 4 : return GCI_YCbCr_YBand;
620 32 : if( EQUAL(psBandInfo->szIREPBAND,"Cb") )
621 4 : return GCI_YCbCr_CbBand;
622 28 : if( EQUAL(psBandInfo->szIREPBAND,"Cr") )
623 4 : return GCI_YCbCr_CrBand;
624 :
625 24 : return GCI_Undefined;
626 : }
627 :
628 : /************************************************************************/
629 : /* NITFSetColorInterpretation() */
630 : /************************************************************************/
631 :
632 48 : CPLErr NITFSetColorInterpretation( NITFImage *psImage,
633 : int nBand,
634 : GDALColorInterp eInterp )
635 :
636 : {
637 48 : NITFBandInfo *psBandInfo = psImage->pasBandInfo + nBand - 1;
638 48 : const char *pszREP = NULL;
639 : GUIntBig nOffset;
640 :
641 48 : if( eInterp == GCI_RedBand )
642 16 : pszREP = "R";
643 32 : else if( eInterp == GCI_GreenBand )
644 16 : pszREP = "G";
645 16 : else if( eInterp == GCI_BlueBand )
646 16 : pszREP = "B";
647 0 : else if( eInterp == GCI_GrayIndex )
648 0 : pszREP = "M";
649 0 : else if( eInterp == GCI_YCbCr_YBand )
650 0 : pszREP = "Y";
651 0 : else if( eInterp == GCI_YCbCr_CbBand )
652 0 : pszREP = "Cb";
653 0 : else if( eInterp == GCI_YCbCr_CrBand )
654 0 : pszREP = "Cr";
655 0 : else if( eInterp == GCI_Undefined )
656 0 : return CE_None;
657 :
658 48 : if( pszREP == NULL )
659 : {
660 : CPLError( CE_Failure, CPLE_NotSupported,
661 : "Requested color interpretation (%s) not supported in NITF.",
662 0 : GDALGetColorInterpretationName( eInterp ) );
663 0 : return CE_Failure;
664 : }
665 :
666 : /* -------------------------------------------------------------------- */
667 : /* Where does this go in the file? */
668 : /* -------------------------------------------------------------------- */
669 48 : strcpy( psBandInfo->szIREPBAND, pszREP );
670 48 : nOffset = NITFIHFieldOffset( psImage, "IREPBAND" );
671 :
672 48 : if( nOffset != 0 )
673 48 : nOffset += (nBand - 1) * 13;
674 :
675 : /* -------------------------------------------------------------------- */
676 : /* write it (space padded). */
677 : /* -------------------------------------------------------------------- */
678 : char szPadded[4];
679 48 : strcpy( szPadded, pszREP );
680 48 : strcat( szPadded, " " );
681 :
682 48 : if( nOffset != 0 )
683 : {
684 48 : if( VSIFSeekL( psImage->psFile->fp, nOffset, SEEK_SET ) != 0
685 : || VSIFWriteL( (void *) szPadded, 1, 2, psImage->psFile->fp ) != 2 )
686 : {
687 : CPLError( CE_Failure, CPLE_AppDefined,
688 0 : "IO failure writing new IREPBAND value to NITF file." );
689 0 : return CE_Failure;
690 : }
691 : }
692 :
693 48 : return CE_None;
694 : }
695 :
696 : /************************************************************************/
697 : /* SetColorInterpretation() */
698 : /************************************************************************/
699 :
700 42 : CPLErr NITFRasterBand::SetColorInterpretation( GDALColorInterp eInterp )
701 :
702 : {
703 42 : return NITFSetColorInterpretation( psImage, nBand, eInterp );
704 : }
705 :
706 : /************************************************************************/
707 : /* GetColorTable() */
708 : /************************************************************************/
709 :
710 72 : GDALColorTable *NITFRasterBand::GetColorTable()
711 :
712 : {
713 72 : return poColorTable;
714 : }
715 :
716 : /************************************************************************/
717 : /* SetColorTable() */
718 : /************************************************************************/
719 :
720 4 : CPLErr NITFRasterBand::SetColorTable( GDALColorTable *poNewCT )
721 :
722 : {
723 4 : NITFDataset *poGDS = (NITFDataset *) poDS;
724 4 : if( poGDS->bInLoadXML )
725 0 : return GDALPamRasterBand::SetColorTable(poNewCT);
726 :
727 4 : if( poNewCT == NULL )
728 0 : return CE_Failure;
729 :
730 : GByte abyNITFLUT[768];
731 : int i;
732 4 : int nCount = MIN(256,poNewCT->GetColorEntryCount());
733 :
734 4 : memset( abyNITFLUT, 0, 768 );
735 270 : for( i = 0; i < nCount; i++ )
736 : {
737 : GDALColorEntry sEntry;
738 :
739 266 : poNewCT->GetColorEntryAsRGB( i, &sEntry );
740 266 : abyNITFLUT[i ] = (GByte) sEntry.c1;
741 266 : abyNITFLUT[i+256] = (GByte) sEntry.c2;
742 266 : abyNITFLUT[i+512] = (GByte) sEntry.c3;
743 : }
744 :
745 4 : if( NITFWriteLUT( psImage, nBand, nCount, abyNITFLUT ) )
746 4 : return CE_None;
747 : else
748 0 : return CE_Failure;
749 : }
750 :
751 : /************************************************************************/
752 : /* Unpack() */
753 : /************************************************************************/
754 :
755 144 : void NITFRasterBand::Unpack( GByte* pData )
756 : {
757 144 : long n = nBlockXSize*nBlockYSize;
758 : long i;
759 : long k;
760 :
761 144 : GByte abyTempData[7] = {0, 0, 0, 0, 0, 0, 0};
762 144 : const GByte* pDataSrc = pData;
763 144 : if (n < psImage->nBitsPerSample &&
764 : psImage->nBitsPerSample < 8)
765 : {
766 42 : memcpy(abyTempData, pData, n);
767 42 : pDataSrc = abyTempData;
768 : }
769 :
770 144 : switch (psImage->nBitsPerSample)
771 : {
772 : case 1:
773 : {
774 : // unpack 1-bit in-place in reverse
775 2101052 : for (i = n; --i >= 0; )
776 2101004 : pData[i] = (pData[i>>3] & (0x80 >> (i&7))) != 0;
777 :
778 24 : break;
779 : }
780 : case 2:
781 : {
782 : static const int s_Shift2[] = {6, 4, 2, 0};
783 : // unpack 2-bit in-place in reverse
784 104 : for (i = n; --i >= 0; )
785 72 : pData[i] = (pData[i>>2] >> (GByte)s_Shift2[i&3]) & 0x03;
786 :
787 16 : break;
788 : }
789 : case 4:
790 : {
791 : static const int s_Shift4[] = {4, 0};
792 : // unpack 4-bit in-place in reverse
793 104 : for (i = n; --i >= 0; )
794 72 : pData[i] = (pData[i>>1] >> (GByte)s_Shift4[i&1]) & 0x0f;
795 :
796 16 : break;
797 : }
798 : case 3:
799 : {
800 : // unpacks 8 pixels (3 bytes) at time
801 32 : for (i = 0, k = 0; i < n; i += 8, k += 3)
802 : {
803 16 : pUnpackData[i+0] = ((pDataSrc[k+0] >> 5));
804 16 : pUnpackData[i+1] = ((pDataSrc[k+0] >> 2) & 0x07);
805 16 : pUnpackData[i+2] = ((pDataSrc[k+0] << 1) & 0x07) | (pDataSrc[k+1] >> 7);
806 16 : pUnpackData[i+3] = ((pDataSrc[k+1] >> 4) & 0x07);
807 16 : pUnpackData[i+4] = ((pDataSrc[k+1] >> 1) & 0x07);
808 16 : pUnpackData[i+5] = ((pDataSrc[k+1] << 2) & 0x07) | (pDataSrc[k+2] >> 6);
809 16 : pUnpackData[i+6] = ((pDataSrc[k+2] >> 3) & 0x07);
810 16 : pUnpackData[i+7] = ((pDataSrc[k+2]) & 0x7);
811 : }
812 :
813 16 : memcpy(pData, pUnpackData, n);
814 16 : break;
815 : }
816 : case 5:
817 : {
818 : // unpacks 8 pixels (5 bytes) at time
819 32 : for (i = 0, k = 0; i < n; i += 8, k += 5)
820 : {
821 16 : pUnpackData[i+0] = ((pDataSrc[k+0] >> 3));
822 16 : pUnpackData[i+1] = ((pDataSrc[k+0] << 2) & 0x1f) | (pDataSrc[k+1] >> 6);
823 16 : pUnpackData[i+2] = ((pDataSrc[k+1] >> 1) & 0x1f);
824 16 : pUnpackData[i+3] = ((pDataSrc[k+1] << 4) & 0x1f) | (pDataSrc[k+2] >> 4);
825 16 : pUnpackData[i+4] = ((pDataSrc[k+2] << 1) & 0x1f) | (pDataSrc[k+3] >> 7);
826 16 : pUnpackData[i+5] = ((pDataSrc[k+3] >> 2) & 0x1f);
827 16 : pUnpackData[i+6] = ((pDataSrc[k+3] << 3) & 0x1f) | (pDataSrc[k+4] >> 5);
828 16 : pUnpackData[i+7] = ((pDataSrc[k+4]) & 0x1f);
829 : }
830 :
831 16 : memcpy(pData, pUnpackData, n);
832 16 : break;
833 : }
834 : case 6:
835 : {
836 : // unpacks 4 pixels (3 bytes) at time
837 40 : for (i = 0, k = 0; i < n; i += 4, k += 3)
838 : {
839 24 : pUnpackData[i+0] = ((pDataSrc[k+0] >> 2));
840 24 : pUnpackData[i+1] = ((pDataSrc[k+0] << 4) & 0x3f) | (pDataSrc[k+1] >> 4);
841 24 : pUnpackData[i+2] = ((pDataSrc[k+1] << 2) & 0x3f) | (pDataSrc[k+2] >> 6);
842 24 : pUnpackData[i+3] = ((pDataSrc[k+2]) & 0x3f);
843 : }
844 :
845 16 : memcpy(pData, pUnpackData, n);
846 16 : break;
847 : }
848 : case 7:
849 : {
850 : // unpacks 8 pixels (7 bytes) at time
851 32 : for (i = 0, k = 0; i < n; i += 8, k += 7)
852 : {
853 16 : pUnpackData[i+0] = ((pDataSrc[k+0] >> 1));
854 16 : pUnpackData[i+1] = ((pDataSrc[k+0] << 6) & 0x7f) | (pDataSrc[k+1] >> 2);
855 16 : pUnpackData[i+2] = ((pDataSrc[k+1] << 5) & 0x7f) | (pDataSrc[k+2] >> 3) ;
856 16 : pUnpackData[i+3] = ((pDataSrc[k+2] << 4) & 0x7f) | (pDataSrc[k+3] >> 4);
857 16 : pUnpackData[i+4] = ((pDataSrc[k+3] << 3) & 0x7f) | (pDataSrc[k+4] >> 5);
858 16 : pUnpackData[i+5] = ((pDataSrc[k+4] << 2) & 0x7f) | (pDataSrc[k+5] >> 6);
859 16 : pUnpackData[i+6] = ((pDataSrc[k+5] << 1) & 0x7f) | (pDataSrc[k+6] >> 7);
860 16 : pUnpackData[i+7] = ((pDataSrc[k+6]) & 0x7f);
861 : }
862 :
863 16 : memcpy(pData, pUnpackData, n);
864 16 : break;
865 : }
866 : case 12:
867 : {
868 24 : GByte* pabyImage = (GByte *)pData;
869 24 : GUInt16* panImage = (GUInt16*)pData;
870 2097272 : for (i = n; --i >= 0; )
871 : {
872 2097224 : long iOffset = i*3 / 2;
873 2097224 : if (i % 2 == 0)
874 1048616 : panImage[i] = pabyImage[iOffset] + (pabyImage[iOffset+1] & 0xf0) * 16;
875 : else
876 1048608 : panImage[i] = (pabyImage[iOffset] & 0x0f) * 16
877 1048608 : + (pabyImage[iOffset+1] & 0xf0) / 16
878 2097216 : + (pabyImage[iOffset+1] & 0x0f) * 256;
879 : }
880 :
881 : break;
882 : }
883 : }
884 144 : }
885 :
886 : /************************************************************************/
887 : /* ==================================================================== */
888 : /* NITFWrapperRasterBand */
889 : /* ==================================================================== */
890 : /************************************************************************/
891 :
892 : /************************************************************************/
893 : /* NITFWrapperRasterBand() */
894 : /************************************************************************/
895 :
896 112 : NITFWrapperRasterBand::NITFWrapperRasterBand( NITFDataset * poDS,
897 : GDALRasterBand* poBaseBand,
898 112 : int nBand)
899 : {
900 112 : this->poDS = poDS;
901 112 : this->nBand = nBand;
902 112 : this->poBaseBand = poBaseBand;
903 112 : eDataType = poBaseBand->GetRasterDataType();
904 112 : poBaseBand->GetBlockSize(&nBlockXSize, &nBlockYSize);
905 112 : poColorTable = NULL;
906 112 : eInterp = poBaseBand->GetColorInterpretation();
907 112 : }
908 :
909 : /************************************************************************/
910 : /* ~NITFWrapperRasterBand() */
911 : /************************************************************************/
912 :
913 112 : NITFWrapperRasterBand::~NITFWrapperRasterBand()
914 : {
915 112 : if( poColorTable != NULL )
916 8 : delete poColorTable;
917 112 : }
918 :
919 : /************************************************************************/
920 : /* RefUnderlyingRasterBand() */
921 : /************************************************************************/
922 :
923 : /* We don't need ref-counting. Just return the base band */
924 21638 : GDALRasterBand* NITFWrapperRasterBand::RefUnderlyingRasterBand()
925 : {
926 21638 : return poBaseBand;
927 : }
928 :
929 : /************************************************************************/
930 : /* GetColorTable() */
931 : /************************************************************************/
932 :
933 26 : GDALColorTable *NITFWrapperRasterBand::GetColorTable()
934 : {
935 26 : return poColorTable;
936 : }
937 :
938 : /************************************************************************/
939 : /* SetColorTableFromNITFBandInfo() */
940 : /************************************************************************/
941 :
942 8 : void NITFWrapperRasterBand::SetColorTableFromNITFBandInfo()
943 : {
944 8 : NITFDataset* poGDS = (NITFDataset* )poDS;
945 : poColorTable = NITFMakeColorTable(poGDS->psImage,
946 8 : poGDS->psImage->pasBandInfo + nBand - 1);
947 8 : }
948 :
949 : /************************************************************************/
950 : /* GetColorInterpretation() */
951 : /************************************************************************/
952 :
953 64 : GDALColorInterp NITFWrapperRasterBand::GetColorInterpretation()
954 : {
955 64 : return eInterp;
956 : }
957 :
958 : /************************************************************************/
959 : /* SetColorInterpretation() */
960 : /************************************************************************/
961 :
962 100 : CPLErr NITFWrapperRasterBand::SetColorInterpretation( GDALColorInterp eInterp)
963 : {
964 100 : this->eInterp = eInterp;
965 100 : return CE_None;
966 : }
967 :
|