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(&parameters);
691 
692     if (! opj_setup_decoder(pCodec,&parameters))
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(&parameters);
1412 
1413     if (! opj_setup_decoder(pCodec,&parameters))
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(&parameters);
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,&parameters,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