LCOV - code coverage report
Current view: directory - frmts/jpeg2000 - jpeg2000dataset.cpp (source / functions) Found Hit Coverage
Test: gdal_filtered.info Lines: 444 327 73.6 %
Date: 2012-04-28 Functions: 23 17 73.9 %

       1                 : /******************************************************************************
       2                 :  * $Id: jpeg2000dataset.cpp 22678 2011-07-09 19:47:12Z 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 22678 2011-07-09 19:47:12Z 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             148 : JPEG2000RasterBand::JPEG2000RasterBand( JPEG2000Dataset *poDS, int nBand,
     234             148 :                 int iDepth, int bSignedness )
     235                 : 
     236                 : {
     237             148 :     this->poDS = poDS;
     238             148 :     poGDS = poDS;
     239             148 :     this->nBand = nBand;
     240             148 :     this->iDepth = iDepth;
     241             148 :     this->bSignedness = bSignedness;
     242                 : 
     243                 :     // XXX: JasPer can't handle data with depth > 32 bits
     244                 :     // Maximum possible depth for JPEG2000 is 38!
     245             148 :     switch ( bSignedness )
     246                 :     {
     247                 :         case 1:                         // Signed component
     248              12 :         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              12 :         else if (iDepth <= 16)
     253              12 :             this->eDataType = GDT_Int16;
     254               0 :         else if (iDepth <= 32)
     255               0 :             this->eDataType = GDT_Int32;
     256              12 :         break;
     257                 :         case 0:                         // Unsigned component
     258                 :         default:
     259             136 :         if (iDepth <= 8)
     260             118 :             this->eDataType = GDT_Byte;
     261              18 :         else if (iDepth <= 16)
     262              18 :             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             148 :     nBlockXSize = MIN(256, poDS->nRasterXSize);
     270             148 :     nBlockYSize = MIN(256, poDS->nRasterYSize);
     271             148 :     psMatrix = jas_matrix_create(nBlockYSize, nBlockXSize);
     272             148 : }
     273                 : 
     274                 : /************************************************************************/
     275                 : /*                         ~JPEG2000RasterBand()                        */
     276                 : /************************************************************************/
     277                 : 
     278             148 : JPEG2000RasterBand::~JPEG2000RasterBand()
     279                 : {
     280             148 :     if ( psMatrix )
     281             148 :         jas_matrix_destroy( psMatrix );    
     282             148 : }
     283                 : 
     284                 : /************************************************************************/
     285                 : /*                             IReadBlock()                             */
     286                 : /************************************************************************/
     287                 : 
     288             598 : 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             598 :     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             598 :     int nWidthToRead = MIN(nBlockXSize, poGDS->nRasterXSize - nBlockXOff * nBlockXSize);
     306             598 :     int nHeightToRead = MIN(nBlockYSize, poGDS->nRasterYSize - nBlockYOff * nBlockYSize);
     307                 : 
     308                 :     jas_image_readcmpt( poGDS->psImage, nBand - 1,
     309                 :                         nBlockXOff * nBlockXSize, nBlockYOff * nBlockYSize,
     310             598 :                         nWidthToRead, nHeightToRead, psMatrix );
     311                 : 
     312             598 :     int nWordSize = GDALGetDataTypeSize(eDataType) / 8;
     313             598 :     int nLineSize = nBlockXSize * nWordSize;
     314             598 :     GByte* ptr = (GByte*)pImage;
     315                 : 
     316                 :     /* Pad incomplete blocks at the right or bottom of the image */
     317             598 :     if (nWidthToRead != nBlockXSize || nHeightToRead != nBlockYSize)
     318             136 :         memset(pImage, 0, nLineSize * nBlockYSize);
     319                 : 
     320          138222 :     for( i = 0; i < nHeightToRead; i++, ptr += nLineSize )
     321                 :     {
     322        32715304 :         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        32577680 :             switch( eDataType )
     328                 :             {
     329                 :                 case GDT_Int16:
     330                 :                 {
     331            3200 :                     ((GInt16*)ptr)[j] = (GInt16)jas_matrix_get(psMatrix, i, j);
     332                 :                 }
     333            3200 :                 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          623296 :                     ((GUInt16*)ptr)[j] = (GUInt16)jas_matrix_get(psMatrix, i, j);
     342                 :                 }
     343          623296 :                 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        31951184 :                     ((GByte*)ptr)[j] = (GByte)jas_matrix_get(psMatrix, i, j);
     353                 :                 }
     354                 :                 break;
     355                 :             }
     356                 :         }
     357                 :     }
     358                 : 
     359             598 :     return CE_None;
     360                 : }
     361                 : 
     362                 : /************************************************************************/
     363                 : /*                       GetColorInterpretation()                       */
     364                 : /************************************************************************/
     365                 : 
     366              84 : GDALColorInterp JPEG2000RasterBand::GetColorInterpretation()
     367                 : {
     368                 :     // Decode image from the stream, if not yet
     369              84 :     if ( !poGDS->DecodeImage() )
     370                 :     {
     371               0 :         return GCI_Undefined;
     372                 :     }
     373                 :     
     374              84 :     if ( jas_clrspc_fam( jas_image_clrspc( poGDS->psImage ) ) ==
     375                 :          JAS_CLRSPC_FAM_GRAY )
     376              42 :         return GCI_GrayIndex;
     377              42 :     else if ( jas_clrspc_fam( jas_image_clrspc( poGDS->psImage ) ) == 
     378                 :               JAS_CLRSPC_FAM_RGB )
     379                 :     {
     380              42 :         switch ( jas_image_cmpttype( poGDS->psImage, nBand - 1 ) )
     381                 :         {
     382                 :             case JAS_IMAGE_CT_RGB_R:
     383              10 :                 return GCI_RedBand;
     384                 :             case JAS_IMAGE_CT_RGB_G:
     385              10 :                 return GCI_GreenBand;
     386                 :             case JAS_IMAGE_CT_RGB_B:
     387              10 :                 return GCI_BlueBand;
     388                 :             case JAS_IMAGE_CT_OPACITY:
     389              10 :                 return GCI_AlphaBand;
     390                 :             default:
     391               2 :                 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              90 : JPEG2000Dataset::JPEG2000Dataset()
     409                 : {
     410              90 :     psStream = NULL;
     411              90 :     psImage = NULL;
     412              90 :     nBands = 0;
     413              90 :     pszProjection = CPLStrdup("");
     414              90 :     nGCPCount = 0;
     415              90 :     pasGCPList = NULL;
     416              90 :     bGeoTransformValid = FALSE;
     417              90 :     adfGeoTransform[0] = 0.0;
     418              90 :     adfGeoTransform[1] = 1.0;
     419              90 :     adfGeoTransform[2] = 0.0;
     420              90 :     adfGeoTransform[3] = 0.0;
     421              90 :     adfGeoTransform[4] = 0.0;
     422              90 :     adfGeoTransform[5] = 1.0;
     423              90 :     bAlreadyDecoded = FALSE;
     424                 :     
     425              90 :     poDriver = (GDALDriver *)GDALGetDriverByName("JPEG2000");
     426              90 : }
     427                 : 
     428                 : /************************************************************************/
     429                 : /*                            ~JPEG2000Dataset()                        */
     430                 : /************************************************************************/
     431                 : 
     432              90 : JPEG2000Dataset::~JPEG2000Dataset()
     433                 : 
     434                 : {
     435              90 :     FlushCache();
     436                 : 
     437              90 :     if ( psStream )
     438              90 :         jas_stream_close( psStream );
     439              90 :     if ( psImage )
     440              82 :         jas_image_destroy( psImage );
     441                 : 
     442              90 :     if ( pszProjection )
     443              90 :         CPLFree( pszProjection );
     444              90 :     if( nGCPCount > 0 )
     445                 :     {
     446               4 :         GDALDeinitGCPs( nGCPCount, pasGCPList );
     447               4 :         CPLFree( pasGCPList );
     448                 :     }
     449              90 : }
     450                 : 
     451                 : /************************************************************************/
     452                 : /*                             DecodeImage()                            */
     453                 : /************************************************************************/
     454             710 : int JPEG2000Dataset::DecodeImage()
     455                 : {
     456             710 :     if (bAlreadyDecoded)
     457             628 :         return psImage != NULL;
     458                 :         
     459              82 :     bAlreadyDecoded = TRUE;    
     460              82 :     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              82 :     if (nBands != 0)
     470                 :     {
     471              54 :         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             108 :         if (nRasterXSize != jas_image_cmptwidth( psImage, 0 ) ||
     483              54 :             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             142 :         for ( iBand = 0; iBand < nBands; iBand++ )
     498                 :         {
     499              88 :             JPEG2000RasterBand* poBand = (JPEG2000RasterBand*) GetRasterBand(iBand+1);
     500             176 :             if (poBand->iDepth != jas_image_cmptprec( psImage, iBand ) ||
     501              88 :                 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              82 :     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               2 :         CPLDebug( "JPEG2000", "forcing conversion to sRGB");
     521               2 :         if (!(psRGBProf = jas_cmprof_createfromclrspc(JAS_CLRSPC_SRGB))) {
     522               0 :             CPLDebug( "JPEG2000", "cannot create sRGB profile");
     523               0 :             return TRUE;
     524                 :         }
     525               2 :         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               2 :         jas_image_destroy(psImage);
     531               2 :         jas_cmprof_destroy(psRGBProf);
     532               2 :         psImage = psRGBImage;
     533                 :     }
     534                 :     
     535              82 :     return TRUE;
     536                 : }
     537                 : 
     538                 : 
     539                 : /************************************************************************/
     540                 : /*                          GetProjectionRef()                          */
     541                 : /************************************************************************/
     542                 : 
     543              68 : const char *JPEG2000Dataset::GetProjectionRef()
     544                 : 
     545                 : {
     546              68 :     return( pszProjection );
     547                 : }
     548                 : 
     549                 : /************************************************************************/
     550                 : /*                          GetGeoTransform()                           */
     551                 : /************************************************************************/
     552                 : 
     553              56 : CPLErr JPEG2000Dataset::GetGeoTransform( double * padfTransform )
     554                 : {
     555              56 :     if( bGeoTransformValid )
     556                 :     {
     557              54 :         memcpy( padfTransform, adfGeoTransform, sizeof(adfGeoTransform[0]) * 6 );
     558              54 :         return CE_None;
     559                 :     }
     560                 :     else
     561               2 :         return CE_Failure;
     562                 : }
     563                 : 
     564                 : /************************************************************************/
     565                 : /*                            GetGCPCount()                             */
     566                 : /************************************************************************/
     567                 : 
     568              16 : int JPEG2000Dataset::GetGCPCount()
     569                 : 
     570                 : {
     571              16 :     return nGCPCount;
     572                 : }
     573                 : 
     574                 : /************************************************************************/
     575                 : /*                          GetGCPProjection()                          */
     576                 : /************************************************************************/
     577                 : 
     578               2 : const char *JPEG2000Dataset::GetGCPProjection()
     579                 : 
     580                 : {
     581               2 :     if( nGCPCount > 0 )
     582               2 :         return pszProjection;
     583                 :     else
     584               0 :         return "";
     585                 : }
     586                 : 
     587                 : /************************************************************************/
     588                 : /*                               GetGCP()                               */
     589                 : /************************************************************************/
     590                 : 
     591               2 : const GDAL_GCP *JPEG2000Dataset::GetGCPs()
     592                 : 
     593                 : {
     594               2 :     return pasGCPList;
     595                 : }
     596                 : 
     597             114 : static void JPEG2000Init()
     598                 : {
     599                 :     static int bHasInit = FALSE;
     600             114 :     if (!bHasInit)
     601                 :     {
     602               6 :         bHasInit = TRUE;
     603               6 :         jas_init();
     604                 :     }
     605             114 : }
     606                 : 
     607                 : /************************************************************************/
     608                 : /*                            Identify()                                */
     609                 : /************************************************************************/
     610                 : 
     611           22666 : 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           22666 :     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              90 :         return TRUE;
     628                 :     
     629                 :     else
     630           22576 :         return FALSE;
     631                 : }
     632                 : 
     633                 : /************************************************************************/
     634                 : /*                                Open()                                */
     635                 : /************************************************************************/
     636                 : 
     637            3806 : GDALDataset *JPEG2000Dataset::Open( GDALOpenInfo * poOpenInfo )
     638                 : 
     639                 : {
     640                 :     int         iFormat;
     641            3806 :     char        *pszFormatName = NULL;
     642                 :     jas_stream_t *sS;
     643                 :     
     644            3806 :     if (!Identify(poOpenInfo))
     645            3716 :         return NULL;
     646                 : 
     647              90 :     JPEG2000Init();
     648              90 :     if( !(sS = JPEG2000_VSIL_fopen( poOpenInfo->pszFilename, "rb" )) )
     649                 :     {
     650               0 :         return NULL;
     651                 :     }
     652                 : 
     653              90 :     iFormat = jas_image_getfmt( sS );
     654              90 :     if ( !(pszFormatName = jas_image_fmttostr( iFormat )) )
     655                 :     {
     656               0 :         jas_stream_close( sS );
     657               0 :         return NULL;
     658                 :     }
     659              90 :     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              90 :     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              90 :     int                 *paiDepth = NULL, *pabSignedness = NULL;
     686                 :     int                 iBand;
     687                 : 
     688              90 :     poDS = new JPEG2000Dataset();
     689                 : 
     690              90 :     poDS->psStream = sS;
     691              90 :     poDS->iFormat = iFormat;
     692                 : 
     693              90 :     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              62 :         box = 0;
     699             640 :         while ( ( box = jp2_box_get(poDS->psStream) ) )
     700                 :         {
     701             516 :             switch (box->type)
     702                 :             {
     703                 :                 case JP2_BOX_IHDR:
     704              62 :                 poDS->nBands = box->data.ihdr.numcmpts;
     705              62 :                 poDS->nRasterXSize = box->data.ihdr.width;
     706              62 :                 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              62 :                           (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              62 :                 if ( box->data.ihdr.bpc != 255 )
     716                 :                 {
     717              58 :                     paiDepth = (int *)CPLMalloc(poDS->nBands * sizeof(int));
     718              58 :                     pabSignedness = (int *)CPLMalloc(poDS->nBands * sizeof(int));
     719             130 :                     for ( iBand = 0; iBand < poDS->nBands; iBand++ )
     720                 :                     {
     721              72 :                         paiDepth[iBand] = (box->data.ihdr.bpc & 0x7F) + 1;
     722              72 :                         pabSignedness[iBand] = box->data.ihdr.bpc >> 7;
     723                 :                         CPLDebug( "JPEG2000",
     724                 :                                   "Component %d: bpp=%d, signedness=%d",
     725              72 :                                   iBand, paiDepth[iBand], pabSignedness[iBand] );
     726                 :                     }
     727                 :                 }
     728              62 :                 break;
     729                 : 
     730                 :                 case JP2_BOX_BPCC:
     731               4 :                 CPLDebug( "JPEG2000", "BPCC box found. Dump:" );
     732               4 :                 if ( !paiDepth && !pabSignedness )
     733                 :                 {
     734                 :                     paiDepth = (int *)
     735               4 :                         CPLMalloc( box->data.bpcc.numcmpts * sizeof(int) );
     736                 :                     pabSignedness = (int *)
     737               4 :                         CPLMalloc( box->data.bpcc.numcmpts * sizeof(int) );
     738              20 :                     for( iBand = 0; iBand < (int)box->data.bpcc.numcmpts; iBand++ )
     739                 :                     {
     740              16 :                         paiDepth[iBand] = (box->data.bpcc.bpcs[iBand] & 0x7F) + 1;
     741              16 :                         pabSignedness[iBand] = box->data.bpcc.bpcs[iBand] >> 7;
     742                 :                         CPLDebug( "JPEG2000",
     743                 :                                   "Component %d: bpp=%d, signedness=%d",
     744              16 :                                   iBand, paiDepth[iBand], pabSignedness[iBand] );
     745                 :                     }
     746                 :                 }
     747               4 :                 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               4 :                           (int)box->data.pclr.numlutents, box->data.pclr.numchans );
     754               4 :                 poDS->nBands = box->data.pclr.numchans;
     755               4 :                 if ( paiDepth )
     756               4 :                     CPLFree( paiDepth );
     757               4 :                 if ( pabSignedness )
     758               4 :                     CPLFree( pabSignedness );
     759                 :                 paiDepth = (int *)
     760               4 :                         CPLMalloc( box->data.pclr.numchans * sizeof(int) );
     761                 :                 pabSignedness = (int *)
     762               4 :                         CPLMalloc( box->data.pclr.numchans * sizeof(int) );
     763              16 :                 for( iBand = 0; iBand < (int)box->data.pclr.numchans; iBand++ )
     764                 :                 {
     765              12 :                     paiDepth[iBand] = (box->data.pclr.bpc[iBand] & 0x7F) + 1;
     766              12 :                     pabSignedness[iBand] = box->data.pclr.bpc[iBand] >> 7;
     767                 :                     CPLDebug( "JPEG2000",
     768                 :                               "Component %d: bpp=%d, signedness=%d",
     769              12 :                               iBand, paiDepth[iBand], pabSignedness[iBand] );
     770                 :                 }
     771                 :                 break;
     772                 :             }
     773             516 :             jp2_box_destroy( box );
     774             516 :             box = 0;
     775                 :         }
     776              62 :         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              62 :         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              28 :         if ( !poDS->DecodeImage() )
     792                 :         {
     793               0 :             delete poDS;
     794               0 :             return NULL;
     795                 :         }
     796                 : 
     797              28 :         poDS->nBands = jas_image_numcmpts( poDS->psImage );
     798              28 :         poDS->nRasterXSize = jas_image_cmptwidth( poDS->psImage, 0 );
     799              28 :         poDS->nRasterYSize = jas_image_cmptheight( poDS->psImage, 0 );
     800              28 :         paiDepth = (int *)CPLMalloc( poDS->nBands * sizeof(int) );
     801              28 :         pabSignedness = (int *)CPLMalloc( poDS->nBands * sizeof(int) );
     802              80 :         for ( iBand = 0; iBand < poDS->nBands; iBand++ )
     803                 :         {
     804              52 :             paiDepth[iBand] = jas_image_cmptprec( poDS->psImage, iBand );
     805              52 :             pabSignedness[iBand] = jas_image_cmptsgnd( poDS->psImage, iBand );
     806                 :         }
     807                 :     }
     808                 :     
     809              90 :     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             476 :     for( iBand = 1; iBand <= poDS->nBands; iBand++ )
     823                 :     {
     824                 :         poDS->SetBand( iBand, new JPEG2000RasterBand( poDS, iBand,
     825             148 :             paiDepth[iBand - 1], pabSignedness[iBand - 1] ) );
     826                 :         
     827                 :     }
     828                 :     
     829              90 :     if ( paiDepth )
     830              90 :         CPLFree( paiDepth );
     831              90 :     if ( pabSignedness )
     832              90 :         CPLFree( pabSignedness );
     833                 : 
     834                 : /* -------------------------------------------------------------------- */
     835                 : /*      Check for georeferencing information.                           */
     836                 : /* -------------------------------------------------------------------- */
     837              90 :     GDALJP2Metadata oJP2Geo;
     838                 :     
     839              90 :     if( oJP2Geo.ReadAndParse( poOpenInfo->pszFilename ) )
     840                 :     {
     841              56 :         if ( poDS->pszProjection )
     842              56 :             CPLFree( poDS->pszProjection );
     843              56 :         poDS->pszProjection = CPLStrdup(oJP2Geo.pszProjection);
     844              56 :         poDS->bGeoTransformValid = oJP2Geo.bHaveGeoTransform;
     845                 :         memcpy( poDS->adfGeoTransform, oJP2Geo.adfGeoTransform, 
     846              56 :                 sizeof(double) * 6 );
     847              56 :         poDS->nGCPCount = oJP2Geo.nGCPCount;
     848                 :         poDS->pasGCPList =
     849              56 :             GDALDuplicateGCPs( oJP2Geo.nGCPCount, oJP2Geo.pasGCPList );
     850                 :     }
     851                 : 
     852              90 :     if (oJP2Geo.pszXMPMetadata)
     853                 :     {
     854                 :         char *apszMDList[2];
     855               2 :         apszMDList[0] = (char *) oJP2Geo.pszXMPMetadata;
     856               2 :         apszMDList[1] = NULL;
     857               2 :         poDS->SetMetadata(apszMDList, "xml:XMP");
     858                 :     }
     859                 : 
     860                 : /* -------------------------------------------------------------------- */
     861                 : /*      Initialize any PAM information.                                 */
     862                 : /* -------------------------------------------------------------------- */
     863              90 :     poDS->SetDescription( poOpenInfo->pszFilename );
     864              90 :     poDS->TryLoadXML();
     865                 : 
     866                 : /* -------------------------------------------------------------------- */
     867                 : /*      Check for overviews.                                            */
     868                 : /* -------------------------------------------------------------------- */
     869              90 :     poDS->oOvManager.Initialize( poDS, poOpenInfo->pszFilename );
     870                 :     
     871              90 :     return( poDS );
     872                 : }
     873                 : 
     874                 : /************************************************************************/
     875                 : /*                      JPEG2000CreateCopy()                            */
     876                 : /************************************************************************/
     877                 : 
     878                 : static GDALDataset *
     879              26 : JPEG2000CreateCopy( const char * pszFilename, GDALDataset *poSrcDS, 
     880                 :                     int bStrict, char ** papszOptions, 
     881                 :                     GDALProgressFunc pfnProgress, void * pProgressData )
     882                 : 
     883                 : {
     884              26 :     int  nBands = poSrcDS->GetRasterCount();
     885              26 :     int  nXSize = poSrcDS->GetRasterXSize();
     886              26 :     int  nYSize = poSrcDS->GetRasterYSize();
     887                 : 
     888              26 :     if( nBands == 0 )
     889                 :     {
     890                 :         CPLError( CE_Failure, CPLE_NotSupported,
     891               2 :                   "Unable to export files with zero bands." );
     892               2 :         return NULL;
     893                 :     }
     894                 : 
     895              24 :     if (poSrcDS->GetRasterBand(1)->GetColorTable() != NULL)
     896                 :     {
     897                 :         CPLError( (bStrict) ? CE_Failure : CE_Warning, CPLE_NotSupported, 
     898                 :                   "JPEG2000 driver ignores color table. "
     899                 :                   "The source raster band will be considered as grey level.\n"
     900               0 :                   "Consider using color table expansion (-expand option in gdal_translate)\n");
     901               0 :         if (bStrict)
     902               0 :             return NULL;
     903                 :     }
     904                 :     
     905              24 :     if( !pfnProgress( 0.0, NULL, pProgressData ) )
     906               0 :         return NULL;
     907                 : 
     908                 : /* -------------------------------------------------------------------- */
     909                 : /*      Create the dataset.                                             */
     910                 : /* -------------------------------------------------------------------- */
     911                 :     int                 iBand;
     912                 :     jas_stream_t        *psStream;
     913                 :     jas_image_t         *psImage;
     914                 : 
     915              24 :     JPEG2000Init();
     916              24 :     const char* pszAccess = EQUALN(pszFilename, "/vsisubfile/", 12) ? "r+b" : "w+b";
     917              24 :     if( !(psStream = JPEG2000_VSIL_fopen( pszFilename, pszAccess) ) )
     918                 :     {
     919                 :         CPLError( CE_Failure, CPLE_FileIO, "Unable to create file %s.\n", 
     920               4 :                   pszFilename );
     921               4 :         return NULL;
     922                 :     }
     923                 :     
     924              20 :     if ( !(psImage = jas_image_create0()) )
     925                 :     {
     926                 :         CPLError( CE_Failure, CPLE_OutOfMemory, "Unable to create image %s.\n", 
     927               0 :                   pszFilename );
     928               0 :         return NULL;
     929                 :     }
     930                 : 
     931                 : /* -------------------------------------------------------------------- */
     932                 : /*      Loop over image, copying image data.                            */
     933                 : /* -------------------------------------------------------------------- */
     934                 :     GDALRasterBand      *poBand;
     935                 :     GUInt32             *paiScanline;
     936                 :     int                 iLine, iPixel;
     937              20 :     CPLErr              eErr = CE_None;
     938                 :     jas_matrix_t        *psMatrix;
     939                 :     jas_image_cmptparm_t *sComps; // Array of pointers to image components
     940                 : 
     941                 :     sComps = (jas_image_cmptparm_t*)
     942              20 :         CPLMalloc( nBands * sizeof(jas_image_cmptparm_t) );
     943                 :   
     944              20 :     if ( !(psMatrix = jas_matrix_create( 1, nXSize )) )
     945                 :     {
     946                 :         CPLError( CE_Failure, CPLE_OutOfMemory, 
     947               0 :                   "Unable to create matrix with size %dx%d.\n", 1, nYSize );
     948               0 :         CPLFree( sComps );
     949               0 :         jas_image_destroy( psImage );
     950               0 :         return NULL;
     951                 :     }
     952                 :     paiScanline = (GUInt32 *) CPLMalloc( nXSize *
     953              20 :                             GDALGetDataTypeSize(GDT_UInt32) / 8 );
     954                 :     
     955              50 :     for ( iBand = 0; iBand < nBands; iBand++ )
     956                 :     {
     957              30 :         poBand = poSrcDS->GetRasterBand( iBand + 1);
     958                 :         
     959              30 :         sComps[iBand].tlx = sComps[iBand].tly = 0;
     960              30 :         sComps[iBand].hstep = sComps[iBand].vstep = 1;
     961              30 :         sComps[iBand].width = nXSize;
     962              30 :         sComps[iBand].height = nYSize;
     963              30 :         sComps[iBand].prec = GDALGetDataTypeSize( poBand->GetRasterDataType() );
     964              30 :         switch ( poBand->GetRasterDataType() )
     965                 :         {
     966                 :             case GDT_Int16:
     967                 :             case GDT_Int32:
     968                 :             case GDT_Float32:
     969                 :             case GDT_Float64:
     970               4 :             sComps[iBand].sgnd = 1;
     971               4 :             break;
     972                 :             case GDT_Byte:
     973                 :             case GDT_UInt16:
     974                 :             case GDT_UInt32:
     975                 :             default:
     976              26 :             sComps[iBand].sgnd = 0;
     977                 :             break;
     978                 :         }
     979              30 :         jas_image_addcmpt(psImage, iBand, sComps);
     980                 : 
     981            1734 :         for( iLine = 0; eErr == CE_None && iLine < nYSize; iLine++ )
     982                 :         {
     983                 :             eErr = poBand->RasterIO( GF_Read, 0, iLine, nXSize, 1, 
     984                 :                               paiScanline, nXSize, 1, GDT_UInt32,
     985            1704 :                               sizeof(GUInt32), sizeof(GUInt32) * nXSize );
     986          569592 :             for ( iPixel = 0; iPixel < nXSize; iPixel++ )
     987          567888 :                 jas_matrix_setv( psMatrix, iPixel, paiScanline[iPixel] );
     988                 :             
     989            1704 :             if( (jas_image_writecmpt(psImage, iBand, 0, iLine,
     990                 :                               nXSize, 1, psMatrix)) < 0 )
     991                 :             {
     992                 :                 CPLError( CE_Failure, CPLE_AppDefined, 
     993                 :                     "Unable to write scanline %d of the component %d.\n", 
     994               0 :                     iLine, iBand );
     995               0 :                 jas_matrix_destroy( psMatrix );
     996               0 :                 CPLFree( paiScanline );
     997               0 :                 CPLFree( sComps );
     998               0 :                 jas_image_destroy( psImage );
     999               0 :                 return NULL;
    1000                 :             }
    1001                 :             
    1002            1704 :             if( eErr == CE_None &&
    1003                 :             !pfnProgress( ((iLine + 1) + iBand * nYSize) /
    1004                 :                           ((double) nYSize * nBands),
    1005                 :                          NULL, pProgressData) )
    1006                 :             {
    1007               0 :                 eErr = CE_Failure;
    1008                 :                 CPLError( CE_Failure, CPLE_UserInterrupt, 
    1009               0 :                       "User terminated CreateCopy()" );
    1010                 :             }
    1011                 :         }
    1012                 :     }
    1013                 : 
    1014                 : /* -------------------------------------------------------------------- */
    1015                 : /*       Read compression parameters and encode the image.              */
    1016                 : /* -------------------------------------------------------------------- */
    1017                 :     int             i, j;
    1018              20 :     const int       OPTSMAX = 4096;
    1019                 :     const char      *pszFormatName;
    1020                 :     char            pszOptionBuf[OPTSMAX + 1];
    1021                 : 
    1022                 :     const char  *apszComprOptions[]=
    1023                 :     {
    1024                 :         "imgareatlx",
    1025                 :         "imgareatly",
    1026                 :         "tilegrdtlx",
    1027                 :         "tilegrdtly",
    1028                 :         "tilewidth",
    1029                 :         "tileheight",
    1030                 :         "prcwidth",
    1031                 :         "prcheight",
    1032                 :         "cblkwidth",
    1033                 :         "cblkheight",
    1034                 :         "mode",
    1035                 :         "rate",
    1036                 :         "ilyrrates",
    1037                 :         "prg",
    1038                 :         "numrlvls",
    1039                 :         "sop",
    1040                 :         "eph",
    1041                 :         "lazy",
    1042                 :         "termall",
    1043                 :         "segsym",
    1044                 :         "vcausal",
    1045                 :         "pterm",
    1046                 :         "resetprob",
    1047                 :         "numgbits",
    1048                 :         NULL
    1049              20 :     };
    1050                 :     
    1051              20 :     pszFormatName = CSLFetchNameValue( papszOptions, "FORMAT" );
    1052              20 :     if ( !pszFormatName ||
    1053                 :          (!EQUALN( pszFormatName, "jp2", 3 ) &&
    1054                 :           !EQUALN( pszFormatName, "jpc", 3 ) ) )
    1055              18 :         pszFormatName = "jp2";
    1056                 :     
    1057              20 :     pszOptionBuf[0] = '\0';
    1058              20 :     if ( papszOptions )
    1059                 :     {
    1060               2 :         CPLDebug( "JPEG2000", "User supplied parameters:" );
    1061               4 :         for ( i = 0; papszOptions[i] != NULL; i++ )
    1062                 :         {
    1063               2 :             CPLDebug( "JPEG2000", "%s\n", papszOptions[i] );
    1064              50 :             for ( j = 0; apszComprOptions[j] != NULL; j++ )
    1065              48 :                 if( EQUALN( apszComprOptions[j], papszOptions[i],
    1066                 :                             strlen(apszComprOptions[j]) ) )
    1067                 :                 {
    1068                 :                     int m, n;
    1069                 : 
    1070               0 :                     n = strlen( pszOptionBuf );
    1071               0 :                     m = n + strlen( papszOptions[i] ) + 1;
    1072               0 :                     if ( m > OPTSMAX )
    1073               0 :                         break;
    1074               0 :                     if ( n > 0 )
    1075                 :                     {
    1076               0 :                         strcat( pszOptionBuf, "\n" );
    1077                 :                     }
    1078               0 :                     strcat( pszOptionBuf, papszOptions[i] );
    1079                 :                 }
    1080                 :         }
    1081                 :     }
    1082              20 :     CPLDebug( "JPEG2000", "Parameters, delivered to the JasPer library:" );
    1083              20 :     CPLDebug( "JPEG2000", "%s", pszOptionBuf );
    1084                 : 
    1085              20 :     if ( nBands == 1 )                      // Grayscale
    1086                 :     {
    1087              16 :         jas_image_setclrspc( psImage, JAS_CLRSPC_SGRAY );
    1088              16 :         jas_image_setcmpttype( psImage, 0, JAS_IMAGE_CT_GRAY_Y );
    1089                 :     }
    1090               8 :     else if ( nBands == 3 || nBands == 4 )  // Assume as RGB(A)
    1091                 :     {
    1092               4 :         jas_image_setclrspc( psImage, JAS_CLRSPC_SRGB );
    1093              18 :         for ( iBand = 0; iBand < nBands; iBand++ )
    1094                 :         {
    1095              14 :             poBand = poSrcDS->GetRasterBand( iBand + 1);
    1096              14 :             switch ( poBand->GetColorInterpretation() )
    1097                 :             {
    1098                 :                 case GCI_RedBand:
    1099               4 :                 jas_image_setcmpttype( psImage, iBand, JAS_IMAGE_CT_RGB_R );
    1100               4 :                 break;
    1101                 :                 case GCI_GreenBand:
    1102               4 :                 jas_image_setcmpttype( psImage, iBand, JAS_IMAGE_CT_RGB_G );
    1103               4 :                 break;
    1104                 :                 case GCI_BlueBand:
    1105               4 :                 jas_image_setcmpttype( psImage, iBand, JAS_IMAGE_CT_RGB_B );
    1106               4 :                 break;
    1107                 :                 case GCI_AlphaBand:
    1108               2 :                 jas_image_setcmpttype( psImage, iBand, JAS_IMAGE_CT_OPACITY );
    1109               2 :                 break;
    1110                 :                 default:
    1111               0 :                 jas_image_setcmpttype( psImage, iBand, JAS_IMAGE_CT_UNKNOWN );
    1112                 :                 break;
    1113                 :             }
    1114                 :         }
    1115                 :     }
    1116                 :     else                                    // Unknown
    1117                 :     {
    1118               0 :         jas_image_setclrspc( psImage, JAS_CLRSPC_UNKNOWN );
    1119               0 :         for ( iBand = 0; iBand < nBands; iBand++ )
    1120               0 :             jas_image_setcmpttype( psImage, iBand, JAS_IMAGE_CT_UNKNOWN );
    1121                 :     }
    1122                 : 
    1123                 : /* -------------------------------------------------------------------- */
    1124                 : /*      Set the GeoTIFF box if georeferencing is available, and this    */
    1125                 : /*      is a JP2 file.                                                  */
    1126                 : /* -------------------------------------------------------------------- */
    1127              20 :     if ( EQUALN( pszFormatName, "jp2", 3 ) )
    1128                 :     {
    1129                 : #ifdef HAVE_JASPER_UUID
    1130                 :         double  adfGeoTransform[6];
    1131              36 :         if( ((poSrcDS->GetGeoTransform(adfGeoTransform) == CE_None
    1132              18 :                  && (adfGeoTransform[0] != 0.0 
    1133               0 :                      || adfGeoTransform[1] != 1.0 
    1134               0 :                      || adfGeoTransform[2] != 0.0 
    1135               0 :                      || adfGeoTransform[3] != 0.0 
    1136               0 :                      || adfGeoTransform[4] != 0.0 
    1137               0 :                      || ABS(adfGeoTransform[5]) != 1.0))
    1138               0 :                 || poSrcDS->GetGCPCount() > 0) )
    1139                 :         {
    1140              18 :             GDALJP2Metadata oJP2Geo;
    1141                 : 
    1142              18 :             if( poSrcDS->GetGCPCount() > 0 )
    1143                 :             {
    1144               0 :                 oJP2Geo.SetProjection( poSrcDS->GetGCPProjection() );
    1145               0 :                 oJP2Geo.SetGCPs( poSrcDS->GetGCPCount(), poSrcDS->GetGCPs() );
    1146                 :             }
    1147                 :             else
    1148                 :             {
    1149              18 :                 oJP2Geo.SetProjection( poSrcDS->GetProjectionRef() );
    1150              18 :                 oJP2Geo.SetGeoTransform( adfGeoTransform );
    1151                 :             }
    1152                 : 
    1153              18 :             GDALJP2Box *poBox = oJP2Geo.CreateJP2GeoTIFF();
    1154              18 :             jp2_box_t  *box = jp2_box_create( JP2_BOX_UUID );
    1155              18 :             memcpy( box->data.uuid.uuid, poBox->GetUUID(), 16 );
    1156              18 :             box->data.uuid.datalen = poBox->GetDataLength() - 16;
    1157                 :             box->data.uuid.data =
    1158              18 :                 (uint_fast8_t *)jas_malloc( poBox->GetDataLength() - 16 );
    1159                 :             memcpy( box->data.uuid.data, poBox->GetWritableData() + 16,
    1160              18 :                     poBox->GetDataLength() - 16 );
    1161              18 :             delete poBox;
    1162              18 :             poBox = NULL;
    1163                 : 
    1164              18 :             if ( jp2_encode_uuid( psImage, psStream, pszOptionBuf, box) < 0 )
    1165                 :             {
    1166                 :                 CPLError( CE_Failure, CPLE_FileIO,
    1167               0 :                           "Unable to encode image %s.", pszFilename );
    1168               0 :                 jp2_box_destroy( box );
    1169               0 :                 jas_matrix_destroy( psMatrix );
    1170               0 :                 CPLFree( paiScanline );
    1171               0 :                 CPLFree( sComps );
    1172               0 :                 jas_image_destroy( psImage );
    1173               0 :                 return NULL;
    1174                 :             }
    1175              18 :             jp2_box_destroy( box );
    1176                 :         }
    1177                 :         else
    1178                 :         {
    1179                 : #endif
    1180               0 :             if ( jp2_encode( psImage, psStream, pszOptionBuf) < 0 )
    1181                 :             {
    1182                 :                 CPLError( CE_Failure, CPLE_FileIO,
    1183               0 :                           "Unable to encode image %s.", pszFilename );
    1184               0 :                 jas_matrix_destroy( psMatrix );
    1185               0 :                 CPLFree( paiScanline );
    1186               0 :                 CPLFree( sComps );
    1187               0 :                 jas_image_destroy( psImage );
    1188               0 :                 return NULL;
    1189                 :             }
    1190                 : #ifdef HAVE_JASPER_UUID
    1191                 :         }
    1192                 : #endif
    1193                 :     }
    1194                 :     else    // Write JPC code stream
    1195                 :     {
    1196               2 :         if ( jpc_encode(psImage, psStream, pszOptionBuf) < 0 )
    1197                 :         {
    1198                 :             CPLError( CE_Failure, CPLE_FileIO,
    1199               0 :                       "Unable to encode image %s.\n", pszFilename );
    1200               0 :             jas_matrix_destroy( psMatrix );
    1201               0 :             CPLFree( paiScanline );
    1202               0 :             CPLFree( sComps );
    1203               0 :             jas_image_destroy( psImage );
    1204               0 :             return NULL;
    1205                 :         }
    1206                 :     }
    1207                 : 
    1208              20 :     jas_stream_flush( psStream );
    1209                 :     
    1210              20 :     jas_matrix_destroy( psMatrix );
    1211              20 :     CPLFree( paiScanline );
    1212              20 :     CPLFree( sComps );
    1213              20 :     jas_image_destroy( psImage );
    1214              20 :     if ( jas_stream_close( psStream ) )
    1215                 :     {
    1216                 :         CPLError( CE_Failure, CPLE_FileIO, "Unable to close file %s.\n",
    1217               0 :                   pszFilename );
    1218               0 :         return NULL;
    1219                 :     }
    1220                 : 
    1221                 : /* -------------------------------------------------------------------- */
    1222                 : /*      Do we need a world file?                                        */
    1223                 : /* -------------------------------------------------------------------- */
    1224              20 :     if( CSLFetchBoolean( papszOptions, "WORLDFILE", FALSE ) )
    1225                 :     {
    1226                 :         double      adfGeoTransform[6];
    1227                 :         
    1228               0 :         poSrcDS->GetGeoTransform( adfGeoTransform );
    1229               0 :         GDALWriteWorldFile( pszFilename, "wld", adfGeoTransform );
    1230                 :     }
    1231                 : 
    1232                 : /* -------------------------------------------------------------------- */
    1233                 : /*      Re-open dataset, and copy any auxilary pam information.         */
    1234                 : /* -------------------------------------------------------------------- */
    1235              20 :     GDALOpenInfo oOpenInfo(pszFilename, GA_ReadOnly);
    1236              20 :     GDALPamDataset *poDS = (GDALPamDataset*) JPEG2000Dataset::Open(&oOpenInfo);
    1237                 : 
    1238              20 :     if( poDS )
    1239              20 :         poDS->CloneInfo( poSrcDS, GCIF_PAM_DEFAULT );
    1240                 : 
    1241              20 :     return poDS;
    1242                 : }
    1243                 : 
    1244                 : /************************************************************************/
    1245                 : /*                        GDALRegister_JPEG2000()                       */
    1246                 : /************************************************************************/
    1247                 : 
    1248            1135 : void GDALRegister_JPEG2000()
    1249                 : 
    1250                 : {
    1251                 :     GDALDriver  *poDriver;
    1252                 :     
    1253            1135 :     if (! GDAL_CHECK_VERSION("JPEG2000 driver"))
    1254               0 :         return;
    1255                 : 
    1256            1135 :     if( GDALGetDriverByName( "JPEG2000" ) == NULL )
    1257                 :     {
    1258            1093 :         poDriver = new GDALDriver();
    1259                 :         
    1260            1093 :         poDriver->SetDescription( "JPEG2000" );
    1261                 :         poDriver->SetMetadataItem( GDAL_DMD_LONGNAME, 
    1262            1093 :                                    "JPEG-2000 part 1 (ISO/IEC 15444-1)" );
    1263                 :         poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC, 
    1264            1093 :                                    "frmt_jpeg2000.html" );
    1265                 :         poDriver->SetMetadataItem( GDAL_DMD_CREATIONDATATYPES, 
    1266            1093 :                                    "Byte Int16 UInt16 Int32 UInt32" );
    1267            1093 :         poDriver->SetMetadataItem( GDAL_DMD_MIMETYPE, "image/jp2" );
    1268            1093 :         poDriver->SetMetadataItem( GDAL_DMD_EXTENSION, "jp2" );
    1269                 :         
    1270            1093 :         poDriver->SetMetadataItem( GDAL_DCAP_VIRTUALIO, "YES" );
    1271                 : 
    1272            1093 :         poDriver->pfnIdentify = JPEG2000Dataset::Identify;
    1273            1093 :         poDriver->pfnOpen = JPEG2000Dataset::Open;
    1274            1093 :         poDriver->pfnCreateCopy = JPEG2000CreateCopy;
    1275                 : 
    1276            1093 :         GetGDALDriverManager()->RegisterDriver( poDriver );
    1277                 :     }
    1278                 : }
    1279                 : 

Generated by: LCOV version 1.7