LCOV - code coverage report
Current view: directory - frmts/openjpeg - openjpegdataset.cpp (source / functions) Found Hit Coverage
Test: gdal_filtered.info Lines: 869 692 79.6 %
Date: 2012-12-26 Functions: 42 36 85.7 %

       1                 : /******************************************************************************
       2                 :  * $Id: openjpegdataset.cpp 25264 2012-11-29 06:57:39Z 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 mines dash paris dot org>
       7                 :  *
       8                 :  ******************************************************************************
       9                 :  * Copyright (c) 2010, Even Rouault, <even dot rouault at mines dash paris dot org>
      10                 :  *
      11                 :  * Permission is hereby granted, free of charge, to any person obtaining a
      12                 :  * copy of this software and associated documentation files (the "Software"),
      13                 :  * to deal in the Software without restriction, including without limitation
      14                 :  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
      15                 :  * and/or sell copies of the Software, and to permit persons to whom the
      16                 :  * Software is furnished to do so, subject to the following conditions:
      17                 :  *
      18                 :  * The above copyright notice and this permission notice shall be included
      19                 :  * in all copies or substantial portions of the Software.
      20                 :  *
      21                 :  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
      22                 :  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
      23                 :  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
      24                 :  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
      25                 :  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
      26                 :  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
      27                 :  * DEALINGS IN THE SOFTWARE.
      28                 :  ****************************************************************************/
      29                 : 
      30                 : /* This file is to be used with openjpeg 2.0 */
      31                 : 
      32                 : #include <stdio.h> /* openjpeg.h needs FILE* */
      33                 : #include <openjpeg-2.0/openjpeg.h>
      34                 : #include <vector>
      35                 : 
      36                 : #include "gdal_pam.h"
      37                 : #include "cpl_string.h"
      38                 : #include "gdaljp2metadata.h"
      39                 : #include "cpl_multiproc.h"
      40                 : #include "cpl_atomic_ops.h"
      41                 : 
      42                 : CPL_CVSID("$Id: openjpegdataset.cpp 25264 2012-11-29 06:57:39Z rouault $");
      43                 : 
      44                 : /************************************************************************/
      45                 : /*                  JP2OpenJPEGDataset_ErrorCallback()                  */
      46                 : /************************************************************************/
      47                 : 
      48               6 : static void JP2OpenJPEGDataset_ErrorCallback(const char *pszMsg, void *unused)
      49                 : {
      50               6 :     CPLError(CE_Failure, CPLE_AppDefined, "%s", pszMsg);
      51               6 : }
      52                 : 
      53                 : /************************************************************************/
      54                 : /*               JP2OpenJPEGDataset_WarningCallback()                   */
      55                 : /************************************************************************/
      56                 : 
      57              14 : static void JP2OpenJPEGDataset_WarningCallback(const char *pszMsg, void *unused)
      58                 : {
      59              14 :     if( strcmp(pszMsg, "JP2 box which are after the codestream will not be read by this function.\n") != 0 )
      60               0 :         CPLError(CE_Warning, CPLE_AppDefined, "%s", pszMsg);
      61              14 : }
      62                 : 
      63                 : /************************************************************************/
      64                 : /*                 JP2OpenJPEGDataset_InfoCallback()                    */
      65                 : /************************************************************************/
      66                 : 
      67             437 : static void JP2OpenJPEGDataset_InfoCallback(const char *pszMsg, void *unused)
      68                 : {
      69             437 :     char* pszMsgTmp = CPLStrdup(pszMsg);
      70             438 :     int nLen = (int)strlen(pszMsgTmp);
      71            1385 :     while( nLen > 0 && pszMsgTmp[nLen-1] == '\n' )
      72                 :     {
      73             509 :         pszMsgTmp[nLen-1] = '\0';
      74             509 :         nLen --;
      75                 :     }
      76             438 :     CPLDebug("OPENJPEG", "info: %s", pszMsgTmp);
      77             438 :     CPLFree(pszMsgTmp);
      78             438 : }
      79                 : 
      80                 : /************************************************************************/
      81                 : /*                      JP2OpenJPEGDataset_Read()                       */
      82                 : /************************************************************************/
      83                 : 
      84             883 : static OPJ_SIZE_T JP2OpenJPEGDataset_Read(void* pBuffer, OPJ_SIZE_T nBytes,
      85                 :                                        void *pUserData)
      86                 : {
      87             883 :     int nRet = VSIFReadL(pBuffer, 1, nBytes, (VSILFILE*)pUserData);
      88                 : #ifdef DEBUG_IO
      89                 :     CPLDebug("OPENJPEG", "JP2OpenJPEGDataset_Read(%d) = %d", (int)nBytes, nRet);
      90                 : #endif
      91             885 :     if (nRet == 0)
      92              14 :         nRet = -1;
      93             885 :     return nRet;
      94                 : }
      95                 : 
      96                 : /************************************************************************/
      97                 : /*                      JP2OpenJPEGDataset_Write()                      */
      98                 : /************************************************************************/
      99                 : 
     100              10 : static OPJ_SIZE_T JP2OpenJPEGDataset_Write(void* pBuffer, OPJ_SIZE_T nBytes,
     101                 :                                        void *pUserData)
     102                 : {
     103              10 :     int nRet = VSIFWriteL(pBuffer, 1, nBytes, (VSILFILE*)pUserData);
     104                 : #ifdef DEBUG_IO
     105                 :     CPLDebug("OPENJPEG", "JP2OpenJPEGDataset_Write(%d) = %d", (int)nBytes, nRet);
     106                 : #endif
     107              10 :     return nRet;
     108                 : }
     109                 : 
     110                 : /************************************************************************/
     111                 : /*                       JP2OpenJPEGDataset_Seek()                      */
     112                 : /************************************************************************/
     113                 : 
     114              77 : static OPJ_BOOL JP2OpenJPEGDataset_Seek(OPJ_OFF_T nBytes, void * pUserData)
     115                 : {
     116                 : #ifdef DEBUG_IO
     117                 :     CPLDebug("OPENJPEG", "JP2OpenJPEGDataset_Seek(%d)", (int)nBytes);
     118                 : #endif
     119              77 :     return VSIFSeekL((VSILFILE*)pUserData, nBytes, SEEK_SET) == 0;
     120                 : }
     121                 : 
     122                 : /************************************************************************/
     123                 : /*                     JP2OpenJPEGDataset_Skip()                        */
     124                 : /************************************************************************/
     125                 : 
     126             633 : static OPJ_OFF_T JP2OpenJPEGDataset_Skip(OPJ_OFF_T nBytes, void * pUserData)
     127                 : {
     128             633 :     vsi_l_offset nOffset = VSIFTellL((VSILFILE*)pUserData);
     129             630 :     nOffset += nBytes;
     130                 : #ifdef DEBUG_IO
     131                 :     CPLDebug("OPENJPEG", "JP2OpenJPEGDataset_Skip(%d -> " CPL_FRMT_GUIB ")",
     132                 :              (int)nBytes, (GUIntBig)nOffset);
     133                 : #endif
     134             630 :     VSIFSeekL((VSILFILE*)pUserData, nOffset, SEEK_SET);
     135             633 :     return nBytes;
     136                 : }
     137                 : 
     138                 : /************************************************************************/
     139                 : /* ==================================================================== */
     140                 : /*                           JP2OpenJPEGDataset                         */
     141                 : /* ==================================================================== */
     142                 : /************************************************************************/
     143                 : 
     144                 : class JP2OpenJPEGRasterBand;
     145                 : 
     146                 : class JP2OpenJPEGDataset : public GDALPamDataset
     147                 : {
     148                 :     friend class JP2OpenJPEGRasterBand;
     149                 : 
     150                 :     VSILFILE   *fp; /* Large FILE API */
     151                 : 
     152                 :     char        *pszProjection;
     153                 :     int         bGeoTransformValid;
     154                 :     double      adfGeoTransform[6];
     155                 :     int         nGCPCount;
     156                 :     GDAL_GCP    *pasGCPList;
     157                 : 
     158                 :     OPJ_CODEC_FORMAT eCodecFormat;
     159                 :     OPJ_COLOR_SPACE eColorSpace;
     160                 : 
     161                 :     int         bIs420;
     162                 : 
     163                 :     int         iLevel;
     164                 :     int         nOverviewCount;
     165                 :     JP2OpenJPEGDataset** papoOverviewDS;
     166                 :     int         bUseSetDecodeArea;
     167                 : 
     168                 :     int         nThreads;
     169                 :     int         GetNumThreads();
     170                 :     int         bEnoughMemoryToLoadOtherBands;
     171                 : 
     172                 :   protected:
     173                 :     virtual int         CloseDependentDatasets();
     174                 : 
     175                 :   public:
     176                 :                 JP2OpenJPEGDataset();
     177                 :                 ~JP2OpenJPEGDataset();
     178                 :     
     179                 :     static int Identify( GDALOpenInfo * poOpenInfo );
     180                 :     static GDALDataset  *Open( GDALOpenInfo * );
     181                 :     static GDALDataset  *CreateCopy( const char * pszFilename,
     182                 :                                            GDALDataset *poSrcDS, 
     183                 :                                            int bStrict, char ** papszOptions, 
     184                 :                                            GDALProgressFunc pfnProgress,
     185                 :                                            void * pProgressData );
     186                 :     CPLErr              GetGeoTransform( double* );
     187                 :     virtual const char  *GetProjectionRef(void);
     188                 :     virtual int         GetGCPCount();
     189                 :     virtual const char  *GetGCPProjection();
     190                 :     virtual const GDAL_GCP *GetGCPs();
     191                 : 
     192                 :     virtual CPLErr  IRasterIO( GDALRWFlag eRWFlag,
     193                 :                                int nXOff, int nYOff, int nXSize, int nYSize,
     194                 :                                void * pData, int nBufXSize, int nBufYSize,
     195                 :                                GDALDataType eBufType, 
     196                 :                                int nBandCount, int *panBandMap,
     197                 :                                int nPixelSpace, int nLineSpace, int nBandSpace);
     198                 : 
     199                 :     static void         WriteBox(VSILFILE* fp, GDALJP2Box* poBox);
     200                 : 
     201                 :     CPLErr      ReadBlock( int nBand, VSILFILE* fp,
     202                 :                            int nBlockXOff, int nBlockYOff, void * pImage,
     203                 :                            int nBandCount, int *panBandMap );
     204                 : 
     205                 :     int         PreloadBlocks( JP2OpenJPEGRasterBand* poBand,
     206                 :                                int nXOff, int nYOff, int nXSize, int nYSize,
     207                 :                                int nBandCount, int *panBandMap );
     208                 : };
     209                 : 
     210                 : /************************************************************************/
     211                 : /* ==================================================================== */
     212                 : /*                         JP2OpenJPEGRasterBand                        */
     213                 : /* ==================================================================== */
     214                 : /************************************************************************/
     215                 : 
     216                 : class JP2OpenJPEGRasterBand : public GDALPamRasterBand
     217                 : {
     218                 :     friend class JP2OpenJPEGDataset;
     219                 : 
     220                 :   public:
     221                 : 
     222                 :                 JP2OpenJPEGRasterBand( JP2OpenJPEGDataset * poDS, int nBand,
     223                 :                                     GDALDataType eDataType, int nBits,
     224                 :                                     int nBlockXSize, int nBlockYSize);
     225                 :                 ~JP2OpenJPEGRasterBand();
     226                 : 
     227                 :     virtual CPLErr          IReadBlock( int, int, void * );
     228                 :     virtual CPLErr          IRasterIO( GDALRWFlag eRWFlag,
     229                 :                                   int nXOff, int nYOff, int nXSize, int nYSize,
     230                 :                                   void * pData, int nBufXSize, int nBufYSize,
     231                 :                                   GDALDataType eBufType,
     232                 :                                   int nPixelSpace, int nLineSpace );
     233                 : 
     234                 :     virtual GDALColorInterp GetColorInterpretation();
     235                 : 
     236                 :     virtual int             GetOverviewCount();
     237                 :     virtual GDALRasterBand* GetOverview(int iOvrLevel);
     238                 :     
     239               8 :     virtual int HasArbitraryOverviews() { return TRUE; }
     240                 : };
     241                 : 
     242                 : 
     243                 : /************************************************************************/
     244                 : /*                        JP2OpenJPEGRasterBand()                       */
     245                 : /************************************************************************/
     246                 : 
     247             122 : JP2OpenJPEGRasterBand::JP2OpenJPEGRasterBand( JP2OpenJPEGDataset *poDS, int nBand,
     248                 :                                         GDALDataType eDataType, int nBits,
     249             122 :                                         int nBlockXSize, int nBlockYSize)
     250                 : 
     251                 : {
     252             122 :     this->poDS = poDS;
     253             122 :     this->nBand = nBand;
     254             122 :     this->eDataType = eDataType;
     255             122 :     this->nBlockXSize = nBlockXSize;
     256             122 :     this->nBlockYSize = nBlockYSize;
     257                 : 
     258             122 :     if( (nBits % 8) != 0 )
     259                 :         SetMetadataItem("NBITS",
     260                 :                         CPLString().Printf("%d",nBits),
     261              24 :                         "IMAGE_STRUCTURE" );
     262             122 : }
     263                 : 
     264                 : /************************************************************************/
     265                 : /*                      ~JP2OpenJPEGRasterBand()                        */
     266                 : /************************************************************************/
     267                 : 
     268             122 : JP2OpenJPEGRasterBand::~JP2OpenJPEGRasterBand()
     269                 : {
     270             122 : }
     271                 : 
     272                 : /************************************************************************/
     273                 : /*                            CLAMP_0_255()                             */
     274                 : /************************************************************************/
     275                 : 
     276          921600 : static CPL_INLINE GByte CLAMP_0_255(int val)
     277                 : {
     278          921600 :     if (val < 0)
     279            1383 :         return 0;
     280          920217 :     else if (val > 255)
     281            1778 :         return 255;
     282                 :     else
     283          918439 :         return (GByte)val;
     284                 : }
     285                 : 
     286                 : /************************************************************************/
     287                 : /*                             IReadBlock()                             */
     288                 : /************************************************************************/
     289                 : 
     290              21 : CPLErr JP2OpenJPEGRasterBand::IReadBlock( int nBlockXOff, int nBlockYOff,
     291                 :                                           void * pImage )
     292                 : {
     293              21 :     JP2OpenJPEGDataset *poGDS = (JP2OpenJPEGDataset *) poDS;
     294              21 :     if ( poGDS->bEnoughMemoryToLoadOtherBands )
     295                 :         return poGDS->ReadBlock(nBand, poGDS->fp, nBlockXOff, nBlockYOff, pImage,
     296              21 :                                 poGDS->nBands, NULL);
     297                 :     else
     298                 :         return poGDS->ReadBlock(nBand, poGDS->fp, nBlockXOff, nBlockYOff, pImage,
     299               0 :                                 1, &nBand);
     300                 : }
     301                 : 
     302                 : /************************************************************************/
     303                 : /*                             IRasterIO()                              */
     304                 : /************************************************************************/
     305                 : 
     306           10694 : CPLErr JP2OpenJPEGRasterBand::IRasterIO( GDALRWFlag eRWFlag,
     307                 :                                          int nXOff, int nYOff, int nXSize, int nYSize,
     308                 :                                          void * pData, int nBufXSize, int nBufYSize,
     309                 :                                          GDALDataType eBufType,
     310                 :                                          int nPixelSpace, int nLineSpace )
     311                 : {
     312           10694 :     JP2OpenJPEGDataset *poGDS = (JP2OpenJPEGDataset *) poDS;
     313                 : 
     314           10694 :     if( eRWFlag != GF_Read )
     315               0 :         return CE_Failure;
     316                 : 
     317                 : /* ==================================================================== */
     318                 : /*      Do we have overviews that would be appropriate to satisfy       */
     319                 : /*      this request?                                                   */
     320                 : /* ==================================================================== */
     321           10694 :     if( (nBufXSize < nXSize || nBufYSize < nYSize)
     322               0 :         && GetOverviewCount() > 0 && eRWFlag == GF_Read )
     323                 :     {
     324                 :         int         nOverview;
     325                 : 
     326                 :         nOverview =
     327                 :             GDALBandGetBestOverviewLevel(this, nXOff, nYOff, nXSize, nYSize,
     328               0 :                                         nBufXSize, nBufYSize);
     329               0 :         if (nOverview >= 0)
     330                 :         {
     331               0 :             GDALRasterBand* poOverviewBand = GetOverview(nOverview);
     332               0 :             if (poOverviewBand == NULL)
     333               0 :                 return CE_Failure;
     334                 : 
     335                 :             return poOverviewBand->RasterIO( eRWFlag, nXOff, nYOff, nXSize, nYSize,
     336                 :                                             pData, nBufXSize, nBufYSize, eBufType,
     337               0 :                                             nPixelSpace, nLineSpace );
     338                 :         }
     339                 :     }
     340                 : 
     341           10694 :     poGDS->bEnoughMemoryToLoadOtherBands = poGDS->PreloadBlocks(this, nXOff, nYOff, nXSize, nYSize, 0, NULL);
     342                 : 
     343                 :     CPLErr eErr = GDALPamRasterBand::IRasterIO( eRWFlag, nXOff, nYOff, nXSize, nYSize,
     344                 :                                          pData, nBufXSize, nBufYSize, eBufType,
     345           10694 :                                          nPixelSpace, nLineSpace );
     346                 : 
     347           10694 :     poGDS->bEnoughMemoryToLoadOtherBands = TRUE;
     348           10694 :     return eErr;
     349                 : }
     350                 : 
     351                 : /************************************************************************/
     352                 : /*                            GetNumThreads()                           */
     353                 : /************************************************************************/
     354                 : 
     355           10695 : int JP2OpenJPEGDataset::GetNumThreads()
     356                 : {
     357           10695 :     if( nThreads >= 1 )
     358           10674 :         return nThreads;
     359                 : 
     360              21 :     const char* pszThreads = CPLGetConfigOption("GDAL_NUM_THREADS", "ALL_CPUS");
     361              21 :     if (EQUAL(pszThreads, "ALL_CPUS"))
     362              21 :         nThreads = CPLGetNumCPUs();
     363                 :     else
     364               0 :         nThreads = atoi(pszThreads);
     365              21 :     if (nThreads > 128)
     366               0 :         nThreads = 128;
     367              21 :     if (nThreads <= 0)
     368               0 :         nThreads = 1;
     369              21 :     return nThreads;
     370                 : }
     371                 : 
     372                 : /************************************************************************/
     373                 : /*                   JP2OpenJPEGReadBlockInThread()                     */
     374                 : /************************************************************************/
     375                 : 
     376                 : class JobStruct
     377              22 : {
     378                 : public:
     379                 : 
     380                 :     JP2OpenJPEGDataset* poGDS;
     381                 :     int                 nBand;
     382                 :     std::vector< std::pair<int, int> > oPairs;
     383                 :     volatile int        nCurPair;
     384                 :     int                 nBandCount;
     385                 :     int                *panBandMap;
     386                 : };
     387                 : 
     388              41 : static void JP2OpenJPEGReadBlockInThread(void* userdata)
     389                 : {
     390                 :     int nPair;
     391              41 :     JobStruct* poJob = (JobStruct*) userdata;
     392              41 :     JP2OpenJPEGDataset* poGDS = poJob->poGDS;
     393              41 :     int nBand = poJob->nBand;
     394              41 :     int nPairs = (int)poJob->oPairs.size();
     395              41 :     int nBandCount = poJob->nBandCount;
     396              41 :     int* panBandMap = poJob->panBandMap;
     397              41 :     VSILFILE* fp = VSIFOpenL(poGDS->GetDescription(), "rb");
     398              41 :     if( fp == NULL )
     399                 :     {
     400               0 :         CPLDebug("OPENJPEG", "Cannot open %s", poGDS->GetDescription());
     401               0 :         return;
     402                 :     }
     403                 : 
     404             132 :     while( (nPair = CPLAtomicInc(&(poJob->nCurPair))) < nPairs )
     405                 :     {
     406              50 :         int nBlockXOff = poJob->oPairs[nPair].first;
     407              50 :         int nBlockYOff = poJob->oPairs[nPair].second;
     408                 :         GDALRasterBlock* poBlock = poGDS->GetRasterBand(nBand)->
     409              50 :                 GetLockedBlockRef(nBlockXOff,nBlockYOff, TRUE);
     410              50 :         if (poBlock == NULL)
     411               0 :             break;
     412                 : 
     413              50 :         void* pDstBuffer = poBlock->GetDataRef();
     414              50 :         if (!pDstBuffer)
     415                 :         {
     416               0 :             poBlock->DropLock();
     417               0 :             break;
     418                 :         }
     419                 : 
     420                 :         poGDS->ReadBlock(nBand, fp, nBlockXOff, nBlockYOff, pDstBuffer,
     421              50 :                          nBandCount, panBandMap);
     422                 : 
     423              50 :         poBlock->DropLock();
     424                 :     }
     425                 : 
     426              41 :     VSIFCloseL(fp);
     427                 : }
     428                 : 
     429                 : /************************************************************************/
     430                 : /*                           PreloadBlocks()                            */
     431                 : /************************************************************************/
     432                 : 
     433           10695 : int JP2OpenJPEGDataset::PreloadBlocks(JP2OpenJPEGRasterBand* poBand,
     434                 :                                       int nXOff, int nYOff, int nXSize, int nYSize,
     435                 :                                       int nBandCount, int *panBandMap)
     436                 : {
     437           10695 :     int bRet = TRUE;
     438           10695 :     int nXStart = nXOff / poBand->nBlockXSize;
     439           10695 :     int nXEnd = (nXOff + nXSize - 1) / poBand->nBlockXSize;
     440           10695 :     int nYStart = nYOff / poBand->nBlockYSize;
     441           10695 :     int nYEnd = (nYOff + nYSize - 1) / poBand->nBlockYSize;
     442                 :     GIntBig nReqMem = (GIntBig)(nXEnd - nXStart + 1) * (nYEnd - nYStart + 1) *
     443           10695 :                       poBand->nBlockXSize * poBand->nBlockYSize * (GDALGetDataTypeSize(poBand->eDataType) / 8);
     444                 : 
     445           10695 :     int nMaxThreads = GetNumThreads();
     446           10695 :     if( !bUseSetDecodeArea && nMaxThreads > 1 )
     447                 :     {
     448           10695 :         if( nReqMem > GDALGetCacheMax64() / (nBandCount == 0 ? 1 : nBandCount) )
     449               0 :             return FALSE;
     450                 : 
     451           10695 :         int nBlocksToLoad = 0;
     452           10695 :         std::vector< std::pair<int,int> > oPairs;
     453           36943 :         for(int nBlockXOff = nXStart; nBlockXOff <= nXEnd; ++nBlockXOff)
     454                 :         {
     455           52500 :             for(int nBlockYOff = nYStart; nBlockYOff <= nYEnd; ++nBlockYOff)
     456                 :             {
     457           26252 :                 GDALRasterBlock* poBlock = poBand->TryGetLockedBlockRef(nBlockXOff,nBlockYOff);
     458           26252 :                 if (poBlock != NULL)
     459                 :                 {
     460           26184 :                     poBlock->DropLock();
     461           26184 :                     continue;
     462                 :                 }
     463              68 :                 oPairs.push_back( std::pair<int,int>(nBlockXOff, nBlockYOff) );
     464              68 :                 nBlocksToLoad ++;
     465                 :             }
     466                 :         }
     467                 : 
     468           10695 :         if( nBlocksToLoad > 1 )
     469                 :         {
     470              11 :             int nThreads = MIN(nBlocksToLoad, nMaxThreads);
     471              11 :             void** pahThreads = (void**) CPLMalloc( sizeof(void*) * nThreads );
     472                 :             int i;
     473                 : 
     474              11 :             CPLDebug("OPENJPEG", "%d blocks to load", nBlocksToLoad);
     475                 : 
     476              11 :             JobStruct oJob;
     477              11 :             oJob.poGDS = this;
     478              11 :             oJob.nBand = poBand->GetBand();
     479              11 :             oJob.oPairs = oPairs;
     480              11 :             oJob.nCurPair = -1;
     481              11 :             if( nBandCount > 0 )
     482                 :             {
     483               0 :                 oJob.nBandCount = nBandCount;
     484               0 :                 oJob.panBandMap = panBandMap;
     485                 :             }
     486                 :             else
     487                 :             {
     488              11 :                 if( nReqMem <= GDALGetCacheMax64() / nBands )
     489                 :                 {
     490              11 :                     oJob.nBandCount = nBands;
     491              11 :                     oJob.panBandMap = NULL;
     492                 :                 }
     493                 :                 else
     494                 :                 {
     495               0 :                     bRet = FALSE;
     496               0 :                     oJob.nBandCount = 1;
     497               0 :                     oJob.panBandMap = &oJob.nBand;
     498                 :                 }
     499                 :             }
     500                 : 
     501              52 :             for(i=0;i<nThreads;i++)
     502              41 :                 pahThreads[i] = CPLCreateJoinableThread(JP2OpenJPEGReadBlockInThread, &oJob);
     503              52 :             for(i=0;i<nThreads;i++)
     504              41 :                 CPLJoinThread( pahThreads[i] );
     505              11 :             CPLFree(pahThreads);
     506           10695 :         }
     507                 :     }
     508                 : 
     509           10695 :     return bRet;
     510                 : }
     511                 : 
     512                 : /************************************************************************/
     513                 : /*                             IRasterIO()                              */
     514                 : /************************************************************************/
     515                 : 
     516               1 : CPLErr  JP2OpenJPEGDataset::IRasterIO( GDALRWFlag eRWFlag,
     517                 :                                int nXOff, int nYOff, int nXSize, int nYSize,
     518                 :                                void * pData, int nBufXSize, int nBufYSize,
     519                 :                                GDALDataType eBufType, 
     520                 :                                int nBandCount, int *panBandMap,
     521                 :                                int nPixelSpace, int nLineSpace, int nBandSpace)
     522                 : {
     523               1 :     if( eRWFlag != GF_Read )
     524               0 :         return CE_Failure;
     525                 : 
     526               1 :     if( nBandCount < 1 )
     527               0 :         return CE_Failure;
     528                 : 
     529               1 :     JP2OpenJPEGRasterBand* poBand = (JP2OpenJPEGRasterBand*) GetRasterBand(panBandMap[0]);
     530                 : 
     531                 : /* ==================================================================== */
     532                 : /*      Do we have overviews that would be appropriate to satisfy       */
     533                 : /*      this request?                                                   */
     534                 : /* ==================================================================== */
     535                 : 
     536               1 :     if( (nBufXSize < nXSize || nBufYSize < nYSize)
     537               0 :         && poBand->GetOverviewCount() > 0 && eRWFlag == GF_Read )
     538                 :     {
     539                 :         int         nOverview;
     540                 : 
     541                 :         nOverview =
     542                 :             GDALBandGetBestOverviewLevel(poBand, nXOff, nYOff, nXSize, nYSize,
     543               0 :                                         nBufXSize, nBufYSize);
     544               0 :         if (nOverview >= 0)
     545                 :         {
     546               0 :             return papoOverviewDS[nOverview]->RasterIO( eRWFlag, nXOff, nYOff, nXSize, nYSize,
     547                 :                                                         pData, nBufXSize, nBufYSize, eBufType,
     548                 :                                                         nBandCount, panBandMap,
     549               0 :                                                         nPixelSpace, nLineSpace, nBandSpace );
     550                 :         }
     551                 :     }
     552                 : 
     553               1 :     bEnoughMemoryToLoadOtherBands = PreloadBlocks(poBand, nXOff, nYOff, nXSize, nYSize, nBandCount, panBandMap);
     554                 : 
     555                 :     CPLErr eErr = GDALPamDataset::IRasterIO(   eRWFlag,
     556                 :                                         nXOff, nYOff, nXSize, nYSize,
     557                 :                                         pData, nBufXSize, nBufYSize,
     558                 :                                         eBufType, 
     559                 :                                         nBandCount, panBandMap,
     560               1 :                                         nPixelSpace, nLineSpace, nBandSpace );
     561                 : 
     562               1 :     bEnoughMemoryToLoadOtherBands = TRUE;
     563               1 :     return eErr;
     564                 : }
     565                 : 
     566                 : /************************************************************************/
     567                 : /*                             ReadBlock()                              */
     568                 : /************************************************************************/
     569                 : 
     570              71 : CPLErr JP2OpenJPEGDataset::ReadBlock( int nBand, VSILFILE* fp,
     571                 :                                       int nBlockXOff, int nBlockYOff, void * pImage,
     572                 :                                       int nBandCount, int* panBandMap )
     573                 : {
     574              71 :     CPLErr          eErr = CE_None;
     575                 :     opj_codec_t*    pCodec;
     576                 :     opj_stream_t *  pStream;
     577                 :     opj_image_t *   psImage;
     578                 :     
     579              71 :     JP2OpenJPEGRasterBand* poBand = (JP2OpenJPEGRasterBand*) GetRasterBand(nBand);
     580              71 :     int nBlockXSize = poBand->nBlockXSize;
     581              71 :     int nBlockYSize = poBand->nBlockYSize;
     582              71 :     GDALDataType eDataType = poBand->eDataType;
     583                 : 
     584              71 :     int nDataTypeSize = (GDALGetDataTypeSize(eDataType) / 8);
     585                 : 
     586              71 :     int nTileNumber = nBlockXOff + nBlockYOff * poBand->nBlocksPerRow;
     587              71 :     int nWidthToRead = MIN(nBlockXSize, nRasterXSize - nBlockXOff * nBlockXSize);
     588              71 :     int nHeightToRead = MIN(nBlockYSize, nRasterYSize - nBlockYOff * nBlockYSize);
     589                 : 
     590              71 :     pCodec = opj_create_decompress(eCodecFormat);
     591                 : 
     592              71 :     opj_set_info_handler(pCodec, JP2OpenJPEGDataset_InfoCallback,NULL);
     593              71 :     opj_set_warning_handler(pCodec, JP2OpenJPEGDataset_WarningCallback, NULL);
     594              71 :     opj_set_error_handler(pCodec, JP2OpenJPEGDataset_ErrorCallback,NULL);
     595                 : 
     596                 :     opj_dparameters_t parameters;
     597              71 :     opj_set_default_decoder_parameters(&parameters);
     598                 : 
     599              71 :     if (! opj_setup_decoder(pCodec,&parameters))
     600                 :     {
     601               0 :         CPLError(CE_Failure, CPLE_AppDefined, "opj_setup_decoder() failed");
     602               0 :         return CE_Failure;
     603                 :     }
     604                 : 
     605              71 :     pStream = opj_stream_create(1024, TRUE); // Default 1MB is way too big for some datasets
     606                 : 
     607              71 :     VSIFSeekL(fp, 0, SEEK_END);
     608              71 :     opj_stream_set_user_data_length(pStream, VSIFTellL(fp));
     609                 :     /* Reseek to file beginning */
     610              71 :     VSIFSeekL(fp, 0, SEEK_SET);
     611                 : 
     612              71 :     opj_stream_set_read_function(pStream, JP2OpenJPEGDataset_Read);
     613              71 :     opj_stream_set_seek_function(pStream, JP2OpenJPEGDataset_Seek);
     614              71 :     opj_stream_set_skip_function(pStream, JP2OpenJPEGDataset_Skip);
     615              71 :     opj_stream_set_user_data(pStream, fp);
     616                 : 
     617              71 :     if(!opj_read_header(pStream,pCodec,&psImage))
     618                 :     {
     619               0 :         CPLError(CE_Failure, CPLE_AppDefined, "opj_read_header() failed");
     620               0 :         return CE_Failure;
     621                 :     }
     622                 : 
     623              71 :     if (!opj_set_decoded_resolution_factor( pCodec, iLevel ))
     624                 :     {
     625               0 :         CPLError(CE_Failure, CPLE_AppDefined, "opj_set_decoded_resolution_factor() failed");
     626               0 :         eErr = CE_Failure;
     627               0 :         goto end;
     628                 :     }
     629                 : 
     630              71 :     if (bUseSetDecodeArea)
     631                 :     {
     632               0 :         if (!opj_set_decode_area(pCodec,psImage,
     633                 :                                 nBlockXOff*nBlockXSize,nBlockYOff*nBlockYSize,
     634                 :                                 (nBlockXOff+1)*nBlockXSize,(nBlockYOff+1)*nBlockYSize))
     635                 :         {
     636               0 :             CPLError(CE_Failure, CPLE_AppDefined, "opj_set_decode_area() failed");
     637               0 :             eErr = CE_Failure;
     638               0 :             goto end;
     639                 :         }
     640               0 :         if (!opj_decode(pCodec,pStream, psImage))
     641                 :         {
     642               0 :             CPLError(CE_Failure, CPLE_AppDefined, "opj_decode() failed");
     643               0 :             eErr = CE_Failure;
     644               0 :             goto end;
     645                 :         }
     646                 :     }
     647                 :     else
     648                 :     {
     649              71 :         if (!opj_get_decoded_tile( pCodec, pStream, psImage, nTileNumber ))
     650                 :         {
     651               0 :             CPLError(CE_Failure, CPLE_AppDefined, "opj_get_decoded_tile() failed");
     652               0 :             eErr = CE_Failure;
     653               0 :             goto end;
     654                 :         }
     655                 :     }
     656                 : 
     657             255 :     for(int xBand = 0; xBand < nBandCount; xBand ++)
     658                 :     {
     659                 :         void* pDstBuffer;
     660             184 :         GDALRasterBlock *poBlock = NULL;
     661             184 :         int iBand = (panBandMap) ? panBandMap[xBand] : xBand + 1;
     662                 : 
     663             184 :         if (iBand == nBand)
     664              71 :             pDstBuffer = pImage;
     665                 :         else
     666                 :         {
     667                 :             poBlock = ((JP2OpenJPEGRasterBand*)GetRasterBand(iBand))->
     668             113 :                 TryGetLockedBlockRef(nBlockXOff,nBlockYOff);
     669             113 :             if (poBlock != NULL)
     670                 :             {
     671               0 :                 poBlock->DropLock();
     672               0 :                 continue;
     673                 :             }
     674                 : 
     675                 :             poBlock = GetRasterBand(iBand)->
     676             113 :                 GetLockedBlockRef(nBlockXOff,nBlockYOff, TRUE);
     677             113 :             if (poBlock == NULL)
     678                 :             {
     679               0 :                 continue;
     680                 :             }
     681                 : 
     682             113 :             pDstBuffer = poBlock->GetDataRef();
     683             113 :             if (!pDstBuffer)
     684                 :             {
     685               0 :                 poBlock->DropLock();
     686               0 :                 continue;
     687                 :             }
     688                 :         }
     689                 : 
     690             184 :         if (bIs420)
     691                 :         {
     692               3 :             CPLAssert((int)psImage->comps[0].w >= nWidthToRead);
     693               3 :             CPLAssert((int)psImage->comps[0].h >= nHeightToRead);
     694               3 :             CPLAssert(psImage->comps[1].w == (psImage->comps[0].w + 1) / 2);
     695               3 :             CPLAssert(psImage->comps[1].h == (psImage->comps[0].h + 1) / 2);
     696               3 :             CPLAssert(psImage->comps[2].w == (psImage->comps[0].w + 1) / 2);
     697               3 :             CPLAssert(psImage->comps[2].h == (psImage->comps[0].h + 1) / 2);
     698                 : 
     699               3 :             OPJ_INT32* pSrcY = psImage->comps[0].data;
     700               3 :             OPJ_INT32* pSrcCb = psImage->comps[1].data;
     701               3 :             OPJ_INT32* pSrcCr = psImage->comps[2].data;
     702               3 :             GByte* pDst = (GByte*)pDstBuffer;
     703            1923 :             for(int j=0;j<nHeightToRead;j++)
     704                 :             {
     705          923520 :                 for(int i=0;i<nWidthToRead;i++)
     706                 :                 {
     707          921600 :                     int Y = pSrcY[j * psImage->comps[0].w + i];
     708          921600 :                     int Cb = pSrcCb[(j/2) * psImage->comps[1].w + (i/2)];
     709          921600 :                     int Cr = pSrcCr[(j/2) * psImage->comps[2].w + (i/2)];
     710          921600 :                     if (iBand == 1)
     711          307200 :                         pDst[j * nBlockXSize + i] = CLAMP_0_255((int)(Y + 1.402 * (Cr - 128)));
     712          614400 :                     else if (iBand == 2)
     713          307200 :                         pDst[j * nBlockXSize + i] = CLAMP_0_255((int)(Y - 0.34414 * (Cb - 128) - 0.71414 * (Cr - 128)));
     714                 :                     else
     715          307200 :                         pDst[j * nBlockXSize + i] = CLAMP_0_255((int)(Y + 1.772 * (Cb - 128)));
     716                 :                 }
     717                 :             }
     718                 :         }
     719                 :         else
     720                 :         {
     721             181 :             CPLAssert((int)psImage->comps[iBand-1].w >= nWidthToRead);
     722             181 :             CPLAssert((int)psImage->comps[iBand-1].h >= nHeightToRead);
     723                 : 
     724             459 :             if ((int)psImage->comps[iBand-1].w == nBlockXSize &&
     725             151 :                 (int)psImage->comps[iBand-1].h == nBlockYSize)
     726                 :             {
     727             127 :                 GDALCopyWords(psImage->comps[iBand-1].data, GDT_Int32, 4,
     728             254 :                             pDstBuffer, eDataType, nDataTypeSize, nBlockXSize * nBlockYSize);
     729                 :             }
     730                 :             else
     731                 :             {
     732           12292 :                 for(int j=0;j<nHeightToRead;j++)
     733                 :                 {
     734           24476 :                     GDALCopyWords(psImage->comps[iBand-1].data + j * psImage->comps[iBand-1].w, GDT_Int32, 4,
     735                 :                                 (GByte*)pDstBuffer + j * nBlockXSize * nDataTypeSize, eDataType, nDataTypeSize,
     736           36714 :                                 nWidthToRead);
     737                 :                 }
     738                 :             }
     739                 :         }
     740                 : 
     741             184 :         if (poBlock != NULL)
     742             113 :             poBlock->DropLock();
     743                 :     }
     744                 : 
     745                 : end:
     746              71 :     opj_end_decompress(pCodec,pStream);
     747              71 :     opj_stream_destroy(pStream);
     748              71 :     opj_destroy_codec(pCodec);
     749              71 :     opj_image_destroy(psImage);
     750                 : 
     751              71 :     return eErr;
     752                 : }
     753                 : 
     754                 : 
     755                 : /************************************************************************/
     756                 : /*                         GetOverviewCount()                           */
     757                 : /************************************************************************/
     758                 : 
     759              24 : int JP2OpenJPEGRasterBand::GetOverviewCount()
     760                 : {
     761              24 :     JP2OpenJPEGDataset *poGDS = (JP2OpenJPEGDataset *) poDS;
     762              24 :     return poGDS->nOverviewCount;
     763                 : }
     764                 : 
     765                 : /************************************************************************/
     766                 : /*                            GetOverview()                             */
     767                 : /************************************************************************/
     768                 : 
     769               8 : GDALRasterBand* JP2OpenJPEGRasterBand::GetOverview(int iOvrLevel)
     770                 : {
     771               8 :     JP2OpenJPEGDataset *poGDS = (JP2OpenJPEGDataset *) poDS;
     772               8 :     if (iOvrLevel < 0 || iOvrLevel >= poGDS->nOverviewCount)
     773               0 :         return NULL;
     774                 : 
     775               8 :     return poGDS->papoOverviewDS[iOvrLevel]->GetRasterBand(nBand);
     776                 : }
     777                 : 
     778                 : /************************************************************************/
     779                 : /*                       GetColorInterpretation()                       */
     780                 : /************************************************************************/
     781                 : 
     782              27 : GDALColorInterp JP2OpenJPEGRasterBand::GetColorInterpretation()
     783                 : {
     784              27 :     JP2OpenJPEGDataset *poGDS = (JP2OpenJPEGDataset *) poDS;
     785                 : 
     786              27 :     if (poGDS->eColorSpace == OPJ_CLRSPC_GRAY)
     787               0 :         return GCI_GrayIndex;
     788              27 :     else if (poGDS->nBands == 3 || poGDS->nBands == 4)
     789                 :     {
     790              22 :         switch(nBand)
     791                 :         {
     792                 :             case 1:
     793               4 :                 return GCI_RedBand;
     794                 :             case 2:
     795               4 :                 return GCI_GreenBand;
     796                 :             case 3:
     797               4 :                 return GCI_BlueBand;
     798                 :             case 4:
     799              10 :                 return GCI_AlphaBand;
     800                 :             default:
     801               0 :                 return GCI_Undefined;
     802                 :         }
     803                 :     }
     804                 : 
     805               5 :     return GCI_Undefined;
     806                 : }
     807                 : 
     808                 : /************************************************************************/
     809                 : /* ==================================================================== */
     810                 : /*                           JP2OpenJPEGDataset                         */
     811                 : /* ==================================================================== */
     812                 : /************************************************************************/
     813                 : 
     814                 : /************************************************************************/
     815                 : /*                        JP2OpenJPEGDataset()                          */
     816                 : /************************************************************************/
     817                 : 
     818              54 : JP2OpenJPEGDataset::JP2OpenJPEGDataset()
     819                 : {
     820              54 :     fp = NULL;
     821              54 :     nBands = 0;
     822              54 :     pszProjection = CPLStrdup("");
     823              54 :     nGCPCount = 0;
     824              54 :     pasGCPList = NULL;
     825              54 :     bGeoTransformValid = FALSE;
     826              54 :     adfGeoTransform[0] = 0.0;
     827              54 :     adfGeoTransform[1] = 1.0;
     828              54 :     adfGeoTransform[2] = 0.0;
     829              54 :     adfGeoTransform[3] = 0.0;
     830              54 :     adfGeoTransform[4] = 0.0;
     831              54 :     adfGeoTransform[5] = 1.0;
     832              54 :     eCodecFormat = OPJ_CODEC_UNKNOWN;
     833              54 :     eColorSpace = OPJ_CLRSPC_UNKNOWN;
     834              54 :     bIs420 = FALSE;
     835              54 :     iLevel = 0;
     836              54 :     nOverviewCount = 0;
     837              54 :     papoOverviewDS = NULL;
     838              54 :     bUseSetDecodeArea = FALSE;
     839              54 :     nThreads = -1;
     840              54 :     bEnoughMemoryToLoadOtherBands = TRUE;
     841              54 : }
     842                 : 
     843                 : /************************************************************************/
     844                 : /*                         ~JP2OpenJPEGDataset()                        */
     845                 : /************************************************************************/
     846                 : 
     847              54 : JP2OpenJPEGDataset::~JP2OpenJPEGDataset()
     848                 : 
     849                 : {
     850              54 :     FlushCache();
     851                 : 
     852              54 :     if ( pszProjection )
     853              54 :         CPLFree( pszProjection );
     854              54 :     if( nGCPCount > 0 )
     855                 :     {
     856               2 :         GDALDeinitGCPs( nGCPCount, pasGCPList );
     857               2 :         CPLFree( pasGCPList );
     858                 :     }
     859              54 :     if( fp != NULL )
     860              54 :         VSIFCloseL( fp );
     861                 : 
     862              54 :     CloseDependentDatasets();
     863              54 : }
     864                 : 
     865                 : /************************************************************************/
     866                 : /*                      CloseDependentDatasets()                        */
     867                 : /************************************************************************/
     868                 : 
     869              54 : int JP2OpenJPEGDataset::CloseDependentDatasets()
     870                 : {
     871              54 :     int bRet = GDALPamDataset::CloseDependentDatasets();
     872              54 :     if ( papoOverviewDS )
     873                 :     {
     874              33 :         for( int i = 0; i < nOverviewCount; i++ )
     875              22 :             delete papoOverviewDS[i];
     876              11 :         CPLFree( papoOverviewDS );
     877              11 :         papoOverviewDS = NULL;
     878              11 :         bRet = TRUE;
     879                 :     }
     880              54 :     return bRet;
     881                 : }
     882                 : 
     883                 : 
     884                 : /************************************************************************/
     885                 : /*                          GetProjectionRef()                          */
     886                 : /************************************************************************/
     887                 : 
     888              23 : const char *JP2OpenJPEGDataset::GetProjectionRef()
     889                 : 
     890                 : {
     891              23 :     if ( pszProjection && pszProjection[0] != 0 )
     892              19 :         return( pszProjection );
     893                 :     else
     894               4 :         return GDALPamDataset::GetProjectionRef();
     895                 : }
     896                 : 
     897                 : /************************************************************************/
     898                 : /*                          GetGeoTransform()                           */
     899                 : /************************************************************************/
     900                 : 
     901              28 : CPLErr JP2OpenJPEGDataset::GetGeoTransform( double * padfTransform )
     902                 : {
     903              28 :     if( bGeoTransformValid )
     904                 :     {
     905              26 :         memcpy( padfTransform, adfGeoTransform, sizeof(adfGeoTransform[0]) * 6 );
     906              26 :         return CE_None;
     907                 :     }
     908                 :     else
     909               2 :         return GDALPamDataset::GetGeoTransform(padfTransform);
     910                 : }
     911                 : 
     912                 : /************************************************************************/
     913                 : /*                            GetGCPCount()                             */
     914                 : /************************************************************************/
     915                 : 
     916               6 : int JP2OpenJPEGDataset::GetGCPCount()
     917                 : 
     918                 : {
     919               6 :     if( nGCPCount > 0 )
     920               1 :         return nGCPCount;
     921                 :     else
     922               5 :         return GDALPamDataset::GetGCPCount();
     923                 : }
     924                 : 
     925                 : /************************************************************************/
     926                 : /*                          GetGCPProjection()                          */
     927                 : /************************************************************************/
     928                 : 
     929               1 : const char *JP2OpenJPEGDataset::GetGCPProjection()
     930                 : 
     931                 : {
     932               1 :     if( nGCPCount > 0 )
     933               1 :         return pszProjection;
     934                 :     else
     935               0 :         return GDALPamDataset::GetGCPProjection();
     936                 : }
     937                 : 
     938                 : /************************************************************************/
     939                 : /*                               GetGCP()                               */
     940                 : /************************************************************************/
     941                 : 
     942               1 : const GDAL_GCP *JP2OpenJPEGDataset::GetGCPs()
     943                 : 
     944                 : {
     945               1 :     if( nGCPCount > 0 )
     946               1 :         return pasGCPList;
     947                 :     else
     948               0 :         return GDALPamDataset::GetGCPs();
     949                 : }
     950                 : 
     951                 : /************************************************************************/
     952                 : /*                            Identify()                                */
     953                 : /************************************************************************/
     954                 : 
     955           12011 : int JP2OpenJPEGDataset::Identify( GDALOpenInfo * poOpenInfo )
     956                 : 
     957                 : {
     958                 :     static const unsigned char jpc_header[] = {0xff,0x4f};
     959                 :     static const unsigned char jp2_box_jp[] = {0x6a,0x50,0x20,0x20}; /* 'jP  ' */
     960                 :         
     961           12011 :     if( poOpenInfo->nHeaderBytes >= 16 
     962                 :         && (memcmp( poOpenInfo->pabyHeader, jpc_header, 
     963                 :                     sizeof(jpc_header) ) == 0
     964                 :             || memcmp( poOpenInfo->pabyHeader + 4, jp2_box_jp, 
     965                 :                     sizeof(jp2_box_jp) ) == 0
     966                 :            ) )
     967              32 :         return TRUE;
     968                 :     
     969                 :     else
     970           11979 :         return FALSE;
     971                 : }
     972                 : /************************************************************************/
     973                 : /*                                Open()                                */
     974                 : /************************************************************************/
     975                 : 
     976            1950 : GDALDataset *JP2OpenJPEGDataset::Open( GDALOpenInfo * poOpenInfo )
     977                 : 
     978                 : {
     979            1950 :     if (!Identify(poOpenInfo))
     980            1918 :         return NULL;
     981                 : 
     982              32 :     VSILFILE* fp = VSIFOpenL(poOpenInfo->pszFilename, "rb");
     983              32 :     if (!fp)
     984               0 :         return NULL;
     985                 : 
     986                 :     OPJ_CODEC_FORMAT eCodecFormat;
     987                 : 
     988                 :     /* Detect which codec to use : J2K or JP2 ? */
     989                 :     static const unsigned char jpc_header[] = {0xff,0x4f};
     990              32 :     if (memcmp( poOpenInfo->pabyHeader, jpc_header, 
     991                 :                     sizeof(jpc_header) ) == 0)
     992              10 :         eCodecFormat = OPJ_CODEC_J2K;
     993                 :     else
     994              22 :         eCodecFormat = OPJ_CODEC_JP2;
     995                 : 
     996                 :     opj_codec_t* pCodec;
     997                 : 
     998              32 :     pCodec = opj_create_decompress(eCodecFormat);
     999                 : 
    1000              32 :     opj_set_info_handler(pCodec, JP2OpenJPEGDataset_InfoCallback,NULL);
    1001              32 :     opj_set_warning_handler(pCodec, JP2OpenJPEGDataset_WarningCallback, NULL);
    1002              32 :     opj_set_error_handler(pCodec, JP2OpenJPEGDataset_ErrorCallback,NULL);
    1003                 : 
    1004                 :     opj_dparameters_t parameters;
    1005              32 :     opj_set_default_decoder_parameters(&parameters);
    1006                 : 
    1007              32 :     if (! opj_setup_decoder(pCodec,&parameters))
    1008                 :     {
    1009               0 :         VSIFCloseL(fp);
    1010               0 :         return NULL;
    1011                 :     }
    1012                 : 
    1013                 :     opj_stream_t * pStream;
    1014              32 :     pStream = opj_stream_create(1024, TRUE); // Default 1MB is way too big for some datasets
    1015                 : 
    1016              32 :     VSIFSeekL(fp, 0, SEEK_END);
    1017              32 :     opj_stream_set_user_data_length(pStream, VSIFTellL(fp));
    1018                 :     /* Reseek to file beginning */
    1019              32 :     VSIFSeekL(fp, 0, SEEK_SET);
    1020                 : 
    1021              32 :     opj_stream_set_read_function(pStream, JP2OpenJPEGDataset_Read);
    1022              32 :     opj_stream_set_seek_function(pStream, JP2OpenJPEGDataset_Seek);
    1023              32 :     opj_stream_set_skip_function(pStream, JP2OpenJPEGDataset_Skip);
    1024              32 :     opj_stream_set_user_data(pStream, fp);
    1025                 : 
    1026              32 :     opj_image_t * psImage = NULL;
    1027                 :     OPJ_INT32  nX0,nY0;
    1028                 :     OPJ_UINT32 nTileW,nTileH,nTilesX,nTilesY;
    1029              32 :     if(!opj_read_header(pStream,pCodec,&psImage))
    1030                 :     {
    1031               0 :         CPLError(CE_Failure, CPLE_AppDefined, "opj_read_header() failed");
    1032               0 :         opj_destroy_codec(pCodec);
    1033               0 :         opj_stream_destroy(pStream);
    1034               0 :         opj_image_destroy(psImage);
    1035               0 :         VSIFCloseL(fp);
    1036               0 :         return NULL;
    1037                 :     }
    1038                 : 
    1039              32 :     opj_codestream_info_v2_t* pCodeStreamInfo = opj_get_cstr_info(pCodec);
    1040              32 :     nX0 = pCodeStreamInfo->tx0;
    1041              32 :     nY0 = pCodeStreamInfo->ty0;
    1042              32 :     nTileW = pCodeStreamInfo->tdx;
    1043              32 :     nTileH = pCodeStreamInfo->tdy;
    1044              32 :     nTilesX = pCodeStreamInfo->tw;
    1045              32 :     nTilesY = pCodeStreamInfo->th;
    1046              32 :     int numResolutions = pCodeStreamInfo->m_default_tile_info.tccp_info[0].numresolutions;
    1047              32 :     opj_destroy_cstr_info(&pCodeStreamInfo);
    1048                 : 
    1049              32 :     if (psImage == NULL)
    1050                 :     {
    1051               0 :         opj_destroy_codec(pCodec);
    1052               0 :         opj_stream_destroy(pStream);
    1053               0 :         opj_image_destroy(psImage);
    1054               0 :         VSIFCloseL(fp);
    1055               0 :         return NULL;
    1056                 :     }
    1057                 : 
    1058                 : #ifdef DEBUG
    1059                 :     int i;
    1060              32 :     CPLDebug("OPENJPEG", "nX0 = %d", nX0);
    1061              32 :     CPLDebug("OPENJPEG", "nY0 = %d", nY0);
    1062              32 :     CPLDebug("OPENJPEG", "nTileW = %d", nTileW);
    1063              32 :     CPLDebug("OPENJPEG", "nTileH = %d", nTileH);
    1064              32 :     CPLDebug("OPENJPEG", "psImage->x0 = %d", psImage->x0);
    1065              32 :     CPLDebug("OPENJPEG", "psImage->y0 = %d", psImage->y0);
    1066              32 :     CPLDebug("OPENJPEG", "psImage->x1 = %d", psImage->x1);
    1067              32 :     CPLDebug("OPENJPEG", "psImage->y1 = %d", psImage->y1);
    1068              32 :     CPLDebug("OPENJPEG", "psImage->numcomps = %d", psImage->numcomps);
    1069              32 :     CPLDebug("OPENJPEG", "psImage->color_space = %d", psImage->color_space);
    1070              32 :     CPLDebug("OPENJPEG", "numResolutions = %d", numResolutions);
    1071              87 :     for(i=0;i<(int)psImage->numcomps;i++)
    1072                 :     {
    1073              55 :         CPLDebug("OPENJPEG", "psImage->comps[%d].dx = %d", i, psImage->comps[i].dx);
    1074              55 :         CPLDebug("OPENJPEG", "psImage->comps[%d].dy = %d", i, psImage->comps[i].dy);
    1075              55 :         CPLDebug("OPENJPEG", "psImage->comps[%d].x0 = %d", i, psImage->comps[i].x0);
    1076              55 :         CPLDebug("OPENJPEG", "psImage->comps[%d].y0 = %d", i, psImage->comps[i].y0);
    1077              55 :         CPLDebug("OPENJPEG", "psImage->comps[%d].w = %d", i, psImage->comps[i].w);
    1078              55 :         CPLDebug("OPENJPEG", "psImage->comps[%d].h = %d", i, psImage->comps[i].h);
    1079              55 :         CPLDebug("OPENJPEG", "psImage->comps[%d].resno_decoded = %d", i, psImage->comps[i].resno_decoded);
    1080              55 :         CPLDebug("OPENJPEG", "psImage->comps[%d].factor = %d", i, psImage->comps[i].factor);
    1081              55 :         CPLDebug("OPENJPEG", "psImage->comps[%d].prec = %d", i, psImage->comps[i].prec);
    1082              55 :         CPLDebug("OPENJPEG", "psImage->comps[%d].sgnd = %d", i, psImage->comps[i].sgnd);
    1083                 :     }
    1084                 : #endif
    1085                 : 
    1086              96 :     if (psImage->x1 <= psImage->x0 ||
    1087                 :         psImage->y1 <= psImage->y0 ||
    1088                 :         psImage->numcomps == 0 ||
    1089              32 :         psImage->comps[0].w != psImage->x1 - psImage->x0 ||
    1090              32 :         psImage->comps[0].h != psImage->y1 - psImage->y0)
    1091                 :     {
    1092               0 :         CPLDebug("OPENJPEG", "Unable to handle that image (1)");
    1093               0 :         opj_destroy_codec(pCodec);
    1094               0 :         opj_stream_destroy(pStream);
    1095               0 :         opj_image_destroy(psImage);
    1096               0 :         VSIFCloseL(fp);
    1097               0 :         return NULL;
    1098                 :     }
    1099                 : 
    1100              32 :     GDALDataType eDataType = GDT_Byte;
    1101              32 :     if (psImage->comps[0].prec > 16)
    1102                 :     {
    1103               0 :         if (psImage->comps[0].sgnd)
    1104               0 :             eDataType = GDT_Int32;
    1105                 :         else
    1106               0 :             eDataType = GDT_UInt32;
    1107                 :     }
    1108              32 :     else if (psImage->comps[0].prec > 8)
    1109                 :     {
    1110              10 :         if (psImage->comps[0].sgnd)
    1111               5 :             eDataType = GDT_Int16;
    1112                 :         else
    1113               5 :             eDataType = GDT_UInt16;
    1114                 :     }
    1115                 : 
    1116                 :     int bIs420  =  (psImage->color_space != OPJ_CLRSPC_SRGB &&
    1117                 :                     eDataType == GDT_Byte &&
    1118                 :                     psImage->numcomps == 3 &&
    1119              14 :                     psImage->comps[1].w == psImage->comps[0].w / 2 &&
    1120               2 :                     psImage->comps[1].h == psImage->comps[0].h / 2 &&
    1121               2 :                     psImage->comps[2].w == psImage->comps[0].w / 2 &&
    1122              50 :                     psImage->comps[2].h == psImage->comps[0].h / 2);
    1123                 : 
    1124              32 :     if (bIs420)
    1125                 :     {
    1126               1 :         CPLDebug("OPENJPEG", "420 format");
    1127                 :     }
    1128                 :     else
    1129                 :     {
    1130                 :         int iBand;
    1131              52 :         for(iBand = 2; iBand <= (int)psImage->numcomps; iBand ++)
    1132                 :         {
    1133              63 :             if( psImage->comps[iBand-1].w != psImage->comps[0].w ||
    1134              42 :                 psImage->comps[iBand-1].h != psImage->comps[0].h )
    1135                 :             {
    1136               0 :                 CPLDebug("OPENJPEG", "Unable to handle that image (2)");
    1137               0 :                 opj_destroy_codec(pCodec);
    1138               0 :                 opj_stream_destroy(pStream);
    1139               0 :                 opj_image_destroy(psImage);
    1140               0 :                 VSIFCloseL(fp);
    1141               0 :                 return NULL;
    1142                 :             }
    1143                 :         }
    1144                 :     }
    1145                 : 
    1146                 : 
    1147                 : /* -------------------------------------------------------------------- */
    1148                 : /*      Create a corresponding GDALDataset.                             */
    1149                 : /* -------------------------------------------------------------------- */
    1150                 :     JP2OpenJPEGDataset     *poDS;
    1151                 :     int                 iBand;
    1152                 : 
    1153              32 :     poDS = new JP2OpenJPEGDataset();
    1154              32 :     poDS->eCodecFormat = eCodecFormat;
    1155              32 :     poDS->eColorSpace = psImage->color_space;
    1156              32 :     poDS->nRasterXSize = psImage->x1 - psImage->x0;
    1157              32 :     poDS->nRasterYSize = psImage->y1 - psImage->y0;
    1158              32 :     poDS->nBands = psImage->numcomps;
    1159              32 :     poDS->fp = fp;
    1160              32 :     poDS->bIs420 = bIs420;
    1161                 : 
    1162                 :     poDS->bUseSetDecodeArea = 
    1163                 :         (poDS->nRasterXSize == (int)nTileW &&
    1164                 :          poDS->nRasterYSize == (int)nTileH &&
    1165                 :          (poDS->nRasterXSize > 1024 ||
    1166              62 :           poDS->nRasterYSize > 1024));
    1167                 : 
    1168              32 :     if (poDS->bUseSetDecodeArea)
    1169                 :     {
    1170               0 :         if (nTileW > 1024) nTileW = 1024;
    1171               0 :         if (nTileH > 1024) nTileH = 1024;
    1172                 :     }
    1173                 : 
    1174                 : /* -------------------------------------------------------------------- */
    1175                 : /*      Create band information objects.                                */
    1176                 : /* -------------------------------------------------------------------- */
    1177             174 :     for( iBand = 1; iBand <= poDS->nBands; iBand++ )
    1178                 :     {
    1179                 :         poDS->SetBand( iBand, new JP2OpenJPEGRasterBand( poDS, iBand, eDataType,
    1180              55 :                                                          psImage->comps[iBand-1].prec,
    1181             110 :                                                          nTileW, nTileH) );
    1182                 :     }
    1183                 : 
    1184                 : /* -------------------------------------------------------------------- */
    1185                 : /*      Create overview datasets.                                       */
    1186                 : /* -------------------------------------------------------------------- */
    1187              32 :     int nW = poDS->nRasterXSize;
    1188              32 :     int nH = poDS->nRasterYSize;
    1189              86 :     while (poDS->nOverviewCount+1 < numResolutions &&
    1190                 :            (nW > 256 || nH > 256) &&
    1191                 :            (poDS->bUseSetDecodeArea || ((nTileW % 2) == 0 && (nTileH % 2) == 0)))
    1192                 :     {
    1193              22 :         nW /= 2;
    1194              22 :         nH /= 2;
    1195                 : 
    1196              22 :         VSILFILE* fpOvr = VSIFOpenL(poOpenInfo->pszFilename, "rb");
    1197              22 :         if (!fpOvr)
    1198               0 :             break;
    1199                 : 
    1200                 :         poDS->papoOverviewDS = (JP2OpenJPEGDataset**) CPLRealloc(
    1201                 :                     poDS->papoOverviewDS,
    1202              22 :                     (poDS->nOverviewCount + 1) * sizeof(JP2OpenJPEGDataset*));
    1203              22 :         JP2OpenJPEGDataset* poODS = new JP2OpenJPEGDataset();
    1204              22 :         poODS->SetDescription( poOpenInfo->pszFilename );
    1205              22 :         poODS->iLevel = poDS->nOverviewCount + 1;
    1206              22 :         poODS->bUseSetDecodeArea = poDS->bUseSetDecodeArea;
    1207              22 :         if (!poDS->bUseSetDecodeArea)
    1208                 :         {
    1209              22 :             nTileW /= 2;
    1210              22 :             nTileH /= 2;
    1211                 :         }
    1212                 :         else
    1213                 :         {
    1214               0 :             if (nW < (int)nTileW || nH < (int)nTileH)
    1215                 :             {
    1216               0 :                 nTileW = nW;
    1217               0 :                 nTileH = nH;
    1218               0 :                 poODS->bUseSetDecodeArea = FALSE;
    1219                 :             }
    1220                 :         }
    1221                 : 
    1222              22 :         poODS->eCodecFormat = poDS->eCodecFormat;
    1223              22 :         poODS->eColorSpace = poDS->eColorSpace;
    1224              22 :         poODS->nRasterXSize = nW;
    1225              22 :         poODS->nRasterYSize = nH;
    1226              22 :         poODS->nBands = poDS->nBands;
    1227              22 :         poODS->fp = fpOvr;
    1228              22 :         poODS->bIs420 = bIs420;
    1229             178 :         for( iBand = 1; iBand <= poDS->nBands; iBand++ )
    1230                 :         {
    1231                 :             poODS->SetBand( iBand, new JP2OpenJPEGRasterBand( poODS, iBand, eDataType,
    1232              67 :                                                               psImage->comps[iBand-1].prec,
    1233             134 :                                                               nTileW, nTileH ) );
    1234                 :         }
    1235                 : 
    1236              22 :         poDS->papoOverviewDS[poDS->nOverviewCount ++] = poODS;
    1237                 : 
    1238                 :     }
    1239                 : 
    1240              32 :     opj_destroy_codec(pCodec);
    1241              32 :     opj_stream_destroy(pStream);
    1242              32 :     opj_image_destroy(psImage);
    1243              32 :     pCodec = NULL;
    1244              32 :     pStream = NULL;
    1245              32 :     psImage = NULL;
    1246                 : 
    1247                 : /* -------------------------------------------------------------------- */
    1248                 : /*      More metadata.                                                  */
    1249                 : /* -------------------------------------------------------------------- */
    1250              32 :     if( poDS->nBands > 1 )
    1251                 :     {
    1252              10 :         poDS->SetMetadataItem( "INTERLEAVE", "PIXEL", "IMAGE_STRUCTURE" );
    1253                 :     }
    1254                 : 
    1255                 : /* -------------------------------------------------------------------- */
    1256                 : /*      Check for georeferencing information.                           */
    1257                 : /* -------------------------------------------------------------------- */
    1258              32 :     GDALJP2Metadata oJP2Geo;
    1259                 : 
    1260              32 :     if( oJP2Geo.ReadAndParse( poOpenInfo->pszFilename ) )
    1261                 :     {
    1262              20 :         if ( poDS->pszProjection )
    1263              20 :             CPLFree( poDS->pszProjection );
    1264              20 :         poDS->pszProjection = CPLStrdup(oJP2Geo.pszProjection);
    1265              20 :         poDS->bGeoTransformValid = oJP2Geo.bHaveGeoTransform;
    1266                 :         memcpy( poDS->adfGeoTransform, oJP2Geo.adfGeoTransform, 
    1267              20 :                 sizeof(double) * 6 );
    1268              20 :         poDS->nGCPCount = oJP2Geo.nGCPCount;
    1269                 :         poDS->pasGCPList =
    1270              20 :             GDALDuplicateGCPs( oJP2Geo.nGCPCount, oJP2Geo.pasGCPList );
    1271                 :     }
    1272                 : 
    1273              32 :     if (oJP2Geo.pszXMPMetadata)
    1274                 :     {
    1275                 :         char *apszMDList[2];
    1276               1 :         apszMDList[0] = (char *) oJP2Geo.pszXMPMetadata;
    1277               1 :         apszMDList[1] = NULL;
    1278               1 :         poDS->SetMetadata(apszMDList, "xml:XMP");
    1279                 :     }
    1280                 : 
    1281                 : /* -------------------------------------------------------------------- */
    1282                 : /*      Do we have other misc metadata?                                 */
    1283                 : /* -------------------------------------------------------------------- */
    1284              32 :     if( oJP2Geo.papszMetadata != NULL )
    1285                 :     {
    1286               4 :         char **papszMD = CSLDuplicate(poDS->GDALPamDataset::GetMetadata());
    1287                 : 
    1288               4 :         papszMD = CSLMerge( papszMD, oJP2Geo.papszMetadata );
    1289               4 :         poDS->GDALPamDataset::SetMetadata( papszMD );
    1290                 : 
    1291               4 :         CSLDestroy( papszMD );
    1292                 :     }
    1293                 : 
    1294                 : /* -------------------------------------------------------------------- */
    1295                 : /*      Check for world file.                                           */
    1296                 : /* -------------------------------------------------------------------- */
    1297              32 :     if( !poDS->bGeoTransformValid )
    1298                 :     {
    1299                 :         poDS->bGeoTransformValid |=
    1300                 :             GDALReadWorldFile2( poOpenInfo->pszFilename, NULL,
    1301                 :                                 poDS->adfGeoTransform,
    1302                 :                                 poOpenInfo->papszSiblingFiles, NULL )
    1303                 :             || GDALReadWorldFile2( poOpenInfo->pszFilename, ".wld",
    1304                 :                                    poDS->adfGeoTransform,
    1305              14 :                                    poOpenInfo->papszSiblingFiles, NULL );
    1306                 :     }
    1307                 : 
    1308                 : /* -------------------------------------------------------------------- */
    1309                 : /*      Initialize any PAM information.                                 */
    1310                 : /* -------------------------------------------------------------------- */
    1311              32 :     poDS->SetDescription( poOpenInfo->pszFilename );
    1312              32 :     poDS->TryLoadXML();
    1313                 : 
    1314                 : /* -------------------------------------------------------------------- */
    1315                 : /*      Check for overviews.                                            */
    1316                 : /* -------------------------------------------------------------------- */
    1317                 :     //poDS->oOvManager.Initialize( poDS, poOpenInfo->pszFilename );
    1318                 : 
    1319              32 :     return( poDS );
    1320                 : }
    1321                 : 
    1322                 : /************************************************************************/
    1323                 : /*                           WriteBox()                                 */
    1324                 : /************************************************************************/
    1325                 : 
    1326               6 : void JP2OpenJPEGDataset::WriteBox(VSILFILE* fp, GDALJP2Box* poBox)
    1327                 : {
    1328                 :     GUInt32   nLBox;
    1329                 :     GUInt32   nTBox;
    1330                 : 
    1331               6 :     nLBox = (int) poBox->GetDataLength() + 8;
    1332               6 :     nLBox = CPL_MSBWORD32( nLBox );
    1333                 : 
    1334               6 :     memcpy(&nTBox, poBox->GetType(), 4);
    1335                 : 
    1336               6 :     VSIFWriteL( &nLBox, 4, 1, fp );
    1337               6 :     VSIFWriteL( &nTBox, 4, 1, fp );
    1338               6 :     VSIFWriteL(poBox->GetWritableData(), 1, (int) poBox->GetDataLength(), fp);
    1339               6 : }
    1340                 : 
    1341                 : /************************************************************************/
    1342                 : /*                          CreateCopy()                                */
    1343                 : /************************************************************************/
    1344                 : 
    1345              22 : GDALDataset * JP2OpenJPEGDataset::CreateCopy( const char * pszFilename,
    1346                 :                                            GDALDataset *poSrcDS, 
    1347                 :                                            int bStrict, char ** papszOptions, 
    1348                 :                                            GDALProgressFunc pfnProgress,
    1349                 :                                            void * pProgressData )
    1350                 : 
    1351                 : {
    1352              22 :     int  nBands = poSrcDS->GetRasterCount();
    1353              22 :     int  nXSize = poSrcDS->GetRasterXSize();
    1354              22 :     int  nYSize = poSrcDS->GetRasterYSize();
    1355                 : 
    1356              22 :     if( nBands != 1 && nBands != 3 )
    1357                 :     {
    1358                 :         CPLError( CE_Failure, CPLE_NotSupported,
    1359               4 :                   "Unable to export files with %d bands.", nBands );
    1360               4 :         return NULL;
    1361                 :     }
    1362                 : 
    1363              18 :     if (poSrcDS->GetRasterBand(1)->GetColorTable() != NULL)
    1364                 :     {
    1365                 :         CPLError( (bStrict) ? CE_Failure : CE_Warning, CPLE_NotSupported, 
    1366                 :                   "JP2OpenJPEG driver ignores color table. "
    1367                 :                   "The source raster band will be considered as grey level.\n"
    1368               0 :                   "Consider using color table expansion (-expand option in gdal_translate)\n");
    1369               0 :         if (bStrict)
    1370               0 :             return NULL;
    1371                 :     }
    1372                 : 
    1373              18 :     GDALDataType eDataType = poSrcDS->GetRasterBand(1)->GetRasterDataType();
    1374              18 :     int nDataTypeSize = (GDALGetDataTypeSize(eDataType) / 8);
    1375              18 :     if (eDataType != GDT_Byte && eDataType != GDT_Int16 && eDataType != GDT_UInt16
    1376                 :         && eDataType != GDT_Int32 && eDataType != GDT_UInt32)
    1377                 :     {
    1378                 :         CPLError( CE_Failure, CPLE_NotSupported,
    1379               6 :                   "JP2OpenJPEG driver only supports creating Byte, GDT_Int16, GDT_UInt16, GDT_Int32, GDT_UInt32");
    1380               6 :         return NULL;
    1381                 :     }
    1382                 : 
    1383                 : /* -------------------------------------------------------------------- */
    1384                 : /*      Analyze creation options.                                       */
    1385                 : /* -------------------------------------------------------------------- */
    1386              12 :     OPJ_CODEC_FORMAT eCodecFormat = OPJ_CODEC_J2K;
    1387              12 :     const char* pszCodec = CSLFetchNameValueDef(papszOptions, "CODEC", NULL);
    1388              12 :     if (pszCodec)
    1389                 :     {
    1390               1 :         if (EQUAL(pszCodec, "JP2"))
    1391               0 :             eCodecFormat = OPJ_CODEC_JP2;
    1392               1 :         else if (EQUAL(pszCodec, "J2K"))
    1393               1 :             eCodecFormat = OPJ_CODEC_J2K;
    1394                 :         else
    1395                 :         {
    1396                 :             CPLError(CE_Warning, CPLE_NotSupported,
    1397                 :                     "Unsupported value for CODEC : %s. Defaulting to J2K",
    1398               0 :                     pszCodec);
    1399                 :         }
    1400                 :     }
    1401                 :     else
    1402                 :     {
    1403              11 :         if (strlen(pszFilename) > 4 &&
    1404                 :             EQUAL(pszFilename + strlen(pszFilename) - 4, ".JP2"))
    1405                 :         {
    1406               3 :             eCodecFormat = OPJ_CODEC_JP2;
    1407                 :         }
    1408                 :     }
    1409                 : 
    1410                 :     int nBlockXSize =
    1411              12 :         atoi(CSLFetchNameValueDef(papszOptions, "BLOCKXSIZE", "1024"));
    1412                 :     int nBlockYSize =
    1413              12 :         atoi(CSLFetchNameValueDef(papszOptions, "BLOCKYSIZE", "1024"));
    1414              12 :     if (nBlockXSize < 32 || nBlockYSize < 32)
    1415                 :     {
    1416               0 :         CPLError(CE_Failure, CPLE_NotSupported, "Invalid block size");
    1417               0 :         return NULL;
    1418                 :     }
    1419                 : 
    1420              12 :     if (nXSize < nBlockXSize)
    1421              10 :         nBlockXSize = nXSize;
    1422              12 :     if (nYSize < nBlockYSize)
    1423              10 :         nBlockYSize = nYSize;
    1424                 : 
    1425              12 :     OPJ_PROG_ORDER eProgOrder = OPJ_LRCP;
    1426                 :     const char* pszPROGORDER =
    1427              12 :             CSLFetchNameValueDef(papszOptions, "PROGRESSION", "LRCP");
    1428              12 :     if (EQUAL(pszPROGORDER, "LRCP"))
    1429              12 :         eProgOrder = OPJ_LRCP;
    1430               0 :     else if (EQUAL(pszPROGORDER, "RLCP"))
    1431               0 :         eProgOrder = OPJ_RLCP;
    1432               0 :     else if (EQUAL(pszPROGORDER, "RPCL"))
    1433               0 :         eProgOrder = OPJ_RPCL;
    1434               0 :     else if (EQUAL(pszPROGORDER, "PCRL"))
    1435               0 :         eProgOrder = OPJ_PCRL;
    1436               0 :     else if (EQUAL(pszPROGORDER, "CPRL"))
    1437               0 :         eProgOrder = OPJ_CPRL;
    1438                 :     else
    1439                 :     {
    1440                 :         CPLError(CE_Warning, CPLE_NotSupported,
    1441                 :                  "Unsupported value for PROGRESSION : %s. Defaulting to LRCP",
    1442               0 :                  pszPROGORDER);
    1443                 :     }
    1444                 : 
    1445                 :     int bIsIrreversible =
    1446              12 :             ! (CSLTestBoolean(CSLFetchNameValueDef(papszOptions, "REVERSIBLE", "NO")));
    1447                 : 
    1448              12 :     double dfRate = 100. / 25;
    1449              12 :     const char* pszQuality = CSLFetchNameValueDef(papszOptions, "QUALITY", NULL);
    1450              12 :     if (pszQuality)
    1451                 :     {
    1452               3 :         double dfQuality = atof(pszQuality);
    1453               6 :         if (dfQuality > 0 && dfQuality <= 100)
    1454                 :         {
    1455               3 :             dfRate = 100 / dfQuality;
    1456                 :         }
    1457                 :         else
    1458                 :         {
    1459                 :             CPLError(CE_Warning, CPLE_NotSupported,
    1460                 :                  "Unsupported value for QUALITY : %s. Defaulting to 25",
    1461               0 :                  pszQuality);
    1462                 :         }
    1463                 :     }
    1464                 : 
    1465              12 :     int nNumResolutions = 6;
    1466              12 :     const char* pszResolutions = CSLFetchNameValueDef(papszOptions, "RESOLUTIONS", NULL);
    1467              12 :     if (pszResolutions)
    1468                 :     {
    1469               1 :         nNumResolutions = atoi(pszResolutions);
    1470               1 :         if (nNumResolutions < 1 || nNumResolutions > 7)
    1471                 :         {
    1472               0 :             nNumResolutions = 6;
    1473                 :             CPLError(CE_Warning, CPLE_NotSupported,
    1474                 :                  "Unsupported value for RESOLUTIONS : %s. Defaulting to 6",
    1475               0 :                  pszResolutions);
    1476                 :         }
    1477                 :     }
    1478                 :     
    1479              12 :     int bSOP = CSLTestBoolean(CSLFetchNameValueDef(papszOptions, "SOP", "FALSE"));
    1480              12 :     int bEPH = CSLTestBoolean(CSLFetchNameValueDef(papszOptions, "EPH", "FALSE"));
    1481                 :     
    1482                 :     int bResample = nBands == 3 && eDataType == GDT_Byte &&
    1483              12 :             CSLTestBoolean(CSLFetchNameValueDef(papszOptions, "YCBCR420", "FALSE"));
    1484              12 :     if (bResample && !((nXSize % 2) == 0 && (nYSize % 2) == 0 && (nBlockXSize % 2) == 0 && (nBlockYSize % 2) == 0))
    1485                 :     {
    1486                 :         CPLError(CE_Warning, CPLE_NotSupported,
    1487               0 :                  "YCBCR420 unsupported when image size and/or tile size are not multiple of 2");
    1488               0 :         bResample = FALSE;
    1489                 :     }
    1490                 : 
    1491                 : /* -------------------------------------------------------------------- */
    1492                 : /*      Setup encoder                                                  */
    1493                 : /* -------------------------------------------------------------------- */
    1494                 : 
    1495                 :     opj_cparameters_t parameters;
    1496              12 :     opj_set_default_encoder_parameters(&parameters);
    1497              12 :     if (bSOP)
    1498               0 :         parameters.csty |= 0x02;
    1499              12 :     if (bEPH)
    1500               0 :         parameters.csty |= 0x04;
    1501              12 :     parameters.cp_disto_alloc = 1;
    1502              12 :     parameters.tcp_numlayers = 1;
    1503              12 :     parameters.tcp_rates[0] = (float) dfRate;
    1504              12 :     parameters.cp_tx0 = 0;
    1505              12 :     parameters.cp_ty0 = 0;
    1506              12 :     parameters.tile_size_on = TRUE;
    1507              12 :     parameters.cp_tdx = nBlockXSize;
    1508              12 :     parameters.cp_tdy = nBlockYSize;
    1509              12 :     parameters.irreversible = bIsIrreversible;
    1510              12 :     parameters.numresolution = nNumResolutions;
    1511              12 :     parameters.prog_order = eProgOrder;
    1512                 : 
    1513                 :     opj_image_cmptparm_t* pasBandParams =
    1514              12 :             (opj_image_cmptparm_t*)CPLMalloc(nBands * sizeof(opj_image_cmptparm_t));
    1515                 :     int iBand;
    1516              26 :     for(iBand=0;iBand<nBands;iBand++)
    1517                 :     {
    1518              14 :         pasBandParams[iBand].x0 = 0;
    1519              14 :         pasBandParams[iBand].y0 = 0;
    1520              14 :         if (bResample && iBand > 0)
    1521                 :         {
    1522               0 :             pasBandParams[iBand].dx = 2;
    1523               0 :             pasBandParams[iBand].dy = 2;
    1524               0 :             pasBandParams[iBand].w = nXSize / 2;
    1525               0 :             pasBandParams[iBand].h = nYSize / 2;
    1526                 :         }
    1527                 :         else
    1528                 :         {
    1529              14 :             pasBandParams[iBand].dx = 1;
    1530              14 :             pasBandParams[iBand].dy = 1;
    1531              14 :             pasBandParams[iBand].w = nXSize;
    1532              14 :             pasBandParams[iBand].h = nYSize;
    1533                 :         }
    1534              14 :         pasBandParams[iBand].sgnd = (eDataType == GDT_Int16 || eDataType == GDT_Int32);
    1535              14 :         pasBandParams[iBand].prec = 8 * nDataTypeSize;
    1536                 :     }
    1537                 : 
    1538              12 :     opj_codec_t* pCodec = opj_create_compress(eCodecFormat);
    1539              12 :     if (pCodec == NULL)
    1540                 :     {
    1541                 :         CPLError(CE_Failure, CPLE_AppDefined,
    1542               0 :                  "opj_create_compress() failed");
    1543               0 :         CPLFree(pasBandParams);
    1544               0 :         return NULL;
    1545                 :     }
    1546                 : 
    1547              12 :     opj_set_info_handler(pCodec, JP2OpenJPEGDataset_InfoCallback,NULL);
    1548              12 :     opj_set_warning_handler(pCodec, JP2OpenJPEGDataset_WarningCallback,NULL);
    1549              12 :     opj_set_error_handler(pCodec, JP2OpenJPEGDataset_ErrorCallback,NULL);
    1550                 : 
    1551              12 :     OPJ_COLOR_SPACE eColorSpace = (bResample) ? OPJ_CLRSPC_SYCC : (nBands == 3) ? OPJ_CLRSPC_SRGB : OPJ_CLRSPC_GRAY;
    1552                 : 
    1553                 :     opj_image_t* psImage = opj_image_tile_create(nBands,pasBandParams,
    1554              12 :                                                  eColorSpace);
    1555                 : 
    1556                 : 
    1557              12 :     CPLFree(pasBandParams);
    1558              12 :     pasBandParams = NULL;
    1559              12 :     if (psImage == NULL)
    1560                 :     {
    1561                 :         CPLError(CE_Failure, CPLE_AppDefined,
    1562               0 :                  "opj_image_tile_create() failed");
    1563               0 :         opj_destroy_codec(pCodec);
    1564               0 :         return NULL;
    1565                 :     }
    1566                 : 
    1567              12 :     psImage->x0 = 0;
    1568              12 :     psImage->y0 = 0;
    1569              12 :     psImage->x1 = nXSize;
    1570              12 :     psImage->y1 = nYSize;
    1571              12 :     psImage->color_space = eColorSpace;
    1572              12 :     psImage->numcomps = nBands;
    1573                 : 
    1574              12 :     if (!opj_setup_encoder(pCodec,&parameters,psImage))
    1575                 :     {
    1576                 :         CPLError(CE_Failure, CPLE_AppDefined,
    1577               0 :                  "opj_setup_encoder() failed");
    1578               0 :         opj_image_destroy(psImage);
    1579               0 :         opj_destroy_codec(pCodec);
    1580               0 :         return NULL;
    1581                 :     }
    1582                 : 
    1583                 : /* -------------------------------------------------------------------- */
    1584                 : /*      Create the dataset.                                             */
    1585                 : /* -------------------------------------------------------------------- */
    1586                 : 
    1587              12 :     const char* pszAccess = EQUALN(pszFilename, "/vsisubfile/", 12) ? "r+b" : "w+b";
    1588              12 :     VSILFILE* fp = VSIFOpenL(pszFilename, pszAccess);
    1589              12 :     if (fp == NULL)
    1590                 :     {
    1591               2 :         CPLError(CE_Failure, CPLE_AppDefined, "Cannot create file");
    1592               2 :         opj_image_destroy(psImage);
    1593               2 :         opj_destroy_codec(pCodec);
    1594               2 :         return NULL;
    1595                 :     }
    1596                 : 
    1597                 :     opj_stream_t * pStream;
    1598              10 :     pStream = opj_stream_create(1024*1024, FALSE);
    1599              10 :     opj_stream_set_write_function(pStream, JP2OpenJPEGDataset_Write);
    1600              10 :     opj_stream_set_seek_function(pStream, JP2OpenJPEGDataset_Seek);
    1601              10 :     opj_stream_set_skip_function(pStream, JP2OpenJPEGDataset_Skip);
    1602              10 :     opj_stream_set_user_data(pStream, fp);
    1603                 : 
    1604              10 :     if (!opj_start_compress(pCodec,psImage,pStream))
    1605                 :     {
    1606                 :         CPLError(CE_Failure, CPLE_AppDefined,
    1607               6 :                  "opj_start_compress() failed");
    1608               6 :         opj_stream_destroy(pStream);
    1609               6 :         opj_image_destroy(psImage);
    1610               6 :         opj_destroy_codec(pCodec);
    1611               6 :         VSIFCloseL(fp);
    1612               6 :         return NULL;
    1613                 :     }
    1614                 : 
    1615               4 :     int nTilesX = (nXSize + nBlockXSize - 1) / nBlockXSize;
    1616               4 :     int nTilesY = (nYSize + nBlockYSize - 1) / nBlockYSize;
    1617                 : 
    1618                 :     GByte* pTempBuffer =(GByte*)VSIMalloc(nBlockXSize * nBlockYSize *
    1619               4 :                                           nBands * nDataTypeSize);
    1620               4 :     if (pTempBuffer == NULL)
    1621                 :     {
    1622               0 :         opj_stream_destroy(pStream);
    1623               0 :         opj_image_destroy(psImage);
    1624               0 :         opj_destroy_codec(pCodec);
    1625               0 :         VSIFCloseL(fp);
    1626               0 :         return NULL;
    1627                 :     }
    1628                 : 
    1629               4 :     GByte* pYUV420Buffer = NULL;
    1630               4 :     if (bResample)
    1631                 :     {
    1632               0 :         pYUV420Buffer =(GByte*)VSIMalloc(3 * nBlockXSize * nBlockYSize / 2);
    1633               0 :         if (pYUV420Buffer == NULL)
    1634                 :         {
    1635               0 :             opj_stream_destroy(pStream);
    1636               0 :             opj_image_destroy(psImage);
    1637               0 :             opj_destroy_codec(pCodec);
    1638               0 :             CPLFree(pTempBuffer);
    1639               0 :             VSIFCloseL(fp);
    1640               0 :             return NULL;
    1641                 :         }
    1642                 :     }
    1643                 : 
    1644                 : /* -------------------------------------------------------------------- */
    1645                 : /*      Setup GML and GeoTIFF information.                              */
    1646                 : /* -------------------------------------------------------------------- */
    1647               4 :     GDALJP2Metadata oJP2MD;
    1648                 : 
    1649               4 :     int bWriteExtraBoxes = FALSE;
    1650               4 :     if( eCodecFormat == OPJ_CODEC_JP2 &&
    1651                 :         (CSLFetchBoolean( papszOptions, "GMLJP2", TRUE ) ||
    1652                 :          CSLFetchBoolean( papszOptions, "GeoJP2", TRUE )) )
    1653                 :     {
    1654               2 :         const char* pszWKT = poSrcDS->GetProjectionRef();
    1655               2 :         if( pszWKT != NULL && pszWKT[0] != '\0' )
    1656                 :         {
    1657               2 :             bWriteExtraBoxes = TRUE;
    1658               2 :             oJP2MD.SetProjection( pszWKT );
    1659                 :         }
    1660                 :         double adfGeoTransform[6];
    1661               2 :         if( poSrcDS->GetGeoTransform( adfGeoTransform ) == CE_None )
    1662                 :         {
    1663               2 :             bWriteExtraBoxes = TRUE;
    1664               2 :             oJP2MD.SetGeoTransform( adfGeoTransform );
    1665                 :         }
    1666                 :     }
    1667                 : 
    1668                 : #define PIXELS_PER_INCH 2
    1669                 : #define PIXELS_PER_CM   3
    1670                 : 
    1671                 :     // Resolution
    1672               4 :     double dfXRes = 0, dfYRes = 0;
    1673               4 :     int nResUnit = 0;
    1674              11 :     if( eCodecFormat == OPJ_CODEC_JP2
    1675               3 :         && poSrcDS->GetMetadataItem("TIFFTAG_XRESOLUTION") != NULL
    1676               2 :         && poSrcDS->GetMetadataItem("TIFFTAG_YRESOLUTION") != NULL
    1677               2 :         && poSrcDS->GetMetadataItem("TIFFTAG_RESOLUTIONUNIT") != NULL )
    1678                 :     {
    1679                 :         dfXRes =
    1680               2 :             CPLAtof(poSrcDS->GetMetadataItem("TIFFTAG_XRESOLUTION"));
    1681                 :         dfYRes =
    1682               2 :             CPLAtof(poSrcDS->GetMetadataItem("TIFFTAG_YRESOLUTION"));
    1683               2 :         nResUnit = atoi(poSrcDS->GetMetadataItem("TIFFTAG_RESOLUTIONUNIT"));
    1684                 : 
    1685               2 :         if( nResUnit == PIXELS_PER_INCH )
    1686                 :         {
    1687                 :             // convert pixels per inch to pixels per cm.
    1688               0 :             dfXRes = dfXRes * 39.37 / 100.0;
    1689               0 :             dfYRes = dfYRes * 39.37 / 100.0;
    1690               0 :             nResUnit = PIXELS_PER_CM;
    1691                 :         }
    1692                 : 
    1693               2 :         if( nResUnit == PIXELS_PER_CM &&
    1694                 :             dfXRes > 0 && dfYRes > 0 &&
    1695                 :             dfXRes < 65535 && dfYRes < 65535 )
    1696                 :         {
    1697               2 :             bWriteExtraBoxes = TRUE;
    1698                 :         }
    1699                 :     }
    1700                 : 
    1701                 :     /* The file pointer should have been set 8 bytes after the */
    1702                 :     /* last written bytes, because openjpeg has reserved it */
    1703                 :     /* for the jp2c header, but still not written. */
    1704               4 :     vsi_l_offset nPosOriginalJP2C = 0;
    1705               4 :     vsi_l_offset nPosRealJP2C = 0;
    1706                 :     GByte abyBackupWhatShouldHaveBeenTheJP2CBoxHeader[8];
    1707                 : 
    1708               4 :     if( bWriteExtraBoxes )
    1709                 :     {
    1710               2 :         nPosOriginalJP2C = VSIFTellL(fp) - 8;
    1711                 : 
    1712                 :         char szBoxName[4+1];
    1713               2 :         int nLBoxJP2H = 0;
    1714                 : 
    1715                 :         /* If we must write a Res/Resd box, */
    1716                 :         /* read the box header at offset 32 */
    1717               2 :         if ( nResUnit == PIXELS_PER_CM )
    1718                 :         {
    1719               2 :             VSIFSeekL(fp, 32, SEEK_SET);
    1720               2 :             VSIFReadL(&nLBoxJP2H, 1, 4, fp);
    1721               2 :             nLBoxJP2H = CPL_MSBWORD32( nLBoxJP2H );
    1722               2 :             VSIFReadL(szBoxName, 1, 4, fp);
    1723               2 :             szBoxName[4] = '\0';
    1724                 :         }
    1725                 : 
    1726               2 :         VSIFSeekL(fp, nPosOriginalJP2C, SEEK_SET);
    1727                 : 
    1728                 :         /* And check that it is the jp2h box before */
    1729                 :         /* writing the res box */
    1730               2 :         if ( nResUnit == PIXELS_PER_CM && EQUAL(szBoxName, "jp2h") )
    1731                 :         {
    1732                 :             /* Format a resd box and embed it inside a res box */
    1733               2 :             GDALJP2Box oResd;
    1734               2 :             oResd.SetType("resd");
    1735                 :             GByte aby[10];
    1736                 : 
    1737               2 :             int nYDenom = 1;
    1738              20 :             while (nYDenom < 32767 && dfYRes < 32767)
    1739                 :             {
    1740              16 :                 dfYRes *= 2;
    1741              16 :                 nYDenom *= 2;
    1742                 :             }
    1743               2 :             int nXDenom = 1;
    1744              18 :             while (nXDenom < 32767 && dfXRes < 32767)
    1745                 :             {
    1746              14 :                 dfXRes *= 2;
    1747              14 :                 nXDenom *= 2;
    1748                 :             }
    1749                 : 
    1750               2 :             aby[0] = (GByte) (((int)dfYRes) / 256);
    1751               2 :             aby[1] = ((int)dfYRes) % 256;
    1752               2 :             aby[2] = (GByte) (nYDenom / 256);
    1753               2 :             aby[3] = nYDenom % 256;
    1754               2 :             aby[4] = (GByte) (((int)dfXRes) / 256);
    1755               2 :             aby[5] = ((int)dfXRes) % 256;
    1756               2 :             aby[6] = (GByte) (nXDenom / 256);
    1757               2 :             aby[7] = nXDenom % 256;
    1758               2 :             aby[8] = 2;
    1759               2 :             aby[9] = 2;
    1760               2 :             oResd.SetWritableData(10, aby);
    1761               2 :             GDALJP2Box* poResd = &oResd;
    1762               2 :             GDALJP2Box* poRes = GDALJP2Box::CreateAsocBox( 1, &poResd );
    1763               2 :             poRes->SetType("res ");
    1764                 : 
    1765                 :             /* Now let's extend the jp2c box header so that the */
    1766                 :             /* res box becomes a sub-box of it */
    1767               2 :             nLBoxJP2H += (int)poRes->GetDataLength() + 8;
    1768               2 :             nLBoxJP2H = CPL_MSBWORD32( nLBoxJP2H );
    1769               2 :             VSIFSeekL(fp, 32, SEEK_SET);
    1770               2 :             VSIFWriteL(&nLBoxJP2H, 1, 4, fp);
    1771                 : 
    1772                 :             /* Write the box at the end of the file */
    1773               2 :             VSIFSeekL(fp, nPosOriginalJP2C, SEEK_SET);
    1774               2 :             WriteBox(fp, poRes);
    1775                 : 
    1776               2 :             delete poRes;
    1777                 :         }
    1778                 : 
    1779               2 :         if( CSLFetchBoolean( papszOptions, "GMLJP2", TRUE ) )
    1780                 :         {
    1781               2 :             GDALJP2Box* poBox = oJP2MD.CreateGMLJP2(nXSize,nYSize);
    1782               2 :             WriteBox(fp, poBox);
    1783               2 :             delete poBox;
    1784                 :         }
    1785               2 :         if( CSLFetchBoolean( papszOptions, "GeoJP2", TRUE ) )
    1786                 :         {
    1787               2 :             GDALJP2Box* poBox = oJP2MD.CreateJP2GeoTIFF();
    1788               2 :             WriteBox(fp, poBox);
    1789               2 :             delete poBox;
    1790                 :         }
    1791                 : 
    1792               2 :         nPosRealJP2C = VSIFTellL(fp);
    1793                 : 
    1794                 :         /* Backup the res, GMLJP2 or GeoJP2 box header */
    1795                 :         /* that will be overwritten by opj_end_compress() */
    1796               2 :         VSIFSeekL(fp, nPosOriginalJP2C, SEEK_SET);
    1797               2 :         VSIFReadL(abyBackupWhatShouldHaveBeenTheJP2CBoxHeader, 1, 8, fp);
    1798                 : 
    1799               2 :         VSIFSeekL(fp, nPosRealJP2C + 8, SEEK_SET);
    1800                 :     }
    1801                 : 
    1802                 : /* -------------------------------------------------------------------- */
    1803                 : /*      Iterate over the tiles                                          */
    1804                 : /* -------------------------------------------------------------------- */
    1805               4 :     pfnProgress( 0.0, NULL, pProgressData );
    1806                 : 
    1807               4 :     CPLErr eErr = CE_None;
    1808                 :     int nBlockXOff, nBlockYOff;
    1809               4 :     int iTile = 0;
    1810               8 :     for(nBlockYOff=0;eErr == CE_None && nBlockYOff<nTilesY;nBlockYOff++)
    1811                 :     {
    1812               8 :         for(nBlockXOff=0;eErr == CE_None && nBlockXOff<nTilesX;nBlockXOff++)
    1813                 :         {
    1814               4 :             int nWidthToRead = MIN(nBlockXSize, nXSize - nBlockXOff * nBlockXSize);
    1815               4 :             int nHeightToRead = MIN(nBlockYSize, nYSize - nBlockYOff * nBlockYSize);
    1816                 :             eErr = poSrcDS->RasterIO(GF_Read,
    1817                 :                                      nBlockXOff * nBlockXSize,
    1818                 :                                      nBlockYOff * nBlockYSize,
    1819                 :                                      nWidthToRead, nHeightToRead,
    1820                 :                                      pTempBuffer, nWidthToRead, nHeightToRead,
    1821                 :                                      eDataType,
    1822                 :                                      nBands, NULL,
    1823               4 :                                      0,0,0);
    1824               4 :             if (eErr == CE_None)
    1825                 :             {
    1826               4 :                 if (bResample)
    1827                 :                 {
    1828                 :                     int j, i;
    1829               0 :                     for(j=0;j<nHeightToRead;j++)
    1830                 :                     {
    1831               0 :                         for(i=0;i<nWidthToRead;i++)
    1832                 :                         {
    1833               0 :                             int R = pTempBuffer[j*nWidthToRead+i];
    1834               0 :                             int G = pTempBuffer[nHeightToRead*nWidthToRead + j*nWidthToRead+i];
    1835               0 :                             int B = pTempBuffer[2*nHeightToRead*nWidthToRead + j*nWidthToRead+i];
    1836               0 :                             int Y = (int) (0.299 * R + 0.587 * G + 0.114 * B);
    1837               0 :                             int Cb = CLAMP_0_255((int) (-0.1687 * R - 0.3313 * G + 0.5 * B  + 128));
    1838               0 :                             int Cr = CLAMP_0_255((int) (0.5 * R - 0.4187 * G - 0.0813 * B  + 128));
    1839               0 :                             pYUV420Buffer[j*nWidthToRead+i] = (GByte) Y;
    1840               0 :                             pYUV420Buffer[nHeightToRead * nWidthToRead + ((j/2) * ((nWidthToRead)/2) + i/2) ] = (GByte) Cb;
    1841               0 :                             pYUV420Buffer[5 * nHeightToRead * nWidthToRead / 4 + ((j/2) * ((nWidthToRead)/2) + i/2) ] = (GByte) Cr;
    1842                 :                         }
    1843                 :                     }
    1844                 : 
    1845               0 :                     if (!opj_write_tile(pCodec,
    1846                 :                                         iTile,
    1847                 :                                         pYUV420Buffer,
    1848                 :                                         3 * nWidthToRead * nHeightToRead / 2,
    1849                 :                                         pStream))
    1850                 :                     {
    1851                 :                         CPLError(CE_Failure, CPLE_AppDefined,
    1852               0 :                                 "opj_write_tile() failed");
    1853               0 :                         eErr = CE_Failure;
    1854                 :                     }
    1855                 :                 }
    1856                 :                 else
    1857                 :                 {
    1858               4 :                     if (!opj_write_tile(pCodec,
    1859                 :                                         iTile,
    1860                 :                                         pTempBuffer,
    1861                 :                                         nWidthToRead * nHeightToRead * nBands * nDataTypeSize,
    1862                 :                                         pStream))
    1863                 :                     {
    1864                 :                         CPLError(CE_Failure, CPLE_AppDefined,
    1865               0 :                                 "opj_write_tile() failed");
    1866               0 :                         eErr = CE_Failure;
    1867                 :                     }
    1868                 :                 }
    1869                 :             }
    1870                 : 
    1871               4 :             if( !pfnProgress( (iTile + 1) * 1.0 / (nTilesX * nTilesY), NULL, pProgressData ) )
    1872               0 :                 eErr = CE_Failure;
    1873                 : 
    1874               4 :             iTile ++;
    1875                 :         }
    1876                 :     }
    1877                 : 
    1878               4 :     VSIFree(pTempBuffer);
    1879               4 :     VSIFree(pYUV420Buffer);
    1880                 : 
    1881               4 :     if (eErr != CE_None)
    1882                 :     {
    1883               0 :         opj_stream_destroy(pStream);
    1884               0 :         opj_image_destroy(psImage);
    1885               0 :         opj_destroy_codec(pCodec);
    1886               0 :         VSIFCloseL(fp);
    1887               0 :         return NULL;
    1888                 :     }
    1889                 : 
    1890               4 :     if (!opj_end_compress(pCodec,pStream))
    1891                 :     {
    1892                 :         CPLError(CE_Failure, CPLE_AppDefined,
    1893               0 :                  "opj_end_compress() failed");
    1894               0 :         opj_stream_destroy(pStream);
    1895               0 :         opj_image_destroy(psImage);
    1896               0 :         opj_destroy_codec(pCodec);
    1897               0 :         VSIFCloseL(fp);
    1898               0 :         return NULL;
    1899                 :     }
    1900                 : 
    1901               4 :     opj_stream_destroy(pStream);
    1902               4 :     opj_image_destroy(psImage);
    1903               4 :     opj_destroy_codec(pCodec);
    1904                 : 
    1905                 :     /* Move the jp2c box header at its real position */
    1906                 :     /* and restore the res, GMLJP2 or GeoJP2 box header that */
    1907                 :     /* has been overwritten */
    1908               4 :     if( bWriteExtraBoxes )
    1909                 :     {
    1910                 :         GByte abyJP2CHeader[8];
    1911                 : 
    1912               2 :         VSIFSeekL(fp, nPosOriginalJP2C, SEEK_SET);
    1913               2 :         VSIFReadL(abyJP2CHeader, 1, 8, fp);
    1914                 : 
    1915               2 :         VSIFSeekL(fp, nPosOriginalJP2C, SEEK_SET);
    1916               2 :         VSIFWriteL(abyBackupWhatShouldHaveBeenTheJP2CBoxHeader, 1, 8, fp);
    1917                 : 
    1918               2 :         VSIFSeekL(fp, nPosRealJP2C, SEEK_SET);
    1919               2 :         VSIFWriteL(abyJP2CHeader, 1, 8, fp);
    1920                 :     }
    1921                 : 
    1922               4 :     VSIFCloseL(fp);
    1923                 : /* -------------------------------------------------------------------- */
    1924                 : /*      Re-open dataset, and copy any auxilary pam information.         */
    1925                 : /* -------------------------------------------------------------------- */
    1926                 : 
    1927               4 :     GDALOpenInfo oOpenInfo(pszFilename, GA_ReadOnly);
    1928               4 :     JP2OpenJPEGDataset *poDS = (JP2OpenJPEGDataset*) JP2OpenJPEGDataset::Open(&oOpenInfo);
    1929                 : 
    1930               4 :     if( poDS )
    1931               4 :         poDS->CloneInfo( poSrcDS, GCIF_PAM_DEFAULT );
    1932                 : 
    1933               4 :     return poDS;
    1934                 : }
    1935                 : 
    1936                 : /************************************************************************/
    1937                 : /*                      GDALRegister_JP2OpenJPEG()                      */
    1938                 : /************************************************************************/
    1939                 : 
    1940             582 : void GDALRegister_JP2OpenJPEG()
    1941                 : 
    1942                 : {
    1943                 :     GDALDriver  *poDriver;
    1944                 :     
    1945             582 :     if (! GDAL_CHECK_VERSION("JP2OpenJPEG driver"))
    1946               0 :         return;
    1947                 : 
    1948             582 :     if( GDALGetDriverByName( "JP2OpenJPEG" ) == NULL )
    1949                 :     {
    1950             561 :         poDriver = new GDALDriver();
    1951                 :         
    1952             561 :         poDriver->SetDescription( "JP2OpenJPEG" );
    1953                 :         poDriver->SetMetadataItem( GDAL_DMD_LONGNAME, 
    1954             561 :                                    "JPEG-2000 driver based on OpenJPEG library" );
    1955                 :         poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC, 
    1956             561 :                                    "frmt_jp2openjpeg.html" );
    1957             561 :         poDriver->SetMetadataItem( GDAL_DMD_MIMETYPE, "image/jp2" );
    1958             561 :         poDriver->SetMetadataItem( GDAL_DMD_EXTENSION, "jp2" );
    1959                 :         poDriver->SetMetadataItem( GDAL_DMD_CREATIONDATATYPES, 
    1960             561 :                                    "Byte Int16 UInt16 Int32 UInt32" );
    1961                 : 
    1962                 :         poDriver->SetMetadataItem( GDAL_DMD_CREATIONOPTIONLIST,
    1963                 : "<CreationOptionList>"
    1964                 : "   <Option name='CODEC' type='string-select' default='according to file extension. If unknown, default to J2K'>"
    1965                 : "       <Value>JP2</Value>"
    1966                 : "       <Value>J2K</Value>"
    1967                 : "   </Option>"
    1968                 : "   <Option name='GeoJP2' type='boolean' description='defaults to ON'/>"
    1969                 : "   <Option name='GMLJP2' type='boolean' description='defaults to ON'/>"
    1970                 : "   <Option name='QUALITY' type='float' description='Quality. 0-100' default='25'/>"
    1971                 : "   <Option name='REVERSIBLE' type='boolean' description='True if the compression is reversible' default='false'/>"
    1972                 : "   <Option name='RESOLUTIONS' type='int' description='Number of resolutions. 1-7' default='6'/>"
    1973                 : "   <Option name='BLOCKXSIZE' type='int' description='Tile Width' default='1024'/>"
    1974                 : "   <Option name='BLOCKYSIZE' type='int' description='Tile Height' default='1024'/>"
    1975                 : "   <Option name='PROGRESSION' type='string-select' default='LRCP'>"
    1976                 : "       <Value>LRCP</Value>"
    1977                 : "       <Value>RLCP</Value>"
    1978                 : "       <Value>RPCL</Value>"
    1979                 : "       <Value>PCRL</Value>"
    1980                 : "       <Value>CPRL</Value>"
    1981                 : "   </Option>"
    1982                 : "   <Option name='SOP' type='boolean' description='True to insert SOP markers' default='false'/>"
    1983                 : "   <Option name='EPH' type='boolean' description='True to insert EPH markers' default='false'/>"
    1984                 : "   <Option name='YCBCR420' type='boolean' description='if RGB must be resampled to YCbCr 4:2:0' default='false'/>"
    1985             561 : "</CreationOptionList>"  );
    1986                 : 
    1987             561 :         poDriver->SetMetadataItem( GDAL_DCAP_VIRTUALIO, "YES" );
    1988                 : 
    1989             561 :         poDriver->pfnIdentify = JP2OpenJPEGDataset::Identify;
    1990             561 :         poDriver->pfnOpen = JP2OpenJPEGDataset::Open;
    1991             561 :         poDriver->pfnCreateCopy = JP2OpenJPEGDataset::CreateCopy;
    1992                 : 
    1993             561 :         GetGDALDriverManager()->RegisterDriver( poDriver );
    1994                 :     }
    1995                 : }
    1996                 : 

Generated by: LCOV version 1.7