LCOV - code coverage report
Current view: directory - frmts/jpeg2000 - jpeg2000dataset.cpp (source / functions) Found Hit Coverage
Test: gdal_filtered.info Lines: 446 333 74.7 %
Date: 2012-12-26 Functions: 23 17 73.9 %

       1                 : /******************************************************************************
       2                 :  * $Id: jpeg2000dataset.cpp 24513 2012-05-29 20:20:23Z rouault $
       3                 :  *
       4                 :  * Project:  JPEG-2000
       5                 :  * Purpose:  Partial implementation of the ISO/IEC 15444-1 standard
       6                 :  * Author:   Andrey Kiselev, dron@ak4719.spb.edu
       7                 :  *
       8                 :  ******************************************************************************
       9                 :  * Copyright (c) 2002, Andrey Kiselev <dron@ak4719.spb.edu>
      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                 : #include "gdal_pam.h"
      31                 : #include "cpl_string.h"
      32                 : #include "gdaljp2metadata.h"
      33                 : 
      34                 : #include <jasper/jasper.h>
      35                 : #include "jpeg2000_vsil_io.h"
      36                 : 
      37                 : CPL_CVSID("$Id: jpeg2000dataset.cpp 24513 2012-05-29 20:20:23Z rouault $");
      38                 : 
      39                 : CPL_C_START
      40                 : void    GDALRegister_JPEG2000(void);
      41                 : CPL_C_END
      42                 : 
      43                 : // XXX: Part of code below extracted from the JasPer internal headers and
      44                 : // must be in sync with JasPer version (this one works with JasPer 1.900.1)
      45                 : #define JP2_FTYP_MAXCOMPATCODES 32
      46                 : #define JP2_BOX_IHDR    0x69686472      /* Image Header */
      47                 : #define JP2_BOX_BPCC    0x62706363      /* Bits Per Component */
      48                 : #define JP2_BOX_PCLR  0x70636c72  /* Palette */
      49                 : #define JP2_BOX_UUID    0x75756964      /* UUID */
      50                 : extern "C" {
      51                 : typedef struct {
      52                 :         uint_fast32_t magic;
      53                 : } jp2_jp_t;
      54                 : typedef struct {
      55                 :         uint_fast32_t majver;
      56                 :         uint_fast32_t minver;
      57                 :         uint_fast32_t numcompatcodes;
      58                 :         uint_fast32_t compatcodes[JP2_FTYP_MAXCOMPATCODES];
      59                 : } jp2_ftyp_t;
      60                 : typedef struct {
      61                 :         uint_fast32_t width;
      62                 :         uint_fast32_t height;
      63                 :         uint_fast16_t numcmpts;
      64                 :         uint_fast8_t bpc;
      65                 :         uint_fast8_t comptype;
      66                 :         uint_fast8_t csunk;
      67                 :         uint_fast8_t ipr;
      68                 : } jp2_ihdr_t;
      69                 : typedef struct {
      70                 :         uint_fast16_t numcmpts;
      71                 :         uint_fast8_t *bpcs;
      72                 : } jp2_bpcc_t;
      73                 : typedef struct {
      74                 :         uint_fast8_t method;
      75                 :         uint_fast8_t pri;
      76                 :         uint_fast8_t approx;
      77                 :         uint_fast32_t csid;
      78                 :         uint_fast8_t *iccp;
      79                 :         int iccplen;
      80                 : } jp2_colr_t;
      81                 : typedef struct {
      82                 :         uint_fast16_t numlutents;
      83                 :         uint_fast8_t numchans;
      84                 :         int_fast32_t *lutdata;
      85                 :         uint_fast8_t *bpc;
      86                 : } jp2_pclr_t;
      87                 : typedef struct {
      88                 :         uint_fast16_t channo;
      89                 :         uint_fast16_t type;
      90                 :         uint_fast16_t assoc;
      91                 : } jp2_cdefchan_t;
      92                 : typedef struct {
      93                 :         uint_fast16_t numchans;
      94                 :         jp2_cdefchan_t *ents;
      95                 : } jp2_cdef_t;
      96                 : typedef struct {
      97                 :         uint_fast16_t cmptno;
      98                 :         uint_fast8_t map;
      99                 :         uint_fast8_t pcol;
     100                 : } jp2_cmapent_t;
     101                 : 
     102                 : typedef struct {
     103                 :         uint_fast16_t numchans;
     104                 :         jp2_cmapent_t *ents;
     105                 : } jp2_cmap_t;
     106                 : 
     107                 : #ifdef HAVE_JASPER_UUID
     108                 : typedef struct {
     109                 :         uint_fast32_t datalen;
     110                 :         uint_fast8_t uuid[16];
     111                 :         uint_fast8_t *data;
     112                 : } jp2_uuid_t;
     113                 : #endif
     114                 : 
     115                 : struct jp2_boxops_s;
     116                 : typedef struct {
     117                 : 
     118                 :         struct jp2_boxops_s *ops;
     119                 :         struct jp2_boxinfo_s *info;
     120                 : 
     121                 :         uint_fast32_t type;
     122                 : 
     123                 :         /* The length of the box including the (variable-length) header. */
     124                 :         uint_fast32_t len;
     125                 : 
     126                 :         /* The length of the box data. */
     127                 :         uint_fast32_t datalen;
     128                 : 
     129                 :         union {
     130                 :                 jp2_jp_t jp;
     131                 :                 jp2_ftyp_t ftyp;
     132                 :                 jp2_ihdr_t ihdr;
     133                 :                 jp2_bpcc_t bpcc;
     134                 :                 jp2_colr_t colr;
     135                 :                 jp2_pclr_t pclr;
     136                 :                 jp2_cdef_t cdef;
     137                 :                 jp2_cmap_t cmap;
     138                 : #ifdef HAVE_JASPER_UUID
     139                 :                 jp2_uuid_t uuid;
     140                 : #endif
     141                 :         } data;
     142                 : 
     143                 : } jp2_box_t;
     144                 : 
     145                 : typedef struct jp2_boxops_s {
     146                 :         void (*init)(jp2_box_t *box);
     147                 :         void (*destroy)(jp2_box_t *box);
     148                 :         int (*getdata)(jp2_box_t *box, jas_stream_t *in);
     149                 :         int (*putdata)(jp2_box_t *box, jas_stream_t *out);
     150                 :         void (*dumpdata)(jp2_box_t *box, FILE *out);
     151                 : } jp2_boxops_t;
     152                 : 
     153                 : extern jp2_box_t *jp2_box_create(int type);
     154                 : extern void jp2_box_destroy(jp2_box_t *box);
     155                 : extern jp2_box_t *jp2_box_get(jas_stream_t *in);
     156                 : extern int jp2_box_put(jp2_box_t *box, jas_stream_t *out);
     157                 : #ifdef HAVE_JASPER_UUID
     158                 : int jp2_encode_uuid(jas_image_t *image, jas_stream_t *out,
     159                 :                     char *optstr, jp2_box_t *uuid);
     160                 : #endif
     161                 : }
     162                 : // XXX: End of JasPer header.
     163                 : 
     164                 : /************************************************************************/
     165                 : /* ==================================================================== */
     166                 : /*                              JPEG2000Dataset                         */
     167                 : /* ==================================================================== */
     168                 : /************************************************************************/
     169                 : 
     170                 : class JPEG2000Dataset : public GDALPamDataset
     171                 : {
     172                 :     friend class JPEG2000RasterBand;
     173                 : 
     174                 :     jas_stream_t *psStream;
     175                 :     jas_image_t *psImage;
     176                 :     int         iFormat;
     177                 : 
     178                 :     char        *pszProjection;
     179                 :     int         bGeoTransformValid;
     180                 :     double      adfGeoTransform[6];
     181                 :     int         nGCPCount;
     182                 :     GDAL_GCP    *pasGCPList;
     183                 : 
     184                 :     int         bAlreadyDecoded;
     185                 :     int         DecodeImage();
     186                 : 
     187                 :   public:
     188                 :                 JPEG2000Dataset();
     189                 :                 ~JPEG2000Dataset();
     190                 :     
     191                 :     static int           Identify( GDALOpenInfo * );
     192                 :     static GDALDataset  *Open( GDALOpenInfo * );
     193                 : 
     194                 :     CPLErr              GetGeoTransform( double* );
     195                 :     virtual const char  *GetProjectionRef(void);
     196                 :     virtual int         GetGCPCount();
     197                 :     virtual const char  *GetGCPProjection();
     198                 :     virtual const GDAL_GCP *GetGCPs();
     199                 : };
     200                 : 
     201                 : /************************************************************************/
     202                 : /* ==================================================================== */
     203                 : /*                            JPEG2000RasterBand                        */
     204                 : /* ==================================================================== */
     205                 : /************************************************************************/
     206                 : 
     207                 : class JPEG2000RasterBand : public GDALPamRasterBand
     208                 : {
     209                 :     friend class JPEG2000Dataset;
     210                 :     
     211                 :     // NOTE: poDS may be altered for NITF/JPEG2000 files!
     212                 :     JPEG2000Dataset     *poGDS;
     213                 : 
     214                 :     jas_matrix_t        *psMatrix;
     215                 :     
     216                 :     int                  iDepth;
     217                 :     int                  bSignedness;
     218                 : 
     219                 :   public:
     220                 : 
     221                 :                 JPEG2000RasterBand( JPEG2000Dataset *, int, int, int );
     222                 :                 ~JPEG2000RasterBand();
     223                 :                 
     224                 :     virtual CPLErr IReadBlock( int, int, void * );
     225                 :     virtual GDALColorInterp GetColorInterpretation();
     226                 : };
     227                 : 
     228                 : 
     229                 : /************************************************************************/
     230                 : /*                           JPEG2000RasterBand()                       */
     231                 : /************************************************************************/
     232                 : 
     233              82 : JPEG2000RasterBand::JPEG2000RasterBand( JPEG2000Dataset *poDS, int nBand,
     234              82 :                 int iDepth, int bSignedness )
     235                 : 
     236                 : {
     237              82 :     this->poDS = poDS;
     238              82 :     poGDS = poDS;
     239              82 :     this->nBand = nBand;
     240              82 :     this->iDepth = iDepth;
     241              82 :     this->bSignedness = bSignedness;
     242                 : 
     243                 :     // XXX: JasPer can't handle data with depth > 32 bits
     244                 :     // Maximum possible depth for JPEG2000 is 38!
     245              82 :     switch ( bSignedness )
     246                 :     {
     247                 :         case 1:                         // Signed component
     248               6 :         if (iDepth <= 8)
     249               0 :             this->eDataType = GDT_Byte; // FIXME: should be signed,
     250                 :                                         // but we haven't signed byte
     251                 :                                         // data type in GDAL
     252               6 :         else if (iDepth <= 16)
     253               6 :             this->eDataType = GDT_Int16;
     254               0 :         else if (iDepth <= 32)
     255               0 :             this->eDataType = GDT_Int32;
     256               6 :         break;
     257                 :         case 0:                         // Unsigned component
     258                 :         default:
     259              76 :         if (iDepth <= 8)
     260              70 :             this->eDataType = GDT_Byte;
     261               6 :         else if (iDepth <= 16)
     262               6 :             this->eDataType = GDT_UInt16;
     263               0 :         else if (iDepth <= 32)
     264               0 :             this->eDataType = GDT_UInt32;
     265                 :         break;
     266                 :     }
     267                 :     // FIXME: Figure out optimal block size!
     268                 :     // Should the block size be fixed or determined dynamically?
     269              82 :     nBlockXSize = MIN(256, poDS->nRasterXSize);
     270              82 :     nBlockYSize = MIN(256, poDS->nRasterYSize);
     271              82 :     psMatrix = jas_matrix_create(nBlockYSize, nBlockXSize);
     272              82 : }
     273                 : 
     274                 : /************************************************************************/
     275                 : /*                         ~JPEG2000RasterBand()                        */
     276                 : /************************************************************************/
     277                 : 
     278              82 : JPEG2000RasterBand::~JPEG2000RasterBand()
     279                 : {
     280              82 :     if ( psMatrix )
     281              82 :         jas_matrix_destroy( psMatrix );    
     282              82 : }
     283                 : 
     284                 : /************************************************************************/
     285                 : /*                             IReadBlock()                             */
     286                 : /************************************************************************/
     287                 : 
     288             304 : CPLErr JPEG2000RasterBand::IReadBlock( int nBlockXOff, int nBlockYOff,
     289                 :                                       void * pImage )
     290                 : {
     291                 :     int             i, j;
     292                 : 
     293                 :     // Decode image from the stream, if not yet
     294             304 :     if ( !poGDS->DecodeImage() )
     295                 :     {
     296               0 :         return CE_Failure;
     297                 :     }
     298                 : 
     299                 :     // Now we can calculate the pixel offset of the top left by multiplying
     300                 :     // block offset with the block size.
     301                 : 
     302                 :     /* In case the dimensions of the image are not multiple of the block dimensions */
     303                 :     /* take care of not requesting more pixels than available for the blocks at the */
     304                 :     /* right or bottom of the image */
     305             304 :     int nWidthToRead = MIN(nBlockXSize, poGDS->nRasterXSize - nBlockXOff * nBlockXSize);
     306             304 :     int nHeightToRead = MIN(nBlockYSize, poGDS->nRasterYSize - nBlockYOff * nBlockYSize);
     307                 : 
     308                 :     jas_image_readcmpt( poGDS->psImage, nBand - 1,
     309                 :                         nBlockXOff * nBlockXSize, nBlockYOff * nBlockYSize,
     310             304 :                         nWidthToRead, nHeightToRead, psMatrix );
     311                 : 
     312             304 :     int nWordSize = GDALGetDataTypeSize(eDataType) / 8;
     313             304 :     int nLineSize = nBlockXSize * nWordSize;
     314             304 :     GByte* ptr = (GByte*)pImage;
     315                 : 
     316                 :     /* Pad incomplete blocks at the right or bottom of the image */
     317             304 :     if (nWidthToRead != nBlockXSize || nHeightToRead != nBlockYSize)
     318              68 :         memset(pImage, 0, nLineSize * nBlockYSize);
     319                 : 
     320           69756 :     for( i = 0; i < nHeightToRead; i++, ptr += nLineSize )
     321                 :     {
     322        16440212 :         for( j = 0; j < nWidthToRead; j++ )
     323                 :         {
     324                 :             // XXX: We need casting because matrix element always
     325                 :             // has 32 bit depth in JasPer
     326                 :             // FIXME: what about float values?
     327        16370760 :             switch( eDataType )
     328                 :             {
     329                 :                 case GDT_Int16:
     330                 :                 {
     331            1600 :                     ((GInt16*)ptr)[j] = (GInt16)jas_matrix_get(psMatrix, i, j);
     332                 :                 }
     333            1600 :                 break;
     334                 :                 case GDT_Int32:
     335                 :                 {
     336               0 :                     ((GInt32*)ptr)[j] = (GInt32)jas_matrix_get(psMatrix, i, j);
     337                 :                 }
     338               0 :                 break;
     339                 :                 case GDT_UInt16:
     340                 :                 {
     341          311648 :                     ((GUInt16*)ptr)[j] = (GUInt16)jas_matrix_get(psMatrix, i, j);
     342                 :                 }
     343          311648 :                 break;
     344                 :                 case GDT_UInt32:
     345                 :                 {
     346               0 :                     ((GUInt32*)ptr)[j] = (GUInt32)jas_matrix_get(psMatrix, i, j);
     347                 :                 }
     348               0 :                 break;
     349                 :                 case GDT_Byte:
     350                 :                 default:
     351                 :                 {
     352        16057512 :                     ((GByte*)ptr)[j] = (GByte)jas_matrix_get(psMatrix, i, j);
     353                 :                 }
     354                 :                 break;
     355                 :             }
     356                 :         }
     357                 :     }
     358                 : 
     359             304 :     return CE_None;
     360                 : }
     361                 : 
     362                 : /************************************************************************/
     363                 : /*                       GetColorInterpretation()                       */
     364                 : /************************************************************************/
     365                 : 
     366              32 : GDALColorInterp JPEG2000RasterBand::GetColorInterpretation()
     367                 : {
     368                 :     // Decode image from the stream, if not yet
     369              32 :     if ( !poGDS->DecodeImage() )
     370                 :     {
     371               0 :         return GCI_Undefined;
     372                 :     }
     373                 :     
     374              32 :     if ( jas_clrspc_fam( jas_image_clrspc( poGDS->psImage ) ) ==
     375                 :          JAS_CLRSPC_FAM_GRAY )
     376              22 :         return GCI_GrayIndex;
     377              10 :     else if ( jas_clrspc_fam( jas_image_clrspc( poGDS->psImage ) ) == 
     378                 :               JAS_CLRSPC_FAM_RGB )
     379                 :     {
     380              10 :         switch ( jas_image_cmpttype( poGDS->psImage, nBand - 1 ) )
     381                 :         {
     382                 :             case JAS_IMAGE_CT_RGB_R:
     383               3 :                 return GCI_RedBand;
     384                 :             case JAS_IMAGE_CT_RGB_G:
     385               3 :                 return GCI_GreenBand;
     386                 :             case JAS_IMAGE_CT_RGB_B:
     387               3 :                 return GCI_BlueBand;
     388                 :             case JAS_IMAGE_CT_OPACITY:
     389               0 :                 return GCI_AlphaBand;
     390                 :             default:
     391               1 :                 return GCI_Undefined;
     392                 :         }
     393                 :     }
     394                 :     else
     395               0 :         return GCI_Undefined;
     396                 : }
     397                 : 
     398                 : /************************************************************************/
     399                 : /* ==================================================================== */
     400                 : /*                              JPEG2000Dataset                         */
     401                 : /* ==================================================================== */
     402                 : /************************************************************************/
     403                 : 
     404                 : /************************************************************************/
     405                 : /*                           JPEG2000Dataset()                          */
     406                 : /************************************************************************/
     407                 : 
     408              48 : JPEG2000Dataset::JPEG2000Dataset()
     409                 : {
     410              48 :     psStream = NULL;
     411              48 :     psImage = NULL;
     412              48 :     nBands = 0;
     413              48 :     pszProjection = CPLStrdup("");
     414              48 :     nGCPCount = 0;
     415              48 :     pasGCPList = NULL;
     416              48 :     bGeoTransformValid = FALSE;
     417              48 :     adfGeoTransform[0] = 0.0;
     418              48 :     adfGeoTransform[1] = 1.0;
     419              48 :     adfGeoTransform[2] = 0.0;
     420              48 :     adfGeoTransform[3] = 0.0;
     421              48 :     adfGeoTransform[4] = 0.0;
     422              48 :     adfGeoTransform[5] = 1.0;
     423              48 :     bAlreadyDecoded = FALSE;
     424                 :     
     425              48 :     poDriver = (GDALDriver *)GDALGetDriverByName("JPEG2000");
     426              48 : }
     427                 : 
     428                 : /************************************************************************/
     429                 : /*                            ~JPEG2000Dataset()                        */
     430                 : /************************************************************************/
     431                 : 
     432              48 : JPEG2000Dataset::~JPEG2000Dataset()
     433                 : 
     434                 : {
     435              48 :     FlushCache();
     436                 : 
     437              48 :     if ( psStream )
     438              48 :         jas_stream_close( psStream );
     439              48 :     if ( psImage )
     440              42 :         jas_image_destroy( psImage );
     441                 : 
     442              48 :     if ( pszProjection )
     443              48 :         CPLFree( pszProjection );
     444              48 :     if( nGCPCount > 0 )
     445                 :     {
     446               2 :         GDALDeinitGCPs( nGCPCount, pasGCPList );
     447               2 :         CPLFree( pasGCPList );
     448                 :     }
     449              48 : }
     450                 : 
     451                 : /************************************************************************/
     452                 : /*                             DecodeImage()                            */
     453                 : /************************************************************************/
     454             350 : int JPEG2000Dataset::DecodeImage()
     455                 : {
     456             350 :     if (bAlreadyDecoded)
     457             308 :         return psImage != NULL;
     458                 :         
     459              42 :     bAlreadyDecoded = TRUE;    
     460              42 :     if ( !( psImage = jas_image_decode(psStream, iFormat, 0) ) )
     461                 :     {
     462                 :         CPLDebug( "JPEG2000", "Unable to decode image. Format: %s, %d",
     463               0 :                   jas_image_fmttostr( iFormat ), iFormat );
     464               0 :         return FALSE;
     465                 :     }
     466                 :     
     467                 :     /* Case of a JP2 image : check that the properties given by */
     468                 :     /* the JP2 boxes match the ones of the code stream */
     469              42 :     if (nBands != 0)
     470                 :     {
     471              28 :         if (nBands != jas_image_numcmpts( psImage ))
     472                 :         {
     473                 :             CPLError(CE_Failure, CPLE_AppDefined,
     474                 :                      "The number of components indicated in the IHDR box (%d) mismatch "
     475                 :                      "the value specified in the code stream (%d)",
     476               0 :                      nBands, jas_image_numcmpts( psImage ));
     477               0 :             jas_image_destroy( psImage );
     478               0 :             psImage = NULL;
     479               0 :             return FALSE;
     480                 :         }
     481                 :         
     482              56 :         if (nRasterXSize != jas_image_cmptwidth( psImage, 0 ) ||
     483              28 :             nRasterYSize != jas_image_cmptheight( psImage, 0 ) )
     484                 :         {
     485                 :             CPLError(CE_Failure, CPLE_AppDefined,
     486                 :                      "The dimensions indicated in the IHDR box (%d x %d) mismatch "
     487                 :                      "the value specified in the code stream (%d x %d)",
     488                 :                      nRasterXSize, nRasterYSize,
     489               0 :                      (int)jas_image_cmptwidth( psImage, 0 ),
     490               0 :                      (int)jas_image_cmptheight( psImage, 0 ));
     491               0 :             jas_image_destroy( psImage );
     492               0 :             psImage = NULL;
     493               0 :             return FALSE;
     494                 :         }
     495                 :         
     496                 :         int iBand;
     497              78 :         for ( iBand = 0; iBand < nBands; iBand++ )
     498                 :         {
     499              50 :             JPEG2000RasterBand* poBand = (JPEG2000RasterBand*) GetRasterBand(iBand+1);
     500             100 :             if (poBand->iDepth != jas_image_cmptprec( psImage, iBand ) ||
     501              50 :                 poBand->bSignedness != jas_image_cmptsgnd( psImage, iBand ))
     502                 :             {
     503                 :                 CPLError(CE_Failure, CPLE_AppDefined,
     504                 :                          "The bit depth of band %d indicated in the IHDR box (%d) mismatch "
     505                 :                          "the value specified in the code stream (%d)",
     506               0 :                          iBand + 1, poBand->iDepth, jas_image_cmptprec( psImage, iBand ));
     507               0 :                 jas_image_destroy( psImage );
     508               0 :                 psImage = NULL;
     509               0 :                 return FALSE;
     510                 :             }
     511                 :         }
     512                 :     }
     513                 :     
     514                 :     /* Ask for YCbCr -> RGB translation */
     515              42 :     if ( jas_clrspc_fam( jas_image_clrspc( psImage ) ) == 
     516                 :               JAS_CLRSPC_FAM_YCBCR )
     517                 :     {
     518                 :         jas_image_t *psRGBImage;
     519                 :         jas_cmprof_t *psRGBProf;
     520               1 :         CPLDebug( "JPEG2000", "forcing conversion to sRGB");
     521               1 :         if (!(psRGBProf = jas_cmprof_createfromclrspc(JAS_CLRSPC_SRGB))) {
     522               0 :             CPLDebug( "JPEG2000", "cannot create sRGB profile");
     523               0 :             return TRUE;
     524                 :         }
     525               1 :         if (!(psRGBImage = jas_image_chclrspc(psImage, psRGBProf, JAS_CMXFORM_INTENT_PER))) {
     526               0 :             CPLDebug( "JPEG2000", "cannot convert to sRGB");
     527               0 :             jas_cmprof_destroy(psRGBProf);
     528               0 :             return TRUE;
     529                 :         }
     530               1 :         jas_image_destroy(psImage);
     531               1 :         jas_cmprof_destroy(psRGBProf);
     532               1 :         psImage = psRGBImage;
     533                 :     }
     534                 :     
     535              42 :     return TRUE;
     536                 : }
     537                 : 
     538                 : 
     539                 : /************************************************************************/
     540                 : /*                          GetProjectionRef()                          */
     541                 : /************************************************************************/
     542                 : 
     543              31 : const char *JPEG2000Dataset::GetProjectionRef()
     544                 : 
     545                 : {
     546              31 :     return( pszProjection );
     547                 : }
     548                 : 
     549                 : /************************************************************************/
     550                 : /*                          GetGeoTransform()                           */
     551                 : /************************************************************************/
     552                 : 
     553              22 : CPLErr JPEG2000Dataset::GetGeoTransform( double * padfTransform )
     554                 : {
     555              22 :     if( bGeoTransformValid )
     556                 :     {
     557              21 :         memcpy( padfTransform, adfGeoTransform, sizeof(adfGeoTransform[0]) * 6 );
     558              21 :         return CE_None;
     559                 :     }
     560                 :     else
     561               1 :         return CE_Failure;
     562                 : }
     563                 : 
     564                 : /************************************************************************/
     565                 : /*                            GetGCPCount()                             */
     566                 : /************************************************************************/
     567                 : 
     568               7 : int JPEG2000Dataset::GetGCPCount()
     569                 : 
     570                 : {
     571               7 :     return nGCPCount;
     572                 : }
     573                 : 
     574                 : /************************************************************************/
     575                 : /*                          GetGCPProjection()                          */
     576                 : /************************************************************************/
     577                 : 
     578               1 : const char *JPEG2000Dataset::GetGCPProjection()
     579                 : 
     580                 : {
     581               1 :     if( nGCPCount > 0 )
     582               1 :         return pszProjection;
     583                 :     else
     584               0 :         return "";
     585                 : }
     586                 : 
     587                 : /************************************************************************/
     588                 : /*                               GetGCP()                               */
     589                 : /************************************************************************/
     590                 : 
     591               1 : const GDAL_GCP *JPEG2000Dataset::GetGCPs()
     592                 : 
     593                 : {
     594               1 :     return pasGCPList;
     595                 : }
     596                 : 
     597              61 : static void JPEG2000Init()
     598                 : {
     599                 :     static int bHasInit = FALSE;
     600              61 :     if (!bHasInit)
     601                 :     {
     602               2 :         bHasInit = TRUE;
     603               2 :         jas_init();
     604                 :     }
     605              61 : }
     606                 : 
     607                 : /************************************************************************/
     608                 : /*                            Identify()                                */
     609                 : /************************************************************************/
     610                 : 
     611           12029 : int JPEG2000Dataset::Identify( GDALOpenInfo * poOpenInfo )
     612                 : 
     613                 : {
     614                 :     static const unsigned char jpc_header[] = {0xff,0x4f};
     615                 :     static const unsigned char jp2_box_jp[] = {0x6a,0x50,0x20,0x20}; /* 'jP  ' */
     616                 :         
     617           12029 :     if( poOpenInfo->nHeaderBytes >= 16 
     618                 :         && (memcmp( poOpenInfo->pabyHeader, jpc_header, 
     619                 :                     sizeof(jpc_header) ) == 0
     620                 :             || memcmp( poOpenInfo->pabyHeader + 4, jp2_box_jp, 
     621                 :                     sizeof(jp2_box_jp) ) == 0
     622                 :             /* PGX file*/
     623                 :             || (memcmp( poOpenInfo->pabyHeader, "PG", 2) == 0 &&
     624               0 :                 (poOpenInfo->pabyHeader[2] == ' ' || poOpenInfo->pabyHeader[2] == '\t') &&
     625                 :                 (memcmp( poOpenInfo->pabyHeader + 3, "ML", 2) == 0 ||
     626                 :                  memcmp( poOpenInfo->pabyHeader + 3, "LM", 2) == 0))) )
     627              48 :         return TRUE;
     628                 :     
     629                 :     else
     630           11981 :         return FALSE;
     631                 : }
     632                 : 
     633                 : /************************************************************************/
     634                 : /*                                Open()                                */
     635                 : /************************************************************************/
     636                 : 
     637            1966 : GDALDataset *JPEG2000Dataset::Open( GDALOpenInfo * poOpenInfo )
     638                 : 
     639                 : {
     640                 :     int         iFormat;
     641            1966 :     char        *pszFormatName = NULL;
     642                 :     jas_stream_t *sS;
     643                 :     
     644            1966 :     if (!Identify(poOpenInfo))
     645            1918 :         return NULL;
     646                 : 
     647              48 :     JPEG2000Init();
     648              48 :     if( !(sS = JPEG2000_VSIL_fopen( poOpenInfo->pszFilename, "rb" )) )
     649                 :     {
     650               0 :         return NULL;
     651                 :     }
     652                 : 
     653              48 :     iFormat = jas_image_getfmt( sS );
     654              48 :     if ( !(pszFormatName = jas_image_fmttostr( iFormat )) )
     655                 :     {
     656               0 :         jas_stream_close( sS );
     657               0 :         return NULL;
     658                 :     }
     659              48 :     if ( strlen( pszFormatName ) < 3 ||
     660                 :         (!EQUALN( pszFormatName, "jp2", 3 ) &&
     661                 :          !EQUALN( pszFormatName, "jpc", 3 ) &&
     662                 :          !EQUALN( pszFormatName, "pgx", 3 )) )
     663                 :     {
     664                 :         CPLDebug( "JPEG2000", "JasPer reports file is format type `%s'.", 
     665               0 :                   pszFormatName );
     666               0 :         jas_stream_close( sS );
     667               0 :         return NULL;
     668                 :     }
     669                 :     
     670                 : /* -------------------------------------------------------------------- */
     671                 : /*      Confirm the requested access is supported.                      */
     672                 : /* -------------------------------------------------------------------- */
     673              48 :     if( poOpenInfo->eAccess == GA_Update )
     674                 :     {
     675               0 :         jas_stream_close(sS);
     676                 :         CPLError( CE_Failure, CPLE_NotSupported, 
     677                 :                   "The JPEG2000 driver does not support update access to existing"
     678               0 :                   " datasets.\n" );
     679               0 :         return NULL;
     680                 :     }
     681                 : /* -------------------------------------------------------------------- */
     682                 : /*      Create a corresponding GDALDataset.                             */
     683                 : /* -------------------------------------------------------------------- */
     684                 :     JPEG2000Dataset     *poDS;
     685              48 :     int                 *paiDepth = NULL, *pabSignedness = NULL;
     686                 :     int                 iBand;
     687                 : 
     688              48 :     poDS = new JPEG2000Dataset();
     689                 : 
     690              48 :     poDS->psStream = sS;
     691              48 :     poDS->iFormat = iFormat;
     692                 : 
     693              48 :     if ( EQUALN( pszFormatName, "jp2", 3 ) )
     694                 :     {
     695                 :         // XXX: Hack to read JP2 boxes from input file. JasPer hasn't public
     696                 :         // API call for such things, so we will use internal JasPer functions.
     697                 :         jp2_box_t *box;
     698              34 :         box = 0;
     699             344 :         while ( ( box = jp2_box_get(poDS->psStream) ) )
     700                 :         {
     701             276 :             switch (box->type)
     702                 :             {
     703                 :                 case JP2_BOX_IHDR:
     704              34 :                 poDS->nBands = box->data.ihdr.numcmpts;
     705              34 :                 poDS->nRasterXSize = box->data.ihdr.width;
     706              34 :                 poDS->nRasterYSize = box->data.ihdr.height;
     707                 :                 CPLDebug( "JPEG2000",
     708                 :                           "IHDR box found. Dump: "
     709                 :                           "width=%d, height=%d, numcmpts=%d, bpp=%d",
     710                 :                           (int)box->data.ihdr.width, (int)box->data.ihdr.height,
     711              34 :                           (int)box->data.ihdr.numcmpts, (box->data.ihdr.bpc & 0x7F) + 1 );
     712                 :                 /* ISO/IEC 15444-1:2004 I.5.3.1 specifies that 255 means that all */
     713                 :                 /* components have not the same bit depth and/or sign and that a */
     714                 :                 /* BPCC box must then follow to specify them for each component */
     715              34 :                 if ( box->data.ihdr.bpc != 255 )
     716                 :                 {
     717              33 :                     paiDepth = (int *)CPLMalloc(poDS->nBands * sizeof(int));
     718              33 :                     pabSignedness = (int *)CPLMalloc(poDS->nBands * sizeof(int));
     719              81 :                     for ( iBand = 0; iBand < poDS->nBands; iBand++ )
     720                 :                     {
     721              48 :                         paiDepth[iBand] = (box->data.ihdr.bpc & 0x7F) + 1;
     722              48 :                         pabSignedness[iBand] = box->data.ihdr.bpc >> 7;
     723                 :                         CPLDebug( "JPEG2000",
     724                 :                                   "Component %d: bpp=%d, signedness=%d",
     725              48 :                                   iBand, paiDepth[iBand], pabSignedness[iBand] );
     726                 :                     }
     727                 :                 }
     728              34 :                 break;
     729                 : 
     730                 :                 case JP2_BOX_BPCC:
     731               1 :                 CPLDebug( "JPEG2000", "BPCC box found. Dump:" );
     732               1 :                 if ( !paiDepth && !pabSignedness )
     733                 :                 {
     734                 :                     paiDepth = (int *)
     735               1 :                         CPLMalloc( box->data.bpcc.numcmpts * sizeof(int) );
     736                 :                     pabSignedness = (int *)
     737               1 :                         CPLMalloc( box->data.bpcc.numcmpts * sizeof(int) );
     738               5 :                     for( iBand = 0; iBand < (int)box->data.bpcc.numcmpts; iBand++ )
     739                 :                     {
     740               4 :                         paiDepth[iBand] = (box->data.bpcc.bpcs[iBand] & 0x7F) + 1;
     741               4 :                         pabSignedness[iBand] = box->data.bpcc.bpcs[iBand] >> 7;
     742                 :                         CPLDebug( "JPEG2000",
     743                 :                                   "Component %d: bpp=%d, signedness=%d",
     744               4 :                                   iBand, paiDepth[iBand], pabSignedness[iBand] );
     745                 :                     }
     746                 :                 }
     747               1 :                 break;
     748                 : 
     749                 :                 case JP2_BOX_PCLR:
     750                 :                 CPLDebug( "JPEG2000",
     751                 :                           "PCLR box found. Dump: number of LUT entries=%d, "
     752                 :                           "number of resulting channels=%d",
     753               2 :                           (int)box->data.pclr.numlutents, box->data.pclr.numchans );
     754               2 :                 poDS->nBands = box->data.pclr.numchans;
     755               2 :                 if ( paiDepth )
     756               2 :                     CPLFree( paiDepth );
     757               2 :                 if ( pabSignedness )
     758               2 :                     CPLFree( pabSignedness );
     759                 :                 paiDepth = (int *)
     760               2 :                         CPLMalloc( box->data.pclr.numchans * sizeof(int) );
     761                 :                 pabSignedness = (int *)
     762               2 :                         CPLMalloc( box->data.pclr.numchans * sizeof(int) );
     763               8 :                 for( iBand = 0; iBand < (int)box->data.pclr.numchans; iBand++ )
     764                 :                 {
     765               6 :                     paiDepth[iBand] = (box->data.pclr.bpc[iBand] & 0x7F) + 1;
     766               6 :                     pabSignedness[iBand] = box->data.pclr.bpc[iBand] >> 7;
     767                 :                     CPLDebug( "JPEG2000",
     768                 :                               "Component %d: bpp=%d, signedness=%d",
     769               6 :                               iBand, paiDepth[iBand], pabSignedness[iBand] );
     770                 :                 }
     771                 :                 break;
     772                 :             }
     773             276 :             jp2_box_destroy( box );
     774             276 :             box = 0;
     775                 :         }
     776              34 :         if( !paiDepth || !pabSignedness )
     777                 :         {
     778               0 :             delete poDS;
     779               0 :             CPLDebug( "JPEG2000", "Unable to read JP2 header boxes.\n" );
     780               0 :             return NULL;
     781                 :         }
     782              34 :         if ( jas_stream_rewind( poDS->psStream ) < 0 )
     783                 :         {
     784               0 :             delete poDS;
     785               0 :             CPLDebug( "JPEG2000", "Unable to rewind input stream.\n" );
     786               0 :             return NULL;
     787                 :         }
     788                 :     }
     789                 :     else
     790                 :     {
     791              14 :         if ( !poDS->DecodeImage() )
     792                 :         {
     793               0 :             delete poDS;
     794               0 :             return NULL;
     795                 :         }
     796                 : 
     797              14 :         poDS->nBands = jas_image_numcmpts( poDS->psImage );
     798              14 :         poDS->nRasterXSize = jas_image_cmptwidth( poDS->psImage, 0 );
     799              14 :         poDS->nRasterYSize = jas_image_cmptheight( poDS->psImage, 0 );
     800              14 :         paiDepth = (int *)CPLMalloc( poDS->nBands * sizeof(int) );
     801              14 :         pabSignedness = (int *)CPLMalloc( poDS->nBands * sizeof(int) );
     802              40 :         for ( iBand = 0; iBand < poDS->nBands; iBand++ )
     803                 :         {
     804              26 :             paiDepth[iBand] = jas_image_cmptprec( poDS->psImage, iBand );
     805              26 :             pabSignedness[iBand] = jas_image_cmptsgnd( poDS->psImage, iBand );
     806                 :         }
     807                 :     }
     808                 :     
     809              48 :     if ( !GDALCheckDatasetDimensions(poDS->nRasterXSize, poDS->nRasterYSize) ||
     810                 :          !GDALCheckBandCount(poDS->nBands, 0) )
     811                 :     {
     812               0 :         CPLFree( paiDepth );
     813               0 :         CPLFree( pabSignedness );
     814               0 :         delete poDS;
     815               0 :         return NULL;
     816                 :     }
     817                 : 
     818                 : /* -------------------------------------------------------------------- */
     819                 : 
     820                 : /*      Create band information objects.                                */
     821                 : /* -------------------------------------------------------------------- */
     822             260 :     for( iBand = 1; iBand <= poDS->nBands; iBand++ )
     823                 :     {
     824                 :         poDS->SetBand( iBand, new JPEG2000RasterBand( poDS, iBand,
     825              82 :             paiDepth[iBand - 1], pabSignedness[iBand - 1] ) );
     826                 :         
     827                 :     }
     828                 :     
     829              48 :     if ( paiDepth )
     830              48 :         CPLFree( paiDepth );
     831              48 :     if ( pabSignedness )
     832              48 :         CPLFree( pabSignedness );
     833                 : 
     834                 : /* -------------------------------------------------------------------- */
     835                 : /*      Check for georeferencing information.                           */
     836                 : /* -------------------------------------------------------------------- */
     837              48 :     GDALJP2Metadata oJP2Geo;
     838                 :     
     839              48 :     if( oJP2Geo.ReadAndParse( poOpenInfo->pszFilename ) )
     840                 :     {
     841              29 :         if ( poDS->pszProjection )
     842              29 :             CPLFree( poDS->pszProjection );
     843              29 :         poDS->pszProjection = CPLStrdup(oJP2Geo.pszProjection);
     844              29 :         poDS->bGeoTransformValid = oJP2Geo.bHaveGeoTransform;
     845                 :         memcpy( poDS->adfGeoTransform, oJP2Geo.adfGeoTransform, 
     846              29 :                 sizeof(double) * 6 );
     847              29 :         poDS->nGCPCount = oJP2Geo.nGCPCount;
     848                 :         poDS->pasGCPList =
     849              29 :             GDALDuplicateGCPs( oJP2Geo.nGCPCount, oJP2Geo.pasGCPList );
     850                 :     }
     851                 : 
     852              48 :     if (oJP2Geo.pszXMPMetadata)
     853                 :     {
     854                 :         char *apszMDList[2];
     855               1 :         apszMDList[0] = (char *) oJP2Geo.pszXMPMetadata;
     856               1 :         apszMDList[1] = NULL;
     857               1 :         poDS->SetMetadata(apszMDList, "xml:XMP");
     858                 :     }
     859                 : 
     860                 : /* -------------------------------------------------------------------- */
     861                 : /*      Check for world file.                                           */
     862                 : /* -------------------------------------------------------------------- */
     863              48 :     if( !poDS->bGeoTransformValid )
     864                 :     {
     865                 :         poDS->bGeoTransformValid |=
     866                 :             GDALReadWorldFile2( poOpenInfo->pszFilename, NULL,
     867                 :                                 poDS->adfGeoTransform,
     868                 :                                 poOpenInfo->papszSiblingFiles, NULL )
     869                 :             || GDALReadWorldFile2( poOpenInfo->pszFilename, ".wld",
     870                 :                                    poDS->adfGeoTransform,
     871              21 :                                    poOpenInfo->papszSiblingFiles, NULL );
     872                 :     }
     873                 : 
     874                 : /* -------------------------------------------------------------------- */
     875                 : /*      Initialize any PAM information.                                 */
     876                 : /* -------------------------------------------------------------------- */
     877              48 :     poDS->SetDescription( poOpenInfo->pszFilename );
     878              48 :     poDS->TryLoadXML();
     879                 : 
     880                 : /* -------------------------------------------------------------------- */
     881                 : /*      Check for overviews.                                            */
     882                 : /* -------------------------------------------------------------------- */
     883              48 :     poDS->oOvManager.Initialize( poDS, poOpenInfo->pszFilename );
     884                 :     
     885              48 :     return( poDS );
     886                 : }
     887                 : 
     888                 : /************************************************************************/
     889                 : /*                      JPEG2000CreateCopy()                            */
     890                 : /************************************************************************/
     891                 : 
     892                 : static GDALDataset *
     893              14 : JPEG2000CreateCopy( const char * pszFilename, GDALDataset *poSrcDS, 
     894                 :                     int bStrict, char ** papszOptions, 
     895                 :                     GDALProgressFunc pfnProgress, void * pProgressData )
     896                 : 
     897                 : {
     898              14 :     int  nBands = poSrcDS->GetRasterCount();
     899              14 :     int  nXSize = poSrcDS->GetRasterXSize();
     900              14 :     int  nYSize = poSrcDS->GetRasterYSize();
     901                 : 
     902              14 :     if( nBands == 0 )
     903                 :     {
     904                 :         CPLError( CE_Failure, CPLE_NotSupported,
     905               1 :                   "Unable to export files with zero bands." );
     906               1 :         return NULL;
     907                 :     }
     908                 : 
     909              13 :     if (poSrcDS->GetRasterBand(1)->GetColorTable() != NULL)
     910                 :     {
     911                 :         CPLError( (bStrict) ? CE_Failure : CE_Warning, CPLE_NotSupported, 
     912                 :                   "JPEG2000 driver ignores color table. "
     913                 :                   "The source raster band will be considered as grey level.\n"
     914               0 :                   "Consider using color table expansion (-expand option in gdal_translate)\n");
     915               0 :         if (bStrict)
     916               0 :             return NULL;
     917                 :     }
     918                 :     
     919              13 :     if( !pfnProgress( 0.0, NULL, pProgressData ) )
     920               0 :         return NULL;
     921                 : 
     922                 : /* -------------------------------------------------------------------- */
     923                 : /*      Create the dataset.                                             */
     924                 : /* -------------------------------------------------------------------- */
     925                 :     int                 iBand;
     926                 :     jas_stream_t        *psStream;
     927                 :     jas_image_t         *psImage;
     928                 : 
     929              13 :     JPEG2000Init();
     930              13 :     const char* pszAccess = EQUALN(pszFilename, "/vsisubfile/", 12) ? "r+b" : "w+b";
     931              13 :     if( !(psStream = JPEG2000_VSIL_fopen( pszFilename, pszAccess) ) )
     932                 :     {
     933                 :         CPLError( CE_Failure, CPLE_FileIO, "Unable to create file %s.\n", 
     934               2 :                   pszFilename );
     935               2 :         return NULL;
     936                 :     }
     937                 :     
     938              11 :     if ( !(psImage = jas_image_create0()) )
     939                 :     {
     940                 :         CPLError( CE_Failure, CPLE_OutOfMemory, "Unable to create image %s.\n", 
     941               0 :                   pszFilename );
     942               0 :         return NULL;
     943                 :     }
     944                 : 
     945                 : /* -------------------------------------------------------------------- */
     946                 : /*      Loop over image, copying image data.                            */
     947                 : /* -------------------------------------------------------------------- */
     948                 :     GDALRasterBand      *poBand;
     949                 :     GUInt32             *paiScanline;
     950                 :     int                 iLine, iPixel;
     951              11 :     CPLErr              eErr = CE_None;
     952                 :     jas_matrix_t        *psMatrix;
     953                 :     jas_image_cmptparm_t *sComps; // Array of pointers to image components
     954                 : 
     955                 :     sComps = (jas_image_cmptparm_t*)
     956              11 :         CPLMalloc( nBands * sizeof(jas_image_cmptparm_t) );
     957                 :   
     958              11 :     if ( !(psMatrix = jas_matrix_create( 1, nXSize )) )
     959                 :     {
     960                 :         CPLError( CE_Failure, CPLE_OutOfMemory, 
     961               0 :                   "Unable to create matrix with size %dx%d.\n", 1, nYSize );
     962               0 :         CPLFree( sComps );
     963               0 :         jas_image_destroy( psImage );
     964               0 :         return NULL;
     965                 :     }
     966                 :     paiScanline = (GUInt32 *) CPLMalloc( nXSize *
     967              11 :                             GDALGetDataTypeSize(GDT_UInt32) / 8 );
     968                 :     
     969              31 :     for ( iBand = 0; iBand < nBands; iBand++ )
     970                 :     {
     971              20 :         poBand = poSrcDS->GetRasterBand( iBand + 1);
     972                 :         
     973              20 :         sComps[iBand].tlx = sComps[iBand].tly = 0;
     974              20 :         sComps[iBand].hstep = sComps[iBand].vstep = 1;
     975              20 :         sComps[iBand].width = nXSize;
     976              20 :         sComps[iBand].height = nYSize;
     977              20 :         sComps[iBand].prec = GDALGetDataTypeSize( poBand->GetRasterDataType() );
     978              20 :         switch ( poBand->GetRasterDataType() )
     979                 :         {
     980                 :             case GDT_Int16:
     981                 :             case GDT_Int32:
     982                 :             case GDT_Float32:
     983                 :             case GDT_Float64:
     984               2 :             sComps[iBand].sgnd = 1;
     985               2 :             break;
     986                 :             case GDT_Byte:
     987                 :             case GDT_UInt16:
     988                 :             case GDT_UInt32:
     989                 :             default:
     990              18 :             sComps[iBand].sgnd = 0;
     991                 :             break;
     992                 :         }
     993              20 :         jas_image_addcmpt(psImage, iBand, sComps);
     994                 : 
     995            1512 :         for( iLine = 0; eErr == CE_None && iLine < nYSize; iLine++ )
     996                 :         {
     997                 :             eErr = poBand->RasterIO( GF_Read, 0, iLine, nXSize, 1, 
     998                 :                               paiScanline, nXSize, 1, GDT_UInt32,
     999            1492 :                               sizeof(GUInt32), sizeof(GUInt32) * nXSize );
    1000          367356 :             for ( iPixel = 0; iPixel < nXSize; iPixel++ )
    1001          365864 :                 jas_matrix_setv( psMatrix, iPixel, paiScanline[iPixel] );
    1002                 :             
    1003            1492 :             if( (jas_image_writecmpt(psImage, iBand, 0, iLine,
    1004                 :                               nXSize, 1, psMatrix)) < 0 )
    1005                 :             {
    1006                 :                 CPLError( CE_Failure, CPLE_AppDefined, 
    1007                 :                     "Unable to write scanline %d of the component %d.\n", 
    1008               0 :                     iLine, iBand );
    1009               0 :                 jas_matrix_destroy( psMatrix );
    1010               0 :                 CPLFree( paiScanline );
    1011               0 :                 CPLFree( sComps );
    1012               0 :                 jas_image_destroy( psImage );
    1013               0 :                 return NULL;
    1014                 :             }
    1015                 :             
    1016            1492 :             if( eErr == CE_None &&
    1017                 :             !pfnProgress( ((iLine + 1) + iBand * nYSize) /
    1018                 :                           ((double) nYSize * nBands),
    1019                 :                          NULL, pProgressData) )
    1020                 :             {
    1021               0 :                 eErr = CE_Failure;
    1022                 :                 CPLError( CE_Failure, CPLE_UserInterrupt, 
    1023               0 :                       "User terminated CreateCopy()" );
    1024                 :             }
    1025                 :         }
    1026                 :     }
    1027                 : 
    1028                 : /* -------------------------------------------------------------------- */
    1029                 : /*       Read compression parameters and encode the image.              */
    1030                 : /* -------------------------------------------------------------------- */
    1031                 :     int             i, j;
    1032              11 :     const int       OPTSMAX = 4096;
    1033                 :     const char      *pszFormatName;
    1034                 :     char            pszOptionBuf[OPTSMAX + 1];
    1035                 : 
    1036                 :     const char  *apszComprOptions[]=
    1037                 :     {
    1038                 :         "imgareatlx",
    1039                 :         "imgareatly",
    1040                 :         "tilegrdtlx",
    1041                 :         "tilegrdtly",
    1042                 :         "tilewidth",
    1043                 :         "tileheight",
    1044                 :         "prcwidth",
    1045                 :         "prcheight",
    1046                 :         "cblkwidth",
    1047                 :         "cblkheight",
    1048                 :         "mode",
    1049                 :         "rate",
    1050                 :         "ilyrrates",
    1051                 :         "prg",
    1052                 :         "numrlvls",
    1053                 :         "sop",
    1054                 :         "eph",
    1055                 :         "lazy",
    1056                 :         "termall",
    1057                 :         "segsym",
    1058                 :         "vcausal",
    1059                 :         "pterm",
    1060                 :         "resetprob",
    1061                 :         "numgbits",
    1062                 :         NULL
    1063              11 :     };
    1064                 :     
    1065              11 :     pszFormatName = CSLFetchNameValue( papszOptions, "FORMAT" );
    1066              11 :     if ( !pszFormatName ||
    1067                 :          (!EQUALN( pszFormatName, "jp2", 3 ) &&
    1068                 :           !EQUALN( pszFormatName, "jpc", 3 ) ) )
    1069              10 :         pszFormatName = "jp2";
    1070                 :     
    1071              11 :     pszOptionBuf[0] = '\0';
    1072              11 :     if ( papszOptions )
    1073                 :     {
    1074               1 :         CPLDebug( "JPEG2000", "User supplied parameters:" );
    1075               2 :         for ( i = 0; papszOptions[i] != NULL; i++ )
    1076                 :         {
    1077               1 :             CPLDebug( "JPEG2000", "%s\n", papszOptions[i] );
    1078              25 :             for ( j = 0; apszComprOptions[j] != NULL; j++ )
    1079              24 :                 if( EQUALN( apszComprOptions[j], papszOptions[i],
    1080                 :                             strlen(apszComprOptions[j]) ) )
    1081                 :                 {
    1082                 :                     int m, n;
    1083                 : 
    1084               0 :                     n = strlen( pszOptionBuf );
    1085               0 :                     m = n + strlen( papszOptions[i] ) + 1;
    1086               0 :                     if ( m > OPTSMAX )
    1087               0 :                         break;
    1088               0 :                     if ( n > 0 )
    1089                 :                     {
    1090               0 :                         strcat( pszOptionBuf, "\n" );
    1091                 :                     }
    1092               0 :                     strcat( pszOptionBuf, papszOptions[i] );
    1093                 :                 }
    1094                 :         }
    1095                 :     }
    1096              11 :     CPLDebug( "JPEG2000", "Parameters, delivered to the JasPer library:" );
    1097              11 :     CPLDebug( "JPEG2000", "%s", pszOptionBuf );
    1098                 : 
    1099              11 :     if ( nBands == 1 )                      // Grayscale
    1100                 :     {
    1101               8 :         jas_image_setclrspc( psImage, JAS_CLRSPC_SGRAY );
    1102               8 :         jas_image_setcmpttype( psImage, 0, JAS_IMAGE_CT_GRAY_Y );
    1103                 :     }
    1104               5 :     else if ( nBands == 3 || nBands == 4 )  // Assume as RGB(A)
    1105                 :     {
    1106               2 :         jas_image_setclrspc( psImage, JAS_CLRSPC_SRGB );
    1107               9 :         for ( iBand = 0; iBand < nBands; iBand++ )
    1108                 :         {
    1109               7 :             poBand = poSrcDS->GetRasterBand( iBand + 1);
    1110               7 :             switch ( poBand->GetColorInterpretation() )
    1111                 :             {
    1112                 :                 case GCI_RedBand:
    1113               2 :                 jas_image_setcmpttype( psImage, iBand, JAS_IMAGE_CT_RGB_R );
    1114               2 :                 break;
    1115                 :                 case GCI_GreenBand:
    1116               2 :                 jas_image_setcmpttype( psImage, iBand, JAS_IMAGE_CT_RGB_G );
    1117               2 :                 break;
    1118                 :                 case GCI_BlueBand:
    1119               2 :                 jas_image_setcmpttype( psImage, iBand, JAS_IMAGE_CT_RGB_B );
    1120               2 :                 break;
    1121                 :                 case GCI_AlphaBand:
    1122               1 :                 jas_image_setcmpttype( psImage, iBand, JAS_IMAGE_CT_OPACITY );
    1123               1 :                 break;
    1124                 :                 default:
    1125               0 :                 jas_image_setcmpttype( psImage, iBand, JAS_IMAGE_CT_UNKNOWN );
    1126                 :                 break;
    1127                 :             }
    1128                 :         }
    1129                 :     }
    1130                 :     else                                    // Unknown
    1131                 :     {
    1132                 :         /* JAS_CLRSPC_UNKNOWN causes crashes in Jasper jp2_enc.c at line 231 */
    1133                 :         /* iccprof = jas_iccprof_createfromcmprof(jas_image_cmprof(image)); */
    1134                 :         /* but if we explictely set the cmprof, it does not work better */
    1135                 :         /* since it would abort at line 281 later ... */
    1136                 :         /* So the best option is to switch to gray colorspace */
    1137                 :         /* And we need to switch at the band level too, otherwise Kakadu or */
    1138                 :         /* JP2MrSID don't like it */
    1139                 :         //jas_image_setclrspc( psImage, JAS_CLRSPC_UNKNOWN );
    1140               1 :         jas_image_setclrspc( psImage, JAS_CLRSPC_SGRAY );
    1141               6 :         for ( iBand = 0; iBand < nBands; iBand++ )
    1142                 :             //jas_image_setcmpttype( psImage, iBand, JAS_IMAGE_CT_UNKNOWN );
    1143               5 :             jas_image_setcmpttype( psImage, iBand, JAS_IMAGE_CT_GRAY_Y );
    1144                 :     }
    1145                 : 
    1146                 : /* -------------------------------------------------------------------- */
    1147                 : /*      Set the GeoTIFF box if georeferencing is available, and this    */
    1148                 : /*      is a JP2 file.                                                  */
    1149                 : /* -------------------------------------------------------------------- */
    1150              11 :     if ( EQUALN( pszFormatName, "jp2", 3 ) )
    1151                 :     {
    1152                 : #ifdef HAVE_JASPER_UUID
    1153                 :         double  adfGeoTransform[6];
    1154              20 :         if( ((poSrcDS->GetGeoTransform(adfGeoTransform) == CE_None
    1155               9 :                  && (adfGeoTransform[0] != 0.0 
    1156               0 :                      || adfGeoTransform[1] != 1.0 
    1157               0 :                      || adfGeoTransform[2] != 0.0 
    1158               0 :                      || adfGeoTransform[3] != 0.0 
    1159               0 :                      || adfGeoTransform[4] != 0.0 
    1160               0 :                      || ABS(adfGeoTransform[5]) != 1.0))
    1161               1 :                 || poSrcDS->GetGCPCount() > 0) )
    1162                 :         {
    1163               9 :             GDALJP2Metadata oJP2Geo;
    1164                 : 
    1165               9 :             if( poSrcDS->GetGCPCount() > 0 )
    1166                 :             {
    1167               0 :                 oJP2Geo.SetProjection( poSrcDS->GetGCPProjection() );
    1168               0 :                 oJP2Geo.SetGCPs( poSrcDS->GetGCPCount(), poSrcDS->GetGCPs() );
    1169                 :             }
    1170                 :             else
    1171                 :             {
    1172               9 :                 oJP2Geo.SetProjection( poSrcDS->GetProjectionRef() );
    1173               9 :                 oJP2Geo.SetGeoTransform( adfGeoTransform );
    1174                 :             }
    1175                 : 
    1176               9 :             GDALJP2Box *poBox = oJP2Geo.CreateJP2GeoTIFF();
    1177               9 :             jp2_box_t  *box = jp2_box_create( JP2_BOX_UUID );
    1178               9 :             memcpy( box->data.uuid.uuid, poBox->GetUUID(), 16 );
    1179               9 :             box->data.uuid.datalen = poBox->GetDataLength() - 16;
    1180                 :             box->data.uuid.data =
    1181               9 :                 (uint_fast8_t *)jas_malloc( poBox->GetDataLength() - 16 );
    1182                 :             memcpy( box->data.uuid.data, poBox->GetWritableData() + 16,
    1183               9 :                     poBox->GetDataLength() - 16 );
    1184               9 :             delete poBox;
    1185               9 :             poBox = NULL;
    1186                 : 
    1187               9 :             if ( jp2_encode_uuid( psImage, psStream, pszOptionBuf, box) < 0 )
    1188                 :             {
    1189                 :                 CPLError( CE_Failure, CPLE_FileIO,
    1190               0 :                           "Unable to encode image %s.", pszFilename );
    1191               0 :                 jp2_box_destroy( box );
    1192               0 :                 jas_matrix_destroy( psMatrix );
    1193               0 :                 CPLFree( paiScanline );
    1194               0 :                 CPLFree( sComps );
    1195               0 :                 jas_image_destroy( psImage );
    1196               0 :                 return NULL;
    1197                 :             }
    1198               9 :             jp2_box_destroy( box );
    1199                 :         }
    1200                 :         else
    1201                 :         {
    1202                 : #endif
    1203               1 :             if ( jp2_encode( psImage, psStream, pszOptionBuf) < 0 )
    1204                 :             {
    1205                 :                 CPLError( CE_Failure, CPLE_FileIO,
    1206               0 :                           "Unable to encode image %s.", pszFilename );
    1207               0 :                 jas_matrix_destroy( psMatrix );
    1208               0 :                 CPLFree( paiScanline );
    1209               0 :                 CPLFree( sComps );
    1210               0 :                 jas_image_destroy( psImage );
    1211               0 :                 return NULL;
    1212                 :             }
    1213                 : #ifdef HAVE_JASPER_UUID
    1214                 :         }
    1215                 : #endif
    1216                 :     }
    1217                 :     else    // Write JPC code stream
    1218                 :     {
    1219               1 :         if ( jpc_encode(psImage, psStream, pszOptionBuf) < 0 )
    1220                 :         {
    1221                 :             CPLError( CE_Failure, CPLE_FileIO,
    1222               0 :                       "Unable to encode image %s.\n", pszFilename );
    1223               0 :             jas_matrix_destroy( psMatrix );
    1224               0 :             CPLFree( paiScanline );
    1225               0 :             CPLFree( sComps );
    1226               0 :             jas_image_destroy( psImage );
    1227               0 :             return NULL;
    1228                 :         }
    1229                 :     }
    1230                 : 
    1231              11 :     jas_stream_flush( psStream );
    1232                 :     
    1233              11 :     jas_matrix_destroy( psMatrix );
    1234              11 :     CPLFree( paiScanline );
    1235              11 :     CPLFree( sComps );
    1236              11 :     jas_image_destroy( psImage );
    1237              11 :     if ( jas_stream_close( psStream ) )
    1238                 :     {
    1239                 :         CPLError( CE_Failure, CPLE_FileIO, "Unable to close file %s.\n",
    1240               0 :                   pszFilename );
    1241               0 :         return NULL;
    1242                 :     }
    1243                 : 
    1244                 : /* -------------------------------------------------------------------- */
    1245                 : /*      Do we need a world file?                                        */
    1246                 : /* -------------------------------------------------------------------- */
    1247              11 :     if( CSLFetchBoolean( papszOptions, "WORLDFILE", FALSE ) )
    1248                 :     {
    1249                 :         double      adfGeoTransform[6];
    1250                 :         
    1251               0 :         poSrcDS->GetGeoTransform( adfGeoTransform );
    1252               0 :         GDALWriteWorldFile( pszFilename, "wld", adfGeoTransform );
    1253                 :     }
    1254                 : 
    1255                 : /* -------------------------------------------------------------------- */
    1256                 : /*      Re-open dataset, and copy any auxilary pam information.         */
    1257                 : /* -------------------------------------------------------------------- */
    1258              11 :     GDALOpenInfo oOpenInfo(pszFilename, GA_ReadOnly);
    1259              11 :     GDALPamDataset *poDS = (GDALPamDataset*) JPEG2000Dataset::Open(&oOpenInfo);
    1260                 : 
    1261              11 :     if( poDS )
    1262              11 :         poDS->CloneInfo( poSrcDS, GCIF_PAM_DEFAULT );
    1263                 : 
    1264              11 :     return poDS;
    1265                 : }
    1266                 : 
    1267                 : /************************************************************************/
    1268                 : /*                        GDALRegister_JPEG2000()                       */
    1269                 : /************************************************************************/
    1270                 : 
    1271             582 : void GDALRegister_JPEG2000()
    1272                 : 
    1273                 : {
    1274                 :     GDALDriver  *poDriver;
    1275                 :     
    1276             582 :     if (! GDAL_CHECK_VERSION("JPEG2000 driver"))
    1277               0 :         return;
    1278                 : 
    1279             582 :     if( GDALGetDriverByName( "JPEG2000" ) == NULL )
    1280                 :     {
    1281             561 :         poDriver = new GDALDriver();
    1282                 :         
    1283             561 :         poDriver->SetDescription( "JPEG2000" );
    1284                 :         poDriver->SetMetadataItem( GDAL_DMD_LONGNAME, 
    1285             561 :                                    "JPEG-2000 part 1 (ISO/IEC 15444-1)" );
    1286                 :         poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC, 
    1287             561 :                                    "frmt_jpeg2000.html" );
    1288                 :         poDriver->SetMetadataItem( GDAL_DMD_CREATIONDATATYPES, 
    1289             561 :                                    "Byte Int16 UInt16 Int32 UInt32" );
    1290             561 :         poDriver->SetMetadataItem( GDAL_DMD_MIMETYPE, "image/jp2" );
    1291             561 :         poDriver->SetMetadataItem( GDAL_DMD_EXTENSION, "jp2" );
    1292                 :         
    1293             561 :         poDriver->SetMetadataItem( GDAL_DCAP_VIRTUALIO, "YES" );
    1294                 : 
    1295             561 :         poDriver->pfnIdentify = JPEG2000Dataset::Identify;
    1296             561 :         poDriver->pfnOpen = JPEG2000Dataset::Open;
    1297             561 :         poDriver->pfnCreateCopy = JPEG2000CreateCopy;
    1298                 : 
    1299             561 :         GetGDALDriverManager()->RegisterDriver( poDriver );
    1300                 :     }
    1301                 : }
    1302                 : 

Generated by: LCOV version 1.7