1 /******************************************************************************
2 * $Id: openjpegdataset.cpp 29330 2015-06-14 12:11:11Z rouault $
3 *
4 * Project: JPEG2000 driver based on OpenJPEG library
5 * Purpose: JPEG2000 driver based on OpenJPEG library
6 * Author: Even Rouault, <even dot rouault at spatialys dot com>
7 *
8 ******************************************************************************
9 * Copyright (c) 2010-2014, Even Rouault <even dot rouault at spatialys dot com>
10 * Copyright (c) 2015, European Union (European Environment Agency)
11 *
12 * Permission is hereby granted, free of charge, to any person obtaining a
13 * copy of this software and associated documentation files (the "Software"),
14 * to deal in the Software without restriction, including without limitation
15 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
16 * and/or sell copies of the Software, and to permit persons to whom the
17 * Software is furnished to do so, subject to the following conditions:
18 *
19 * The above copyright notice and this permission notice shall be included
20 * in all copies or substantial portions of the Software.
21 *
22 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
23 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
24 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
25 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
26 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
27 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
28 * DEALINGS IN THE SOFTWARE.
29 ****************************************************************************/
30
31 /* This file is to be used with openjpeg 2.0 */
32
33 #if defined(OPENJPEG_VERSION) && OPENJPEG_VERSION >= 20100
34 #include <openjpeg-2.1/openjpeg.h>
35 #else
36 #include <stdio.h> /* openjpeg.h needs FILE* */
37 #include <openjpeg-2.0/openjpeg.h>
38 #endif
39 #include <vector>
40
41 #include "gdaljp2abstractdataset.h"
42 #include "cpl_string.h"
43 #include "gdaljp2metadata.h"
44 #include "cpl_multiproc.h"
45 #include "cpl_atomic_ops.h"
46 #include "vrt/vrtdataset.h"
47
48 CPL_CVSID("$Id: openjpegdataset.cpp 29330 2015-06-14 12:11:11Z rouault $");
49
50 /************************************************************************/
51 /* JP2OpenJPEGDataset_ErrorCallback() */
52 /************************************************************************/
53
JP2OpenJPEGDataset_ErrorCallback(const char * pszMsg,CPL_UNUSED void * unused)54 static void JP2OpenJPEGDataset_ErrorCallback(const char *pszMsg, CPL_UNUSED void *unused)
55 {
56 CPLError(CE_Failure, CPLE_AppDefined, "%s", pszMsg);
57 }
58
59 /************************************************************************/
60 /* JP2OpenJPEGDataset_WarningCallback() */
61 /************************************************************************/
62
JP2OpenJPEGDataset_WarningCallback(const char * pszMsg,CPL_UNUSED void * unused)63 static void JP2OpenJPEGDataset_WarningCallback(const char *pszMsg, CPL_UNUSED void *unused)
64 {
65 if( strcmp(pszMsg, "Empty SOT marker detected: Psot=12.\n") == 0 )
66 {
67 static int bWarningEmitted = FALSE;
68 if( bWarningEmitted )
69 return;
70 bWarningEmitted = TRUE;
71 }
72 if( strcmp(pszMsg, "JP2 box which are after the codestream will not be read by this function.\n") != 0 )
73 CPLError(CE_Warning, CPLE_AppDefined, "%s", pszMsg);
74 }
75
76 /************************************************************************/
77 /* JP2OpenJPEGDataset_InfoCallback() */
78 /************************************************************************/
79
JP2OpenJPEGDataset_InfoCallback(const char * pszMsg,CPL_UNUSED void * unused)80 static void JP2OpenJPEGDataset_InfoCallback(const char *pszMsg, CPL_UNUSED void *unused)
81 {
82 char* pszMsgTmp = CPLStrdup(pszMsg);
83 int nLen = (int)strlen(pszMsgTmp);
84 while( nLen > 0 && pszMsgTmp[nLen-1] == '\n' )
85 {
86 pszMsgTmp[nLen-1] = '\0';
87 nLen --;
88 }
89 CPLDebug("OPENJPEG", "info: %s", pszMsgTmp);
90 CPLFree(pszMsgTmp);
91 }
92
93 typedef struct
94 {
95 VSILFILE* fp;
96 vsi_l_offset nBaseOffset;
97 } JP2OpenJPEGFile;
98
99 /************************************************************************/
100 /* JP2OpenJPEGDataset_Read() */
101 /************************************************************************/
102
JP2OpenJPEGDataset_Read(void * pBuffer,OPJ_SIZE_T nBytes,void * pUserData)103 static OPJ_SIZE_T JP2OpenJPEGDataset_Read(void* pBuffer, OPJ_SIZE_T nBytes,
104 void *pUserData)
105 {
106 JP2OpenJPEGFile* psJP2OpenJPEGFile = (JP2OpenJPEGFile* )pUserData;
107 int nRet = VSIFReadL(pBuffer, 1, nBytes, psJP2OpenJPEGFile->fp);
108 #ifdef DEBUG_IO
109 CPLDebug("OPENJPEG", "JP2OpenJPEGDataset_Read(%d) = %d", (int)nBytes, nRet);
110 #endif
111 if (nRet == 0)
112 nRet = -1;
113
114 return nRet;
115 }
116
117 /************************************************************************/
118 /* JP2OpenJPEGDataset_Write() */
119 /************************************************************************/
120
JP2OpenJPEGDataset_Write(void * pBuffer,OPJ_SIZE_T nBytes,void * pUserData)121 static OPJ_SIZE_T JP2OpenJPEGDataset_Write(void* pBuffer, OPJ_SIZE_T nBytes,
122 void *pUserData)
123 {
124 JP2OpenJPEGFile* psJP2OpenJPEGFile = (JP2OpenJPEGFile* )pUserData;
125 int nRet = VSIFWriteL(pBuffer, 1, nBytes, psJP2OpenJPEGFile->fp);
126 #ifdef DEBUG_IO
127 CPLDebug("OPENJPEG", "JP2OpenJPEGDataset_Write(%d) = %d", (int)nBytes, nRet);
128 #endif
129 return nRet;
130 }
131
132 /************************************************************************/
133 /* JP2OpenJPEGDataset_Seek() */
134 /************************************************************************/
135
JP2OpenJPEGDataset_Seek(OPJ_OFF_T nBytes,void * pUserData)136 static OPJ_BOOL JP2OpenJPEGDataset_Seek(OPJ_OFF_T nBytes, void * pUserData)
137 {
138 JP2OpenJPEGFile* psJP2OpenJPEGFile = (JP2OpenJPEGFile* )pUserData;
139 #ifdef DEBUG_IO
140 CPLDebug("OPENJPEG", "JP2OpenJPEGDataset_Seek(%d)", (int)nBytes);
141 #endif
142 return VSIFSeekL(psJP2OpenJPEGFile->fp, psJP2OpenJPEGFile->nBaseOffset +nBytes,
143 SEEK_SET) == 0;
144 }
145
146 /************************************************************************/
147 /* JP2OpenJPEGDataset_Skip() */
148 /************************************************************************/
149
JP2OpenJPEGDataset_Skip(OPJ_OFF_T nBytes,void * pUserData)150 static OPJ_OFF_T JP2OpenJPEGDataset_Skip(OPJ_OFF_T nBytes, void * pUserData)
151 {
152 JP2OpenJPEGFile* psJP2OpenJPEGFile = (JP2OpenJPEGFile* )pUserData;
153 vsi_l_offset nOffset = VSIFTellL(psJP2OpenJPEGFile->fp);
154 nOffset += nBytes;
155 #ifdef DEBUG_IO
156 CPLDebug("OPENJPEG", "JP2OpenJPEGDataset_Skip(%d -> " CPL_FRMT_GUIB ")",
157 (int)nBytes, (GUIntBig)nOffset);
158 #endif
159 VSIFSeekL(psJP2OpenJPEGFile->fp, nOffset, SEEK_SET);
160 return nBytes;
161 }
162
163 /************************************************************************/
164 /* ==================================================================== */
165 /* JP2OpenJPEGDataset */
166 /* ==================================================================== */
167 /************************************************************************/
168
169 class JP2OpenJPEGRasterBand;
170
171 class JP2OpenJPEGDataset : public GDALJP2AbstractDataset
172 {
173 friend class JP2OpenJPEGRasterBand;
174
175 VSILFILE *fp; /* Large FILE API */
176 vsi_l_offset nCodeStreamStart;
177 vsi_l_offset nCodeStreamLength;
178
179 OPJ_COLOR_SPACE eColorSpace;
180 int nRedIndex;
181 int nGreenIndex;
182 int nBlueIndex;
183 int nAlphaIndex;
184
185 int bIs420;
186
187 int iLevel;
188 int nOverviewCount;
189 JP2OpenJPEGDataset** papoOverviewDS;
190 int bUseSetDecodeArea;
191
192 int nThreads;
193 int GetNumThreads();
194 int bEnoughMemoryToLoadOtherBands;
195 int bRewrite;
196 int bHasGeoreferencingAtOpening;
197
198 protected:
199 virtual int CloseDependentDatasets();
200
201 public:
202 JP2OpenJPEGDataset();
203 ~JP2OpenJPEGDataset();
204
205 static int Identify( GDALOpenInfo * poOpenInfo );
206 static GDALDataset *Open( GDALOpenInfo * );
207 static GDALDataset *CreateCopy( const char * pszFilename,
208 GDALDataset *poSrcDS,
209 int bStrict, char ** papszOptions,
210 GDALProgressFunc pfnProgress,
211 void * pProgressData );
212
213 virtual CPLErr SetProjection( const char * );
214 virtual CPLErr SetGeoTransform( double* );
215 virtual CPLErr SetGCPs( int nGCPCount, const GDAL_GCP *pasGCPList,
216 const char *pszGCPProjection );
217 virtual CPLErr SetMetadata( char ** papszMetadata,
218 const char * pszDomain = "" );
219 virtual CPLErr SetMetadataItem( const char * pszName,
220 const char * pszValue,
221 const char * pszDomain = "" );
222
223 virtual CPLErr IRasterIO( GDALRWFlag eRWFlag,
224 int nXOff, int nYOff, int nXSize, int nYSize,
225 void * pData, int nBufXSize, int nBufYSize,
226 GDALDataType eBufType,
227 int nBandCount, int *panBandMap,
228 GSpacing nPixelSpace, GSpacing nLineSpace,
229 GSpacing nBandSpace,
230 GDALRasterIOExtraArg* psExtraArg);
231
232 static void WriteBox(VSILFILE* fp, GDALJP2Box* poBox);
233 static void WriteGDALMetadataBox( VSILFILE* fp, GDALDataset* poSrcDS,
234 char** papszOptions );
235 static void WriteXMLBoxes( VSILFILE* fp, GDALDataset* poSrcDS,
236 char** papszOptions );
237 static void WriteXMPBox( VSILFILE* fp, GDALDataset* poSrcDS,
238 char** papszOptions );
239 static void WriteIPRBox( VSILFILE* fp, GDALDataset* poSrcDS,
240 char** papszOptions );
241
242 CPLErr ReadBlock( int nBand, VSILFILE* fp,
243 int nBlockXOff, int nBlockYOff, void * pImage,
244 int nBandCount, int *panBandMap );
245
246 int PreloadBlocks( JP2OpenJPEGRasterBand* poBand,
247 int nXOff, int nYOff, int nXSize, int nYSize,
248 int nBandCount, int *panBandMap );
249 };
250
251 /************************************************************************/
252 /* ==================================================================== */
253 /* JP2OpenJPEGRasterBand */
254 /* ==================================================================== */
255 /************************************************************************/
256
257 class JP2OpenJPEGRasterBand : public GDALPamRasterBand
258 {
259 friend class JP2OpenJPEGDataset;
260 int bPromoteTo8Bit;
261 GDALColorTable* poCT;
262
263 public:
264
265 JP2OpenJPEGRasterBand( JP2OpenJPEGDataset * poDS, int nBand,
266 GDALDataType eDataType, int nBits,
267 int bPromoteTo8Bit,
268 int nBlockXSize, int nBlockYSize );
269 ~JP2OpenJPEGRasterBand();
270
271 virtual CPLErr IReadBlock( int, int, void * );
272 virtual CPLErr IRasterIO( GDALRWFlag eRWFlag,
273 int nXOff, int nYOff, int nXSize, int nYSize,
274 void * pData, int nBufXSize, int nBufYSize,
275 GDALDataType eBufType,
276 GSpacing nPixelSpace, GSpacing nLineSpace,
277 GDALRasterIOExtraArg* psExtraArg);
278
279 virtual GDALColorInterp GetColorInterpretation();
GetColorTable()280 virtual GDALColorTable* GetColorTable() { return poCT; }
281
282 virtual int GetOverviewCount();
283 virtual GDALRasterBand* GetOverview(int iOvrLevel);
284
HasArbitraryOverviews()285 virtual int HasArbitraryOverviews() { return poCT == NULL; }
286 };
287
288
289 /************************************************************************/
290 /* JP2OpenJPEGRasterBand() */
291 /************************************************************************/
292
JP2OpenJPEGRasterBand(JP2OpenJPEGDataset * poDS,int nBand,GDALDataType eDataType,int nBits,int bPromoteTo8Bit,int nBlockXSize,int nBlockYSize)293 JP2OpenJPEGRasterBand::JP2OpenJPEGRasterBand( JP2OpenJPEGDataset *poDS, int nBand,
294 GDALDataType eDataType, int nBits,
295 int bPromoteTo8Bit,
296 int nBlockXSize, int nBlockYSize )
297
298 {
299 this->eDataType = eDataType;
300 this->nBlockXSize = nBlockXSize;
301 this->nBlockYSize = nBlockYSize;
302 this->bPromoteTo8Bit = bPromoteTo8Bit;
303 poCT = NULL;
304
305 if( (nBits % 8) != 0 )
306 GDALRasterBand::SetMetadataItem("NBITS",
307 CPLString().Printf("%d",nBits),
308 "IMAGE_STRUCTURE" );
309 GDALRasterBand::SetMetadataItem("COMPRESSION", "JPEG2000",
310 "IMAGE_STRUCTURE" );
311 this->poDS = poDS;
312 this->nBand = nBand;
313 }
314
315 /************************************************************************/
316 /* ~JP2OpenJPEGRasterBand() */
317 /************************************************************************/
318
~JP2OpenJPEGRasterBand()319 JP2OpenJPEGRasterBand::~JP2OpenJPEGRasterBand()
320 {
321 delete poCT;
322 }
323
324 /************************************************************************/
325 /* CLAMP_0_255() */
326 /************************************************************************/
327
CLAMP_0_255(int val)328 static CPL_INLINE GByte CLAMP_0_255(int val)
329 {
330 if (val < 0)
331 return 0;
332 else if (val > 255)
333 return 255;
334 else
335 return (GByte)val;
336 }
337
338 /************************************************************************/
339 /* IReadBlock() */
340 /************************************************************************/
341
IReadBlock(int nBlockXOff,int nBlockYOff,void * pImage)342 CPLErr JP2OpenJPEGRasterBand::IReadBlock( int nBlockXOff, int nBlockYOff,
343 void * pImage )
344 {
345 JP2OpenJPEGDataset *poGDS = (JP2OpenJPEGDataset *) poDS;
346 if ( poGDS->bEnoughMemoryToLoadOtherBands )
347 return poGDS->ReadBlock(nBand, poGDS->fp, nBlockXOff, nBlockYOff, pImage,
348 poGDS->nBands, NULL);
349 else
350 return poGDS->ReadBlock(nBand, poGDS->fp, nBlockXOff, nBlockYOff, pImage,
351 1, &nBand);
352 }
353
354 /************************************************************************/
355 /* IRasterIO() */
356 /************************************************************************/
357
IRasterIO(GDALRWFlag eRWFlag,int nXOff,int nYOff,int nXSize,int nYSize,void * pData,int nBufXSize,int nBufYSize,GDALDataType eBufType,GSpacing nPixelSpace,GSpacing nLineSpace,GDALRasterIOExtraArg * psExtraArg)358 CPLErr JP2OpenJPEGRasterBand::IRasterIO( GDALRWFlag eRWFlag,
359 int nXOff, int nYOff, int nXSize, int nYSize,
360 void * pData, int nBufXSize, int nBufYSize,
361 GDALDataType eBufType,
362 GSpacing nPixelSpace, GSpacing nLineSpace,
363 GDALRasterIOExtraArg* psExtraArg )
364 {
365 JP2OpenJPEGDataset *poGDS = (JP2OpenJPEGDataset *) poDS;
366
367 if( eRWFlag != GF_Read )
368 return CE_Failure;
369
370 /* ==================================================================== */
371 /* Do we have overviews that would be appropriate to satisfy */
372 /* this request? */
373 /* ==================================================================== */
374 if( (nBufXSize < nXSize || nBufYSize < nYSize)
375 && GetOverviewCount() > 0 && eRWFlag == GF_Read )
376 {
377 int nOverview;
378 GDALRasterIOExtraArg sExtraArg;
379
380 GDALCopyRasterIOExtraArg(&sExtraArg, psExtraArg);
381
382 nOverview =
383 GDALBandGetBestOverviewLevel2(this, nXOff, nYOff, nXSize, nYSize,
384 nBufXSize, nBufYSize, &sExtraArg);
385 if (nOverview >= 0)
386 {
387 GDALRasterBand* poOverviewBand = GetOverview(nOverview);
388 if (poOverviewBand == NULL)
389 return CE_Failure;
390
391 return poOverviewBand->RasterIO( eRWFlag, nXOff, nYOff, nXSize, nYSize,
392 pData, nBufXSize, nBufYSize, eBufType,
393 nPixelSpace, nLineSpace, &sExtraArg );
394 }
395 }
396
397 poGDS->bEnoughMemoryToLoadOtherBands = poGDS->PreloadBlocks(this, nXOff, nYOff, nXSize, nYSize, 0, NULL);
398
399 CPLErr eErr = GDALPamRasterBand::IRasterIO( eRWFlag, nXOff, nYOff, nXSize, nYSize,
400 pData, nBufXSize, nBufYSize, eBufType,
401 nPixelSpace, nLineSpace, psExtraArg );
402
403 poGDS->bEnoughMemoryToLoadOtherBands = TRUE;
404 return eErr;
405 }
406
407 /************************************************************************/
408 /* GetNumThreads() */
409 /************************************************************************/
410
GetNumThreads()411 int JP2OpenJPEGDataset::GetNumThreads()
412 {
413 if( nThreads >= 1 )
414 return nThreads;
415
416 const char* pszThreads = CPLGetConfigOption("GDAL_NUM_THREADS", "ALL_CPUS");
417 if (EQUAL(pszThreads, "ALL_CPUS"))
418 nThreads = CPLGetNumCPUs();
419 else
420 nThreads = atoi(pszThreads);
421 if (nThreads > 128)
422 nThreads = 128;
423 if (nThreads <= 0)
424 nThreads = 1;
425 return nThreads;
426 }
427
428 /************************************************************************/
429 /* JP2OpenJPEGReadBlockInThread() */
430 /************************************************************************/
431
432 class JobStruct
433 {
434 public:
435
436 JP2OpenJPEGDataset* poGDS;
437 int nBand;
438 std::vector< std::pair<int, int> > oPairs;
439 volatile int nCurPair;
440 int nBandCount;
441 int *panBandMap;
442 };
443
JP2OpenJPEGReadBlockInThread(void * userdata)444 static void JP2OpenJPEGReadBlockInThread(void* userdata)
445 {
446 int nPair;
447 JobStruct* poJob = (JobStruct*) userdata;
448 JP2OpenJPEGDataset* poGDS = poJob->poGDS;
449 int nBand = poJob->nBand;
450 int nPairs = (int)poJob->oPairs.size();
451 int nBandCount = poJob->nBandCount;
452 int* panBandMap = poJob->panBandMap;
453 VSILFILE* fp = VSIFOpenL(poGDS->GetDescription(), "rb");
454 if( fp == NULL )
455 {
456 CPLDebug("OPENJPEG", "Cannot open %s", poGDS->GetDescription());
457 return;
458 }
459
460 while( (nPair = CPLAtomicInc(&(poJob->nCurPair))) < nPairs )
461 {
462 int nBlockXOff = poJob->oPairs[nPair].first;
463 int nBlockYOff = poJob->oPairs[nPair].second;
464 GDALRasterBlock* poBlock = poGDS->GetRasterBand(nBand)->
465 GetLockedBlockRef(nBlockXOff,nBlockYOff, TRUE);
466 if (poBlock == NULL)
467 break;
468
469 void* pDstBuffer = poBlock->GetDataRef();
470 if (!pDstBuffer)
471 {
472 poBlock->DropLock();
473 break;
474 }
475
476 poGDS->ReadBlock(nBand, fp, nBlockXOff, nBlockYOff, pDstBuffer,
477 nBandCount, panBandMap);
478
479 poBlock->DropLock();
480 }
481
482 VSIFCloseL(fp);
483 }
484
485 /************************************************************************/
486 /* PreloadBlocks() */
487 /************************************************************************/
488
PreloadBlocks(JP2OpenJPEGRasterBand * poBand,int nXOff,int nYOff,int nXSize,int nYSize,int nBandCount,int * panBandMap)489 int JP2OpenJPEGDataset::PreloadBlocks(JP2OpenJPEGRasterBand* poBand,
490 int nXOff, int nYOff, int nXSize, int nYSize,
491 int nBandCount, int *panBandMap)
492 {
493 int bRet = TRUE;
494 int nXStart = nXOff / poBand->nBlockXSize;
495 int nXEnd = (nXOff + nXSize - 1) / poBand->nBlockXSize;
496 int nYStart = nYOff / poBand->nBlockYSize;
497 int nYEnd = (nYOff + nYSize - 1) / poBand->nBlockYSize;
498 GIntBig nReqMem = (GIntBig)(nXEnd - nXStart + 1) * (nYEnd - nYStart + 1) *
499 poBand->nBlockXSize * poBand->nBlockYSize * (GDALGetDataTypeSize(poBand->eDataType) / 8);
500
501 int nMaxThreads = GetNumThreads();
502 if( !bUseSetDecodeArea && nMaxThreads > 1 )
503 {
504 if( nReqMem > GDALGetCacheMax64() / (nBandCount == 0 ? 1 : nBandCount) )
505 return FALSE;
506
507 int nBlocksToLoad = 0;
508 std::vector< std::pair<int,int> > oPairs;
509 for(int nBlockXOff = nXStart; nBlockXOff <= nXEnd; ++nBlockXOff)
510 {
511 for(int nBlockYOff = nYStart; nBlockYOff <= nYEnd; ++nBlockYOff)
512 {
513 GDALRasterBlock* poBlock = poBand->TryGetLockedBlockRef(nBlockXOff,nBlockYOff);
514 if (poBlock != NULL)
515 {
516 poBlock->DropLock();
517 continue;
518 }
519 oPairs.push_back( std::pair<int,int>(nBlockXOff, nBlockYOff) );
520 nBlocksToLoad ++;
521 }
522 }
523
524 if( nBlocksToLoad > 1 )
525 {
526 int nThreads = MIN(nBlocksToLoad, nMaxThreads);
527 CPLJoinableThread** pahThreads = (CPLJoinableThread**) CPLMalloc( sizeof(CPLJoinableThread*) * nThreads );
528 int i;
529
530 CPLDebug("OPENJPEG", "%d blocks to load", nBlocksToLoad);
531
532 JobStruct oJob;
533 oJob.poGDS = this;
534 oJob.nBand = poBand->GetBand();
535 oJob.oPairs = oPairs;
536 oJob.nCurPair = -1;
537 if( nBandCount > 0 )
538 {
539 oJob.nBandCount = nBandCount;
540 oJob.panBandMap = panBandMap;
541 }
542 else
543 {
544 if( nReqMem <= GDALGetCacheMax64() / nBands )
545 {
546 oJob.nBandCount = nBands;
547 oJob.panBandMap = NULL;
548 }
549 else
550 {
551 bRet = FALSE;
552 oJob.nBandCount = 1;
553 oJob.panBandMap = &oJob.nBand;
554 }
555 }
556
557 /* Flushes all dirty blocks from cache to disk to avoid them */
558 /* to be flushed randomly, and simultaneously, from our worker threads, */
559 /* which might cause races in the output driver. */
560 /* This is a workaround to a design defect of the block cache */
561 GDALRasterBlock::FlushDirtyBlocks();
562
563 for(i=0;i<nThreads;i++)
564 pahThreads[i] = CPLCreateJoinableThread(JP2OpenJPEGReadBlockInThread, &oJob);
565 for(i=0;i<nThreads;i++)
566 CPLJoinThread( pahThreads[i] );
567 CPLFree(pahThreads);
568 }
569 }
570
571 return bRet;
572 }
573
574 /************************************************************************/
575 /* IRasterIO() */
576 /************************************************************************/
577
IRasterIO(GDALRWFlag eRWFlag,int nXOff,int nYOff,int nXSize,int nYSize,void * pData,int nBufXSize,int nBufYSize,GDALDataType eBufType,int nBandCount,int * panBandMap,GSpacing nPixelSpace,GSpacing nLineSpace,GSpacing nBandSpace,GDALRasterIOExtraArg * psExtraArg)578 CPLErr JP2OpenJPEGDataset::IRasterIO( GDALRWFlag eRWFlag,
579 int nXOff, int nYOff, int nXSize, int nYSize,
580 void * pData, int nBufXSize, int nBufYSize,
581 GDALDataType eBufType,
582 int nBandCount, int *panBandMap,
583 GSpacing nPixelSpace, GSpacing nLineSpace,
584 GSpacing nBandSpace,
585 GDALRasterIOExtraArg* psExtraArg)
586 {
587 if( eRWFlag != GF_Read )
588 return CE_Failure;
589
590 if( nBandCount < 1 )
591 return CE_Failure;
592
593 JP2OpenJPEGRasterBand* poBand = (JP2OpenJPEGRasterBand*) GetRasterBand(panBandMap[0]);
594
595 /* ==================================================================== */
596 /* Do we have overviews that would be appropriate to satisfy */
597 /* this request? */
598 /* ==================================================================== */
599
600 if( (nBufXSize < nXSize || nBufYSize < nYSize)
601 && poBand->GetOverviewCount() > 0 && eRWFlag == GF_Read )
602 {
603 int nOverview;
604 GDALRasterIOExtraArg sExtraArg;
605
606 GDALCopyRasterIOExtraArg(&sExtraArg, psExtraArg);
607
608 nOverview =
609 GDALBandGetBestOverviewLevel2(poBand, nXOff, nYOff, nXSize, nYSize,
610 nBufXSize, nBufYSize, &sExtraArg);
611 if (nOverview >= 0)
612 {
613 return papoOverviewDS[nOverview]->RasterIO( eRWFlag, nXOff, nYOff, nXSize, nYSize,
614 pData, nBufXSize, nBufYSize, eBufType,
615 nBandCount, panBandMap,
616 nPixelSpace, nLineSpace, nBandSpace,
617 &sExtraArg);
618 }
619 }
620
621 bEnoughMemoryToLoadOtherBands = PreloadBlocks(poBand, nXOff, nYOff, nXSize, nYSize, nBandCount, panBandMap);
622
623 CPLErr eErr = GDALPamDataset::IRasterIO( eRWFlag,
624 nXOff, nYOff, nXSize, nYSize,
625 pData, nBufXSize, nBufYSize,
626 eBufType,
627 nBandCount, panBandMap,
628 nPixelSpace, nLineSpace, nBandSpace,
629 psExtraArg );
630
631 bEnoughMemoryToLoadOtherBands = TRUE;
632 return eErr;
633 }
634
635 /************************************************************************/
636 /* JP2OpenJPEGCreateReadStream() */
637 /************************************************************************/
638
JP2OpenJPEGCreateReadStream(JP2OpenJPEGFile * psJP2OpenJPEGFile,vsi_l_offset nSize)639 static opj_stream_t* JP2OpenJPEGCreateReadStream(JP2OpenJPEGFile* psJP2OpenJPEGFile,
640 vsi_l_offset nSize)
641 {
642 opj_stream_t *pStream = opj_stream_create(1024, TRUE); // Default 1MB is way too big for some datasets
643
644 VSIFSeekL(psJP2OpenJPEGFile->fp, psJP2OpenJPEGFile->nBaseOffset, SEEK_SET);
645 opj_stream_set_user_data_length(pStream, nSize);
646
647 opj_stream_set_read_function(pStream, JP2OpenJPEGDataset_Read);
648 opj_stream_set_seek_function(pStream, JP2OpenJPEGDataset_Seek);
649 opj_stream_set_skip_function(pStream, JP2OpenJPEGDataset_Skip);
650 #if defined(OPENJPEG_VERSION) && OPENJPEG_VERSION >= 20100
651 opj_stream_set_user_data(pStream, psJP2OpenJPEGFile, NULL);
652 #else
653 opj_stream_set_user_data(pStream, psJP2OpenJPEGFile);
654 #endif
655
656 return pStream;
657 }
658
659 /************************************************************************/
660 /* ReadBlock() */
661 /************************************************************************/
662
ReadBlock(int nBand,VSILFILE * fp,int nBlockXOff,int nBlockYOff,void * pImage,int nBandCount,int * panBandMap)663 CPLErr JP2OpenJPEGDataset::ReadBlock( int nBand, VSILFILE* fp,
664 int nBlockXOff, int nBlockYOff, void * pImage,
665 int nBandCount, int* panBandMap )
666 {
667 CPLErr eErr = CE_None;
668 opj_codec_t* pCodec;
669 opj_stream_t * pStream;
670 opj_image_t * psImage;
671
672 JP2OpenJPEGRasterBand* poBand = (JP2OpenJPEGRasterBand*) GetRasterBand(nBand);
673 int nBlockXSize = poBand->nBlockXSize;
674 int nBlockYSize = poBand->nBlockYSize;
675 GDALDataType eDataType = poBand->eDataType;
676
677 int nDataTypeSize = (GDALGetDataTypeSize(eDataType) / 8);
678
679 int nTileNumber = nBlockXOff + nBlockYOff * poBand->nBlocksPerRow;
680 int nWidthToRead = MIN(nBlockXSize, nRasterXSize - nBlockXOff * nBlockXSize);
681 int nHeightToRead = MIN(nBlockYSize, nRasterYSize - nBlockYOff * nBlockYSize);
682
683 pCodec = opj_create_decompress(OPJ_CODEC_J2K);
684
685 opj_set_info_handler(pCodec, JP2OpenJPEGDataset_InfoCallback,NULL);
686 opj_set_warning_handler(pCodec, JP2OpenJPEGDataset_WarningCallback, NULL);
687 opj_set_error_handler(pCodec, JP2OpenJPEGDataset_ErrorCallback,NULL);
688
689 opj_dparameters_t parameters;
690 opj_set_default_decoder_parameters(¶meters);
691
692 if (! opj_setup_decoder(pCodec,¶meters))
693 {
694 CPLError(CE_Failure, CPLE_AppDefined, "opj_setup_decoder() failed");
695 return CE_Failure;
696 }
697
698 JP2OpenJPEGFile sJP2OpenJPEGFile;
699 sJP2OpenJPEGFile.fp = fp;
700 sJP2OpenJPEGFile.nBaseOffset = nCodeStreamStart;
701 pStream = JP2OpenJPEGCreateReadStream(&sJP2OpenJPEGFile, nCodeStreamLength);
702
703 if(!opj_read_header(pStream,pCodec,&psImage))
704 {
705 CPLError(CE_Failure, CPLE_AppDefined, "opj_read_header() failed");
706 return CE_Failure;
707 }
708
709 if (!opj_set_decoded_resolution_factor( pCodec, iLevel ))
710 {
711 CPLError(CE_Failure, CPLE_AppDefined, "opj_set_decoded_resolution_factor() failed");
712 eErr = CE_Failure;
713 goto end;
714 }
715
716 if (bUseSetDecodeArea)
717 {
718 if (!opj_set_decode_area(pCodec,psImage,
719 nBlockXOff*nBlockXSize,
720 nBlockYOff*nBlockYSize,
721 nBlockXOff*nBlockXSize+nWidthToRead,
722 nBlockYOff*nBlockYSize+nHeightToRead))
723 {
724 CPLError(CE_Failure, CPLE_AppDefined, "opj_set_decode_area() failed");
725 eErr = CE_Failure;
726 goto end;
727 }
728 if (!opj_decode(pCodec,pStream, psImage))
729 {
730 CPLError(CE_Failure, CPLE_AppDefined, "opj_decode() failed");
731 eErr = CE_Failure;
732 goto end;
733 }
734 }
735 else
736 {
737 if (!opj_get_decoded_tile( pCodec, pStream, psImage, nTileNumber ))
738 {
739 CPLError(CE_Failure, CPLE_AppDefined, "opj_get_decoded_tile() failed");
740 eErr = CE_Failure;
741 goto end;
742 }
743 }
744
745 for(int xBand = 0; xBand < nBandCount; xBand ++)
746 {
747 void* pDstBuffer;
748 GDALRasterBlock *poBlock = NULL;
749 int iBand = (panBandMap) ? panBandMap[xBand] : xBand + 1;
750 int bPromoteTo8Bit = ((JP2OpenJPEGRasterBand*)GetRasterBand(iBand))->bPromoteTo8Bit;
751
752 if (iBand == nBand)
753 pDstBuffer = pImage;
754 else
755 {
756 poBlock = ((JP2OpenJPEGRasterBand*)GetRasterBand(iBand))->
757 TryGetLockedBlockRef(nBlockXOff,nBlockYOff);
758 if (poBlock != NULL)
759 {
760 poBlock->DropLock();
761 continue;
762 }
763
764 poBlock = GetRasterBand(iBand)->
765 GetLockedBlockRef(nBlockXOff,nBlockYOff, TRUE);
766 if (poBlock == NULL)
767 {
768 continue;
769 }
770
771 pDstBuffer = poBlock->GetDataRef();
772 if (!pDstBuffer)
773 {
774 poBlock->DropLock();
775 continue;
776 }
777 }
778
779 if (bIs420)
780 {
781 CPLAssert((int)psImage->comps[0].w >= nWidthToRead);
782 CPLAssert((int)psImage->comps[0].h >= nHeightToRead);
783 CPLAssert(psImage->comps[1].w == (psImage->comps[0].w + 1) / 2);
784 CPLAssert(psImage->comps[1].h == (psImage->comps[0].h + 1) / 2);
785 CPLAssert(psImage->comps[2].w == (psImage->comps[0].w + 1) / 2);
786 CPLAssert(psImage->comps[2].h == (psImage->comps[0].h + 1) / 2);
787 if( nBands == 4 )
788 {
789 CPLAssert((int)psImage->comps[3].w >= nWidthToRead);
790 CPLAssert((int)psImage->comps[3].h >= nHeightToRead);
791 }
792
793 OPJ_INT32* pSrcY = psImage->comps[0].data;
794 OPJ_INT32* pSrcCb = psImage->comps[1].data;
795 OPJ_INT32* pSrcCr = psImage->comps[2].data;
796 OPJ_INT32* pSrcA = (nBands == 4) ? psImage->comps[3].data : NULL;
797 GByte* pDst = (GByte*)pDstBuffer;
798 for(int j=0;j<nHeightToRead;j++)
799 {
800 for(int i=0;i<nWidthToRead;i++)
801 {
802 int Y = pSrcY[j * psImage->comps[0].w + i];
803 int Cb = pSrcCb[(j/2) * psImage->comps[1].w + (i/2)];
804 int Cr = pSrcCr[(j/2) * psImage->comps[2].w + (i/2)];
805 if (iBand == 1)
806 pDst[j * nBlockXSize + i] = CLAMP_0_255((int)(Y + 1.402 * (Cr - 128)));
807 else if (iBand == 2)
808 pDst[j * nBlockXSize + i] = CLAMP_0_255((int)(Y - 0.34414 * (Cb - 128) - 0.71414 * (Cr - 128)));
809 else if (iBand == 3)
810 pDst[j * nBlockXSize + i] = CLAMP_0_255((int)(Y + 1.772 * (Cb - 128)));
811 else if (iBand == 4)
812 pDst[j * nBlockXSize + i] = pSrcA[j * psImage->comps[0].w + i];
813 }
814 }
815
816 if( bPromoteTo8Bit )
817 {
818 for(int j=0;j<nHeightToRead;j++)
819 {
820 for(int i=0;i<nWidthToRead;i++)
821 {
822 pDst[j * nBlockXSize + i] *= 255;
823 }
824 }
825 }
826 }
827 else
828 {
829 CPLAssert((int)psImage->comps[iBand-1].w >= nWidthToRead);
830 CPLAssert((int)psImage->comps[iBand-1].h >= nHeightToRead);
831
832 if( bPromoteTo8Bit )
833 {
834 for(int j=0;j<nHeightToRead;j++)
835 {
836 for(int i=0;i<nWidthToRead;i++)
837 {
838 psImage->comps[iBand-1].data[j * psImage->comps[iBand-1].w + i] *= 255;
839 }
840 }
841 }
842
843 if ((int)psImage->comps[iBand-1].w == nBlockXSize &&
844 (int)psImage->comps[iBand-1].h == nBlockYSize)
845 {
846 GDALCopyWords(psImage->comps[iBand-1].data, GDT_Int32, 4,
847 pDstBuffer, eDataType, nDataTypeSize, nBlockXSize * nBlockYSize);
848 }
849 else
850 {
851 for(int j=0;j<nHeightToRead;j++)
852 {
853 GDALCopyWords(psImage->comps[iBand-1].data + j * psImage->comps[iBand-1].w, GDT_Int32, 4,
854 (GByte*)pDstBuffer + j * nBlockXSize * nDataTypeSize, eDataType, nDataTypeSize,
855 nWidthToRead);
856 }
857 }
858 }
859
860 if (poBlock != NULL)
861 poBlock->DropLock();
862 }
863
864 end:
865 opj_end_decompress(pCodec,pStream);
866 opj_stream_destroy(pStream);
867 opj_destroy_codec(pCodec);
868 opj_image_destroy(psImage);
869
870 return eErr;
871 }
872
873
874 /************************************************************************/
875 /* GetOverviewCount() */
876 /************************************************************************/
877
GetOverviewCount()878 int JP2OpenJPEGRasterBand::GetOverviewCount()
879 {
880 JP2OpenJPEGDataset *poGDS = (JP2OpenJPEGDataset *) poDS;
881 return poGDS->nOverviewCount;
882 }
883
884 /************************************************************************/
885 /* GetOverview() */
886 /************************************************************************/
887
GetOverview(int iOvrLevel)888 GDALRasterBand* JP2OpenJPEGRasterBand::GetOverview(int iOvrLevel)
889 {
890 JP2OpenJPEGDataset *poGDS = (JP2OpenJPEGDataset *) poDS;
891 if (iOvrLevel < 0 || iOvrLevel >= poGDS->nOverviewCount)
892 return NULL;
893
894 return poGDS->papoOverviewDS[iOvrLevel]->GetRasterBand(nBand);
895 }
896
897 /************************************************************************/
898 /* GetColorInterpretation() */
899 /************************************************************************/
900
GetColorInterpretation()901 GDALColorInterp JP2OpenJPEGRasterBand::GetColorInterpretation()
902 {
903 JP2OpenJPEGDataset *poGDS = (JP2OpenJPEGDataset *) poDS;
904
905 if( poCT )
906 return GCI_PaletteIndex;
907
908 if( nBand == poGDS->nAlphaIndex + 1 )
909 return GCI_AlphaBand;
910
911 if (poGDS->nBands <= 2 && poGDS->eColorSpace == OPJ_CLRSPC_GRAY)
912 return GCI_GrayIndex;
913 else if (poGDS->eColorSpace == OPJ_CLRSPC_SRGB ||
914 poGDS->eColorSpace == OPJ_CLRSPC_SYCC)
915 {
916 if( nBand == poGDS->nRedIndex + 1 )
917 return GCI_RedBand;
918 if( nBand == poGDS->nGreenIndex + 1 )
919 return GCI_GreenBand;
920 if( nBand == poGDS->nBlueIndex + 1 )
921 return GCI_BlueBand;
922 }
923
924 return GCI_Undefined;
925 }
926
927 /************************************************************************/
928 /* ==================================================================== */
929 /* JP2OpenJPEGDataset */
930 /* ==================================================================== */
931 /************************************************************************/
932
933 /************************************************************************/
934 /* JP2OpenJPEGDataset() */
935 /************************************************************************/
936
JP2OpenJPEGDataset()937 JP2OpenJPEGDataset::JP2OpenJPEGDataset()
938 {
939 fp = NULL;
940 nCodeStreamStart = 0;
941 nCodeStreamLength = 0;
942 nBands = 0;
943 eColorSpace = OPJ_CLRSPC_UNKNOWN;
944 nRedIndex = 0;
945 nGreenIndex = 1;
946 nBlueIndex = 2;
947 nAlphaIndex = -1;
948 bIs420 = FALSE;
949 iLevel = 0;
950 nOverviewCount = 0;
951 papoOverviewDS = NULL;
952 bUseSetDecodeArea = FALSE;
953 nThreads = -1;
954 bEnoughMemoryToLoadOtherBands = TRUE;
955 bRewrite = FALSE;
956 bHasGeoreferencingAtOpening = FALSE;
957 }
958
959 /************************************************************************/
960 /* ~JP2OpenJPEGDataset() */
961 /************************************************************************/
962
~JP2OpenJPEGDataset()963 JP2OpenJPEGDataset::~JP2OpenJPEGDataset()
964
965 {
966 FlushCache();
967
968 if( iLevel == 0 && fp != NULL )
969 {
970 if( bRewrite )
971 {
972 GDALJP2Box oBox( fp );
973 vsi_l_offset nOffsetJP2C = 0, nLengthJP2C = 0,
974 nOffsetXML = 0, nOffsetASOC = 0, nOffsetUUID = 0,
975 nOffsetIHDR = 0, nLengthIHDR = 0;
976 int bMSIBox = FALSE, bGMLData = FALSE;
977 int bUnsupportedConfiguration = FALSE;
978 if( oBox.ReadFirst() )
979 {
980 while( strlen(oBox.GetType()) > 0 )
981 {
982 if( EQUAL(oBox.GetType(),"jp2c") )
983 {
984 if( nOffsetJP2C == 0 )
985 {
986 nOffsetJP2C = VSIFTellL(fp);
987 nLengthJP2C = oBox.GetDataLength();
988 }
989 else
990 bUnsupportedConfiguration = TRUE;
991 }
992 else if( EQUAL(oBox.GetType(),"jp2h") )
993 {
994 GDALJP2Box oSubBox( fp );
995 if( oSubBox.ReadFirstChild( &oBox ) &&
996 EQUAL(oSubBox.GetType(),"ihdr") )
997 {
998 nOffsetIHDR = VSIFTellL(fp);
999 nLengthIHDR = oSubBox.GetDataLength();
1000 }
1001 }
1002 else if( EQUAL(oBox.GetType(),"xml ") )
1003 {
1004 if( nOffsetXML == 0 )
1005 nOffsetXML = VSIFTellL(fp);
1006 }
1007 else if( EQUAL(oBox.GetType(),"asoc") )
1008 {
1009 if( nOffsetASOC == 0 )
1010 nOffsetASOC = VSIFTellL(fp);
1011
1012 GDALJP2Box oSubBox( fp );
1013 if( oSubBox.ReadFirstChild( &oBox ) &&
1014 EQUAL(oSubBox.GetType(),"lbl ") )
1015 {
1016 char *pszLabel = (char *) oSubBox.ReadBoxData();
1017 if( pszLabel != NULL && EQUAL(pszLabel,"gml.data") )
1018 {
1019 bGMLData = TRUE;
1020 }
1021 else
1022 bUnsupportedConfiguration = TRUE;
1023 CPLFree( pszLabel );
1024 }
1025 else
1026 bUnsupportedConfiguration = TRUE;
1027 }
1028 else if( EQUAL(oBox.GetType(),"uuid") )
1029 {
1030 if( nOffsetUUID == 0 )
1031 nOffsetUUID = VSIFTellL(fp);
1032 if( GDALJP2Metadata::IsUUID_MSI(oBox.GetUUID()) )
1033 bMSIBox = TRUE;
1034 else if( !GDALJP2Metadata::IsUUID_XMP(oBox.GetUUID()) )
1035 bUnsupportedConfiguration = TRUE;
1036 }
1037 else if( !EQUAL(oBox.GetType(),"jP ") &&
1038 !EQUAL(oBox.GetType(),"ftyp") &&
1039 !EQUAL(oBox.GetType(),"rreq") &&
1040 !EQUAL(oBox.GetType(),"jp2h") &&
1041 !EQUAL(oBox.GetType(),"jp2i") )
1042 {
1043 bUnsupportedConfiguration = TRUE;
1044 }
1045
1046 if (bUnsupportedConfiguration || !oBox.ReadNext())
1047 break;
1048 }
1049 }
1050
1051 const char* pszGMLJP2;
1052 int bGeoreferencingCompatOfGMLJP2 =
1053 ((pszProjection != NULL && pszProjection[0] != '\0' ) &&
1054 bGeoTransformValid && nGCPCount == 0);
1055 if( bGeoreferencingCompatOfGMLJP2 &&
1056 ((bHasGeoreferencingAtOpening && bGMLData) ||
1057 (!bHasGeoreferencingAtOpening)) )
1058 pszGMLJP2 = "GMLJP2=YES";
1059 else
1060 pszGMLJP2 = "GMLJP2=NO";
1061
1062 const char* pszGeoJP2;
1063 int bGeoreferencingCompatOfGeoJP2 =
1064 ((pszProjection != NULL && pszProjection[0] != '\0' ) ||
1065 nGCPCount != 0 || bGeoTransformValid);
1066 if( bGeoreferencingCompatOfGeoJP2 &&
1067 ((bHasGeoreferencingAtOpening && bMSIBox) ||
1068 (!bHasGeoreferencingAtOpening) || nGCPCount > 0) )
1069 pszGeoJP2 = "GeoJP2=YES";
1070 else
1071 pszGeoJP2 = "GeoJP2=NO";
1072
1073 /* Test that the length of the JP2C box is not 0 */
1074 int bJP2CBoxOKForRewriteInPlace = TRUE;
1075 if( nOffsetJP2C > 16 && !bUnsupportedConfiguration )
1076 {
1077 VSIFSeekL(fp, nOffsetJP2C - 8, SEEK_SET);
1078 GByte abyBuffer[8];
1079 VSIFReadL(abyBuffer, 1, 8, fp);
1080 if( EQUALN((const char*)abyBuffer + 4, "jp2c", 4) &&
1081 abyBuffer[0] == 0 && abyBuffer[1] == 0 &&
1082 abyBuffer[2] == 0 && abyBuffer[3] == 0 )
1083 {
1084 if( (vsi_l_offset)(GUInt32)(nLengthJP2C + 8) == (nLengthJP2C + 8) )
1085 {
1086 CPLDebug("OPENJPEG", "Patching length of JP2C box with real length");
1087 VSIFSeekL(fp, nOffsetJP2C - 8, SEEK_SET);
1088 GUInt32 nLength = (GUInt32)nLengthJP2C + 8;
1089 CPL_MSBPTR32(&nLength);
1090 VSIFWriteL(&nLength, 1, 4, fp);
1091 }
1092 else
1093 bJP2CBoxOKForRewriteInPlace = FALSE;
1094 }
1095 }
1096
1097 if( nOffsetJP2C == 0 || bUnsupportedConfiguration )
1098 {
1099 CPLError(CE_Failure, CPLE_AppDefined,
1100 "Cannot rewrite file due to unsupported JP2 box configuration");
1101 VSIFCloseL( fp );
1102 }
1103 else if( bJP2CBoxOKForRewriteInPlace &&
1104 (nOffsetXML == 0 || nOffsetXML > nOffsetJP2C) &&
1105 (nOffsetASOC == 0 || nOffsetASOC > nOffsetJP2C) &&
1106 (nOffsetUUID == 0 || nOffsetUUID > nOffsetJP2C) )
1107 {
1108 CPLDebug("OPENJPEG", "Rewriting boxes after codestream");
1109
1110 /* Update IPR flag */
1111 if( nLengthIHDR == 14 )
1112 {
1113 VSIFSeekL( fp, nOffsetIHDR + nLengthIHDR - 1, SEEK_SET );
1114 GByte bIPR = GetMetadata("xml:IPR") != NULL;
1115 VSIFWriteL( &bIPR, 1, 1, fp );
1116 }
1117
1118 VSIFSeekL( fp, nOffsetJP2C + nLengthJP2C, SEEK_SET );
1119
1120 GDALJP2Metadata oJP2MD;
1121 if( GetGCPCount() > 0 )
1122 {
1123 oJP2MD.SetGCPs( GetGCPCount(),
1124 GetGCPs() );
1125 oJP2MD.SetProjection( GetGCPProjection() );
1126 }
1127 else
1128 {
1129 const char* pszWKT = GetProjectionRef();
1130 if( pszWKT != NULL && pszWKT[0] != '\0' )
1131 {
1132 oJP2MD.SetProjection( pszWKT );
1133 }
1134 if( bGeoTransformValid )
1135 {
1136 oJP2MD.SetGeoTransform( adfGeoTransform );
1137 }
1138 }
1139
1140 const char* pszAreaOrPoint = GetMetadataItem(GDALMD_AREA_OR_POINT);
1141 oJP2MD.bPixelIsPoint = pszAreaOrPoint != NULL && EQUAL(pszAreaOrPoint, GDALMD_AOP_POINT);
1142
1143 WriteIPRBox(fp, this, NULL);
1144
1145 if( bGeoreferencingCompatOfGMLJP2 && EQUAL(pszGMLJP2, "GMLJP2=YES") )
1146 {
1147 GDALJP2Box* poBox = oJP2MD.CreateGMLJP2(nRasterXSize,nRasterYSize);
1148 WriteBox(fp, poBox);
1149 delete poBox;
1150 }
1151
1152 WriteXMLBoxes(fp, this, NULL);
1153 WriteGDALMetadataBox(fp, this, NULL);
1154
1155 if( bGeoreferencingCompatOfGeoJP2 && EQUAL(pszGeoJP2, "GeoJP2=YES") )
1156 {
1157 GDALJP2Box* poBox = oJP2MD.CreateJP2GeoTIFF();
1158 WriteBox(fp, poBox);
1159 delete poBox;
1160 }
1161
1162 WriteXMPBox(fp, this, NULL);
1163
1164 VSIFTruncateL( fp, VSIFTellL(fp) );
1165
1166 VSIFCloseL( fp );
1167 }
1168 else
1169 {
1170 VSIFCloseL( fp );
1171
1172 CPLDebug("OPENJPEG", "Rewriting whole file");
1173
1174 const char* apszOptions[] = {
1175 "USE_SRC_CODESTREAM=YES", "CODEC=JP2", "WRITE_METADATA=YES",
1176 NULL, NULL, NULL };
1177 apszOptions[3] = pszGMLJP2;
1178 apszOptions[4] = pszGeoJP2;
1179 CPLString osTmpFilename(CPLSPrintf("%s.tmp", GetDescription()));
1180 GDALDataset* poOutDS = CreateCopy( osTmpFilename, this, FALSE,
1181 (char**)apszOptions, GDALDummyProgress, NULL );
1182 if( poOutDS )
1183 {
1184 GDALClose(poOutDS);
1185 VSIRename(osTmpFilename, GetDescription());
1186 }
1187 else
1188 VSIUnlink(osTmpFilename);
1189 VSIUnlink(CPLSPrintf("%s.tmp.aux.xml", GetDescription()));
1190 }
1191 }
1192 else
1193 VSIFCloseL( fp );
1194 }
1195
1196 CloseDependentDatasets();
1197 }
1198
1199 /************************************************************************/
1200 /* CloseDependentDatasets() */
1201 /************************************************************************/
1202
CloseDependentDatasets()1203 int JP2OpenJPEGDataset::CloseDependentDatasets()
1204 {
1205 int bRet = GDALJP2AbstractDataset::CloseDependentDatasets();
1206 if ( papoOverviewDS )
1207 {
1208 for( int i = 0; i < nOverviewCount; i++ )
1209 delete papoOverviewDS[i];
1210 CPLFree( papoOverviewDS );
1211 papoOverviewDS = NULL;
1212 bRet = TRUE;
1213 }
1214 return bRet;
1215 }
1216
1217 /************************************************************************/
1218 /* SetProjection() */
1219 /************************************************************************/
1220
SetProjection(const char * pszProjectionIn)1221 CPLErr JP2OpenJPEGDataset::SetProjection( const char * pszProjectionIn )
1222 {
1223 if( eAccess == GA_Update )
1224 {
1225 bRewrite = TRUE;
1226 CPLFree(pszProjection);
1227 pszProjection = (pszProjectionIn) ? CPLStrdup(pszProjectionIn) : CPLStrdup("");
1228 return CE_None;
1229 }
1230 else
1231 return GDALJP2AbstractDataset::SetProjection(pszProjectionIn);
1232 }
1233
1234 /************************************************************************/
1235 /* SetGeoTransform() */
1236 /************************************************************************/
1237
SetGeoTransform(double * padfGeoTransform)1238 CPLErr JP2OpenJPEGDataset::SetGeoTransform( double *padfGeoTransform )
1239 {
1240 if( eAccess == GA_Update )
1241 {
1242 bRewrite = TRUE;
1243 memcpy(adfGeoTransform, padfGeoTransform, 6* sizeof(double));
1244 bGeoTransformValid = !(
1245 adfGeoTransform[0] == 0.0 && adfGeoTransform[1] == 1.0 &&
1246 adfGeoTransform[2] == 0.0 && adfGeoTransform[3] == 0.0 &&
1247 adfGeoTransform[4] == 0.0 && adfGeoTransform[5] == 1.0);
1248 return CE_None;
1249 }
1250 else
1251 return GDALJP2AbstractDataset::SetGeoTransform(padfGeoTransform);
1252 }
1253
1254 /************************************************************************/
1255 /* SetGCPs() */
1256 /************************************************************************/
1257
SetGCPs(int nGCPCountIn,const GDAL_GCP * pasGCPListIn,const char * pszGCPProjectionIn)1258 CPLErr JP2OpenJPEGDataset::SetGCPs( int nGCPCountIn, const GDAL_GCP *pasGCPListIn,
1259 const char *pszGCPProjectionIn )
1260 {
1261 if( eAccess == GA_Update )
1262 {
1263 bRewrite = TRUE;
1264 CPLFree( pszProjection );
1265 if( nGCPCount > 0 )
1266 {
1267 GDALDeinitGCPs( nGCPCount, pasGCPList );
1268 CPLFree( pasGCPList );
1269 }
1270
1271 pszProjection = (pszGCPProjectionIn) ? CPLStrdup(pszGCPProjectionIn) : CPLStrdup("");
1272 nGCPCount = nGCPCountIn;
1273 pasGCPList = GDALDuplicateGCPs( nGCPCount, pasGCPListIn );
1274
1275 return CE_None;
1276 }
1277 else
1278 return GDALJP2AbstractDataset::SetGCPs(nGCPCountIn, pasGCPListIn,
1279 pszGCPProjectionIn);
1280 }
1281
1282 /************************************************************************/
1283 /* SetMetadata() */
1284 /************************************************************************/
1285
SetMetadata(char ** papszMetadata,const char * pszDomain)1286 CPLErr JP2OpenJPEGDataset::SetMetadata( char ** papszMetadata,
1287 const char * pszDomain )
1288 {
1289 if( eAccess == GA_Update )
1290 {
1291 bRewrite = TRUE;
1292 return GDALDataset::SetMetadata(papszMetadata, pszDomain);
1293 }
1294 return GDALJP2AbstractDataset::SetMetadata(papszMetadata, pszDomain);
1295 }
1296
1297 /************************************************************************/
1298 /* SetMetadata() */
1299 /************************************************************************/
1300
SetMetadataItem(const char * pszName,const char * pszValue,const char * pszDomain)1301 CPLErr JP2OpenJPEGDataset::SetMetadataItem( const char * pszName,
1302 const char * pszValue,
1303 const char * pszDomain )
1304 {
1305 if( eAccess == GA_Update )
1306 {
1307 bRewrite = TRUE;
1308 return GDALDataset::SetMetadataItem(pszName, pszValue, pszDomain);
1309 }
1310 return GDALJP2AbstractDataset::SetMetadataItem(pszName, pszValue, pszDomain);
1311 }
1312
1313 /************************************************************************/
1314 /* Identify() */
1315 /************************************************************************/
1316
1317 static const unsigned char jpc_header[] = {0xff,0x4f};
1318 static const unsigned char jp2_box_jp[] = {0x6a,0x50,0x20,0x20}; /* 'jP ' */
1319
Identify(GDALOpenInfo * poOpenInfo)1320 int JP2OpenJPEGDataset::Identify( GDALOpenInfo * poOpenInfo )
1321
1322 {
1323 if( poOpenInfo->nHeaderBytes >= 16
1324 && (memcmp( poOpenInfo->pabyHeader, jpc_header,
1325 sizeof(jpc_header) ) == 0
1326 || memcmp( poOpenInfo->pabyHeader + 4, jp2_box_jp,
1327 sizeof(jp2_box_jp) ) == 0
1328 ) )
1329 return TRUE;
1330
1331 else
1332 return FALSE;
1333 }
1334
1335 /************************************************************************/
1336 /* JP2OpenJPEGFindCodeStream() */
1337 /************************************************************************/
1338
JP2OpenJPEGFindCodeStream(VSILFILE * fp,vsi_l_offset * pnLength)1339 static vsi_l_offset JP2OpenJPEGFindCodeStream( VSILFILE* fp,
1340 vsi_l_offset* pnLength )
1341 {
1342 vsi_l_offset nCodeStreamStart = 0;
1343 vsi_l_offset nCodeStreamLength = 0;
1344
1345 VSIFSeekL(fp, 0, SEEK_SET);
1346 GByte abyHeader[16];
1347 VSIFReadL(abyHeader, 1, 16, fp);
1348
1349 if (memcmp( abyHeader, jpc_header, sizeof(jpc_header) ) == 0)
1350 {
1351 VSIFSeekL(fp, 0, SEEK_END);
1352 nCodeStreamLength = VSIFTellL(fp);
1353 }
1354 else if (memcmp( abyHeader + 4, jp2_box_jp, sizeof(jp2_box_jp) ) == 0)
1355 {
1356 /* Find offset of first jp2c box */
1357 GDALJP2Box oBox( fp );
1358 if( oBox.ReadFirst() )
1359 {
1360 while( strlen(oBox.GetType()) > 0 )
1361 {
1362 if( EQUAL(oBox.GetType(),"jp2c") )
1363 {
1364 nCodeStreamStart = VSIFTellL(fp);
1365 nCodeStreamLength = oBox.GetDataLength();
1366 break;
1367 }
1368
1369 if (!oBox.ReadNext())
1370 break;
1371 }
1372 }
1373 }
1374 *pnLength = nCodeStreamLength;
1375 return nCodeStreamStart;
1376 }
1377
1378 /************************************************************************/
1379 /* Open() */
1380 /************************************************************************/
1381
Open(GDALOpenInfo * poOpenInfo)1382 GDALDataset *JP2OpenJPEGDataset::Open( GDALOpenInfo * poOpenInfo )
1383
1384 {
1385 if (!Identify(poOpenInfo) || poOpenInfo->fpL == NULL)
1386 return NULL;
1387
1388 /* Detect which codec to use : J2K or JP2 ? */
1389 vsi_l_offset nCodeStreamLength = 0;
1390 vsi_l_offset nCodeStreamStart = JP2OpenJPEGFindCodeStream(poOpenInfo->fpL,
1391 &nCodeStreamLength);
1392
1393 if( nCodeStreamStart == 0 && nCodeStreamLength == 0 )
1394 {
1395 CPLError(CE_Failure, CPLE_AppDefined, "No code-stream in JP2 file");
1396 return NULL;
1397 }
1398
1399 OPJ_CODEC_FORMAT eCodecFormat = (nCodeStreamStart == 0) ? OPJ_CODEC_J2K : OPJ_CODEC_JP2;
1400
1401
1402 opj_codec_t* pCodec;
1403
1404 pCodec = opj_create_decompress(OPJ_CODEC_J2K);
1405
1406 opj_set_info_handler(pCodec, JP2OpenJPEGDataset_InfoCallback,NULL);
1407 opj_set_warning_handler(pCodec, JP2OpenJPEGDataset_WarningCallback, NULL);
1408 opj_set_error_handler(pCodec, JP2OpenJPEGDataset_ErrorCallback,NULL);
1409
1410 opj_dparameters_t parameters;
1411 opj_set_default_decoder_parameters(¶meters);
1412
1413 if (! opj_setup_decoder(pCodec,¶meters))
1414 {
1415 return NULL;
1416 }
1417
1418 JP2OpenJPEGFile sJP2OpenJPEGFile;
1419 sJP2OpenJPEGFile.fp = poOpenInfo->fpL;
1420 sJP2OpenJPEGFile.nBaseOffset = nCodeStreamStart;
1421 opj_stream_t * pStream = JP2OpenJPEGCreateReadStream(&sJP2OpenJPEGFile,
1422 nCodeStreamLength);
1423
1424 opj_image_t * psImage = NULL;
1425
1426 if(!opj_read_header(pStream,pCodec,&psImage))
1427 {
1428 CPLError(CE_Failure, CPLE_AppDefined, "opj_read_header() failed");
1429 opj_destroy_codec(pCodec);
1430 opj_stream_destroy(pStream);
1431 opj_image_destroy(psImage);
1432 return NULL;
1433 }
1434
1435 opj_codestream_info_v2_t* pCodeStreamInfo = opj_get_cstr_info(pCodec);
1436 OPJ_UINT32 nTileW,nTileH;
1437 nTileW = pCodeStreamInfo->tdx;
1438 nTileH = pCodeStreamInfo->tdy;
1439 #ifdef DEBUG
1440 OPJ_UINT32 nX0,nY0;
1441 OPJ_UINT32 nTilesX,nTilesY;
1442 nX0 = pCodeStreamInfo->tx0;
1443 nY0 = pCodeStreamInfo->ty0;
1444 nTilesX = pCodeStreamInfo->tw;
1445 nTilesY = pCodeStreamInfo->th;
1446 int mct = pCodeStreamInfo->m_default_tile_info.mct;
1447 #endif
1448 int numResolutions = pCodeStreamInfo->m_default_tile_info.tccp_info[0].numresolutions;
1449 opj_destroy_cstr_info(&pCodeStreamInfo);
1450
1451 if (psImage == NULL)
1452 {
1453 opj_destroy_codec(pCodec);
1454 opj_stream_destroy(pStream);
1455 opj_image_destroy(psImage);
1456 return NULL;
1457 }
1458
1459 #ifdef DEBUG
1460 int i;
1461 CPLDebug("OPENJPEG", "nX0 = %u", nX0);
1462 CPLDebug("OPENJPEG", "nY0 = %u", nY0);
1463 CPLDebug("OPENJPEG", "nTileW = %u", nTileW);
1464 CPLDebug("OPENJPEG", "nTileH = %u", nTileH);
1465 CPLDebug("OPENJPEG", "nTilesX = %u", nTilesX);
1466 CPLDebug("OPENJPEG", "nTilesY = %u", nTilesY);
1467 CPLDebug("OPENJPEG", "mct = %d", mct);
1468 CPLDebug("OPENJPEG", "psImage->x0 = %u", psImage->x0);
1469 CPLDebug("OPENJPEG", "psImage->y0 = %u", psImage->y0);
1470 CPLDebug("OPENJPEG", "psImage->x1 = %u", psImage->x1);
1471 CPLDebug("OPENJPEG", "psImage->y1 = %u", psImage->y1);
1472 CPLDebug("OPENJPEG", "psImage->numcomps = %d", psImage->numcomps);
1473 //CPLDebug("OPENJPEG", "psImage->color_space = %d", psImage->color_space);
1474 CPLDebug("OPENJPEG", "numResolutions = %d", numResolutions);
1475 for(i=0;i<(int)psImage->numcomps;i++)
1476 {
1477 CPLDebug("OPENJPEG", "psImage->comps[%d].dx = %u", i, psImage->comps[i].dx);
1478 CPLDebug("OPENJPEG", "psImage->comps[%d].dy = %u", i, psImage->comps[i].dy);
1479 CPLDebug("OPENJPEG", "psImage->comps[%d].x0 = %u", i, psImage->comps[i].x0);
1480 CPLDebug("OPENJPEG", "psImage->comps[%d].y0 = %u", i, psImage->comps[i].y0);
1481 CPLDebug("OPENJPEG", "psImage->comps[%d].w = %u", i, psImage->comps[i].w);
1482 CPLDebug("OPENJPEG", "psImage->comps[%d].h = %u", i, psImage->comps[i].h);
1483 CPLDebug("OPENJPEG", "psImage->comps[%d].resno_decoded = %d", i, psImage->comps[i].resno_decoded);
1484 CPLDebug("OPENJPEG", "psImage->comps[%d].factor = %d", i, psImage->comps[i].factor);
1485 CPLDebug("OPENJPEG", "psImage->comps[%d].prec = %d", i, psImage->comps[i].prec);
1486 CPLDebug("OPENJPEG", "psImage->comps[%d].sgnd = %d", i, psImage->comps[i].sgnd);
1487 }
1488 #endif
1489
1490 if (psImage->x1 <= psImage->x0 ||
1491 psImage->y1 <= psImage->y0 ||
1492 psImage->numcomps == 0 ||
1493 (psImage->comps[0].w >> 31) != 0 ||
1494 (psImage->comps[0].h >> 31) != 0 ||
1495 (nTileW >> 31) != 0 ||
1496 (nTileH >> 31) != 0 ||
1497 psImage->comps[0].w != psImage->x1 - psImage->x0 ||
1498 psImage->comps[0].h != psImage->y1 - psImage->y0)
1499 {
1500 CPLDebug("OPENJPEG", "Unable to handle that image (1)");
1501 opj_destroy_codec(pCodec);
1502 opj_stream_destroy(pStream);
1503 opj_image_destroy(psImage);
1504 return NULL;
1505 }
1506
1507 GDALDataType eDataType = GDT_Byte;
1508 if (psImage->comps[0].prec > 16)
1509 {
1510 if (psImage->comps[0].sgnd)
1511 eDataType = GDT_Int32;
1512 else
1513 eDataType = GDT_UInt32;
1514 }
1515 else if (psImage->comps[0].prec > 8)
1516 {
1517 if (psImage->comps[0].sgnd)
1518 eDataType = GDT_Int16;
1519 else
1520 eDataType = GDT_UInt16;
1521 }
1522
1523 int bIs420 = (psImage->color_space != OPJ_CLRSPC_SRGB &&
1524 eDataType == GDT_Byte &&
1525 (psImage->numcomps == 3 || psImage->numcomps == 4) &&
1526 psImage->comps[1].w == psImage->comps[0].w / 2 &&
1527 psImage->comps[1].h == psImage->comps[0].h / 2 &&
1528 psImage->comps[2].w == psImage->comps[0].w / 2 &&
1529 psImage->comps[2].h == psImage->comps[0].h / 2) &&
1530 (psImage->numcomps == 3 ||
1531 (psImage->numcomps == 4 &&
1532 psImage->comps[3].w == psImage->comps[0].w &&
1533 psImage->comps[3].h == psImage->comps[0].h));
1534
1535 if (bIs420)
1536 {
1537 CPLDebug("OPENJPEG", "420 format");
1538 }
1539 else
1540 {
1541 int iBand;
1542 for(iBand = 2; iBand <= (int)psImage->numcomps; iBand ++)
1543 {
1544 if( psImage->comps[iBand-1].w != psImage->comps[0].w ||
1545 psImage->comps[iBand-1].h != psImage->comps[0].h )
1546 {
1547 CPLDebug("OPENJPEG", "Unable to handle that image (2)");
1548 opj_destroy_codec(pCodec);
1549 opj_stream_destroy(pStream);
1550 opj_image_destroy(psImage);
1551 return NULL;
1552 }
1553 }
1554 }
1555
1556
1557 /* -------------------------------------------------------------------- */
1558 /* Create a corresponding GDALDataset. */
1559 /* -------------------------------------------------------------------- */
1560 JP2OpenJPEGDataset *poDS;
1561 int iBand;
1562
1563 poDS = new JP2OpenJPEGDataset();
1564 if( eCodecFormat == OPJ_CODEC_JP2 )
1565 poDS->eAccess = poOpenInfo->eAccess;
1566 poDS->eColorSpace = psImage->color_space;
1567 poDS->nRasterXSize = psImage->x1 - psImage->x0;
1568 poDS->nRasterYSize = psImage->y1 - psImage->y0;
1569 poDS->nBands = psImage->numcomps;
1570 poDS->fp = poOpenInfo->fpL;
1571 poOpenInfo->fpL = NULL;
1572 poDS->nCodeStreamStart = nCodeStreamStart;
1573 poDS->nCodeStreamLength = nCodeStreamLength;
1574 poDS->bIs420 = bIs420;
1575
1576 poDS->bUseSetDecodeArea =
1577 (poDS->nRasterXSize == (int)nTileW &&
1578 poDS->nRasterYSize == (int)nTileH &&
1579 (poDS->nRasterXSize > 1024 ||
1580 poDS->nRasterYSize > 1024));
1581
1582 if (poDS->bUseSetDecodeArea)
1583 {
1584 if (nTileW > 1024) nTileW = 1024;
1585 if (nTileH > 1024) nTileH = 1024;
1586 }
1587
1588 GDALColorTable* poCT = NULL;
1589
1590 /* -------------------------------------------------------------------- */
1591 /* Look for color table or cdef box */
1592 /* -------------------------------------------------------------------- */
1593 if( eCodecFormat == OPJ_CODEC_JP2 )
1594 {
1595 GDALJP2Box oBox( poDS->fp );
1596 if( oBox.ReadFirst() )
1597 {
1598 while( strlen(oBox.GetType()) > 0 )
1599 {
1600 if( EQUAL(oBox.GetType(),"jp2h") )
1601 {
1602 GDALJP2Box oSubBox( poDS->fp );
1603
1604 for( oSubBox.ReadFirstChild( &oBox );
1605 strlen(oSubBox.GetType()) > 0;
1606 oSubBox.ReadNextChild( &oBox ) )
1607 {
1608 GIntBig nDataLength = oSubBox.GetDataLength();
1609 if( poCT == NULL &&
1610 EQUAL(oSubBox.GetType(),"pclr") &&
1611 nDataLength >= 3 &&
1612 nDataLength <= 2 + 1 + 4 + 4 * 256 )
1613 {
1614 GByte* pabyCT = oSubBox.ReadBoxData();
1615 if( pabyCT != NULL )
1616 {
1617 int nEntries = (pabyCT[0] << 8) | pabyCT[1];
1618 int nComponents = pabyCT[2];
1619 /* CPLDebug("OPENJPEG", "Color table found"); */
1620 if( nEntries <= 256 && nComponents == 3 )
1621 {
1622 /*CPLDebug("OPENJPEG", "resol[0] = %d", pabyCT[3]);
1623 CPLDebug("OPENJPEG", "resol[1] = %d", pabyCT[4]);
1624 CPLDebug("OPENJPEG", "resol[2] = %d", pabyCT[5]);*/
1625 if( pabyCT[3] == 7 && pabyCT[4] == 7 && pabyCT[5] == 7 &&
1626 nDataLength == 2 + 1 + 3 + 3 * nEntries )
1627 {
1628 poCT = new GDALColorTable();
1629 for(int i=0;i<nEntries;i++)
1630 {
1631 GDALColorEntry sEntry;
1632 sEntry.c1 = pabyCT[6 + 3 * i];
1633 sEntry.c2 = pabyCT[6 + 3 * i + 1];
1634 sEntry.c3 = pabyCT[6 + 3 * i + 2];
1635 sEntry.c4 = 255;
1636 poCT->SetColorEntry(i, &sEntry);
1637 }
1638 }
1639 }
1640 else if ( nEntries <= 256 && nComponents == 4 )
1641 {
1642 if( pabyCT[3] == 7 && pabyCT[4] == 7 &&
1643 pabyCT[5] == 7 && pabyCT[6] == 7 &&
1644 nDataLength == 2 + 1 + 4 + 4 * nEntries )
1645 {
1646 poCT = new GDALColorTable();
1647 for(int i=0;i<nEntries;i++)
1648 {
1649 GDALColorEntry sEntry;
1650 sEntry.c1 = pabyCT[7 + 4 * i];
1651 sEntry.c2 = pabyCT[7 + 4 * i + 1];
1652 sEntry.c3 = pabyCT[7 + 4 * i + 2];
1653 sEntry.c4 = pabyCT[7 + 4 * i + 3];
1654 poCT->SetColorEntry(i, &sEntry);
1655 }
1656 }
1657 }
1658 CPLFree(pabyCT);
1659 }
1660 }
1661 /* There's a bug/misfeature in openjpeg: the color_space
1662 only gets set at read tile time */
1663 else if( EQUAL(oSubBox.GetType(),"colr") &&
1664 nDataLength == 7 )
1665 {
1666 GByte* pabyContent = oSubBox.ReadBoxData();
1667 if( pabyContent != NULL )
1668 {
1669 if( pabyContent[0] == 1 /* enumerated colourspace */ )
1670 {
1671 GUInt32 enumcs = (pabyContent[3] << 24) |
1672 (pabyContent[4] << 16) |
1673 (pabyContent[5] << 8) |
1674 (pabyContent[6]);
1675 if( enumcs == 16 )
1676 {
1677 poDS->eColorSpace = OPJ_CLRSPC_SRGB;
1678 CPLDebug("OPENJPEG", "SRGB color space");
1679 }
1680 else if( enumcs == 17 )
1681 {
1682 poDS->eColorSpace = OPJ_CLRSPC_GRAY;
1683 CPLDebug("OPENJPEG", "Grayscale color space");
1684 }
1685 else if( enumcs == 18 )
1686 {
1687 poDS->eColorSpace = OPJ_CLRSPC_SYCC;
1688 CPLDebug("OPENJPEG", "SYCC color space");
1689 }
1690 else if( enumcs == 20 )
1691 {
1692 /* Used by J2KP4files/testfiles_jp2/file7.jp2 */
1693 poDS->eColorSpace = OPJ_CLRSPC_SRGB;
1694 CPLDebug("OPENJPEG", "e-sRGB color space");
1695 }
1696 else if( enumcs == 21 )
1697 {
1698 /* Used by J2KP4files/testfiles_jp2/file5.jp2 */
1699 poDS->eColorSpace = OPJ_CLRSPC_SRGB;
1700 CPLDebug("OPENJPEG", "ROMM-RGB color space");
1701 }
1702 else
1703 {
1704 poDS->eColorSpace = OPJ_CLRSPC_UNKNOWN;
1705 CPLDebug("OPENJPEG", "Unknown color space");
1706 }
1707 }
1708 CPLFree(pabyContent);
1709 }
1710 }
1711 /* Check if there's an alpha channel or odd channel attribution */
1712 else if( EQUAL(oSubBox.GetType(),"cdef") &&
1713 nDataLength == 2 + poDS->nBands * 6 )
1714 {
1715 GByte* pabyContent = oSubBox.ReadBoxData();
1716 if( pabyContent != NULL )
1717 {
1718 int nEntries = (pabyContent[0] << 8) | pabyContent[1];
1719 if( nEntries == poDS->nBands )
1720 {
1721 poDS->nRedIndex = -1;
1722 poDS->nGreenIndex = -1;
1723 poDS->nBlueIndex = -1;
1724 for(int i=0;i<poDS->nBands;i++)
1725 {
1726 int CNi = (pabyContent[2+6*i] << 8) | pabyContent[2+6*i+1];
1727 int Typi = (pabyContent[2+6*i+2] << 8) | pabyContent[2+6*i+3];
1728 int Asoci = (pabyContent[2+6*i+4] << 8) | pabyContent[2+6*i+5];
1729 if( CNi < 0 || CNi >= poDS->nBands )
1730 {
1731 CPLError(CE_Failure, CPLE_AppDefined,
1732 "Wrong value of CN%d=%d", i, CNi);
1733 break;
1734 }
1735 if( Typi == 0 )
1736 {
1737 if( Asoci == 1 )
1738 poDS->nRedIndex = CNi;
1739 else if( Asoci == 2 )
1740 poDS->nGreenIndex = CNi;
1741 else if( Asoci == 3 )
1742 poDS->nBlueIndex = CNi;
1743 else if( Asoci < 0 || (Asoci > poDS->nBands && Asoci != 65535) )
1744 {
1745 CPLError(CE_Failure, CPLE_AppDefined,
1746 "Wrong value of Asoc%d=%d", i, Asoci);
1747 break;
1748 }
1749 }
1750 else if( Typi == 1 )
1751 {
1752 poDS->nAlphaIndex = CNi;
1753 }
1754 }
1755 }
1756 else
1757 {
1758 CPLDebug("OPENJPEG", "Unsupported cdef content");
1759 }
1760 CPLFree(pabyContent);
1761 }
1762 }
1763 }
1764 }
1765
1766 if (!oBox.ReadNext())
1767 break;
1768 }
1769 }
1770 }
1771
1772 /* -------------------------------------------------------------------- */
1773 /* Create band information objects. */
1774 /* -------------------------------------------------------------------- */
1775 for( iBand = 1; iBand <= poDS->nBands; iBand++ )
1776 {
1777 int bPromoteTo8Bit = (
1778 iBand == poDS->nAlphaIndex + 1 &&
1779 psImage->comps[(poDS->nAlphaIndex==0 && poDS->nBands > 1) ? 1 : 0].prec == 8 &&
1780 psImage->comps[poDS->nAlphaIndex ].prec == 1 &&
1781 CSLFetchBoolean(poOpenInfo->papszOpenOptions, "1BIT_ALPHA_PROMOTION",
1782 CSLTestBoolean(CPLGetConfigOption("JP2OPENJPEG_PROMOTE_1BIT_ALPHA_AS_8BIT", "YES"))) );
1783 if( bPromoteTo8Bit )
1784 CPLDebug("JP2OpenJPEG", "Alpha band is promoted from 1 bit to 8 bit");
1785
1786 JP2OpenJPEGRasterBand* poBand =
1787 new JP2OpenJPEGRasterBand( poDS, iBand, eDataType,
1788 bPromoteTo8Bit ? 8: psImage->comps[iBand-1].prec,
1789 bPromoteTo8Bit,
1790 nTileW, nTileH);
1791 if( iBand == 1 && poCT != NULL )
1792 poBand->poCT = poCT;
1793 poDS->SetBand( iBand, poBand );
1794 }
1795
1796 /* -------------------------------------------------------------------- */
1797 /* Create overview datasets. */
1798 /* -------------------------------------------------------------------- */
1799 int nW = poDS->nRasterXSize;
1800 int nH = poDS->nRasterYSize;
1801
1802 /* Lower resolutions are not compatible with a color-table */
1803 if( poCT != NULL )
1804 numResolutions = 0;
1805
1806 while (poDS->nOverviewCount+1 < numResolutions &&
1807 (nW > 128 || nH > 128) &&
1808 (poDS->bUseSetDecodeArea || ((nTileW % 2) == 0 && (nTileH % 2) == 0)))
1809 {
1810 nW /= 2;
1811 nH /= 2;
1812
1813 poDS->papoOverviewDS = (JP2OpenJPEGDataset**) CPLRealloc(
1814 poDS->papoOverviewDS,
1815 (poDS->nOverviewCount + 1) * sizeof(JP2OpenJPEGDataset*));
1816 JP2OpenJPEGDataset* poODS = new JP2OpenJPEGDataset();
1817 poODS->SetDescription( poOpenInfo->pszFilename );
1818 poODS->iLevel = poDS->nOverviewCount + 1;
1819 poODS->bUseSetDecodeArea = poDS->bUseSetDecodeArea;
1820 poODS->nRedIndex = poDS->nRedIndex;
1821 poODS->nGreenIndex = poDS->nGreenIndex;
1822 poODS->nBlueIndex = poDS->nBlueIndex;
1823 poODS->nAlphaIndex = poDS->nAlphaIndex;
1824 if (!poDS->bUseSetDecodeArea)
1825 {
1826 nTileW /= 2;
1827 nTileH /= 2;
1828 }
1829 else
1830 {
1831 if (nW < (int)nTileW || nH < (int)nTileH)
1832 {
1833 nTileW = nW;
1834 nTileH = nH;
1835 poODS->bUseSetDecodeArea = FALSE;
1836 }
1837 }
1838
1839 poODS->eColorSpace = poDS->eColorSpace;
1840 poODS->nRasterXSize = nW;
1841 poODS->nRasterYSize = nH;
1842 poODS->nBands = poDS->nBands;
1843 poODS->fp = poDS->fp;
1844 poODS->nCodeStreamStart = nCodeStreamStart;
1845 poODS->nCodeStreamLength = nCodeStreamLength;
1846 poODS->bIs420 = bIs420;
1847 for( iBand = 1; iBand <= poDS->nBands; iBand++ )
1848 {
1849 int bPromoteTo8Bit = (
1850 iBand == poDS->nAlphaIndex + 1 &&
1851 psImage->comps[(poDS->nAlphaIndex==0 && poDS->nBands > 1) ? 1 : 0].prec == 8 &&
1852 psImage->comps[poDS->nAlphaIndex].prec == 1 &&
1853 CSLFetchBoolean(poOpenInfo->papszOpenOptions, "1BIT_ALPHA_PROMOTION",
1854 CSLTestBoolean(CPLGetConfigOption("JP2OPENJPEG_PROMOTE_1BIT_ALPHA_AS_8BIT", "YES"))) );
1855
1856 poODS->SetBand( iBand, new JP2OpenJPEGRasterBand( poODS, iBand, eDataType,
1857 bPromoteTo8Bit ? 8: psImage->comps[iBand-1].prec,
1858 bPromoteTo8Bit,
1859 nTileW, nTileH ) );
1860 }
1861
1862 poDS->papoOverviewDS[poDS->nOverviewCount ++] = poODS;
1863
1864 }
1865
1866 opj_destroy_codec(pCodec);
1867 opj_stream_destroy(pStream);
1868 opj_image_destroy(psImage);
1869 pCodec = NULL;
1870 pStream = NULL;
1871 psImage = NULL;
1872
1873 /* -------------------------------------------------------------------- */
1874 /* More metadata. */
1875 /* -------------------------------------------------------------------- */
1876 if( poDS->nBands > 1 )
1877 {
1878 poDS->GDALDataset::SetMetadataItem( "INTERLEAVE", "PIXEL", "IMAGE_STRUCTURE" );
1879 }
1880
1881 poOpenInfo->fpL = poDS->fp;
1882 poDS->LoadJP2Metadata(poOpenInfo);
1883 poOpenInfo->fpL = NULL;
1884
1885 poDS->bHasGeoreferencingAtOpening =
1886 ((poDS->pszProjection != NULL && poDS->pszProjection[0] != '\0' )||
1887 poDS->nGCPCount != 0 || poDS->bGeoTransformValid);
1888
1889 /* -------------------------------------------------------------------- */
1890 /* Vector layers */
1891 /* -------------------------------------------------------------------- */
1892 if( poOpenInfo->nOpenFlags & GDAL_OF_VECTOR )
1893 {
1894 poDS->LoadVectorLayers(
1895 CSLFetchBoolean(poOpenInfo->papszOpenOptions, "OPEN_REMOTE_GML", FALSE));
1896
1897 // If file opened in vector-only mode and there's no vector,
1898 // return
1899 if( (poOpenInfo->nOpenFlags & GDAL_OF_RASTER) == 0 &&
1900 poDS->GetLayerCount() == 0 )
1901 {
1902 delete poDS;
1903 return NULL;
1904 }
1905 }
1906
1907 /* -------------------------------------------------------------------- */
1908 /* Initialize any PAM information. */
1909 /* -------------------------------------------------------------------- */
1910 poDS->SetDescription( poOpenInfo->pszFilename );
1911 poDS->TryLoadXML();
1912
1913 /* -------------------------------------------------------------------- */
1914 /* Check for overviews. */
1915 /* -------------------------------------------------------------------- */
1916 //poDS->oOvManager.Initialize( poDS, poOpenInfo->pszFilename );
1917
1918 return( poDS );
1919 }
1920
1921 /************************************************************************/
1922 /* WriteBox() */
1923 /************************************************************************/
1924
WriteBox(VSILFILE * fp,GDALJP2Box * poBox)1925 void JP2OpenJPEGDataset::WriteBox(VSILFILE* fp, GDALJP2Box* poBox)
1926 {
1927 GUInt32 nLBox;
1928 GUInt32 nTBox;
1929
1930 if( poBox == NULL )
1931 return;
1932
1933 nLBox = (int) poBox->GetDataLength() + 8;
1934 nLBox = CPL_MSBWORD32( nLBox );
1935
1936 memcpy(&nTBox, poBox->GetType(), 4);
1937
1938 VSIFWriteL( &nLBox, 4, 1, fp );
1939 VSIFWriteL( &nTBox, 4, 1, fp );
1940 VSIFWriteL(poBox->GetWritableData(), 1, (int) poBox->GetDataLength(), fp);
1941 }
1942
1943 /************************************************************************/
1944 /* WriteGDALMetadataBox() */
1945 /************************************************************************/
1946
WriteGDALMetadataBox(VSILFILE * fp,GDALDataset * poSrcDS,char ** papszOptions)1947 void JP2OpenJPEGDataset::WriteGDALMetadataBox( VSILFILE* fp,
1948 GDALDataset* poSrcDS,
1949 char** papszOptions )
1950 {
1951 GDALJP2Box* poBox = GDALJP2Metadata::CreateGDALMultiDomainMetadataXMLBox(
1952 poSrcDS, CSLFetchBoolean(papszOptions, "MAIN_MD_DOMAIN_ONLY", FALSE));
1953 if( poBox )
1954 WriteBox(fp, poBox);
1955 delete poBox;
1956 }
1957
1958 /************************************************************************/
1959 /* WriteXMLBoxes() */
1960 /************************************************************************/
1961
WriteXMLBoxes(VSILFILE * fp,GDALDataset * poSrcDS,CPL_UNUSED char ** papszOptions)1962 void JP2OpenJPEGDataset::WriteXMLBoxes( VSILFILE* fp, GDALDataset* poSrcDS,
1963 CPL_UNUSED char** papszOptions )
1964 {
1965 int nBoxes = 0;
1966 GDALJP2Box** papoBoxes = GDALJP2Metadata::CreateXMLBoxes(poSrcDS, &nBoxes);
1967 for(int i=0;i<nBoxes;i++)
1968 {
1969 WriteBox(fp, papoBoxes[i]);
1970 delete papoBoxes[i];
1971 }
1972 CPLFree(papoBoxes);
1973 }
1974
1975 /************************************************************************/
1976 /* WriteXMPBox() */
1977 /************************************************************************/
1978
WriteXMPBox(VSILFILE * fp,GDALDataset * poSrcDS,CPL_UNUSED char ** papszOptions)1979 void JP2OpenJPEGDataset::WriteXMPBox ( VSILFILE* fp, GDALDataset* poSrcDS,
1980 CPL_UNUSED char** papszOptions )
1981 {
1982 GDALJP2Box* poBox = GDALJP2Metadata::CreateXMPBox(poSrcDS);
1983 if( poBox )
1984 WriteBox(fp, poBox);
1985 delete poBox;
1986 }
1987
1988 /************************************************************************/
1989 /* WriteIPRBox() */
1990 /************************************************************************/
1991
WriteIPRBox(VSILFILE * fp,GDALDataset * poSrcDS,CPL_UNUSED char ** papszOptions)1992 void JP2OpenJPEGDataset::WriteIPRBox ( VSILFILE* fp, GDALDataset* poSrcDS,
1993 CPL_UNUSED char** papszOptions )
1994 {
1995 GDALJP2Box* poBox = GDALJP2Metadata::CreateIPRBox(poSrcDS);
1996 if( poBox )
1997 WriteBox(fp, poBox);
1998 delete poBox;
1999 }
2000 /************************************************************************/
2001 /* FloorPowerOfTwo() */
2002 /************************************************************************/
2003
FloorPowerOfTwo(int nVal)2004 static int FloorPowerOfTwo(int nVal)
2005 {
2006 int nBits = 0;
2007 while( nVal > 1 )
2008 {
2009 nBits ++;
2010 nVal >>= 1;
2011 }
2012 return 1 << nBits;
2013 }
2014
2015 /************************************************************************/
2016 /* CreateCopy() */
2017 /************************************************************************/
2018
CreateCopy(const char * pszFilename,GDALDataset * poSrcDS,int bStrict,char ** papszOptions,GDALProgressFunc pfnProgress,void * pProgressData)2019 GDALDataset * JP2OpenJPEGDataset::CreateCopy( const char * pszFilename,
2020 GDALDataset *poSrcDS,
2021 int bStrict, char ** papszOptions,
2022 GDALProgressFunc pfnProgress,
2023 void * pProgressData )
2024
2025 {
2026 int nBands = poSrcDS->GetRasterCount();
2027 int nXSize = poSrcDS->GetRasterXSize();
2028 int nYSize = poSrcDS->GetRasterYSize();
2029
2030 if( nBands == 0 || nBands > 16384 )
2031 {
2032 CPLError( CE_Failure, CPLE_NotSupported,
2033 "Unable to export files with %d bands. Must be >= 1 and <= 16384", nBands );
2034 return NULL;
2035 }
2036
2037 GDALColorTable* poCT = poSrcDS->GetRasterBand(1)->GetColorTable();
2038 if (poCT != NULL && nBands != 1)
2039 {
2040 CPLError( CE_Failure, CPLE_NotSupported,
2041 "JP2OpenJPEG driver only supports a color table for a single-band dataset");
2042 return NULL;
2043 }
2044
2045 GDALDataType eDataType = poSrcDS->GetRasterBand(1)->GetRasterDataType();
2046 int nDataTypeSize = (GDALGetDataTypeSize(eDataType) / 8);
2047 if (eDataType != GDT_Byte && eDataType != GDT_Int16 && eDataType != GDT_UInt16
2048 && eDataType != GDT_Int32 && eDataType != GDT_UInt32)
2049 {
2050 CPLError( CE_Failure, CPLE_NotSupported,
2051 "JP2OpenJPEG driver only supports creating Byte, GDT_Int16, GDT_UInt16, GDT_Int32, GDT_UInt32");
2052 return NULL;
2053 }
2054
2055 int bInspireTG = CSLFetchBoolean(papszOptions, "INSPIRE_TG", FALSE);
2056
2057 /* -------------------------------------------------------------------- */
2058 /* Analyze creation options. */
2059 /* -------------------------------------------------------------------- */
2060 OPJ_CODEC_FORMAT eCodecFormat = OPJ_CODEC_J2K;
2061 const char* pszCodec = CSLFetchNameValueDef(papszOptions, "CODEC", NULL);
2062 if (pszCodec)
2063 {
2064 if (EQUAL(pszCodec, "JP2"))
2065 eCodecFormat = OPJ_CODEC_JP2;
2066 else if (EQUAL(pszCodec, "J2K"))
2067 eCodecFormat = OPJ_CODEC_J2K;
2068 else
2069 {
2070 CPLError(CE_Warning, CPLE_NotSupported,
2071 "Unsupported value for CODEC : %s. Defaulting to J2K",
2072 pszCodec);
2073 }
2074 }
2075 else
2076 {
2077 if (strlen(pszFilename) > 4 &&
2078 EQUAL(pszFilename + strlen(pszFilename) - 4, ".JP2"))
2079 {
2080 eCodecFormat = OPJ_CODEC_JP2;
2081 }
2082 }
2083 if( eCodecFormat != OPJ_CODEC_JP2 && bInspireTG )
2084 {
2085 CPLError(CE_Warning, CPLE_NotSupported,
2086 "INSPIRE_TG=YES mandates CODEC=JP2 (TG requirement 21)");
2087 return NULL;
2088 }
2089
2090 int nBlockXSize =
2091 atoi(CSLFetchNameValueDef(papszOptions, "BLOCKXSIZE", "1024"));
2092 int nBlockYSize =
2093 atoi(CSLFetchNameValueDef(papszOptions, "BLOCKYSIZE", "1024"));
2094 if (nBlockXSize < 32 || nBlockYSize < 32)
2095 {
2096 CPLError(CE_Failure, CPLE_NotSupported, "Invalid block size");
2097 return NULL;
2098 }
2099
2100 if (nXSize < nBlockXSize)
2101 nBlockXSize = nXSize;
2102 if (nYSize < nBlockYSize)
2103 nBlockYSize = nYSize;
2104
2105 OPJ_PROG_ORDER eProgOrder = OPJ_LRCP;
2106 const char* pszPROGORDER =
2107 CSLFetchNameValueDef(papszOptions, "PROGRESSION", "LRCP");
2108 if (EQUAL(pszPROGORDER, "LRCP"))
2109 eProgOrder = OPJ_LRCP;
2110 else if (EQUAL(pszPROGORDER, "RLCP"))
2111 eProgOrder = OPJ_RLCP;
2112 else if (EQUAL(pszPROGORDER, "RPCL"))
2113 eProgOrder = OPJ_RPCL;
2114 else if (EQUAL(pszPROGORDER, "PCRL"))
2115 eProgOrder = OPJ_PCRL;
2116 else if (EQUAL(pszPROGORDER, "CPRL"))
2117 eProgOrder = OPJ_CPRL;
2118 else
2119 {
2120 CPLError(CE_Warning, CPLE_NotSupported,
2121 "Unsupported value for PROGRESSION : %s. Defaulting to LRCP",
2122 pszPROGORDER);
2123 }
2124
2125 int bIsIrreversible =
2126 ! (CSLFetchBoolean(papszOptions, "REVERSIBLE", poCT != NULL));
2127
2128 std::vector<double> adfRates;
2129 const char* pszQuality = CSLFetchNameValueDef(papszOptions, "QUALITY", NULL);
2130 double dfDefaultQuality = ( poCT != NULL ) ? 100.0 : 25.0;
2131 if (pszQuality)
2132 {
2133 char **papszTokens = CSLTokenizeStringComplex( pszQuality, ",", FALSE, FALSE );
2134 for(int i=0; papszTokens[i] != NULL; i++ )
2135 {
2136 double dfQuality = CPLAtof(papszTokens[i]);
2137 if (dfQuality > 0 && dfQuality <= 100)
2138 {
2139 double dfRate = 100 / dfQuality;
2140 adfRates.push_back(dfRate);
2141 }
2142 else
2143 {
2144 CPLError(CE_Warning, CPLE_NotSupported,
2145 "Unsupported value for QUALITY: %s. Defaulting to single-layer, with quality=%.0f",
2146 papszTokens[i], dfDefaultQuality);
2147 adfRates.resize(0);
2148 break;
2149 }
2150 }
2151 if( papszTokens[0] == NULL )
2152 {
2153 CPLError(CE_Warning, CPLE_NotSupported,
2154 "Unsupported value for QUALITY: %s. Defaulting to single-layer, with quality=%.0f",
2155 pszQuality, dfDefaultQuality);
2156 }
2157 CSLDestroy(papszTokens);
2158 }
2159 if( adfRates.size() == 0 )
2160 {
2161 adfRates.push_back(100. / dfDefaultQuality);
2162 }
2163
2164 if( poCT != NULL && (bIsIrreversible || adfRates[adfRates.size()-1] != 100.0 / 100.0) )
2165 {
2166 CPLError(CE_Warning, CPLE_AppDefined,
2167 "Encoding a dataset with a color table with REVERSIBLE != YES "
2168 "or QUALITY != 100 will likely lead to bad visual results");
2169 }
2170
2171 int nMaxTileDim = MAX(nBlockXSize, nBlockYSize);
2172 int nNumResolutions = 1;
2173 /* Pickup a reasonable value compatible with PROFILE_1 requirements */
2174 while( (nMaxTileDim >> (nNumResolutions-1)) > 128 )
2175 nNumResolutions ++;
2176 int nMinProfile1Resolutions = nNumResolutions;
2177 const char* pszResolutions = CSLFetchNameValueDef(papszOptions, "RESOLUTIONS", NULL);
2178 if (pszResolutions)
2179 {
2180 nNumResolutions = atoi(pszResolutions);
2181 if (nNumResolutions <= 0 || nNumResolutions >= 32 ||
2182 (nMaxTileDim >> nNumResolutions) == 0 )
2183 {
2184 CPLError(CE_Warning, CPLE_NotSupported,
2185 "Unsupported value for RESOLUTIONS : %s. Defaulting to %d",
2186 pszResolutions, nMinProfile1Resolutions);
2187 nNumResolutions = nMinProfile1Resolutions;
2188 }
2189 }
2190
2191 int bSOP = CSLTestBoolean(CSLFetchNameValueDef(papszOptions, "SOP", "FALSE"));
2192 int bEPH = CSLTestBoolean(CSLFetchNameValueDef(papszOptions, "EPH", "FALSE"));
2193
2194 int nRedBandIndex = -1, nGreenBandIndex = -1, nBlueBandIndex = -1;
2195 int nAlphaBandIndex = -1;
2196 for(int i=0;i<nBands;i++)
2197 {
2198 GDALColorInterp eInterp = poSrcDS->GetRasterBand(i+1)->GetColorInterpretation();
2199 if( eInterp == GCI_RedBand )
2200 nRedBandIndex = i;
2201 else if( eInterp == GCI_GreenBand )
2202 nGreenBandIndex = i;
2203 else if( eInterp == GCI_BlueBand )
2204 nBlueBandIndex = i;
2205 else if( eInterp == GCI_AlphaBand )
2206 nAlphaBandIndex = i;
2207 }
2208 const char* pszAlpha = CSLFetchNameValue(papszOptions, "ALPHA");
2209 if( nAlphaBandIndex < 0 && nBands > 1 && pszAlpha != NULL && CSLTestBoolean(pszAlpha) )
2210 {
2211 nAlphaBandIndex = nBands - 1;
2212 }
2213
2214 const char* pszYCBCR420 = CSLFetchNameValue(papszOptions, "YCBCR420");
2215 int bYCBCR420 = FALSE;
2216 if( pszYCBCR420 && CSLTestBoolean(pszYCBCR420) )
2217 {
2218 if ((nBands == 3 || nBands == 4) && eDataType == GDT_Byte &&
2219 nRedBandIndex == 0 && nGreenBandIndex == 1 && nBlueBandIndex == 2)
2220 {
2221 if( ((nXSize % 2) == 0 && (nYSize % 2) == 0 && (nBlockXSize % 2) == 0 && (nBlockYSize % 2) == 0) )
2222 {
2223 bYCBCR420 = TRUE;
2224 }
2225 else
2226 {
2227 CPLError(CE_Warning, CPLE_NotSupported,
2228 "YCBCR420 unsupported when image size and/or tile size are not multiple of 2");
2229 }
2230 }
2231 else
2232 {
2233 CPLError(CE_Warning, CPLE_NotSupported,
2234 "YCBCR420 unsupported with this image band count and/or data byte");
2235 }
2236 }
2237
2238 const char* pszYCC = CSLFetchNameValue(papszOptions, "YCC");
2239 int bYCC = ((nBands == 3 || nBands == 4) && eDataType == GDT_Byte &&
2240 CSLTestBoolean(CSLFetchNameValueDef(papszOptions, "YCC", "TRUE")));
2241
2242 /* TODO: when OpenJPEG 2.2 is released, make this conditional */
2243 /* Depending on the way OpenJPEG <= r2950 is built, YCC with 4 bands might work on
2244 * Debug mode, but this relies on unreliable stack buffer overflows, so
2245 * better err on the safe side */
2246 if( bYCC && nBands > 3 )
2247 {
2248 if( pszYCC != NULL )
2249 {
2250 CPLError(CE_Warning, CPLE_AppDefined,
2251 "OpenJPEG r2950 and below can generate invalid output with "
2252 "MCT YCC transform and more than 3 bands. Disabling YCC");
2253 }
2254 bYCC = FALSE;
2255 }
2256
2257 if( bYCBCR420 && bYCC )
2258 {
2259 if( pszYCC != NULL )
2260 {
2261 CPLError(CE_Warning, CPLE_NotSupported,
2262 "YCC unsupported when YCbCr requesting");
2263 }
2264 bYCC = FALSE;
2265 }
2266
2267 /* -------------------------------------------------------------------- */
2268 /* Deal with codeblocks size */
2269 /* -------------------------------------------------------------------- */
2270
2271 int nCblockW = atoi(CSLFetchNameValueDef( papszOptions, "CODEBLOCK_WIDTH", "64" ));
2272 int nCblockH = atoi(CSLFetchNameValueDef( papszOptions, "CODEBLOCK_HEIGHT", "64" ));
2273 if( nCblockW < 4 || nCblockW > 1024 || nCblockH < 4 || nCblockH > 1024 )
2274 {
2275 CPLError(CE_Warning, CPLE_NotSupported,
2276 "Invalid values for codeblock size. Defaulting to 64x64");
2277 nCblockW = 64;
2278 nCblockH = 64;
2279 }
2280 else if( nCblockW * nCblockH > 4096 )
2281 {
2282 CPLError(CE_Warning, CPLE_NotSupported,
2283 "Invalid values for codeblock size. "
2284 "CODEBLOCK_WIDTH * CODEBLOCK_HEIGHT should be <= 4096. "
2285 "Defaulting to 64x64");
2286 nCblockW = 64;
2287 nCblockH = 64;
2288 }
2289 int nCblockW_po2 = FloorPowerOfTwo(nCblockW);
2290 int nCblockH_po2 = FloorPowerOfTwo(nCblockH);
2291 if( nCblockW_po2 != nCblockW || nCblockH_po2 != nCblockH )
2292 {
2293 CPLError(CE_Warning, CPLE_NotSupported,
2294 "Non power of two values used for codeblock size. "
2295 "Using to %dx%d",
2296 nCblockW_po2, nCblockH_po2);
2297 }
2298 nCblockW = nCblockW_po2;
2299 nCblockH = nCblockH_po2;
2300
2301 /* -------------------------------------------------------------------- */
2302 /* Deal with codestream PROFILE */
2303 /* -------------------------------------------------------------------- */
2304 const char* pszProfile = CSLFetchNameValueDef( papszOptions, "PROFILE", "AUTO" );
2305 int bProfile1 = FALSE;
2306 if( EQUAL(pszProfile, "UNRESTRICTED") )
2307 {
2308 bProfile1 = FALSE;
2309 if( bInspireTG )
2310 {
2311 CPLError(CE_Failure, CPLE_NotSupported,
2312 "INSPIRE_TG=YES mandates PROFILE=PROFILE_1 (TG requirement 21)");
2313 return NULL;
2314 }
2315 }
2316 else if( EQUAL(pszProfile, "UNRESTRICTED_FORCED") )
2317 {
2318 bProfile1 = FALSE;
2319 }
2320 else if( EQUAL(pszProfile, "PROFILE_1_FORCED") ) /* For debug only: can produce inconsistent codestream */
2321 {
2322 bProfile1 = TRUE;
2323 }
2324 else
2325 {
2326 if( !(EQUAL(pszProfile, "PROFILE_1") || EQUAL(pszProfile, "AUTO")) )
2327 {
2328 CPLError(CE_Warning, CPLE_NotSupported,
2329 "Unsupported value for PROFILE : %s. Defaulting to AUTO",
2330 pszProfile);
2331 pszProfile = "AUTO";
2332 }
2333
2334 bProfile1 = TRUE;
2335 const char* pszReq21OrEmpty = (bInspireTG) ? " (TG requirement 21)" : "";
2336 if( (nBlockXSize != nXSize || nBlockYSize != nYSize) &&
2337 (nBlockXSize != nBlockYSize || nBlockXSize > 1024 || nBlockYSize > 1024 ) )
2338 {
2339 bProfile1 = FALSE;
2340 if( bInspireTG || EQUAL(pszProfile, "PROFILE_1") )
2341 {
2342 CPLError(CE_Failure, CPLE_NotSupported,
2343 "Tile dimensions incompatible with PROFILE_1%s. "
2344 "Should be whole image or square with dimension <= 1024.",
2345 pszReq21OrEmpty);
2346 return NULL;
2347 }
2348 }
2349 if( (nMaxTileDim >> (nNumResolutions-1)) > 128 )
2350 {
2351 bProfile1 = FALSE;
2352 if( bInspireTG || EQUAL(pszProfile, "PROFILE_1") )
2353 {
2354 CPLError(CE_Failure, CPLE_NotSupported,
2355 "Number of resolutions incompatible with PROFILE_1%s. "
2356 "Should be at least %d.",
2357 pszReq21OrEmpty,
2358 nMinProfile1Resolutions);
2359 return NULL;
2360 }
2361 }
2362 if( nCblockW > 64 || nCblockH > 64 )
2363 {
2364 bProfile1 = FALSE;
2365 if( bInspireTG || EQUAL(pszProfile, "PROFILE_1") )
2366 {
2367 CPLError(CE_Failure, CPLE_NotSupported,
2368 "Codeblock width incompatible with PROFILE_1%s. "
2369 "Codeblock width or height should be <= 64.",
2370 pszReq21OrEmpty);
2371 return NULL;
2372 }
2373 }
2374 }
2375
2376 /* -------------------------------------------------------------------- */
2377 /* Work out the precision. */
2378 /* -------------------------------------------------------------------- */
2379 int nBits;
2380 if( CSLFetchNameValue( papszOptions, "NBITS" ) != NULL )
2381 {
2382 nBits = atoi(CSLFetchNameValue(papszOptions,"NBITS"));
2383 if( bInspireTG &&
2384 !(nBits == 1 || nBits == 8 || nBits == 16 || nBits == 32) )
2385 {
2386 CPLError(CE_Failure, CPLE_NotSupported,
2387 "INSPIRE_TG=YES mandates NBITS=1,8,16 or 32 (TG requirement 24)");
2388 return NULL;
2389 }
2390 }
2391 else if( poSrcDS->GetRasterBand(1)->GetMetadataItem( "NBITS", "IMAGE_STRUCTURE" )
2392 != NULL )
2393 {
2394 nBits = atoi(poSrcDS->GetRasterBand(1)->GetMetadataItem( "NBITS",
2395 "IMAGE_STRUCTURE" ));
2396 if( bInspireTG &&
2397 !(nBits == 1 || nBits == 8 || nBits == 16 || nBits == 32) )
2398 {
2399 /* Implements "NOTE If the original data do not satisfy this "
2400 "requirement, they will be converted in a representation using "
2401 "the next higher power of 2" */
2402 nBits = GDALGetDataTypeSize(eDataType);
2403 }
2404 }
2405 else
2406 {
2407 nBits = GDALGetDataTypeSize(eDataType);
2408 }
2409
2410 if( (GDALGetDataTypeSize(eDataType) == 8 && nBits > 8) ||
2411 (GDALGetDataTypeSize(eDataType) == 16 && (nBits <= 8 || nBits > 16)) ||
2412 (GDALGetDataTypeSize(eDataType) == 32 && (nBits <= 16 || nBits > 32)) )
2413 {
2414 CPLError(CE_Warning, CPLE_NotSupported,
2415 "Inconsistent NBITS value with data type. Using %d",
2416 GDALGetDataTypeSize(eDataType));
2417 }
2418
2419 /* -------------------------------------------------------------------- */
2420 /* Georeferencing options */
2421 /* -------------------------------------------------------------------- */
2422
2423 int bGMLJP2Option = CSLFetchBoolean( papszOptions, "GMLJP2", TRUE );
2424 int nGMLJP2Version = 1;
2425 const char* pszGMLJP2V2Def = CSLFetchNameValue( papszOptions, "GMLJP2V2_DEF" );
2426 if( pszGMLJP2V2Def != NULL )
2427 {
2428 bGMLJP2Option = TRUE;
2429 nGMLJP2Version = 2;
2430 if( bInspireTG )
2431 {
2432 CPLError(CE_Warning, CPLE_NotSupported,
2433 "INSPIRE_TG=YES is only compatible with GMLJP2 v1");
2434 return NULL;
2435 }
2436 }
2437 int bGeoJP2Option = CSLFetchBoolean( papszOptions, "GeoJP2", TRUE );
2438
2439 GDALJP2Metadata oJP2MD;
2440
2441 int bGeoreferencingCompatOfGeoJP2 = FALSE;
2442 int bGeoreferencingCompatOfGMLJP2 = FALSE;
2443 if( eCodecFormat == OPJ_CODEC_JP2 && (bGMLJP2Option || bGeoJP2Option) )
2444 {
2445 if( poSrcDS->GetGCPCount() > 0 )
2446 {
2447 bGeoreferencingCompatOfGeoJP2 = TRUE;
2448 oJP2MD.SetGCPs( poSrcDS->GetGCPCount(),
2449 poSrcDS->GetGCPs() );
2450 oJP2MD.SetProjection( poSrcDS->GetGCPProjection() );
2451 }
2452 else
2453 {
2454 const char* pszWKT = poSrcDS->GetProjectionRef();
2455 if( pszWKT != NULL && pszWKT[0] != '\0' )
2456 {
2457 bGeoreferencingCompatOfGeoJP2 = TRUE;
2458 oJP2MD.SetProjection( pszWKT );
2459 }
2460 double adfGeoTransform[6];
2461 if( poSrcDS->GetGeoTransform( adfGeoTransform ) == CE_None )
2462 {
2463 bGeoreferencingCompatOfGeoJP2 = TRUE;
2464 oJP2MD.SetGeoTransform( adfGeoTransform );
2465 }
2466 bGeoreferencingCompatOfGMLJP2 =
2467 ( pszWKT != NULL && pszWKT[0] != '\0' ) &&
2468 poSrcDS->GetGeoTransform( adfGeoTransform ) == CE_None;
2469 }
2470 if( poSrcDS->GetMetadata("RPC") != NULL )
2471 {
2472 oJP2MD.SetRPCMD( poSrcDS->GetMetadata("RPC") );
2473 bGeoreferencingCompatOfGeoJP2 = TRUE;
2474 }
2475
2476 const char* pszAreaOrPoint = poSrcDS->GetMetadataItem(GDALMD_AREA_OR_POINT);
2477 oJP2MD.bPixelIsPoint = pszAreaOrPoint != NULL && EQUAL(pszAreaOrPoint, GDALMD_AOP_POINT);
2478
2479 if( bGMLJP2Option && CPLGetConfigOption("GMLJP2OVERRIDE", NULL) != NULL )
2480 bGeoreferencingCompatOfGMLJP2 = TRUE;
2481 }
2482
2483 if( CSLFetchNameValue( papszOptions, "GMLJP2" ) != NULL && bGMLJP2Option &&
2484 !bGeoreferencingCompatOfGMLJP2 && nGMLJP2Version == 1 )
2485 {
2486 CPLError(CE_Warning, CPLE_AppDefined,
2487 "GMLJP2 box was explicitly required but cannot be written due "
2488 "to lack of georeferencing and/or unsupported georeferencing for GMLJP2");
2489 }
2490
2491 if( CSLFetchNameValue( papszOptions, "GeoJP2" ) != NULL && bGeoJP2Option &&
2492 !bGeoreferencingCompatOfGeoJP2 )
2493 {
2494 CPLError(CE_Warning, CPLE_AppDefined,
2495 "GeoJP2 box was explicitly required but cannot be written due "
2496 "to lack of georeferencing");
2497 }
2498 int bGeoBoxesAfter = CSLFetchBoolean(papszOptions, "GEOBOXES_AFTER_JP2C",
2499 bInspireTG);
2500 GDALJP2Box* poGMLJP2Box = NULL;
2501 if( eCodecFormat == OPJ_CODEC_JP2 && bGMLJP2Option && bGeoreferencingCompatOfGMLJP2 )
2502 {
2503 if( nGMLJP2Version == 1)
2504 poGMLJP2Box = oJP2MD.CreateGMLJP2(nXSize,nYSize);
2505 else
2506 poGMLJP2Box = oJP2MD.CreateGMLJP2V2(nXSize,nYSize,pszGMLJP2V2Def,poSrcDS);
2507 if( poGMLJP2Box == NULL )
2508 return NULL;
2509 }
2510
2511 /* -------------------------------------------------------------------- */
2512 /* Setup encoder */
2513 /* -------------------------------------------------------------------- */
2514
2515 opj_cparameters_t parameters;
2516 opj_set_default_encoder_parameters(¶meters);
2517 if (bSOP)
2518 parameters.csty |= 0x02;
2519 if (bEPH)
2520 parameters.csty |= 0x04;
2521 parameters.cp_disto_alloc = 1;
2522 parameters.tcp_numlayers = (int)adfRates.size();
2523 for(int i=0;i<(int)adfRates.size();i++)
2524 parameters.tcp_rates[i] = (float) adfRates[i];
2525 parameters.cp_tx0 = 0;
2526 parameters.cp_ty0 = 0;
2527 parameters.tile_size_on = TRUE;
2528 parameters.cp_tdx = nBlockXSize;
2529 parameters.cp_tdy = nBlockYSize;
2530 parameters.irreversible = bIsIrreversible;
2531 parameters.numresolution = nNumResolutions;
2532 parameters.prog_order = eProgOrder;
2533 parameters.tcp_mct = bYCC;
2534 parameters.cblockw_init = nCblockW;
2535 parameters.cblockh_init = nCblockH;
2536
2537 /* Add precincts */
2538 const char* pszPrecincts = CSLFetchNameValueDef(papszOptions, "PRECINCTS",
2539 "{512,512},{256,512},{128,512},{64,512},{32,512},{16,512},{8,512},{4,512},{2,512}");
2540 char **papszTokens = CSLTokenizeStringComplex( pszPrecincts, "{},", FALSE, FALSE );
2541 int nPrecincts = CSLCount(papszTokens) / 2;
2542 for(int i=0;i<nPrecincts && i < OPJ_J2K_MAXRLVLS;i++)
2543 {
2544 int nPCRW = atoi(papszTokens[2*i]);
2545 int nPCRH = atoi(papszTokens[2*i+1]);
2546 if( nPCRW < 1 || nPCRH < 1 )
2547 break;
2548 parameters.csty |= 0x01;
2549 parameters.res_spec ++;
2550 parameters.prcw_init[i] = nPCRW;
2551 parameters.prch_init[i] = nPCRH;
2552 }
2553 CSLDestroy(papszTokens);
2554
2555 /* Add tileparts setting */
2556 const char* pszTileParts = CSLFetchNameValueDef(papszOptions, "TILEPARTS", "DISABLED");
2557 if( EQUAL(pszTileParts, "RESOLUTIONS") )
2558 {
2559 parameters.tp_on = 1;
2560 parameters.tp_flag = 'R';
2561 }
2562 else if( EQUAL(pszTileParts, "LAYERS") )
2563 {
2564 if( parameters.tcp_numlayers == 1 )
2565 {
2566 CPLError(CE_Warning, CPLE_AppDefined,
2567 "TILEPARTS=LAYERS has no real interest with single-layer codestream");
2568 }
2569 parameters.tp_on = 1;
2570 parameters.tp_flag = 'L';
2571 }
2572 else if( EQUAL(pszTileParts, "COMPONENTS") )
2573 {
2574 parameters.tp_on = 1;
2575 parameters.tp_flag = 'C';
2576 }
2577 else if( !EQUAL(pszTileParts, "DISABLED") )
2578 {
2579 CPLError(CE_Warning, CPLE_NotSupported,
2580 "Invalid value for TILEPARTS");
2581 }
2582
2583 if( bProfile1 )
2584 {
2585 #if defined(OPENJPEG_VERSION) && OPENJPEG_VERSION >= 20100
2586 parameters.rsiz = OPJ_PROFILE_1;
2587 #else
2588 /* This is a hack but this works */
2589 parameters.cp_rsiz = (OPJ_RSIZ_CAPABILITIES) 2; /* Profile 1 */
2590 #endif
2591 }
2592
2593 opj_image_cmptparm_t* pasBandParams =
2594 (opj_image_cmptparm_t*)CPLMalloc(nBands * sizeof(opj_image_cmptparm_t));
2595 int iBand;
2596 int bSamePrecision = TRUE;
2597 int b1BitAlpha = FALSE;
2598 for(iBand=0;iBand<nBands;iBand++)
2599 {
2600 pasBandParams[iBand].x0 = 0;
2601 pasBandParams[iBand].y0 = 0;
2602 if (bYCBCR420 && (iBand == 1 || iBand == 2))
2603 {
2604 pasBandParams[iBand].dx = 2;
2605 pasBandParams[iBand].dy = 2;
2606 pasBandParams[iBand].w = nXSize / 2;
2607 pasBandParams[iBand].h = nYSize / 2;
2608 }
2609 else
2610 {
2611 pasBandParams[iBand].dx = 1;
2612 pasBandParams[iBand].dy = 1;
2613 pasBandParams[iBand].w = nXSize;
2614 pasBandParams[iBand].h = nYSize;
2615 }
2616
2617 pasBandParams[iBand].sgnd = (eDataType == GDT_Int16 || eDataType == GDT_Int32);
2618 pasBandParams[iBand].prec = nBits;
2619
2620 const char* pszNBits = poSrcDS->GetRasterBand(iBand+1)->GetMetadataItem(
2621 "NBITS", "IMAGE_STRUCTURE");
2622 /* Recommendation 38 In the case of an opacity channel, the bit depth should be 1-bit. */
2623 if( iBand == nAlphaBandIndex &&
2624 ((pszNBits != NULL && EQUAL(pszNBits, "1")) ||
2625 CSLFetchBoolean(papszOptions, "1BIT_ALPHA", bInspireTG)) )
2626 {
2627 if( iBand != nBands - 1 && nBits != 1 )
2628 {
2629 /* Might be a bug in openjpeg, but it seems that if the alpha */
2630 /* band is the first one, it would select 1-bit for all channels... */
2631 CPLError(CE_Warning, CPLE_NotSupported,
2632 "Cannot output 1-bit alpha channel if it is not the last one");
2633 }
2634 else
2635 {
2636 CPLDebug("OPENJPEG", "Using 1-bit alpha channel");
2637 pasBandParams[iBand].sgnd = 0;
2638 pasBandParams[iBand].prec = 1;
2639 bSamePrecision = FALSE;
2640 b1BitAlpha = TRUE;
2641 }
2642 }
2643 }
2644
2645 if( bInspireTG && nAlphaBandIndex >= 0 && !b1BitAlpha )
2646 {
2647 CPLError(CE_Warning, CPLE_NotSupported,
2648 "INSPIRE_TG=YES recommends 1BIT_ALPHA=YES (Recommendation 38)");
2649 }
2650
2651 /* Always ask OpenJPEG to do codestream only. We will take care */
2652 /* of JP2 boxes */
2653 opj_codec_t* pCodec = opj_create_compress(OPJ_CODEC_J2K);
2654 if (pCodec == NULL)
2655 {
2656 CPLError(CE_Failure, CPLE_AppDefined,
2657 "opj_create_compress() failed");
2658 CPLFree(pasBandParams);
2659 delete poGMLJP2Box;
2660 return NULL;
2661 }
2662
2663 opj_set_info_handler(pCodec, JP2OpenJPEGDataset_InfoCallback,NULL);
2664 opj_set_warning_handler(pCodec, JP2OpenJPEGDataset_WarningCallback,NULL);
2665 opj_set_error_handler(pCodec, JP2OpenJPEGDataset_ErrorCallback,NULL);
2666
2667 OPJ_COLOR_SPACE eColorSpace = OPJ_CLRSPC_GRAY;
2668
2669 if( bYCBCR420 )
2670 {
2671 eColorSpace = OPJ_CLRSPC_SYCC;
2672 }
2673 else if( (nBands == 3 || nBands == 4) &&
2674 nRedBandIndex >= 0 && nGreenBandIndex >= 0 && nBlueBandIndex >= 0 )
2675 {
2676 eColorSpace = OPJ_CLRSPC_SRGB;
2677 }
2678 else if (poCT != NULL)
2679 {
2680 eColorSpace = OPJ_CLRSPC_SRGB;
2681 }
2682
2683 opj_image_t* psImage = opj_image_tile_create(nBands,pasBandParams,
2684 eColorSpace);
2685
2686 if (psImage == NULL)
2687 {
2688 CPLError(CE_Failure, CPLE_AppDefined,
2689 "opj_image_tile_create() failed");
2690 opj_destroy_codec(pCodec);
2691 CPLFree(pasBandParams);
2692 pasBandParams = NULL;
2693 delete poGMLJP2Box;
2694 return NULL;
2695 }
2696
2697 psImage->x0 = 0;
2698 psImage->y0 = 0;
2699 psImage->x1 = nXSize;
2700 psImage->y1 = nYSize;
2701 psImage->color_space = eColorSpace;
2702 psImage->numcomps = nBands;
2703
2704 if (!opj_setup_encoder(pCodec,¶meters,psImage))
2705 {
2706 CPLError(CE_Failure, CPLE_AppDefined,
2707 "opj_setup_encoder() failed");
2708 opj_image_destroy(psImage);
2709 opj_destroy_codec(pCodec);
2710 CPLFree(pasBandParams);
2711 pasBandParams = NULL;
2712 delete poGMLJP2Box;
2713 return NULL;
2714 }
2715
2716 /* -------------------------------------------------------------------- */
2717 /* Create the dataset. */
2718 /* -------------------------------------------------------------------- */
2719
2720 const char* pszAccess = EQUALN(pszFilename, "/vsisubfile/", 12) ? "r+b" : "w+b";
2721 VSILFILE* fp = VSIFOpenL(pszFilename, pszAccess);
2722 if (fp == NULL)
2723 {
2724 CPLError(CE_Failure, CPLE_AppDefined, "Cannot create file");
2725 opj_image_destroy(psImage);
2726 opj_destroy_codec(pCodec);
2727 CPLFree(pasBandParams);
2728 pasBandParams = NULL;
2729 delete poGMLJP2Box;
2730 return NULL;
2731 }
2732
2733 /* -------------------------------------------------------------------- */
2734 /* Add JP2 boxes. */
2735 /* -------------------------------------------------------------------- */
2736 vsi_l_offset nStartJP2C = 0;
2737 int bUseXLBoxes = FALSE;
2738
2739 if( eCodecFormat == OPJ_CODEC_JP2 )
2740 {
2741 GDALJP2Box jPBox(fp);
2742 jPBox.SetType("jP ");
2743 jPBox.AppendWritableData(4, "\x0D\x0A\x87\x0A");
2744 WriteBox(fp, &jPBox);
2745
2746 GDALJP2Box ftypBox(fp);
2747 ftypBox.SetType("ftyp");
2748 ftypBox.AppendWritableData(4, "jp2 "); /* Branding */
2749 ftypBox.AppendUInt32(0); /* minimum version */
2750 ftypBox.AppendWritableData(4, "jp2 "); /* Compatibility list: first value */
2751
2752 int bJPXOption = CSLFetchBoolean( papszOptions, "JPX", TRUE );
2753 if( bInspireTG && poGMLJP2Box != NULL && !bJPXOption )
2754 {
2755 CPLError(CE_Warning, CPLE_AppDefined,
2756 "INSPIRE_TG=YES implies following GMLJP2 specification which "
2757 "recommends advertize reader requirement 67 feature, and thus JPX capability");
2758 }
2759 else if( poGMLJP2Box != NULL && bJPXOption )
2760 {
2761 /* GMLJP2 uses lbl and asoc boxes, which are JPEG2000 Part II spec */
2762 /* advertizing jpx is required per 8.1 of 05-047r3 GMLJP2 */
2763 ftypBox.AppendWritableData(4, "jpx "); /* Compatibility list: second value */
2764 }
2765 WriteBox(fp, &ftypBox);
2766
2767 int bIPR = poSrcDS->GetMetadata("xml:IPR") != NULL &&
2768 CSLFetchBoolean(papszOptions, "WRITE_METADATA", FALSE);
2769
2770 /* Reader requirement box */
2771 if( poGMLJP2Box != NULL && bJPXOption )
2772 {
2773 GDALJP2Box rreqBox(fp);
2774 rreqBox.SetType("rreq");
2775 rreqBox.AppendUInt8(1); /* ML = 1 byte for mask length */
2776
2777 rreqBox.AppendUInt8(0x80 | 0x40 | (bIPR ? 0x20 : 0)); /* FUAM */
2778 rreqBox.AppendUInt8(0x80); /* DCM */
2779
2780 rreqBox.AppendUInt16(2 + bIPR); /* NSF: Number of standard features */
2781
2782 rreqBox.AppendUInt16((bProfile1) ? 4 : 5); /* SF0 : PROFILE 1 or PROFILE 2 */
2783 rreqBox.AppendUInt8(0x80); /* SM0 */
2784
2785 rreqBox.AppendUInt16(67); /* SF1 : GMLJP2 box */
2786 rreqBox.AppendUInt8(0x40); /* SM1 */
2787
2788 if( bIPR )
2789 {
2790 rreqBox.AppendUInt16(35); /* SF2 : IPR metadata */
2791 rreqBox.AppendUInt8(0x20); /* SM2 */
2792 }
2793 rreqBox.AppendUInt16(0); /* NVF */
2794 WriteBox(fp, &rreqBox);
2795 }
2796
2797 GDALJP2Box ihdrBox(fp);
2798 ihdrBox.SetType("ihdr");
2799 ihdrBox.AppendUInt32(nYSize);
2800 ihdrBox.AppendUInt32(nXSize);
2801 ihdrBox.AppendUInt16(nBands);
2802 GByte BPC;
2803 if( bSamePrecision )
2804 BPC = (pasBandParams[0].prec-1) | (pasBandParams[0].sgnd << 7);
2805 else
2806 BPC = 255;
2807 ihdrBox.AppendUInt8(BPC);
2808 ihdrBox.AppendUInt8(7); /* C=Compression type: fixed value */
2809 ihdrBox.AppendUInt8(0); /* UnkC: 0= colourspace of the image is known */
2810 /*and correctly specified in the Colourspace Specification boxes within the file */
2811 ihdrBox.AppendUInt8(bIPR); /* IPR: 0=no intellectual property, 1=IPR box */
2812
2813 GDALJP2Box bpccBox(fp);
2814 if( !bSamePrecision )
2815 {
2816 bpccBox.SetType("bpcc");
2817 for(int i=0;i<nBands;i++)
2818 bpccBox.AppendUInt8((pasBandParams[i].prec-1) | (pasBandParams[i].sgnd << 7));
2819 }
2820
2821 GDALJP2Box colrBox(fp);
2822 colrBox.SetType("colr");
2823 colrBox.AppendUInt8(1); /* METHOD: 1=Enumerated Colourspace */
2824 colrBox.AppendUInt8(0); /* PREC: Precedence. 0=(field reserved for ISO use) */
2825 colrBox.AppendUInt8(0); /* APPROX: Colourspace approximation. */
2826 GUInt32 enumcs = 16;
2827 if( eColorSpace == OPJ_CLRSPC_SRGB )
2828 enumcs = 16;
2829 else if( eColorSpace == OPJ_CLRSPC_GRAY )
2830 enumcs = 17;
2831 else if( eColorSpace == OPJ_CLRSPC_SYCC )
2832 enumcs = 18;
2833 colrBox.AppendUInt32(enumcs); /* EnumCS: Enumerated colourspace */
2834
2835 GDALJP2Box pclrBox(fp);
2836 GDALJP2Box cmapBox(fp);
2837 int nCTComponentCount = 0;
2838 if (poCT != NULL)
2839 {
2840 pclrBox.SetType("pclr");
2841 int nEntries = MIN(256, poCT->GetColorEntryCount());
2842 nCTComponentCount = atoi(CSLFetchNameValueDef(papszOptions, "CT_COMPONENTS", "0"));
2843 if( bInspireTG )
2844 {
2845 if( nCTComponentCount != 0 && nCTComponentCount != 3 )
2846 CPLError(CE_Warning, CPLE_AppDefined, "Inspire TG mandates 3 components for color table");
2847 else
2848 nCTComponentCount = 3;
2849 }
2850 else if( nCTComponentCount != 3 && nCTComponentCount != 4 )
2851 {
2852 nCTComponentCount = 3;
2853 for(int i=0;i<nEntries;i++)
2854 {
2855 const GDALColorEntry* psEntry = poCT->GetColorEntry(i);
2856 if( psEntry->c4 != 255 )
2857 {
2858 CPLDebug("OPENJPEG", "Color table has at least one non-opaque value. "
2859 "This may cause compatibility problems with some readers. "
2860 "In which case use CT_COMPONENTS=3 creation option");
2861 nCTComponentCount = 4;
2862 break;
2863 }
2864 }
2865 }
2866 nRedBandIndex = 0;
2867 nGreenBandIndex = 1;
2868 nBlueBandIndex = 2;
2869 nAlphaBandIndex = (nCTComponentCount == 4) ? 3 : -1;
2870
2871 pclrBox.AppendUInt16(nEntries);
2872 pclrBox.AppendUInt8(nCTComponentCount); /* NPC: Number of components */
2873 for(int i=0;i<nCTComponentCount;i++)
2874 {
2875 pclrBox.AppendUInt8(7); /* Bi: unsigned 8 bits */
2876 }
2877 for(int i=0;i<nEntries;i++)
2878 {
2879 const GDALColorEntry* psEntry = poCT->GetColorEntry(i);
2880 pclrBox.AppendUInt8((GByte)psEntry->c1);
2881 pclrBox.AppendUInt8((GByte)psEntry->c2);
2882 pclrBox.AppendUInt8((GByte)psEntry->c3);
2883 if( nCTComponentCount == 4 )
2884 pclrBox.AppendUInt8((GByte)psEntry->c4);
2885 }
2886
2887 cmapBox.SetType("cmap");
2888 for(int i=0;i<nCTComponentCount;i++)
2889 {
2890 cmapBox.AppendUInt16(0); /* CMPi: code stream component index */
2891 cmapBox.AppendUInt8(1); /* MYTPi: 1=palette mapping */
2892 cmapBox.AppendUInt8(i); /* PCOLi: index component from the map */
2893 }
2894 }
2895
2896 GDALJP2Box cdefBox(fp);
2897 if( ((nBands == 3 || nBands == 4) &&
2898 (eColorSpace == OPJ_CLRSPC_SRGB || eColorSpace == OPJ_CLRSPC_SYCC) &&
2899 (nRedBandIndex != 0 || nGreenBandIndex != 1 || nBlueBandIndex != 2)) ||
2900 nAlphaBandIndex >= 0)
2901 {
2902 cdefBox.SetType("cdef");
2903 int nComponents = (nCTComponentCount == 4) ? 4 : nBands;
2904 cdefBox.AppendUInt16(nComponents);
2905 for(int i=0;i<nComponents;i++)
2906 {
2907 cdefBox.AppendUInt16(i); /* Component number */
2908 if( i != nAlphaBandIndex )
2909 {
2910 cdefBox.AppendUInt16(0); /* Signification: This channel is the colour image data for the associated colour */
2911 if( eColorSpace == OPJ_CLRSPC_GRAY && nComponents == 2)
2912 cdefBox.AppendUInt16(1); /* Colour of the component: associated with a particular colour */
2913 else if ((eColorSpace == OPJ_CLRSPC_SRGB ||
2914 eColorSpace == OPJ_CLRSPC_SYCC) &&
2915 (nComponents == 3 || nComponents == 4) )
2916 {
2917 if( i == nRedBandIndex )
2918 cdefBox.AppendUInt16(1);
2919 else if( i == nGreenBandIndex )
2920 cdefBox.AppendUInt16(2);
2921 else if( i == nBlueBandIndex )
2922 cdefBox.AppendUInt16(3);
2923 else
2924 {
2925 CPLError(CE_Warning, CPLE_AppDefined,
2926 "Could not associate band %d with a red/green/blue channel",
2927 i+1);
2928 cdefBox.AppendUInt16(65535);
2929 }
2930 }
2931 else
2932 cdefBox.AppendUInt16(65535); /* Colour of the component: not associated with any particular colour */
2933 }
2934 else
2935 {
2936 cdefBox.AppendUInt16(1); /* Signification: Non pre-multiplied alpha */
2937 cdefBox.AppendUInt16(0); /* Colour of the component: This channel is associated as the image as a whole */
2938 }
2939 }
2940 }
2941
2942 // Add res box if needed
2943 double dfXRes = 0, dfYRes = 0;
2944 int nResUnit = 0;
2945 GDALJP2Box* poRes = NULL;
2946 if( poSrcDS->GetMetadataItem("TIFFTAG_XRESOLUTION") != NULL
2947 && poSrcDS->GetMetadataItem("TIFFTAG_YRESOLUTION") != NULL
2948 && poSrcDS->GetMetadataItem("TIFFTAG_RESOLUTIONUNIT") != NULL )
2949 {
2950 dfXRes =
2951 CPLAtof(poSrcDS->GetMetadataItem("TIFFTAG_XRESOLUTION"));
2952 dfYRes =
2953 CPLAtof(poSrcDS->GetMetadataItem("TIFFTAG_YRESOLUTION"));
2954 nResUnit = atoi(poSrcDS->GetMetadataItem("TIFFTAG_RESOLUTIONUNIT"));
2955 #define PIXELS_PER_INCH 2
2956 #define PIXELS_PER_CM 3
2957
2958 if( nResUnit == PIXELS_PER_INCH )
2959 {
2960 // convert pixels per inch to pixels per cm.
2961 dfXRes = dfXRes * 39.37 / 100.0;
2962 dfYRes = dfYRes * 39.37 / 100.0;
2963 nResUnit = PIXELS_PER_CM;
2964 }
2965
2966 if( nResUnit == PIXELS_PER_CM &&
2967 dfXRes > 0 && dfYRes > 0 &&
2968 dfXRes < 65535 && dfYRes < 65535 )
2969 {
2970 /* Format a resd box and embed it inside a res box */
2971 GDALJP2Box oResd;
2972 oResd.SetType("resd");
2973
2974 int nYDenom = 1;
2975 while (nYDenom < 32767 && dfYRes < 32767)
2976 {
2977 dfYRes *= 2;
2978 nYDenom *= 2;
2979 }
2980 int nXDenom = 1;
2981 while (nXDenom < 32767 && dfXRes < 32767)
2982 {
2983 dfXRes *= 2;
2984 nXDenom *= 2;
2985 }
2986
2987 oResd.AppendUInt16((GUInt16)dfYRes);
2988 oResd.AppendUInt16((GUInt16)nYDenom);
2989 oResd.AppendUInt16((GUInt16)dfXRes);
2990 oResd.AppendUInt16((GUInt16)nXDenom);
2991 oResd.AppendUInt8(2); /* vertical exponent */
2992 oResd.AppendUInt8(2); /* horizontal exponent */
2993
2994 GDALJP2Box* poResd = &oResd;
2995 poRes = GDALJP2Box::CreateAsocBox( 1, &poResd );
2996 poRes->SetType("res ");
2997 }
2998 }
2999
3000 /* Build and write jp2h super box now */
3001 GDALJP2Box* apoBoxes[7];
3002 int nBoxes = 1;
3003 apoBoxes[0] = &ihdrBox;
3004 if( bpccBox.GetDataLength() )
3005 apoBoxes[nBoxes++] = &bpccBox;
3006 apoBoxes[nBoxes++] = &colrBox;
3007 if( pclrBox.GetDataLength() )
3008 apoBoxes[nBoxes++] = &pclrBox;
3009 if( cmapBox.GetDataLength() )
3010 apoBoxes[nBoxes++] = &cmapBox;
3011 if( cdefBox.GetDataLength() )
3012 apoBoxes[nBoxes++] = &cdefBox;
3013 if( poRes )
3014 apoBoxes[nBoxes++] = poRes;
3015 GDALJP2Box* psJP2HBox = GDALJP2Box::CreateSuperBox( "jp2h",
3016 nBoxes,
3017 apoBoxes );
3018 WriteBox(fp, psJP2HBox);
3019 delete psJP2HBox;
3020 delete poRes;
3021
3022 if( !bGeoBoxesAfter )
3023 {
3024 if( bGeoJP2Option && bGeoreferencingCompatOfGeoJP2 )
3025 {
3026 GDALJP2Box* poBox = oJP2MD.CreateJP2GeoTIFF();
3027 WriteBox(fp, poBox);
3028 delete poBox;
3029 }
3030
3031 if( CSLFetchBoolean(papszOptions, "WRITE_METADATA", FALSE) &&
3032 !CSLFetchBoolean(papszOptions, "MAIN_MD_DOMAIN_ONLY", FALSE) )
3033 {
3034 WriteXMPBox(fp, poSrcDS, papszOptions);
3035 }
3036
3037 if( CSLFetchBoolean(papszOptions, "WRITE_METADATA", FALSE) )
3038 {
3039 if( !CSLFetchBoolean(papszOptions, "MAIN_MD_DOMAIN_ONLY", FALSE) )
3040 WriteXMLBoxes(fp, poSrcDS, papszOptions);
3041 WriteGDALMetadataBox(fp, poSrcDS, papszOptions);
3042 }
3043
3044 if( poGMLJP2Box != NULL )
3045 {
3046 WriteBox(fp, poGMLJP2Box);
3047 }
3048 }
3049 }
3050 CPLFree(pasBandParams);
3051 pasBandParams = NULL;
3052
3053 /* -------------------------------------------------------------------- */
3054 /* Try lossless reuse of an existing JPEG2000 codestream */
3055 /* -------------------------------------------------------------------- */
3056 vsi_l_offset nCodeStreamLength = 0;
3057 vsi_l_offset nCodeStreamStart = 0;
3058 VSILFILE* fpSrc = NULL;
3059 if( CSLFetchBoolean(papszOptions, "USE_SRC_CODESTREAM", FALSE) )
3060 {
3061 CPLString osSrcFilename( poSrcDS->GetDescription() );
3062 if( poSrcDS->GetDriver() != NULL &&
3063 poSrcDS->GetDriver() == GDALGetDriverByName("VRT") )
3064 {
3065 VRTDataset* poVRTDS = (VRTDataset* )poSrcDS;
3066 GDALDataset* poSimpleSourceDS = poVRTDS->GetSingleSimpleSource();
3067 if( poSimpleSourceDS )
3068 osSrcFilename = poSimpleSourceDS->GetDescription();
3069 }
3070
3071 fpSrc = VSIFOpenL( osSrcFilename, "rb" );
3072 if( fpSrc )
3073 {
3074 nCodeStreamStart = JP2OpenJPEGFindCodeStream(fpSrc,
3075 &nCodeStreamLength);
3076 }
3077 if( nCodeStreamLength == 0 )
3078 {
3079 CPLError(CE_Warning, CPLE_AppDefined,
3080 "USE_SRC_CODESTREAM=YES specified, but no codestream found");
3081 }
3082 }
3083
3084 if( eCodecFormat == OPJ_CODEC_JP2 )
3085 {
3086 // Start codestream box
3087 nStartJP2C = VSIFTellL(fp);
3088 if( nCodeStreamLength )
3089 bUseXLBoxes = ((vsi_l_offset)(GUInt32)nCodeStreamLength != nCodeStreamLength);
3090 else
3091 bUseXLBoxes = CSLFetchBoolean(papszOptions, "JP2C_XLBOX", FALSE) || /* For debugging */
3092 (GIntBig)nXSize * nYSize * nBands * nDataTypeSize / adfRates[adfRates.size()-1] > 4e9;
3093 GUInt32 nLBox = (bUseXLBoxes) ? 1 : 0;
3094 CPL_MSBPTR32(&nLBox);
3095 VSIFWriteL(&nLBox, 1, 4, fp);
3096 VSIFWriteL("jp2c", 1, 4, fp);
3097 if( bUseXLBoxes )
3098 {
3099 GUIntBig nXLBox = 0;
3100 VSIFWriteL(&nXLBox, 1, 8, fp);
3101 }
3102 }
3103
3104 /* -------------------------------------------------------------------- */
3105 /* Do lossless reuse of an existing JPEG2000 codestream */
3106 /* -------------------------------------------------------------------- */
3107 if( fpSrc )
3108 {
3109 const char* apszIgnoredOptions[] = {
3110 "BLOCKXSIZE", "BLOCKYSIZE", "QUALITY", "REVERSIBLE",
3111 "RESOLUTIONS", "PROGRESSION", "SOP", "EPH",
3112 "YCBCR420", "YCC", "NBITS", "1BIT_ALPHA", "PRECINCTS",
3113 "TILEPARTS", "CODEBLOCK_WIDTH", "CODEBLOCK_HEIGHT", NULL };
3114 for( int i = 0; apszIgnoredOptions[i]; i ++)
3115 {
3116 if( CSLFetchNameValue(papszOptions, apszIgnoredOptions[i]) )
3117 {
3118 CPLError(CE_Warning, CPLE_NotSupported,
3119 "Option %s ignored when USE_SRC_CODESTREAM=YES",
3120 apszIgnoredOptions[i]);
3121 }
3122 }
3123 GByte abyBuffer[4096];
3124 VSIFSeekL( fpSrc, nCodeStreamStart, SEEK_SET );
3125 vsi_l_offset nRead = 0;
3126 while( nRead < nCodeStreamLength )
3127 {
3128 int nToRead = ( nCodeStreamLength-nRead > 4096 ) ? 4049 :
3129 (int)(nCodeStreamLength-nRead);
3130 if( (int)VSIFReadL(abyBuffer, 1, nToRead, fpSrc) != nToRead )
3131 {
3132 VSIFCloseL(fp);
3133 VSIFCloseL(fpSrc);
3134 opj_image_destroy(psImage);
3135 opj_destroy_codec(pCodec);
3136 delete poGMLJP2Box;
3137 return NULL;
3138 }
3139 if( nRead == 0 && (pszProfile || bInspireTG) &&
3140 abyBuffer[2] == 0xFF && abyBuffer[3] == 0x51 )
3141 {
3142 if( EQUAL(pszProfile, "UNRESTRICTED") )
3143 {
3144 abyBuffer[6] = 0;
3145 abyBuffer[7] = 0;
3146 }
3147 else if( EQUAL(pszProfile, "PROFILE_1") || bInspireTG )
3148 {
3149 // TODO: ultimately we should check that we can really set Profile 1
3150 abyBuffer[6] = 0;
3151 abyBuffer[7] = 2;
3152 }
3153 }
3154 if( (int)VSIFWriteL(abyBuffer, 1, nToRead, fp) != nToRead ||
3155 !pfnProgress( (nRead + nToRead) * 1.0 / nCodeStreamLength,
3156 NULL, pProgressData ) )
3157 {
3158 VSIFCloseL(fp);
3159 VSIFCloseL(fpSrc);
3160 opj_image_destroy(psImage);
3161 opj_destroy_codec(pCodec);
3162 delete poGMLJP2Box;
3163 return NULL;
3164 }
3165 nRead += nToRead;
3166 }
3167
3168 VSIFCloseL(fpSrc);
3169 }
3170 else
3171 {
3172 opj_stream_t * pStream;
3173 JP2OpenJPEGFile sJP2OpenJPEGFile;
3174 sJP2OpenJPEGFile.fp = fp;
3175 sJP2OpenJPEGFile.nBaseOffset = VSIFTellL(fp);
3176 pStream = opj_stream_create(1024*1024, FALSE);
3177 opj_stream_set_write_function(pStream, JP2OpenJPEGDataset_Write);
3178 opj_stream_set_seek_function(pStream, JP2OpenJPEGDataset_Seek);
3179 opj_stream_set_skip_function(pStream, JP2OpenJPEGDataset_Skip);
3180 #if defined(OPENJPEG_VERSION) && OPENJPEG_VERSION >= 20100
3181 opj_stream_set_user_data(pStream, &sJP2OpenJPEGFile, NULL);
3182 #else
3183 opj_stream_set_user_data(pStream, &sJP2OpenJPEGFile);
3184 #endif
3185
3186 if (!opj_start_compress(pCodec,psImage,pStream))
3187 {
3188 CPLError(CE_Failure, CPLE_AppDefined,
3189 "opj_start_compress() failed");
3190 opj_stream_destroy(pStream);
3191 opj_image_destroy(psImage);
3192 opj_destroy_codec(pCodec);
3193 VSIFCloseL(fp);
3194 delete poGMLJP2Box;
3195 return NULL;
3196 }
3197
3198 int nTilesX = (nXSize + nBlockXSize - 1) / nBlockXSize;
3199 int nTilesY = (nYSize + nBlockYSize - 1) / nBlockYSize;
3200
3201 GUIntBig nTileSize = (GUIntBig)nBlockXSize * nBlockYSize * nBands * nDataTypeSize;
3202 GByte* pTempBuffer;
3203 if( nTileSize != (GUIntBig)(GUInt32)nTileSize )
3204 {
3205 CPLError(CE_Failure, CPLE_NotSupported, "Tile size exceeds 4GB");
3206 pTempBuffer = NULL;
3207 }
3208 else
3209 {
3210 pTempBuffer = (GByte*)VSIMalloc((size_t)nTileSize);
3211 }
3212 if (pTempBuffer == NULL)
3213 {
3214 opj_stream_destroy(pStream);
3215 opj_image_destroy(psImage);
3216 opj_destroy_codec(pCodec);
3217 VSIFCloseL(fp);
3218 delete poGMLJP2Box;
3219 return NULL;
3220 }
3221
3222 GByte* pYUV420Buffer = NULL;
3223 if (bYCBCR420)
3224 {
3225 pYUV420Buffer =(GByte*)VSIMalloc(3 * nBlockXSize * nBlockYSize / 2 +
3226 ((nBands == 4) ? nBlockXSize * nBlockYSize : 0));
3227 if (pYUV420Buffer == NULL)
3228 {
3229 opj_stream_destroy(pStream);
3230 opj_image_destroy(psImage);
3231 opj_destroy_codec(pCodec);
3232 CPLFree(pTempBuffer);
3233 VSIFCloseL(fp);
3234 delete poGMLJP2Box;
3235 return NULL;
3236 }
3237 }
3238
3239 /* -------------------------------------------------------------------- */
3240 /* Iterate over the tiles */
3241 /* -------------------------------------------------------------------- */
3242 pfnProgress( 0.0, NULL, pProgressData );
3243
3244 CPLErr eErr = CE_None;
3245 int nBlockXOff, nBlockYOff;
3246 int iTile = 0;
3247 for(nBlockYOff=0;eErr == CE_None && nBlockYOff<nTilesY;nBlockYOff++)
3248 {
3249 for(nBlockXOff=0;eErr == CE_None && nBlockXOff<nTilesX;nBlockXOff++)
3250 {
3251 int nWidthToRead = MIN(nBlockXSize, nXSize - nBlockXOff * nBlockXSize);
3252 int nHeightToRead = MIN(nBlockYSize, nYSize - nBlockYOff * nBlockYSize);
3253 eErr = poSrcDS->RasterIO(GF_Read,
3254 nBlockXOff * nBlockXSize,
3255 nBlockYOff * nBlockYSize,
3256 nWidthToRead, nHeightToRead,
3257 pTempBuffer, nWidthToRead, nHeightToRead,
3258 eDataType,
3259 nBands, NULL,
3260 0,0,0,NULL);
3261 if( b1BitAlpha )
3262 {
3263 for(int i=0;i<nWidthToRead*nHeightToRead;i++)
3264 {
3265 if( pTempBuffer[nAlphaBandIndex*nWidthToRead*nHeightToRead+i] )
3266 pTempBuffer[nAlphaBandIndex*nWidthToRead*nHeightToRead+i] = 1;
3267 else
3268 pTempBuffer[nAlphaBandIndex*nWidthToRead*nHeightToRead+i] = 0;
3269 }
3270 }
3271 if (eErr == CE_None)
3272 {
3273 if (bYCBCR420)
3274 {
3275 int j, i;
3276 for(j=0;j<nHeightToRead;j++)
3277 {
3278 for(i=0;i<nWidthToRead;i++)
3279 {
3280 int R = pTempBuffer[j*nWidthToRead+i];
3281 int G = pTempBuffer[nHeightToRead*nWidthToRead + j*nWidthToRead+i];
3282 int B = pTempBuffer[2*nHeightToRead*nWidthToRead + j*nWidthToRead+i];
3283 int Y = (int) (0.299 * R + 0.587 * G + 0.114 * B);
3284 int Cb = CLAMP_0_255((int) (-0.1687 * R - 0.3313 * G + 0.5 * B + 128));
3285 int Cr = CLAMP_0_255((int) (0.5 * R - 0.4187 * G - 0.0813 * B + 128));
3286 pYUV420Buffer[j*nWidthToRead+i] = (GByte) Y;
3287 pYUV420Buffer[nHeightToRead * nWidthToRead + ((j/2) * ((nWidthToRead)/2) + i/2) ] = (GByte) Cb;
3288 pYUV420Buffer[5 * nHeightToRead * nWidthToRead / 4 + ((j/2) * ((nWidthToRead)/2) + i/2) ] = (GByte) Cr;
3289 if( nBands == 4 )
3290 {
3291 pYUV420Buffer[3 * nHeightToRead * nWidthToRead / 2 + j*nWidthToRead+i ] =
3292 (GByte) pTempBuffer[3*nHeightToRead*nWidthToRead + j*nWidthToRead+i];
3293 }
3294 }
3295 }
3296
3297 int nBytesToWrite = 3 * nWidthToRead * nHeightToRead / 2;
3298 if (nBands == 4)
3299 nBytesToWrite += nBlockXSize * nBlockYSize;
3300
3301 if (!opj_write_tile(pCodec,
3302 iTile,
3303 pYUV420Buffer,
3304 nBytesToWrite,
3305 pStream))
3306 {
3307 CPLError(CE_Failure, CPLE_AppDefined,
3308 "opj_write_tile() failed");
3309 eErr = CE_Failure;
3310 }
3311 }
3312 else
3313 {
3314 if (!opj_write_tile(pCodec,
3315 iTile,
3316 pTempBuffer,
3317 nWidthToRead * nHeightToRead * nBands * nDataTypeSize,
3318 pStream))
3319 {
3320 CPLError(CE_Failure, CPLE_AppDefined,
3321 "opj_write_tile() failed");
3322 eErr = CE_Failure;
3323 }
3324 }
3325 }
3326
3327 if( !pfnProgress( (iTile + 1) * 1.0 / (nTilesX * nTilesY), NULL, pProgressData ) )
3328 eErr = CE_Failure;
3329
3330 iTile ++;
3331 }
3332 }
3333
3334 VSIFree(pTempBuffer);
3335 VSIFree(pYUV420Buffer);
3336
3337 if (eErr != CE_None)
3338 {
3339 opj_stream_destroy(pStream);
3340 opj_image_destroy(psImage);
3341 opj_destroy_codec(pCodec);
3342 VSIFCloseL(fp);
3343 delete poGMLJP2Box;
3344 return NULL;
3345 }
3346
3347 if (!opj_end_compress(pCodec,pStream))
3348 {
3349 CPLError(CE_Failure, CPLE_AppDefined,
3350 "opj_end_compress() failed");
3351 opj_stream_destroy(pStream);
3352 opj_image_destroy(psImage);
3353 opj_destroy_codec(pCodec);
3354 VSIFCloseL(fp);
3355 delete poGMLJP2Box;
3356 return NULL;
3357 }
3358 opj_stream_destroy(pStream);
3359 }
3360
3361 opj_image_destroy(psImage);
3362 opj_destroy_codec(pCodec);
3363
3364 /* -------------------------------------------------------------------- */
3365 /* Patch JP2C box length and add trailing JP2 boxes */
3366 /* -------------------------------------------------------------------- */
3367 if( eCodecFormat == OPJ_CODEC_JP2 &&
3368 !CSLFetchBoolean(papszOptions, "JP2C_LENGTH_ZERO", FALSE) /* debug option */ )
3369 {
3370 vsi_l_offset nEndJP2C = VSIFTellL(fp);
3371 GUIntBig nBoxSize = nEndJP2C -nStartJP2C;
3372 if( bUseXLBoxes )
3373 {
3374 VSIFSeekL(fp, nStartJP2C + 8, SEEK_SET);
3375 CPL_MSBPTR64(&nBoxSize);
3376 VSIFWriteL(&nBoxSize, 8, 1, fp);
3377 }
3378 else
3379 {
3380 GUInt32 nBoxSize32 = (GUInt32)nBoxSize;
3381 if( (vsi_l_offset)nBoxSize32 != nBoxSize )
3382 {
3383 /* Shouldn't happen hopefully */
3384 if( (bGeoreferencingCompatOfGeoJP2 || poGMLJP2Box) && bGeoBoxesAfter )
3385 {
3386 CPLError(CE_Warning, CPLE_AppDefined,
3387 "Cannot write GMLJP2/GeoJP2 boxes as codestream is unexpectedly > 4GB");
3388 bGeoreferencingCompatOfGeoJP2 = FALSE;
3389 delete poGMLJP2Box;
3390 poGMLJP2Box = NULL;
3391 }
3392 }
3393 else
3394 {
3395 VSIFSeekL(fp, nStartJP2C, SEEK_SET);
3396 CPL_MSBPTR32(&nBoxSize32);
3397 VSIFWriteL(&nBoxSize32, 4, 1, fp);
3398 }
3399 }
3400 VSIFSeekL(fp, 0, SEEK_END);
3401
3402 if( CSLFetchBoolean(papszOptions, "WRITE_METADATA", FALSE) )
3403 {
3404 WriteIPRBox(fp, poSrcDS, papszOptions);
3405 }
3406
3407 if( bGeoBoxesAfter )
3408 {
3409 if( poGMLJP2Box != NULL )
3410 {
3411 WriteBox(fp, poGMLJP2Box);
3412 }
3413
3414 if( CSLFetchBoolean(papszOptions, "WRITE_METADATA", FALSE) )
3415 {
3416 if( !CSLFetchBoolean(papszOptions, "MAIN_MD_DOMAIN_ONLY", FALSE) )
3417 WriteXMLBoxes(fp, poSrcDS, papszOptions);
3418 WriteGDALMetadataBox(fp, poSrcDS, papszOptions);
3419 }
3420
3421 if( bGeoJP2Option && bGeoreferencingCompatOfGeoJP2 )
3422 {
3423 GDALJP2Box* poBox = oJP2MD.CreateJP2GeoTIFF();
3424 WriteBox(fp, poBox);
3425 delete poBox;
3426 }
3427
3428 if( CSLFetchBoolean(papszOptions, "WRITE_METADATA", FALSE) &&
3429 !CSLFetchBoolean(papszOptions, "MAIN_MD_DOMAIN_ONLY", FALSE) )
3430 {
3431 WriteXMPBox(fp, poSrcDS, papszOptions);
3432 }
3433 }
3434 }
3435
3436 VSIFCloseL(fp);
3437 delete poGMLJP2Box;
3438
3439 /* -------------------------------------------------------------------- */
3440 /* Re-open dataset, and copy any auxiliary pam information. */
3441 /* -------------------------------------------------------------------- */
3442
3443 GDALOpenInfo oOpenInfo(pszFilename, GA_ReadOnly);
3444 JP2OpenJPEGDataset *poDS = (JP2OpenJPEGDataset*) JP2OpenJPEGDataset::Open(&oOpenInfo);
3445
3446 if( poDS )
3447 {
3448 poDS->CloneInfo( poSrcDS, GCIF_PAM_DEFAULT & (~GCIF_METADATA) );
3449
3450 /* Only write relevant metadata to PAM, and if needed */
3451 if( !CSLFetchBoolean(papszOptions, "WRITE_METADATA", FALSE) )
3452 {
3453 char** papszSrcMD = CSLDuplicate(poSrcDS->GetMetadata());
3454 papszSrcMD = CSLSetNameValue(papszSrcMD, GDALMD_AREA_OR_POINT, NULL);
3455 papszSrcMD = CSLSetNameValue(papszSrcMD, "Corder", NULL);
3456 for(char** papszSrcMDIter = papszSrcMD;
3457 papszSrcMDIter && *papszSrcMDIter; )
3458 {
3459 /* Remove entries like KEY= (without value) */
3460 if( (*papszSrcMDIter)[0] &&
3461 (*papszSrcMDIter)[strlen((*papszSrcMDIter))-1] == '=' )
3462 {
3463 CPLFree(*papszSrcMDIter);
3464 memmove(papszSrcMDIter, papszSrcMDIter + 1,
3465 sizeof(char*) * (CSLCount(papszSrcMDIter + 1) + 1));
3466 }
3467 else
3468 ++papszSrcMDIter;
3469 }
3470 char** papszMD = CSLDuplicate(poDS->GetMetadata());
3471 papszMD = CSLSetNameValue(papszMD, GDALMD_AREA_OR_POINT, NULL);
3472 if( papszSrcMD && papszSrcMD[0] != NULL &&
3473 CSLCount(papszSrcMD) != CSLCount(papszMD) )
3474 {
3475 poDS->SetMetadata(papszSrcMD);
3476 }
3477 CSLDestroy(papszSrcMD);
3478 CSLDestroy(papszMD);
3479 }
3480 }
3481
3482 return poDS;
3483 }
3484
3485 /************************************************************************/
3486 /* GDALRegister_JP2OpenJPEG() */
3487 /************************************************************************/
3488
GDALRegister_JP2OpenJPEG()3489 void GDALRegister_JP2OpenJPEG()
3490
3491 {
3492 GDALDriver *poDriver;
3493
3494 if (! GDAL_CHECK_VERSION("JP2OpenJPEG driver"))
3495 return;
3496
3497 if( GDALGetDriverByName( "JP2OpenJPEG" ) == NULL )
3498 {
3499 poDriver = new GDALDriver();
3500
3501 poDriver->SetDescription( "JP2OpenJPEG" );
3502 poDriver->SetMetadataItem( GDAL_DCAP_RASTER, "YES" );
3503 poDriver->SetMetadataItem( GDAL_DCAP_VECTOR, "YES" );
3504 poDriver->SetMetadataItem( GDAL_DMD_LONGNAME,
3505 "JPEG-2000 driver based on OpenJPEG library" );
3506 poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC,
3507 "frmt_jp2openjpeg.html" );
3508 poDriver->SetMetadataItem( GDAL_DMD_MIMETYPE, "image/jp2" );
3509 poDriver->SetMetadataItem( GDAL_DMD_EXTENSION, "jp2" );
3510 poDriver->SetMetadataItem( GDAL_DMD_EXTENSIONS, "jp2 j2k" );
3511 poDriver->SetMetadataItem( GDAL_DMD_CREATIONDATATYPES,
3512 "Byte Int16 UInt16 Int32 UInt32" );
3513
3514 poDriver->SetMetadataItem( GDAL_DMD_OPENOPTIONLIST,
3515 "<OpenOptionList>"
3516 " <Option name='1BIT_ALPHA_PROMOTION' type='boolean' description='Whether a 1-bit alpha channel should be promoted to 8-bit' default='YES'/>"
3517 " <Option name='OPEN_REMOTE_GML' type='boolean' description='Whether to load remote vector layers referenced by a link in a GMLJP2 v2 box' default='NO'/>"
3518 "</OpenOptionList>" );
3519
3520 poDriver->SetMetadataItem( GDAL_DMD_CREATIONOPTIONLIST,
3521 "<CreationOptionList>"
3522 " <Option name='CODEC' type='string-select' default='according to file extension. If unknown, default to J2K'>"
3523 " <Value>JP2</Value>"
3524 " <Value>J2K</Value>"
3525 " </Option>"
3526 " <Option name='GeoJP2' type='boolean' description='Whether to emit a GeoJP2 box' default='YES'/>"
3527 " <Option name='GMLJP2' type='boolean' description='Whether to emit a GMLJP2 v1 box' default='YES'/>"
3528 " <Option name='GMLJP2V2_DEF' type='string' description='Definition file to describe how a GMLJP2 v2 box should be generated. If set to YES, a minimal instance will be created'/>"
3529 " <Option name='QUALITY' type='string' description='Single quality value or comma separated list of increasing quality values for several layers, each in the 0-100 range' default='25'/>"
3530 " <Option name='REVERSIBLE' type='boolean' description='True if the compression is reversible' default='false'/>"
3531 " <Option name='RESOLUTIONS' type='int' description='Number of resolutions.' min='1' max='30'/>"
3532 " <Option name='BLOCKXSIZE' type='int' description='Tile Width' default='1024'/>"
3533 " <Option name='BLOCKYSIZE' type='int' description='Tile Height' default='1024'/>"
3534 " <Option name='PROGRESSION' type='string-select' default='LRCP'>"
3535 " <Value>LRCP</Value>"
3536 " <Value>RLCP</Value>"
3537 " <Value>RPCL</Value>"
3538 " <Value>PCRL</Value>"
3539 " <Value>CPRL</Value>"
3540 " </Option>"
3541 " <Option name='SOP' type='boolean' description='True to insert SOP markers' default='false'/>"
3542 " <Option name='EPH' type='boolean' description='True to insert EPH markers' default='false'/>"
3543 " <Option name='YCBCR420' type='boolean' description='if RGB must be resampled to YCbCr 4:2:0' default='false'/>"
3544 " <Option name='YCC' type='boolean' description='if RGB must be transformed to YCC color space (lossless MCT transform)' default='YES'/>"
3545 " <Option name='NBITS' type='int' description='Bits (precision) for sub-byte files (1-7), sub-uint16 (9-15), sub-uint32 (17-31)'/>"
3546 " <Option name='1BIT_ALPHA' type='boolean' description='Whether to encode the alpha channel as a 1-bit channel' default='NO'/>"
3547 " <Option name='ALPHA' type='boolean' description='Whether to force encoding last channel as alpha channel' default='NO'/>"
3548 " <Option name='PROFILE' type='string-select' description='Which codestream profile to use' default='AUTO'>"
3549 " <Value>AUTO</Value>"
3550 " <Value>UNRESTRICTED</Value>"
3551 " <Value>PROFILE_1</Value>"
3552 " </Option>"
3553 " <Option name='INSPIRE_TG' type='boolean' description='Whether to use features that comply with Inspire Orthoimagery Technical Guidelines' default='NO'/>"
3554 " <Option name='JPX' type='boolean' description='Whether to advertize JPX features when a GMLJP2 box is written' default='YES'/>"
3555 " <Option name='GEOBOXES_AFTER_JP2C' type='boolean' description='Whether to place GeoJP2/GMLJP2 boxes after the code-stream' default='NO'/>"
3556 " <Option name='PRECINCTS' type='string' description='Precincts size as a string of the form {w,h},{w,h},... with power-of-two values'/>"
3557 " <Option name='TILEPARTS' type='string-select' description='Whether to generate tile-parts and according to which criterion' default='DISABLED'>"
3558 " <Value>DISABLED</Value>"
3559 " <Value>RESOLUTIONS</Value>"
3560 " <Value>LAYERS</Value>"
3561 " <Value>COMPONENTS</Value>"
3562 " </Option>"
3563 " <Option name='CODEBLOCK_WIDTH' type='int' description='Codeblock width' default='64' min='4' max='1024'/>"
3564 " <Option name='CODEBLOCK_HEIGHT' type='int' description='Codeblock height' default='64' min='4' max='1024'/>"
3565 " <Option name='CT_COMPONENTS' type='int' min='3' max='4' description='If there is one color table, number of color table components to write. Autodetected if not specified.'/>"
3566 " <Option name='WRITE_METADATA' type='boolean' description='Whether metadata should be written, in a dedicated JP2 XML box' default='NO'/>"
3567 " <Option name='MAIN_MD_DOMAIN_ONLY' type='boolean' description='(Only if WRITE_METADATA=YES) Whether only metadata from the main domain should be written' default='NO'/>"
3568 " <Option name='USE_SRC_CODESTREAM' type='boolean' description='When source dataset is JPEG2000, whether to reuse the codestream of the source dataset unmodified' default='NO'/>"
3569 "</CreationOptionList>" );
3570
3571 poDriver->SetMetadataItem( GDAL_DCAP_VIRTUALIO, "YES" );
3572
3573 poDriver->pfnIdentify = JP2OpenJPEGDataset::Identify;
3574 poDriver->pfnOpen = JP2OpenJPEGDataset::Open;
3575 poDriver->pfnCreateCopy = JP2OpenJPEGDataset::CreateCopy;
3576
3577 GetGDALDriverManager()->RegisterDriver( poDriver );
3578 }
3579 }
3580