LCOV - code coverage report
Current view: directory - frmts/openjpeg - openjpegdataset.cpp (source / functions) Found Hit Coverage
Test: gdal_filtered.info Lines: 681 524 76.9 %
Date: 2012-04-28 Functions: 31 24 77.4 %

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

Generated by: LCOV version 1.7