LCOV - code coverage report
Current view: directory - frmts/openjpeg - openjpegdataset.cpp (source / functions) Found Hit Coverage
Test: gdal_filtered.info Lines: 581 420 72.3 %
Date: 2011-12-18 Functions: 30 22 73.3 %

       1                 : /******************************************************************************
       2                 :  * $Id: openjpegdataset.cpp 23033 2011-09-03 18:46:11Z rouault $
       3                 :  *
       4                 :  * Project:  JPEG2000 driver based on OpenJPEG library
       5                 :  * Purpose:  JPEG2000 driver based on OpenJPEG library
       6                 :  * Author:   Even Rouault, <even dot rouault at 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                 : /* Necessary for opj_setup_decoder() */
      31                 : #define USE_OPJ_DEPRECATED
      32                 : 
      33                 : /* A bit of explanation for this ugly "#define bool int"... */
      34                 : /* openjpeg.h contains itself a "#define bool int" when it is included from a C file */
      35                 : /* The openjpeg library is written in C, so every reference to bool within the library */
      36                 : /* assumes that bool is a int. So we have also to reinforce this when including the library */
      37                 : /* and when calling openjpeg API from the driver, we have to replace bool by int also */
      38                 : #define bool int
      39                 : #define GDAL_OPENJPEG_BOOL int
      40                 : #include <openjpeg.h>
      41                 : #undef bool /* undef now, so that later includes are happy */
      42                 : 
      43                 : #include "gdal_pam.h"
      44                 : #include "cpl_string.h"
      45                 : #include "gdaljp2metadata.h"
      46                 : 
      47                 : CPL_CVSID("$Id: openjpegdataset.cpp 23033 2011-09-03 18:46:11Z rouault $");
      48                 : 
      49                 : /************************************************************************/
      50                 : /*                  JP2OpenJPEGDataset_ErrorCallback()                  */
      51                 : /************************************************************************/
      52                 : 
      53               6 : static void JP2OpenJPEGDataset_ErrorCallback(const char *pszMsg, void *unused)
      54                 : {
      55               6 :     CPLError(CE_Failure, CPLE_AppDefined, "%s", pszMsg);
      56               6 : }
      57                 : 
      58                 : /************************************************************************/
      59                 : /*               JP2OpenJPEGDataset_WarningCallback()                   */
      60                 : /************************************************************************/
      61                 : 
      62               0 : static void JP2OpenJPEGDataset_WarningCallback(const char *pszMsg, void *unused)
      63                 : {
      64               0 :     CPLError(CE_Warning, CPLE_AppDefined, "%s", pszMsg);
      65               0 : }
      66                 : 
      67                 : /************************************************************************/
      68                 : /*                 JP2OpenJPEGDataset_InfoCallback()                    */
      69                 : /************************************************************************/
      70                 : 
      71              23 : static void JP2OpenJPEGDataset_InfoCallback(const char *pszMsg, void *unused)
      72                 : {
      73              23 :     CPLDebug("OPENJPEG", "info: %s", pszMsg);
      74              23 : }
      75                 : 
      76                 : /************************************************************************/
      77                 : /*                      JP2OpenJPEGDataset_Read()                       */
      78                 : /************************************************************************/
      79                 : 
      80            1456 : static OPJ_UINT32 JP2OpenJPEGDataset_Read(void* pBuffer, OPJ_UINT32 nBytes,
      81                 :                                        void *pUserData)
      82                 : {
      83            1456 :     int nRet = VSIFReadL(pBuffer, 1, nBytes, (VSILFILE*)pUserData);
      84                 : #ifdef DEBUG
      85            1456 :     CPLDebug("OPENJPEG", "JP2OpenJPEGDataset_Read(%d) = %d", nBytes, nRet);
      86                 : #endif
      87            1456 :     if (nRet == 0)
      88              21 :         nRet = -1;
      89            1456 :     return nRet;
      90                 : }
      91                 : 
      92                 : /************************************************************************/
      93                 : /*                      JP2OpenJPEGDataset_Write()                      */
      94                 : /************************************************************************/
      95                 : 
      96               2 : static OPJ_UINT32 JP2OpenJPEGDataset_Write(void* pBuffer, OPJ_UINT32 nBytes,
      97                 :                                        void *pUserData)
      98                 : {
      99               2 :     int nRet = VSIFWriteL(pBuffer, 1, nBytes, (VSILFILE*)pUserData);
     100                 : #ifdef DEBUG
     101               2 :     CPLDebug("OPENJPEG", "JP2OpenJPEGDataset_Write(%d) = %d", nBytes, nRet);
     102                 : #endif
     103               2 :     return nRet;
     104                 : }
     105                 : 
     106                 : /************************************************************************/
     107                 : /*                       JP2OpenJPEGDataset_Seek()                      */
     108                 : /************************************************************************/
     109                 : 
     110               0 : static GDAL_OPENJPEG_BOOL JP2OpenJPEGDataset_Seek(OPJ_SIZE_T nBytes, void * pUserData)
     111                 : {
     112                 : #ifdef DEBUG
     113               0 :     CPLDebug("OPENJPEG", "JP2OpenJPEGDataset_Seek(%d)", nBytes);
     114                 : #endif
     115               0 :     return VSIFSeekL((VSILFILE*)pUserData, nBytes, SEEK_SET) == 0;
     116                 : }
     117                 : 
     118                 : /************************************************************************/
     119                 : /*                     JP2OpenJPEGDataset_Skip()                        */
     120                 : /************************************************************************/
     121                 : 
     122            1218 : static OPJ_SIZE_T JP2OpenJPEGDataset_Skip(OPJ_SIZE_T nBytes, void * pUserData)
     123                 : {
     124            1218 :     vsi_l_offset nOffset = VSIFTellL((VSILFILE*)pUserData);
     125            1218 :     nOffset += nBytes;
     126                 : #ifdef DEBUG
     127                 :     CPLDebug("OPENJPEG", "JP2OpenJPEGDataset_Skip(%d -> " CPL_FRMT_GUIB ")",
     128            1218 :              nBytes, (GUIntBig)nOffset);
     129                 : #endif
     130            1218 :     VSIFSeekL((VSILFILE*)pUserData, nOffset, SEEK_SET);
     131            1218 :     return nBytes;
     132                 : }
     133                 : 
     134                 : /************************************************************************/
     135                 : /* ==================================================================== */
     136                 : /*                           JP2OpenJPEGDataset                         */
     137                 : /* ==================================================================== */
     138                 : /************************************************************************/
     139                 : 
     140                 : class JP2OpenJPEGDataset : public GDALPamDataset
     141                 : {
     142                 :     friend class JP2OpenJPEGRasterBand;
     143                 : 
     144                 :     VSILFILE   *fp; /* Large FILE API */
     145                 : 
     146                 :     char        *pszProjection;
     147                 :     int         bGeoTransformValid;
     148                 :     double      adfGeoTransform[6];
     149                 :     int         nGCPCount;
     150                 :     GDAL_GCP    *pasGCPList;
     151                 : 
     152                 :     OPJ_CODEC_FORMAT eCodecFormat;
     153                 :     OPJ_COLOR_SPACE eColorSpace;
     154                 : 
     155                 :     int         bLoadingOtherBands;
     156                 :     int         bIs420;
     157                 :     OPJ_BYTE *  pFullBuffer;
     158                 : 
     159                 :   public:
     160                 :                 JP2OpenJPEGDataset();
     161                 :                 ~JP2OpenJPEGDataset();
     162                 :     
     163                 :     static int Identify( GDALOpenInfo * poOpenInfo );
     164                 :     static GDALDataset  *Open( GDALOpenInfo * );
     165                 :     static GDALDataset  *CreateCopy( const char * pszFilename,
     166                 :                                            GDALDataset *poSrcDS, 
     167                 :                                            int bStrict, char ** papszOptions, 
     168                 :                                            GDALProgressFunc pfnProgress,
     169                 :                                            void * pProgressData );
     170                 :     CPLErr              GetGeoTransform( double* );
     171                 :     virtual const char  *GetProjectionRef(void);
     172                 :     virtual int         GetGCPCount();
     173                 :     virtual const char  *GetGCPProjection();
     174                 :     virtual const GDAL_GCP *GetGCPs();
     175                 : };
     176                 : 
     177                 : /************************************************************************/
     178                 : /* ==================================================================== */
     179                 : /*                         JP2OpenJPEGRasterBand                        */
     180                 : /* ==================================================================== */
     181                 : /************************************************************************/
     182                 : 
     183                 : class JP2OpenJPEGRasterBand : public GDALPamRasterBand
     184                 : {
     185                 :     friend class JP2OpenJPEGDataset;
     186                 : 
     187                 :   public:
     188                 : 
     189                 :                 JP2OpenJPEGRasterBand( JP2OpenJPEGDataset * poDS, int nBand,
     190                 :                                     GDALDataType eDataType,
     191                 :                                     int nBlockXSize, int nBlockYSize);
     192                 :                 ~JP2OpenJPEGRasterBand();
     193                 :                 
     194                 :     virtual CPLErr          IReadBlock( int, int, void * );
     195                 :     virtual GDALColorInterp GetColorInterpretation();
     196                 : };
     197                 : 
     198                 : 
     199                 : /************************************************************************/
     200                 : /*                        JP2OpenJPEGRasterBand()                       */
     201                 : /************************************************************************/
     202                 : 
     203              38 : JP2OpenJPEGRasterBand::JP2OpenJPEGRasterBand( JP2OpenJPEGDataset *poDS, int nBand,
     204                 :                                         GDALDataType eDataType,
     205              38 :                                         int nBlockXSize, int nBlockYSize)
     206                 : 
     207                 : {
     208              38 :     this->poDS = poDS;
     209              38 :     this->nBand = nBand;
     210              38 :     this->eDataType = eDataType;
     211              38 :     this->nBlockXSize = nBlockXSize;
     212              38 :     this->nBlockYSize = nBlockYSize;
     213              38 : }
     214                 : 
     215                 : /************************************************************************/
     216                 : /*                      ~JP2OpenJPEGRasterBand()                        */
     217                 : /************************************************************************/
     218                 : 
     219              38 : JP2OpenJPEGRasterBand::~JP2OpenJPEGRasterBand()
     220                 : {
     221              38 : }
     222                 : 
     223                 : /************************************************************************/
     224                 : /*                            CopySrcToDst()                            */
     225                 : /************************************************************************/
     226                 : 
     227          921600 : static CPL_INLINE GByte CLAMP_0_255(int val)
     228                 : {
     229          921600 :     if (val < 0)
     230            1383 :         return 0;
     231          920217 :     else if (val > 255)
     232            1778 :         return 255;
     233                 :     else
     234          918439 :         return (GByte)val;
     235                 : }
     236                 : 
     237             179 : static void CopySrcToDst(int nWidthToRead, int nHeightToRead,
     238                 :                          GByte* pTempBuffer,
     239                 :                          int nBlockXSize, int nBlockYSize, int nDataTypeSize,
     240                 :                          void* pImage, int nBand, int bIs420)
     241                 : {
     242                 :     int i, j;
     243             179 :     if (bIs420)
     244                 :     {
     245               3 :         GByte* pSrc = (GByte*)pTempBuffer;
     246               3 :         GByte* pDst = (GByte*)pImage;
     247            1923 :         for(j=0;j<nHeightToRead;j++)
     248                 :         {
     249          923520 :             for(i=0;i<nWidthToRead;i++)
     250                 :             {
     251          921600 :                 int Y = pSrc[j * nWidthToRead + i];
     252          921600 :                 int Cb = pSrc[nHeightToRead * nWidthToRead + ((j/2) * (nWidthToRead/2) + i/2) ];
     253          921600 :                 int Cr = pSrc[5 * nHeightToRead * nWidthToRead / 4 + ((j/2) * (nWidthToRead/2) + i/2) ];
     254          921600 :                 if (nBand == 1)
     255          307200 :                     pDst[j * nBlockXSize + i] = CLAMP_0_255((int)(Y + 1.402 * (Cr - 128)));
     256          614400 :                 else if (nBand == 2)
     257          307200 :                     pDst[j * nBlockXSize + i] = CLAMP_0_255((int)(Y - 0.34414 * (Cb - 128) - 0.71414 * (Cr - 128)));
     258                 :                 else
     259          307200 :                     pDst[j * nBlockXSize + i] = CLAMP_0_255((int)(Y + 1.772 * (Cb - 128)));
     260                 :             }
     261                 :         }
     262                 :     }
     263                 :     else
     264                 :     {
     265           66992 :         for(j=0;j<nHeightToRead;j++)
     266                 :         {
     267                 :             memcpy(((GByte*)pImage) + j*nBlockXSize * nDataTypeSize,
     268                 :                     pTempBuffer + (j*nWidthToRead + (nBand-1) * nHeightToRead * nWidthToRead) * nDataTypeSize,
     269           66816 :                     nWidthToRead * nDataTypeSize);
     270                 :         }
     271                 :     }
     272             179 : }
     273                 : 
     274                 : /************************************************************************/
     275                 : /*                             IReadBlock()                             */
     276                 : /************************************************************************/
     277                 : 
     278              69 : CPLErr JP2OpenJPEGRasterBand::IReadBlock( int nBlockXOff, int nBlockYOff,
     279                 :                                       void * pImage )
     280                 : {
     281              69 :     JP2OpenJPEGDataset *poGDS = (JP2OpenJPEGDataset *) poDS;
     282              69 :     opj_codec_t* pCodec = NULL;
     283              69 :     int nDataTypeSize = (GDALGetDataTypeSize(eDataType) / 8);
     284                 : 
     285                 :     CPLDebug("OPENJPEG", "xoff=%d yoff=%d band=%d",
     286              69 :              nBlockXOff, nBlockYOff, nBand);
     287                 : 
     288              69 :     int nWidthToRead = MIN(nBlockXSize, poGDS->nRasterXSize - nBlockXOff * nBlockXSize);
     289              69 :     int nHeightToRead = MIN(nBlockYSize, poGDS->nRasterYSize - nBlockYOff * nBlockYSize);
     290                 : 
     291              69 :     if (poGDS->pFullBuffer)
     292                 :     {
     293                 :         CopySrcToDst(nWidthToRead, nHeightToRead, poGDS->pFullBuffer,
     294                 :                      nBlockXSize, nBlockYSize, nDataTypeSize, pImage,
     295               0 :                      nBand, poGDS->bIs420);
     296               0 :         return CE_None;
     297                 :     }
     298                 : 
     299              69 :     if (nWidthToRead != nBlockXSize || nHeightToRead != nBlockYSize)
     300                 :     {
     301              18 :         memset(pImage, 0, nBlockXSize * nBlockYSize * nDataTypeSize);
     302                 :     }
     303                 : 
     304                 :     /* FIXME ? Well, this is pretty inefficient as for each block we recreate */
     305                 :     /* a new decoding session. But currently there's no way to call opj_set_decode_area() */
     306                 :     /* twice on the same codec instance... */
     307                 : 
     308              69 :     pCodec = opj_create_decompress(poGDS->eCodecFormat);
     309                 : 
     310              69 :     opj_set_info_handler(pCodec, JP2OpenJPEGDataset_InfoCallback,NULL);
     311              69 :     opj_set_warning_handler(pCodec, JP2OpenJPEGDataset_WarningCallback,NULL);
     312              69 :     opj_set_error_handler(pCodec, JP2OpenJPEGDataset_ErrorCallback,NULL);
     313                 : 
     314                 :     opj_dparameters_t parameters;
     315              69 :     opj_set_default_decoder_parameters(&parameters);
     316                 : 
     317              69 :     if (! opj_setup_decoder(pCodec,&parameters))
     318                 :     {
     319               0 :         CPLError(CE_Failure, CPLE_AppDefined, "opj_setup_decoder() failed");
     320               0 :         opj_destroy_codec(pCodec);
     321               0 :         return CE_Failure;
     322                 :     }
     323                 : 
     324                 :     /* Reseek to file beginning */
     325              69 :     VSIFSeekL(poGDS->fp, 0, SEEK_SET);
     326                 : 
     327                 :     opj_stream_t * pStream;
     328              69 :     pStream = opj_stream_create(1024, TRUE); // Default 1MB is way too big for some datasets
     329              69 :     opj_stream_set_read_function(pStream, JP2OpenJPEGDataset_Read);
     330              69 :     opj_stream_set_seek_function(pStream, JP2OpenJPEGDataset_Seek);
     331              69 :     opj_stream_set_skip_function(pStream, JP2OpenJPEGDataset_Skip);
     332              69 :     opj_stream_set_user_data(pStream, poGDS->fp);
     333                 : 
     334              69 :     opj_image_t * psImage = NULL;
     335                 :     OPJ_INT32  nX0,nY0;
     336                 :     OPJ_UINT32 nTileW,nTileH,nTilesX,nTilesY;
     337              69 :     if(!opj_read_header(pCodec, &psImage, &nX0, &nY0, &nTileW, &nTileH,
     338                 :                         &nTilesX, &nTilesY, pStream))
     339                 :     {
     340               0 :         CPLError(CE_Failure, CPLE_AppDefined, "opj_read_header() failed");
     341               0 :         opj_destroy_codec(pCodec);
     342               0 :         opj_stream_destroy(pStream);
     343               0 :         return CE_Failure;
     344                 :     }
     345                 : 
     346              69 :     if (!opj_set_decode_area(pCodec,
     347                 :                             nBlockXOff * nBlockXSize,
     348                 :                             nBlockYOff * nBlockYSize,
     349                 :                             nBlockXOff * nBlockXSize + nWidthToRead,
     350                 :                             nBlockYOff * nBlockYSize + nHeightToRead))
     351                 :     {
     352               0 :         CPLError(CE_Failure, CPLE_AppDefined, "opj_set_decode_area() failed");
     353               0 :         opj_destroy_codec(pCodec);
     354               0 :         opj_stream_destroy(pStream);
     355               0 :         opj_image_destroy(psImage);
     356               0 :         return CE_Failure;
     357                 :     }
     358                 : 
     359                 :     GDAL_OPENJPEG_BOOL bDataToUncompress;
     360                 :     OPJ_UINT32 nTileIndex,nCompCount;
     361                 :     OPJ_INT32 nTileX0,nTileY0,nTileX1,nTileY1;
     362                 :     OPJ_UINT32 nRequiredSize;
     363                 : 
     364                 :     int nAllocatedSize;
     365              69 :     if (poGDS->bIs420)
     366               1 :         nAllocatedSize = 3 * nWidthToRead * nHeightToRead * nDataTypeSize / 2;
     367                 :     else
     368              68 :         nAllocatedSize = poGDS->nBands * nWidthToRead * nHeightToRead * nDataTypeSize;
     369              69 :     OPJ_BYTE *pTempBuffer = (OPJ_BYTE *)VSIMalloc(nAllocatedSize);
     370              69 :     if (pTempBuffer == NULL)
     371                 :     {
     372               0 :         CPLError(CE_Failure, CPLE_AppDefined, "Cannot allocate temp buffer");
     373               0 :         opj_destroy_codec(pCodec);
     374               0 :         opj_stream_destroy(pStream);
     375               0 :         opj_image_destroy(psImage);
     376               0 :         return CE_Failure;
     377                 :     }
     378                 : 
     379             138 :     do
     380                 :     {
     381             138 :         if (!opj_read_tile_header(pCodec, &nTileIndex, &nRequiredSize,
     382                 :                                   &nTileX0, &nTileY0, &nTileX1, &nTileY1,
     383                 :                                   &nCompCount, &bDataToUncompress, pStream))
     384                 :         {
     385               0 :             CPLError(CE_Failure, CPLE_AppDefined, "opj_read_tile_header() failed");
     386               0 :             CPLFree(pTempBuffer);
     387               0 :             opj_destroy_codec(pCodec);
     388               0 :             opj_stream_destroy(pStream);
     389               0 :             opj_image_destroy(psImage);
     390               0 :             return CE_Failure;
     391                 :         }
     392                 : 
     393                 :         /* A few sanity checks */
     394             138 :         if (nTileX0 != nBlockXOff * nBlockXSize ||
     395                 :             nTileY0 != nBlockYOff * nBlockYSize ||
     396                 :             nTileX1 != nBlockXOff * nBlockXSize + nWidthToRead ||
     397                 :             nTileY1 != nBlockYOff * nBlockYSize + nHeightToRead ||
     398                 :             (int)nRequiredSize != nAllocatedSize ||
     399                 :             (int)nCompCount != poGDS->nBands)
     400                 :         {
     401                 :             CPLDebug("OPENJPEG",
     402                 :                      "bDataToUncompress=%d nTileIndex=%d nRequiredSize=%d nCompCount=%d",
     403               0 :                      bDataToUncompress, nTileIndex, nRequiredSize, nCompCount);
     404                 :             CPLDebug("OPENJPEG",
     405                 :                      "nTileX0=%d nTileY0=%d nTileX1=%d nTileY1=%d",
     406               0 :                      nTileX0, nTileY0, nTileX1, nTileY1);
     407                 :             CPLError(CE_Failure, CPLE_AppDefined,
     408               0 :                      "opj_read_tile_header() returned unexpected parameters");
     409               0 :             CPLFree(pTempBuffer);
     410               0 :             opj_destroy_codec(pCodec);
     411               0 :             opj_stream_destroy(pStream);
     412               0 :             opj_image_destroy(psImage);
     413               0 :             return CE_Failure;
     414                 :         }
     415                 : 
     416             138 :         if (bDataToUncompress)
     417                 :         {
     418              69 :             if (!opj_decode_tile_data(pCodec,nTileIndex,pTempBuffer,
     419                 :                                       nRequiredSize,pStream))
     420                 :             {
     421               0 :                 CPLError(CE_Failure, CPLE_AppDefined, "opj_decode_tile_data() failed");
     422               0 :                 CPLFree(pTempBuffer);
     423               0 :                 opj_destroy_codec(pCodec);
     424               0 :                 opj_stream_destroy(pStream);
     425               0 :                 opj_image_destroy(psImage);
     426               0 :                 return CE_Failure;
     427                 :             }
     428                 :         }
     429                 :     } while(bDataToUncompress);
     430                 : 
     431                 :     CopySrcToDst(nWidthToRead, nHeightToRead, pTempBuffer,
     432                 :                  nBlockXSize, nBlockYSize, nDataTypeSize, pImage,
     433              69 :                  nBand, poGDS->bIs420);
     434                 : 
     435                 :     /* Let's cache other bands */
     436              69 :     if( poGDS->nBands != 1 && !poGDS->bLoadingOtherBands &&
     437                 :         poGDS->nBands * nWidthToRead * nHeightToRead * nDataTypeSize <= GDALGetCacheMax64())
     438                 :     {
     439                 :         int iOtherBand;
     440                 : 
     441              55 :         poGDS->bLoadingOtherBands = TRUE;
     442                 : 
     443             220 :         for( iOtherBand = 1; iOtherBand <= poGDS->nBands; iOtherBand++ )
     444                 :         {
     445             165 :             if( iOtherBand == nBand )
     446              55 :                 continue;
     447                 : 
     448                 :             GDALRasterBlock *poBlock;
     449                 : 
     450                 :             poBlock = poGDS->GetRasterBand(iOtherBand)->
     451             110 :                 GetLockedBlockRef(nBlockXOff,nBlockYOff, TRUE);
     452             110 :             if (poBlock == NULL)
     453                 :             {
     454               0 :                 break;
     455                 :             }
     456                 : 
     457             110 :             void* pData = poBlock->GetDataRef();
     458             110 :             if (pData)
     459                 :             {
     460                 :                 CopySrcToDst(nWidthToRead, nHeightToRead, pTempBuffer,
     461                 :                              nBlockXSize, nBlockYSize, nDataTypeSize, pData,
     462             110 :                              iOtherBand, poGDS->bIs420);
     463                 :             }
     464                 : 
     465             110 :             poBlock->DropLock();
     466                 :         }
     467                 : 
     468              55 :         poGDS->bLoadingOtherBands = FALSE;
     469                 :     }
     470                 : 
     471              69 :     if (nBlockXSize == nRasterXSize && nBlockYSize == nRasterYSize &&
     472                 :         poGDS->nBands * nWidthToRead * nHeightToRead * nDataTypeSize > GDALGetCacheMax64())
     473                 :     {
     474               0 :         poGDS->pFullBuffer = pTempBuffer;
     475                 :     }
     476                 :     else
     477                 :     {
     478              69 :         CPLFree(pTempBuffer);
     479                 :     }
     480                 : 
     481              69 :     opj_end_decompress(pCodec,pStream);
     482              69 :     opj_stream_destroy(pStream);
     483              69 :     opj_destroy_codec(pCodec);
     484              69 :     opj_image_destroy(psImage);
     485                 : 
     486              69 :     return CE_None;
     487                 : }
     488                 : 
     489                 : /************************************************************************/
     490                 : /*                       GetColorInterpretation()                       */
     491                 : /************************************************************************/
     492                 : 
     493               3 : GDALColorInterp JP2OpenJPEGRasterBand::GetColorInterpretation()
     494                 : {
     495               3 :     JP2OpenJPEGDataset *poGDS = (JP2OpenJPEGDataset *) poDS;
     496                 : 
     497               3 :     if (poGDS->eColorSpace == CLRSPC_GRAY)
     498               0 :         return GCI_GrayIndex;
     499               3 :     else if (poGDS->nBands == 3 || poGDS->nBands == 4)
     500                 :     {
     501               0 :         switch(nBand)
     502                 :         {
     503                 :             case 1:
     504               0 :                 return GCI_RedBand;
     505                 :             case 2:
     506               0 :                 return GCI_GreenBand;
     507                 :             case 3:
     508               0 :                 return GCI_BlueBand;
     509                 :             case 4:
     510               0 :                 return GCI_AlphaBand;
     511                 :             default:
     512               0 :                 return GCI_Undefined;
     513                 :         }
     514                 :     }
     515                 : 
     516               3 :     return GCI_Undefined;
     517                 : }
     518                 : 
     519                 : /************************************************************************/
     520                 : /* ==================================================================== */
     521                 : /*                           JP2OpenJPEGDataset                         */
     522                 : /* ==================================================================== */
     523                 : /************************************************************************/
     524                 : 
     525                 : /************************************************************************/
     526                 : /*                        JP2OpenJPEGDataset()                          */
     527                 : /************************************************************************/
     528                 : 
     529              24 : JP2OpenJPEGDataset::JP2OpenJPEGDataset()
     530                 : {
     531              24 :     fp = NULL;
     532              24 :     nBands = 0;
     533              24 :     pszProjection = CPLStrdup("");
     534              24 :     nGCPCount = 0;
     535              24 :     pasGCPList = NULL;
     536              24 :     bGeoTransformValid = FALSE;
     537              24 :     adfGeoTransform[0] = 0.0;
     538              24 :     adfGeoTransform[1] = 1.0;
     539              24 :     adfGeoTransform[2] = 0.0;
     540              24 :     adfGeoTransform[3] = 0.0;
     541              24 :     adfGeoTransform[4] = 0.0;
     542              24 :     adfGeoTransform[5] = 1.0;
     543              24 :     bLoadingOtherBands = FALSE;
     544              24 :     eCodecFormat = CODEC_UNKNOWN;
     545              24 :     eColorSpace = CLRSPC_UNKNOWN;
     546              24 :     bIs420 = FALSE;
     547              24 :     pFullBuffer = NULL;
     548              24 : }
     549                 : 
     550                 : /************************************************************************/
     551                 : /*                         ~JP2OpenJPEGDataset()                        */
     552                 : /************************************************************************/
     553                 : 
     554              24 : JP2OpenJPEGDataset::~JP2OpenJPEGDataset()
     555                 : 
     556                 : {
     557              24 :     FlushCache();
     558                 : 
     559              24 :     if ( pszProjection )
     560              24 :         CPLFree( pszProjection );
     561              24 :     if( nGCPCount > 0 )
     562                 :     {
     563               2 :         GDALDeinitGCPs( nGCPCount, pasGCPList );
     564               2 :         CPLFree( pasGCPList );
     565                 :     }
     566              24 :     if( fp != NULL )
     567              24 :         VSIFCloseL( fp );
     568              24 :     VSIFree(pFullBuffer);
     569              24 : }
     570                 : 
     571                 : /************************************************************************/
     572                 : /*                          GetProjectionRef()                          */
     573                 : /************************************************************************/
     574                 : 
     575               9 : const char *JP2OpenJPEGDataset::GetProjectionRef()
     576                 : 
     577                 : {
     578               9 :     if ( pszProjection && pszProjection[0] != 0 )
     579               5 :         return( pszProjection );
     580                 :     else
     581               4 :         return GDALPamDataset::GetProjectionRef();
     582                 : }
     583                 : 
     584                 : /************************************************************************/
     585                 : /*                          GetGeoTransform()                           */
     586                 : /************************************************************************/
     587                 : 
     588               7 : CPLErr JP2OpenJPEGDataset::GetGeoTransform( double * padfTransform )
     589                 : {
     590               7 :     if( bGeoTransformValid )
     591                 :     {
     592               5 :         memcpy( padfTransform, adfGeoTransform, sizeof(adfGeoTransform[0]) * 6 );
     593               5 :         return CE_None;
     594                 :     }
     595                 :     else
     596               2 :         return GDALPamDataset::GetGeoTransform(padfTransform);
     597                 : }
     598                 : 
     599                 : /************************************************************************/
     600                 : /*                            GetGCPCount()                             */
     601                 : /************************************************************************/
     602                 : 
     603               3 : int JP2OpenJPEGDataset::GetGCPCount()
     604                 : 
     605                 : {
     606               3 :     if( nGCPCount > 0 )
     607               1 :         return nGCPCount;
     608                 :     else
     609               2 :         return GDALPamDataset::GetGCPCount();
     610                 : }
     611                 : 
     612                 : /************************************************************************/
     613                 : /*                          GetGCPProjection()                          */
     614                 : /************************************************************************/
     615                 : 
     616               1 : const char *JP2OpenJPEGDataset::GetGCPProjection()
     617                 : 
     618                 : {
     619               1 :     if( nGCPCount > 0 )
     620               1 :         return pszProjection;
     621                 :     else
     622               0 :         return GDALPamDataset::GetGCPProjection();
     623                 : }
     624                 : 
     625                 : /************************************************************************/
     626                 : /*                               GetGCP()                               */
     627                 : /************************************************************************/
     628                 : 
     629               1 : const GDAL_GCP *JP2OpenJPEGDataset::GetGCPs()
     630                 : 
     631                 : {
     632               1 :     if( nGCPCount > 0 )
     633               1 :         return pasGCPList;
     634                 :     else
     635               0 :         return GDALPamDataset::GetGCPs();
     636                 : }
     637                 : 
     638                 : /************************************************************************/
     639                 : /*                            Identify()                                */
     640                 : /************************************************************************/
     641                 : 
     642           11003 : int JP2OpenJPEGDataset::Identify( GDALOpenInfo * poOpenInfo )
     643                 : 
     644                 : {
     645                 :     static const unsigned char jpc_header[] = {0xff,0x4f};
     646                 :     static const unsigned char jp2_box_jp[] = {0x6a,0x50,0x20,0x20}; /* 'jP  ' */
     647                 :         
     648           11003 :     if( poOpenInfo->nHeaderBytes >= 16 
     649                 :         && (memcmp( poOpenInfo->pabyHeader, jpc_header, 
     650                 :                     sizeof(jpc_header) ) == 0
     651                 :             || memcmp( poOpenInfo->pabyHeader + 4, jp2_box_jp, 
     652                 :                     sizeof(jp2_box_jp) ) == 0
     653                 :            ) )
     654              25 :         return TRUE;
     655                 :     
     656                 :     else
     657           10978 :         return FALSE;
     658                 : }
     659                 : /************************************************************************/
     660                 : /*                                Open()                                */
     661                 : /************************************************************************/
     662                 : 
     663            1783 : GDALDataset *JP2OpenJPEGDataset::Open( GDALOpenInfo * poOpenInfo )
     664                 : 
     665                 : {
     666            1783 :     if (!Identify(poOpenInfo))
     667            1758 :         return NULL;
     668                 : 
     669              25 :     VSILFILE* fp = VSIFOpenL(poOpenInfo->pszFilename, "rb");
     670              25 :     if (!fp)
     671               0 :         return NULL;
     672                 : 
     673                 :     OPJ_CODEC_FORMAT eCodecFormat;
     674                 : 
     675                 :     /* Detect which codec to use : J2K or JP2 ? */
     676                 :     static const unsigned char jpc_header[] = {0xff,0x4f};
     677              25 :     if (memcmp( poOpenInfo->pabyHeader, jpc_header, 
     678                 :                     sizeof(jpc_header) ) == 0)
     679              13 :         eCodecFormat = CODEC_J2K;
     680                 :     else
     681              12 :         eCodecFormat = CODEC_JP2;
     682                 : 
     683              25 :     opj_codec_t* pCodec = opj_create_decompress(eCodecFormat);
     684                 : 
     685              25 :     opj_set_info_handler(pCodec, JP2OpenJPEGDataset_InfoCallback,NULL);
     686              25 :     opj_set_warning_handler(pCodec, JP2OpenJPEGDataset_WarningCallback,NULL);
     687              25 :     opj_set_error_handler(pCodec, JP2OpenJPEGDataset_ErrorCallback,NULL);
     688                 : 
     689                 :     opj_dparameters_t parameters;
     690              25 :     opj_set_default_decoder_parameters(&parameters);
     691                 : 
     692              25 :     if (! opj_setup_decoder(pCodec,&parameters))
     693                 :     {
     694               0 :         VSIFCloseL(fp);
     695               0 :         return NULL;
     696                 :     }
     697                 : 
     698                 :     opj_stream_t * pStream;
     699              25 :     pStream = opj_stream_create(1024, TRUE); // Default 1MB is way too big for some datasets
     700              25 :     opj_stream_set_read_function(pStream, JP2OpenJPEGDataset_Read);
     701              25 :     opj_stream_set_seek_function(pStream, JP2OpenJPEGDataset_Seek);
     702              25 :     opj_stream_set_skip_function(pStream, JP2OpenJPEGDataset_Skip);
     703              25 :     opj_stream_set_user_data(pStream, fp);
     704                 : 
     705              25 :     opj_image_t * psImage = NULL;
     706                 :     OPJ_INT32  nX0,nY0;
     707                 :     OPJ_UINT32 nTileW,nTileH,nTilesX,nTilesY;
     708              25 :     if(!opj_read_header(pCodec, &psImage, &nX0, &nY0, &nTileW, &nTileH,
     709                 :                         &nTilesX, &nTilesY, pStream))
     710                 :     {
     711               0 :         CPLError(CE_Failure, CPLE_AppDefined, "opj_read_header() failed");
     712               0 :         opj_destroy_codec(pCodec);
     713               0 :         opj_stream_destroy(pStream);
     714               0 :         opj_image_destroy(psImage);
     715               0 :         VSIFCloseL(fp);
     716               0 :         return NULL;
     717                 :     }
     718                 :     
     719              25 :     if (psImage == NULL)
     720                 :     {
     721               0 :         opj_destroy_codec(pCodec);
     722               0 :         opj_stream_destroy(pStream);
     723               0 :         opj_image_destroy(psImage);
     724               0 :         VSIFCloseL(fp);
     725               0 :         return NULL;
     726                 :     }
     727                 : 
     728                 : #ifdef DEBUG
     729                 :     int i;
     730              25 :     CPLDebug("OPENJPEG", "nX0 = %d", nX0);
     731              25 :     CPLDebug("OPENJPEG", "nY0 = %d", nY0);
     732              25 :     CPLDebug("OPENJPEG", "nTileW = %d", nTileW);
     733              25 :     CPLDebug("OPENJPEG", "nTileH = %d", nTileH);
     734              25 :     CPLDebug("OPENJPEG", "psImage->x0 = %d", psImage->x0);
     735              25 :     CPLDebug("OPENJPEG", "psImage->y0 = %d", psImage->y0);
     736              25 :     CPLDebug("OPENJPEG", "psImage->x1 = %d", psImage->x1);
     737              25 :     CPLDebug("OPENJPEG", "psImage->y1 = %d", psImage->y1);
     738              25 :     CPLDebug("OPENJPEG", "psImage->numcomps = %d", psImage->numcomps);
     739              25 :     CPLDebug("OPENJPEG", "psImage->color_space = %d", psImage->color_space);
     740              67 :     for(i=0;i<(int)psImage->numcomps;i++)
     741                 :     {
     742              42 :         CPLDebug("OPENJPEG", "psImage->comps[%d].dx = %d", i, psImage->comps[i].dx);
     743              42 :         CPLDebug("OPENJPEG", "psImage->comps[%d].dy = %d", i, psImage->comps[i].dy);
     744              42 :         CPLDebug("OPENJPEG", "psImage->comps[%d].x0 = %d", i, psImage->comps[i].x0);
     745              42 :         CPLDebug("OPENJPEG", "psImage->comps[%d].y0 = %d", i, psImage->comps[i].y0);
     746              42 :         CPLDebug("OPENJPEG", "psImage->comps[%d].w = %d", i, psImage->comps[i].w);
     747              42 :         CPLDebug("OPENJPEG", "psImage->comps[%d].h = %d", i, psImage->comps[i].h);
     748              42 :         CPLDebug("OPENJPEG", "psImage->comps[%d].factor = %d", i, psImage->comps[i].factor);
     749              42 :         CPLDebug("OPENJPEG", "psImage->comps[%d].prec = %d", i, psImage->comps[i].prec);
     750              42 :         CPLDebug("OPENJPEG", "psImage->comps[%d].sgnd = %d", i, psImage->comps[i].sgnd);
     751                 :     }
     752                 : #endif
     753                 : 
     754              75 :     if (psImage->x1 - psImage->x0 <= 0 ||
     755                 :         psImage->y1 - psImage->y0 <= 0 ||
     756                 :         psImage->numcomps == 0 ||
     757              25 :         (int)psImage->comps[0].w != psImage->x1 - psImage->x0 ||
     758              25 :         (int)psImage->comps[0].h != psImage->y1 - psImage->y0)
     759                 :     {
     760               0 :         opj_destroy_codec(pCodec);
     761               0 :         opj_stream_destroy(pStream);
     762               0 :         opj_image_destroy(psImage);
     763               0 :         VSIFCloseL(fp);
     764               0 :         return NULL;
     765                 :     }
     766                 : 
     767              25 :     GDALDataType eDataType = GDT_Byte;
     768              25 :     if (psImage->comps[0].prec > 16)
     769                 :     {
     770               0 :         if (psImage->comps[0].sgnd)
     771               0 :             eDataType = GDT_Int32;
     772                 :         else
     773               0 :             eDataType = GDT_UInt32;
     774                 :     }
     775              25 :     else if (psImage->comps[0].prec > 8)
     776                 :     {
     777               8 :         if (psImage->comps[0].sgnd)
     778               5 :             eDataType = GDT_Int16;
     779                 :         else
     780               3 :             eDataType = GDT_UInt16;
     781                 :     }
     782                 : 
     783                 :     int bIs420  =  (psImage->color_space != CLRSPC_SRGB &&
     784                 :                     eDataType == GDT_Byte &&
     785                 :                     psImage->numcomps == 3 &&
     786              14 :                     psImage->comps[1].w == psImage->comps[0].w / 2 &&
     787               2 :                     psImage->comps[1].h == psImage->comps[0].h / 2 &&
     788               2 :                     psImage->comps[2].w == psImage->comps[0].w / 2 &&
     789              43 :                     psImage->comps[2].h == psImage->comps[0].h / 2);
     790                 : 
     791              25 :     if (bIs420)
     792                 :     {
     793               1 :         CPLDebug("OPENJPEG", "420 format");
     794                 :     }
     795                 :     else
     796                 :     {
     797                 :         int iBand;
     798              38 :         for(iBand = 2; iBand <= (int)psImage->numcomps; iBand ++)
     799                 :         {
     800              75 :             if (psImage->comps[iBand-1].w != psImage->comps[0].w ||
     801              30 :                 psImage->comps[iBand-1].h != psImage->comps[0].h ||
     802              30 :                 psImage->comps[iBand-1].prec != psImage->comps[0].prec)
     803                 :             {
     804               1 :                 opj_destroy_codec(pCodec);
     805               1 :                 opj_stream_destroy(pStream);
     806               1 :                 opj_image_destroy(psImage);
     807               1 :                 VSIFCloseL(fp);
     808               1 :                 return NULL;
     809                 :             }
     810                 :         }
     811                 :     }
     812                 : 
     813                 : 
     814                 : /* -------------------------------------------------------------------- */
     815                 : /*      Create a corresponding GDALDataset.                             */
     816                 : /* -------------------------------------------------------------------- */
     817                 :     JP2OpenJPEGDataset     *poDS;
     818                 :     int                 iBand;
     819                 : 
     820              24 :     poDS = new JP2OpenJPEGDataset();
     821              24 :     poDS->eCodecFormat = eCodecFormat;
     822              24 :     poDS->eColorSpace = psImage->color_space;
     823              24 :     poDS->nRasterXSize = psImage->x1 - psImage->x0;
     824              24 :     poDS->nRasterYSize = psImage->y1 - psImage->y0;
     825              24 :     poDS->nBands = psImage->numcomps;
     826              24 :     poDS->fp = fp;
     827              24 :     poDS->bIs420 = bIs420;
     828                 : 
     829              24 :     opj_end_decompress(pCodec,pStream);
     830              24 :     opj_stream_destroy(pStream);
     831              24 :     opj_destroy_codec(pCodec);
     832              24 :     opj_image_destroy(psImage);
     833                 : 
     834                 : /* -------------------------------------------------------------------- */
     835                 : /*      Create band information objects.                                */
     836                 : /* -------------------------------------------------------------------- */
     837             124 :     for( iBand = 1; iBand <= poDS->nBands; iBand++ )
     838                 :     {
     839                 :         poDS->SetBand( iBand, new JP2OpenJPEGRasterBand( poDS, iBand, eDataType,
     840              38 :                                                       nTileW, nTileH) );
     841                 :     }
     842                 : 
     843                 : /* -------------------------------------------------------------------- */
     844                 : /*      More metadata.                                                  */
     845                 : /* -------------------------------------------------------------------- */
     846              24 :     if( poDS->nBands > 1 )
     847                 :     {
     848               7 :         poDS->SetMetadataItem( "INTERLEAVE", "PIXEL", "IMAGE_STRUCTURE" );
     849                 :     }
     850                 : 
     851                 : /* -------------------------------------------------------------------- */
     852                 : /*      Check for georeferencing information.                           */
     853                 : /* -------------------------------------------------------------------- */
     854              24 :     GDALJP2Metadata oJP2Geo;
     855                 : 
     856              24 :     if( oJP2Geo.ReadAndParse( poOpenInfo->pszFilename ) )
     857                 :     {
     858              10 :         if ( poDS->pszProjection )
     859              10 :             CPLFree( poDS->pszProjection );
     860              10 :         poDS->pszProjection = CPLStrdup(oJP2Geo.pszProjection);
     861              10 :         poDS->bGeoTransformValid = oJP2Geo.bHaveGeoTransform;
     862                 :         memcpy( poDS->adfGeoTransform, oJP2Geo.adfGeoTransform, 
     863              10 :                 sizeof(double) * 6 );
     864              10 :         poDS->nGCPCount = oJP2Geo.nGCPCount;
     865                 :         poDS->pasGCPList =
     866              10 :             GDALDuplicateGCPs( oJP2Geo.nGCPCount, oJP2Geo.pasGCPList );
     867                 :     }
     868                 : 
     869              24 :     if (oJP2Geo.pszXMPMetadata)
     870                 :     {
     871                 :         char *apszMDList[2];
     872               1 :         apszMDList[0] = (char *) oJP2Geo.pszXMPMetadata;
     873               1 :         apszMDList[1] = NULL;
     874               1 :         poDS->SetMetadata(apszMDList, "xml:XMP");
     875                 :     }
     876                 : /* -------------------------------------------------------------------- */
     877                 : /*      Initialize any PAM information.                                 */
     878                 : /* -------------------------------------------------------------------- */
     879              24 :     poDS->SetDescription( poOpenInfo->pszFilename );
     880              24 :     poDS->TryLoadXML();
     881                 : 
     882                 : /* -------------------------------------------------------------------- */
     883                 : /*      Check for overviews.                                            */
     884                 : /* -------------------------------------------------------------------- */
     885              24 :     poDS->oOvManager.Initialize( poDS, poOpenInfo->pszFilename );
     886                 : 
     887              24 :     return( poDS );
     888                 : }
     889                 : 
     890                 : /************************************************************************/
     891                 : /*                          CreateCopy()                                */
     892                 : /************************************************************************/
     893                 : 
     894              20 : GDALDataset * JP2OpenJPEGDataset::CreateCopy( const char * pszFilename,
     895                 :                                            GDALDataset *poSrcDS, 
     896                 :                                            int bStrict, char ** papszOptions, 
     897                 :                                            GDALProgressFunc pfnProgress,
     898                 :                                            void * pProgressData )
     899                 : 
     900                 : {
     901              20 :     int  nBands = poSrcDS->GetRasterCount();
     902              20 :     int  nXSize = poSrcDS->GetRasterXSize();
     903              20 :     int  nYSize = poSrcDS->GetRasterYSize();
     904                 : 
     905              20 :     if( nBands != 1 && nBands != 3 )
     906                 :     {
     907                 :         CPLError( CE_Failure, CPLE_NotSupported,
     908               4 :                   "Unable to export files with %d bands.", nBands );
     909               4 :         return NULL;
     910                 :     }
     911                 : 
     912              16 :     if (poSrcDS->GetRasterBand(1)->GetColorTable() != NULL)
     913                 :     {
     914                 :         CPLError( (bStrict) ? CE_Failure : CE_Warning, CPLE_NotSupported, 
     915                 :                   "JP2OpenJPEG driver ignores color table. "
     916                 :                   "The source raster band will be considered as grey level.\n"
     917               0 :                   "Consider using color table expansion (-expand option in gdal_translate)\n");
     918               0 :         if (bStrict)
     919               0 :             return NULL;
     920                 :     }
     921                 : 
     922              16 :     GDALDataType eDataType = poSrcDS->GetRasterBand(1)->GetRasterDataType();
     923              16 :     int nDataTypeSize = (GDALGetDataTypeSize(eDataType) / 8);
     924              16 :     if (eDataType != GDT_Byte && eDataType != GDT_Int16 && eDataType != GDT_UInt16
     925                 :         && eDataType != GDT_Int32 && eDataType != GDT_UInt32)
     926                 :     {
     927                 :         CPLError( CE_Failure, CPLE_NotSupported,
     928               6 :                   "JP2OpenJPEG driver only supports creating Byte, GDT_Int16, GDT_UInt16, GDT_Int32, GDT_UInt32");
     929               6 :         return NULL;
     930                 :     }
     931                 : 
     932                 : /* -------------------------------------------------------------------- */
     933                 : /*      Analyze creation options.                                       */
     934                 : /* -------------------------------------------------------------------- */
     935              10 :     OPJ_CODEC_FORMAT eCodecFormat = CODEC_J2K;
     936              10 :     const char* pszCodec = CSLFetchNameValueDef(papszOptions, "CODEC", NULL);
     937              10 :     if (pszCodec)
     938                 :     {
     939               0 :         if (EQUAL(pszCodec, "JP2"))
     940               0 :             eCodecFormat = CODEC_JP2;
     941               0 :         else if (EQUAL(pszCodec, "J2K"))
     942               0 :             eCodecFormat = CODEC_J2K;
     943                 :         else
     944                 :         {
     945                 :             CPLError(CE_Warning, CPLE_NotSupported,
     946                 :                     "Unsupported value for CODEC : %s. Defaulting to J2K",
     947               0 :                     pszCodec);
     948                 :         }
     949                 :     }
     950                 :     else
     951                 :     {
     952              10 :         if (strlen(pszFilename) > 4 &&
     953                 :             EQUAL(pszFilename + strlen(pszFilename) - 4, ".JP2"))
     954                 :         {
     955               0 :             eCodecFormat = CODEC_JP2;
     956                 :         }
     957                 :     }
     958                 : 
     959                 :     int nBlockXSize =
     960              10 :         atoi(CSLFetchNameValueDef(papszOptions, "BLOCKXSIZE", "1024"));
     961                 :     int nBlockYSize =
     962              10 :         atoi(CSLFetchNameValueDef(papszOptions, "BLOCKYSIZE", "1024"));
     963              10 :     if (nBlockXSize < 32 || nBlockYSize < 32)
     964                 :     {
     965               0 :         CPLError(CE_Failure, CPLE_NotSupported, "Invalid block size");
     966               0 :         return NULL;
     967                 :     }
     968                 : 
     969              10 :     if (nXSize < nBlockXSize)
     970               8 :         nBlockXSize = nXSize;
     971              10 :     if (nYSize < nBlockYSize)
     972               8 :         nBlockYSize = nYSize;
     973                 : 
     974              10 :     OPJ_PROG_ORDER eProgOrder = LRCP;
     975                 :     const char* pszPROGORDER =
     976              10 :             CSLFetchNameValueDef(papszOptions, "PROGRESSION", "LRCP");
     977              10 :     if (EQUAL(pszPROGORDER, "LRCP"))
     978              10 :         eProgOrder = LRCP;
     979               0 :     else if (EQUAL(pszPROGORDER, "RLCP"))
     980               0 :         eProgOrder = RLCP;
     981               0 :     else if (EQUAL(pszPROGORDER, "RPCL"))
     982               0 :         eProgOrder = RPCL;
     983               0 :     else if (EQUAL(pszPROGORDER, "PCRL"))
     984               0 :         eProgOrder = PCRL;
     985               0 :     else if (EQUAL(pszPROGORDER, "CPRL"))
     986               0 :         eProgOrder = CPRL;
     987                 :     else
     988                 :     {
     989                 :         CPLError(CE_Warning, CPLE_NotSupported,
     990                 :                  "Unsupported value for PROGRESSION : %s. Defaulting to LRCP",
     991               0 :                  pszPROGORDER);
     992                 :     }
     993                 : 
     994                 :     int bIsIrreversible =
     995              10 :             ! (CSLTestBoolean(CSLFetchNameValueDef(papszOptions, "REVERSIBLE", "NO")));
     996                 : 
     997              10 :     double dfRate = 100. / 25;
     998              10 :     const char* pszQuality = CSLFetchNameValueDef(papszOptions, "QUALITY", NULL);
     999              10 :     if (pszQuality)
    1000                 :     {
    1001               2 :         double dfQuality = atof(pszQuality);
    1002               4 :         if (dfQuality > 0 && dfQuality <= 100)
    1003                 :         {
    1004               2 :             dfRate = 100 / dfQuality;
    1005                 :         }
    1006                 :         else
    1007                 :         {
    1008                 :             CPLError(CE_Warning, CPLE_NotSupported,
    1009                 :                  "Unsupported value for QUALITY : %s. Defaulting to 25",
    1010               0 :                  pszQuality);
    1011                 :         }
    1012                 :     }
    1013                 : 
    1014              10 :     int nNumResolutions = 6;
    1015              10 :     const char* pszResolutions = CSLFetchNameValueDef(papszOptions, "RESOLUTIONS", NULL);
    1016              10 :     if (pszResolutions)
    1017                 :     {
    1018               1 :         nNumResolutions = atoi(pszResolutions);
    1019               1 :         if (nNumResolutions < 1 || nNumResolutions > 7)
    1020                 :         {
    1021               0 :             nNumResolutions = 6;
    1022                 :             CPLError(CE_Warning, CPLE_NotSupported,
    1023                 :                  "Unsupported value for RESOLUTIONS : %s. Defaulting to 6",
    1024               0 :                  pszResolutions);
    1025                 :         }
    1026                 :     }
    1027                 :     
    1028              10 :     int bSOP = CSLTestBoolean(CSLFetchNameValueDef(papszOptions, "SOP", "FALSE"));
    1029              10 :     int bEPH = CSLTestBoolean(CSLFetchNameValueDef(papszOptions, "EPH", "FALSE"));
    1030                 :     
    1031                 :     int bResample = nBands == 3 && eDataType == GDT_Byte &&
    1032              10 :             CSLTestBoolean(CSLFetchNameValueDef(papszOptions, "YCBCR420", "FALSE"));
    1033              10 :     if (bResample && !((nXSize % 2) == 0 && (nYSize % 2) == 0 && (nBlockXSize % 2) == 0 && (nBlockYSize % 2) == 0))
    1034                 :     {
    1035                 :         CPLError(CE_Warning, CPLE_NotSupported,
    1036               0 :                  "YCBCR420 unsupported when image size and/or tile size are not multiple of 2");
    1037               0 :         bResample = FALSE;
    1038                 :     }
    1039                 : 
    1040                 : /* -------------------------------------------------------------------- */
    1041                 : /*      Setup encoder                                                  */
    1042                 : /* -------------------------------------------------------------------- */
    1043                 : 
    1044                 :     opj_cparameters_t parameters;
    1045              10 :     opj_set_default_encoder_parameters(&parameters);
    1046              10 :     if (bSOP)
    1047               0 :         parameters.csty |= 0x02;
    1048              10 :     if (bEPH)
    1049               0 :         parameters.csty |= 0x04;
    1050              10 :     parameters.cp_disto_alloc = 1;
    1051              10 :     parameters.tcp_numlayers = 1;
    1052              10 :     parameters.tcp_rates[0] = (float) dfRate;
    1053              10 :     parameters.cp_tx0 = 0;
    1054              10 :     parameters.cp_ty0 = 0;
    1055              10 :     parameters.tile_size_on = TRUE;
    1056              10 :     parameters.cp_tdx = nBlockXSize;
    1057              10 :     parameters.cp_tdy = nBlockYSize;
    1058              10 :     parameters.irreversible = bIsIrreversible;
    1059              10 :     parameters.numresolution = nNumResolutions;
    1060              10 :     parameters.prog_order = eProgOrder;
    1061                 : 
    1062                 :     opj_image_cmptparm_t* pasBandParams =
    1063              10 :             (opj_image_cmptparm_t*)CPLMalloc(nBands * sizeof(opj_image_cmptparm_t));
    1064                 :     int iBand;
    1065              22 :     for(iBand=0;iBand<nBands;iBand++)
    1066                 :     {
    1067              12 :         pasBandParams[iBand].x0 = 0;
    1068              12 :         pasBandParams[iBand].y0 = 0;
    1069              12 :         if (bResample && iBand > 0)
    1070                 :         {
    1071               0 :             pasBandParams[iBand].dx = 2;
    1072               0 :             pasBandParams[iBand].dy = 2;
    1073               0 :             pasBandParams[iBand].w = nXSize / 2;
    1074               0 :             pasBandParams[iBand].h = nYSize / 2;
    1075                 :         }
    1076                 :         else
    1077                 :         {
    1078              12 :             pasBandParams[iBand].dx = 1;
    1079              12 :             pasBandParams[iBand].dy = 1;
    1080              12 :             pasBandParams[iBand].w = nXSize;
    1081              12 :             pasBandParams[iBand].h = nYSize;
    1082                 :         }
    1083              12 :         pasBandParams[iBand].sgnd = (eDataType == GDT_Int16 || eDataType == GDT_Int32);
    1084              12 :         pasBandParams[iBand].prec = 8 * nDataTypeSize;
    1085                 :     }
    1086                 : 
    1087              10 :     opj_codec_t* pCodec = opj_create_compress(eCodecFormat);
    1088              10 :     if (pCodec == NULL)
    1089                 :     {
    1090                 :         CPLError(CE_Failure, CPLE_AppDefined,
    1091               0 :                  "opj_create_compress() failed");
    1092               0 :         CPLFree(pasBandParams);
    1093               0 :         return NULL;
    1094                 :     }
    1095                 : 
    1096              10 :     opj_set_info_handler(pCodec, JP2OpenJPEGDataset_InfoCallback,NULL);
    1097              10 :     opj_set_warning_handler(pCodec, JP2OpenJPEGDataset_WarningCallback,NULL);
    1098              10 :     opj_set_error_handler(pCodec, JP2OpenJPEGDataset_ErrorCallback,NULL);
    1099                 : 
    1100              10 :     OPJ_COLOR_SPACE eColorSpace = (bResample) ? CLRSPC_SYCC : (nBands == 3) ? CLRSPC_SRGB : CLRSPC_GRAY;
    1101                 :     opj_image_t* psImage = opj_image_tile_create(nBands,pasBandParams,
    1102              10 :                                                  eColorSpace);
    1103              10 :     CPLFree(pasBandParams);
    1104              10 :     pasBandParams = NULL;
    1105              10 :     if (psImage == NULL)
    1106                 :     {
    1107                 :         CPLError(CE_Failure, CPLE_AppDefined,
    1108               0 :                  "opj_image_tile_create() failed");
    1109               0 :         opj_destroy_codec(pCodec);
    1110               0 :         return NULL;
    1111                 :     }
    1112                 : 
    1113              10 :     psImage->x0 = 0;
    1114              10 :     psImage->y0 = 0;
    1115              10 :     psImage->x1 = nXSize;
    1116              10 :     psImage->y1 = nYSize;
    1117              10 :     psImage->color_space = eColorSpace;
    1118              10 :     psImage->numcomps = nBands;
    1119                 : 
    1120              10 :     if (!opj_setup_encoder(pCodec,&parameters,psImage))
    1121                 :     {
    1122                 :         CPLError(CE_Failure, CPLE_AppDefined,
    1123               0 :                  "opj_setup_encoder() failed");
    1124               0 :         opj_image_destroy(psImage);
    1125               0 :         opj_destroy_codec(pCodec);
    1126               0 :         return NULL;
    1127                 :     }
    1128                 : 
    1129                 : /* -------------------------------------------------------------------- */
    1130                 : /*      Create the dataset.                                             */
    1131                 : /* -------------------------------------------------------------------- */
    1132                 : 
    1133              10 :     const char* pszAccess = EQUALN(pszFilename, "/vsisubfile/", 12) ? "r+b" : "w+b";
    1134              10 :     VSILFILE* fp = VSIFOpenL(pszFilename, pszAccess);
    1135              10 :     if (fp == NULL)
    1136                 :     {
    1137               2 :         CPLError(CE_Failure, CPLE_AppDefined, "Cannot create file");
    1138               2 :         opj_image_destroy(psImage);
    1139               2 :         opj_destroy_codec(pCodec);
    1140               2 :         return NULL;
    1141                 :     }
    1142                 : 
    1143                 :     opj_stream_t * pStream;
    1144               8 :     pStream = opj_stream_create(1024*1024, FALSE);
    1145               8 :     opj_stream_set_write_function(pStream, JP2OpenJPEGDataset_Write);
    1146               8 :     opj_stream_set_seek_function(pStream, JP2OpenJPEGDataset_Seek);
    1147               8 :     opj_stream_set_skip_function(pStream, JP2OpenJPEGDataset_Skip);
    1148               8 :     opj_stream_set_user_data(pStream, fp);
    1149                 : 
    1150               8 :     if (!opj_start_compress(pCodec,psImage,pStream))
    1151                 :     {
    1152                 :         CPLError(CE_Failure, CPLE_AppDefined,
    1153               6 :                  "opj_start_compress() failed");
    1154               6 :         opj_stream_destroy(pStream);
    1155               6 :         opj_image_destroy(psImage);
    1156               6 :         opj_destroy_codec(pCodec);
    1157               6 :         VSIFCloseL(fp);
    1158               6 :         return NULL;
    1159                 :     }
    1160                 : 
    1161               2 :     int nTilesX = (nXSize + nBlockXSize - 1) / nBlockXSize;
    1162               2 :     int nTilesY = (nYSize + nBlockYSize - 1) / nBlockYSize;
    1163                 : 
    1164                 :     GByte* pTempBuffer =(GByte*)VSIMalloc(nBlockXSize * nBlockYSize *
    1165               2 :                                           nBands * nDataTypeSize);
    1166               2 :     if (pTempBuffer == NULL)
    1167                 :     {
    1168               0 :         opj_stream_destroy(pStream);
    1169               0 :         opj_image_destroy(psImage);
    1170               0 :         opj_destroy_codec(pCodec);
    1171               0 :         VSIFCloseL(fp);
    1172               0 :         return NULL;
    1173                 :     }
    1174                 : 
    1175               2 :     GByte* pYUV420Buffer = NULL;
    1176               2 :     if (bResample)
    1177                 :     {
    1178               0 :         pYUV420Buffer =(GByte*)VSIMalloc(3 * nBlockXSize * nBlockYSize / 2);
    1179               0 :         if (pYUV420Buffer == NULL)
    1180                 :         {
    1181               0 :             opj_stream_destroy(pStream);
    1182               0 :             opj_image_destroy(psImage);
    1183               0 :             opj_destroy_codec(pCodec);
    1184               0 :             CPLFree(pTempBuffer);
    1185               0 :             VSIFCloseL(fp);
    1186               0 :             return NULL;
    1187                 :         }
    1188                 :     }
    1189                 : 
    1190                 : /* -------------------------------------------------------------------- */
    1191                 : /*      Iterate over the tiles                                          */
    1192                 : /* -------------------------------------------------------------------- */
    1193               2 :     pfnProgress( 0.0, NULL, pProgressData );
    1194                 : 
    1195               2 :     CPLErr eErr = CE_None;
    1196                 :     int nBlockXOff, nBlockYOff;
    1197               2 :     int iTile = 0;
    1198               4 :     for(nBlockYOff=0;eErr == CE_None && nBlockYOff<nTilesY;nBlockYOff++)
    1199                 :     {
    1200               4 :         for(nBlockXOff=0;eErr == CE_None && nBlockXOff<nTilesX;nBlockXOff++)
    1201                 :         {
    1202               2 :             int nWidthToRead = MIN(nBlockXSize, nXSize - nBlockXOff * nBlockXSize);
    1203               2 :             int nHeightToRead = MIN(nBlockYSize, nYSize - nBlockYOff * nBlockYSize);
    1204                 :             eErr = poSrcDS->RasterIO(GF_Read,
    1205                 :                                      nBlockXOff * nBlockXSize,
    1206                 :                                      nBlockYOff * nBlockYSize,
    1207                 :                                      nWidthToRead, nHeightToRead,
    1208                 :                                      pTempBuffer, nWidthToRead, nHeightToRead,
    1209                 :                                      eDataType,
    1210                 :                                      nBands, NULL,
    1211               2 :                                      0,0,0);
    1212               2 :             if (eErr == CE_None)
    1213                 :             {
    1214               2 :                 if (bResample)
    1215                 :                 {
    1216                 :                     int j, i;
    1217               0 :                     for(j=0;j<nHeightToRead;j++)
    1218                 :                     {
    1219               0 :                         for(i=0;i<nWidthToRead;i++)
    1220                 :                         {
    1221               0 :                             int R = pTempBuffer[j*nWidthToRead+i];
    1222               0 :                             int G = pTempBuffer[nHeightToRead*nWidthToRead + j*nWidthToRead+i];
    1223               0 :                             int B = pTempBuffer[2*nHeightToRead*nWidthToRead + j*nWidthToRead+i];
    1224               0 :                             int Y = (int) (0.299 * R + 0.587 * G + 0.114 * B);
    1225               0 :                             int Cb = CLAMP_0_255((int) (-0.1687 * R - 0.3313 * G + 0.5 * B  + 128));
    1226               0 :                             int Cr = CLAMP_0_255((int) (0.5 * R - 0.4187 * G - 0.0813 * B  + 128));
    1227               0 :                             pYUV420Buffer[j*nWidthToRead+i] = (GByte) Y;
    1228               0 :                             pYUV420Buffer[nHeightToRead * nWidthToRead + ((j/2) * ((nWidthToRead)/2) + i/2) ] = (GByte) Cb;
    1229               0 :                             pYUV420Buffer[5 * nHeightToRead * nWidthToRead / 4 + ((j/2) * ((nWidthToRead)/2) + i/2) ] = (GByte) Cr;
    1230                 :                         }
    1231                 :                     }
    1232                 : 
    1233               0 :                     if (!opj_write_tile(pCodec,
    1234                 :                                         iTile,
    1235                 :                                         pYUV420Buffer,
    1236                 :                                         3 * nWidthToRead * nHeightToRead / 2,
    1237                 :                                         pStream))
    1238                 :                     {
    1239                 :                         CPLError(CE_Failure, CPLE_AppDefined,
    1240               0 :                                 "opj_write_tile() failed");
    1241               0 :                         eErr = CE_Failure;
    1242                 :                     }
    1243                 :                 }
    1244                 :                 else
    1245                 :                 {
    1246               2 :                     if (!opj_write_tile(pCodec,
    1247                 :                                         iTile,
    1248                 :                                         pTempBuffer,
    1249                 :                                         nWidthToRead * nHeightToRead * nBands * nDataTypeSize,
    1250                 :                                         pStream))
    1251                 :                     {
    1252                 :                         CPLError(CE_Failure, CPLE_AppDefined,
    1253               0 :                                 "opj_write_tile() failed");
    1254               0 :                         eErr = CE_Failure;
    1255                 :                     }
    1256                 :                 }
    1257                 :             }
    1258                 : 
    1259               2 :             if( !pfnProgress( (iTile + 1) * 1.0 / (nTilesX * nTilesY), NULL, pProgressData ) )
    1260               0 :                 eErr = CE_Failure;
    1261                 : 
    1262               2 :             iTile ++;
    1263                 :         }
    1264                 :     }
    1265                 : 
    1266               2 :     VSIFree(pTempBuffer);
    1267               2 :     VSIFree(pYUV420Buffer);
    1268                 : 
    1269               2 :     if (eErr != CE_None)
    1270                 :     {
    1271               0 :         opj_stream_destroy(pStream);
    1272               0 :         opj_image_destroy(psImage);
    1273               0 :         opj_destroy_codec(pCodec);
    1274               0 :         VSIFCloseL(fp);
    1275               0 :         return NULL;
    1276                 :     }
    1277                 : 
    1278               2 :     if (!opj_end_compress(pCodec,pStream))
    1279                 :     {
    1280                 :         CPLError(CE_Failure, CPLE_AppDefined,
    1281               0 :                  "opj_end_compress() failed");
    1282               0 :         opj_stream_destroy(pStream);
    1283               0 :         opj_image_destroy(psImage);
    1284               0 :         opj_destroy_codec(pCodec);
    1285               0 :         VSIFCloseL(fp);
    1286               0 :         return NULL;
    1287                 :     }
    1288                 : 
    1289               2 :     opj_stream_destroy(pStream);
    1290               2 :     opj_image_destroy(psImage);
    1291               2 :     opj_destroy_codec(pCodec);
    1292               2 :     VSIFCloseL(fp);
    1293                 : 
    1294                 : /* -------------------------------------------------------------------- */
    1295                 : /*      Re-open dataset, and copy any auxilary pam information.         */
    1296                 : /* -------------------------------------------------------------------- */
    1297               2 :     GDALOpenInfo oOpenInfo(pszFilename, GA_ReadOnly);
    1298               2 :     JP2OpenJPEGDataset *poDS = (JP2OpenJPEGDataset*) JP2OpenJPEGDataset::Open(&oOpenInfo);
    1299                 : 
    1300               2 :     if( poDS )
    1301               2 :         poDS->CloneInfo( poSrcDS, GCIF_PAM_DEFAULT );
    1302                 : 
    1303               2 :     return poDS;
    1304                 : }
    1305                 : 
    1306                 : /************************************************************************/
    1307                 : /*                      GDALRegister_JP2OpenJPEG()                      */
    1308                 : /************************************************************************/
    1309                 : 
    1310             558 : void GDALRegister_JP2OpenJPEG()
    1311                 : 
    1312                 : {
    1313                 :     GDALDriver  *poDriver;
    1314                 :     
    1315             558 :     if (! GDAL_CHECK_VERSION("JP2OpenJPEG driver"))
    1316               0 :         return;
    1317                 : 
    1318             558 :     if( GDALGetDriverByName( "JP2OpenJPEG" ) == NULL )
    1319                 :     {
    1320             537 :         poDriver = new GDALDriver();
    1321                 :         
    1322             537 :         poDriver->SetDescription( "JP2OpenJPEG" );
    1323                 :         poDriver->SetMetadataItem( GDAL_DMD_LONGNAME, 
    1324             537 :                                    "JPEG-2000 driver based on OpenJPEG library" );
    1325                 :         poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC, 
    1326             537 :                                    "frmt_jp2openjpeg.html" );
    1327             537 :         poDriver->SetMetadataItem( GDAL_DMD_MIMETYPE, "image/jp2" );
    1328             537 :         poDriver->SetMetadataItem( GDAL_DMD_EXTENSION, "jp2" );
    1329                 :         poDriver->SetMetadataItem( GDAL_DMD_CREATIONDATATYPES, 
    1330             537 :                                    "Byte Int16 UInt16 Int32 UInt32" );
    1331                 : 
    1332                 :         poDriver->SetMetadataItem( GDAL_DMD_CREATIONOPTIONLIST,
    1333                 : "<CreationOptionList>"
    1334                 : "   <Option name='CODEC' type='string-select' default='according to file extension. If unknown, default to J2K'>"
    1335                 : "       <Value>JP2</Value>"
    1336                 : "       <Value>J2K</Value>"
    1337                 : "   </Option>"
    1338                 : "   <Option name='QUALITY' type='float' description='Quality. 0-100' default='25'/>"
    1339                 : "   <Option name='REVERSIBLE' type='boolean' description='True if the compression is reversible' default='false'/>"
    1340                 : "   <Option name='RESOLUTIONS' type='int' description='Number of resolutions. 1-7' default='6'/>"
    1341                 : "   <Option name='BLOCKXSIZE' type='int' description='Tile Width' default='1024'/>"
    1342                 : "   <Option name='BLOCKYSIZE' type='int' description='Tile Height' default='1024'/>"
    1343                 : "   <Option name='PROGRESSION' type='string-select' default='LRCP'>"
    1344                 : "       <Value>LRCP</Value>"
    1345                 : "       <Value>RLCP</Value>"
    1346                 : "       <Value>RPCL</Value>"
    1347                 : "       <Value>PCRL</Value>"
    1348                 : "       <Value>CPRL</Value>"
    1349                 : "   </Option>"
    1350                 : "   <Option name='SOP' type='boolean' description='True to insert SOP markers' default='false'/>"
    1351                 : "   <Option name='EPH' type='boolean' description='True to insert EPH markers' default='false'/>"
    1352                 : "   <Option name='YCBCR420' type='boolean' description='if RGB must be resampled to YCbCr 4:2:0' default='false'/>"
    1353             537 : "</CreationOptionList>"  );
    1354                 : 
    1355             537 :         poDriver->SetMetadataItem( GDAL_DCAP_VIRTUALIO, "YES" );
    1356                 : 
    1357             537 :         poDriver->pfnIdentify = JP2OpenJPEGDataset::Identify;
    1358             537 :         poDriver->pfnOpen = JP2OpenJPEGDataset::Open;
    1359             537 :         poDriver->pfnCreateCopy = JP2OpenJPEGDataset::CreateCopy;
    1360                 : 
    1361             537 :         GetGDALDriverManager()->RegisterDriver( poDriver );
    1362                 :     }
    1363                 : }
    1364                 : 

Generated by: LCOV version 1.7