LTP GCOV extension - code coverage report
Current view: directory - frmts/mrsid - mrsiddataset.cpp
Test: gdal_filtered.info
Date: 2010-07-12 Instrumented lines: 936
Code covered: 60.3 % Executed lines: 564

       1                 : /******************************************************************************
       2                 :  * $Id: mrsiddataset.cpp 17906 2009-10-26 19:47:21Z rouault $
       3                 :  *
       4                 :  * Project:  Multi-resolution Seamless Image Database (MrSID)
       5                 :  * Purpose:  Read/write LizardTech's MrSID file format - Version 4+ SDK.
       6                 :  * Author:   Andrey Kiselev, dron@ak4719.spb.edu
       7                 :  *
       8                 :  ******************************************************************************
       9                 :  * Copyright (c) 2003, 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                 : #define NO_DELETE
      31                 : 
      32                 : #include "gdal_pam.h"
      33                 : #include "ogr_spatialref.h"
      34                 : #include "cpl_string.h"
      35                 : #include <string>
      36                 : 
      37                 : #include <geo_normalize.h>
      38                 : #include <geovalues.h>
      39                 : 
      40                 : CPL_CVSID("$Id: mrsiddataset.cpp 17906 2009-10-26 19:47:21Z rouault $");
      41                 : 
      42                 : CPL_C_START
      43                 : double GTIFAngleToDD( double dfAngle, int nUOMAngle );
      44                 : CPL_C_END
      45                 : 
      46                 : // Key Macros from Makefile:
      47                 : //   MRSID_ESDK: Means we have the encoding SDK (version 5 or newer required)
      48                 : //   MRSID_J2K: Means we are enabling MrSID SDK JPEG2000 support. 
      49                 : 
      50                 : #include "lt_types.h"
      51                 : #include "lt_base.h"
      52                 : #include "lt_fileSpec.h"
      53                 : #include "lt_ioFileStream.h"
      54                 : #include "lt_utilStatusStrings.h"
      55                 : #include "lti_geoCoord.h"
      56                 : #include "lti_pixel.h"
      57                 : #include "lti_navigator.h"
      58                 : #include "lti_sceneBuffer.h"
      59                 : #include "lti_metadataDatabase.h"
      60                 : #include "lti_metadataRecord.h"
      61                 : #include "lti_utils.h"
      62                 : #include "lt_utilStatus.h"
      63                 : #include "MrSIDImageReader.h"
      64                 : 
      65                 : #ifdef MRSID_J2K
      66                 : #  include "J2KImageReader.h"
      67                 : #endif
      68                 : 
      69                 : // It seems that LT_STS_UTIL_TimeUnknown was added in version 6, also
      70                 : // the first version with lti_version.h
      71                 : #ifdef LT_STS_UTIL_TimeUnknown
      72                 : #  include "lti_version.h"
      73                 : #endif
      74                 : 
      75                 : // Are we using version 6 or newer?
      76                 : #if defined(LTI_SDK_MAJOR) && LTI_SDK_MAJOR >= 6
      77                 : #  define MRSID_POST5
      78                 : #endif
      79                 : 
      80                 : #ifdef MRSID_ESDK
      81                 : # include "MG3ImageWriter.h"
      82                 : # include "MG3WriterParams.h"
      83                 : # include "MG2ImageWriter.h"
      84                 : # include "MG2WriterParams.h"
      85                 : # ifdef MRSID_J2K
      86                 : #   ifdef MRSID_POST5
      87                 : #     include "JP2WriterManager.h"
      88                 : #     include "JPCWriterParams.h"
      89                 : #   else
      90                 : #     include "J2KImageWriter.h"
      91                 : #     include "J2KWriterParams.h"
      92                 : #   endif
      93                 : # endif
      94                 : #endif /* MRSID_ESDK */
      95                 : 
      96                 : #ifdef MRSID_POST5
      97                 : #  define MRSID_HAVE_GETWKT
      98                 : #endif
      99                 : 
     100                 : #include "mrsidstream.h"
     101                 : 
     102                 : LT_USE_NAMESPACE(LizardTech)
     103                 : 
     104                 : /* -------------------------------------------------------------------- */
     105                 : /*      Various wrapper templates used to force new/delete to happen    */
     106                 : /*      in the same heap.  See bug 1213 and MSDN knowledgebase          */
     107                 : /*      article 122675.                                                 */
     108                 : /* -------------------------------------------------------------------- */
     109                 : 
     110                 : template <class T>
     111                 : class LTIDLLPixel : public T
     112                 : {
     113                 : public:
     114                 :    LTIDLLPixel(LTIColorSpace colorSpace,
     115                 :             lt_uint16 numBands,
     116             178 :             LTIDataType dataType) : T(colorSpace,numBands,dataType) {}
     117             178 :    virtual ~LTIDLLPixel() {};
     118                 : };
     119                 : 
     120                 : template <class T>
     121                 : class LTIDLLReader : public T
     122                 : {
     123                 : public:
     124                 :    LTIDLLReader(const LTFileSpec& fileSpec,
     125                 :                 bool useWorldFile = false) : T(fileSpec, useWorldFile) {}
     126                 :    LTIDLLReader(LTIOStreamInf &oStream,
     127                 :                 bool useWorldFile = false) : T(oStream, useWorldFile) {}
     128                 :    LTIDLLReader(LTIOStreamInf *poStream,
     129                 :                 LTIOStreamInf *poWorldFile = NULL) : T(poStream, poWorldFile) {}
     130                 :    virtual ~LTIDLLReader() {};
     131                 : };
     132                 : 
     133                 : template <class T>
     134                 : class LTIDLLNavigator : public T
     135                 : {
     136                 : public:
     137             106 :    LTIDLLNavigator(const LTIImage& image ) : T(image) {}
     138             106 :    virtual ~LTIDLLNavigator() {};
     139                 : };
     140                 : 
     141                 : template <class T>
     142                 : class LTIDLLBuffer : public T
     143                 : {
     144                 : public:
     145                 :    LTIDLLBuffer(const LTIPixel& pixelProps,
     146                 :                   lt_uint32 totalNumCols,
     147                 :                   lt_uint32 totalNumRows,
     148              13 :                   void** data ) : T(pixelProps,totalNumCols,totalNumRows,data) {}
     149              13 :    virtual ~LTIDLLBuffer() {};
     150                 : };
     151                 : 
     152                 : template <class T>
     153                 : class LTIDLLCopy : public T
     154                 : {
     155                 : public:
     156              19 :    LTIDLLCopy(const T& original) : T(original) {}
     157              19 :    virtual ~LTIDLLCopy() {};
     158                 : };
     159                 : 
     160                 : /************************************************************************/
     161                 : /* ==================================================================== */
     162                 : /*                              MrSIDDataset                            */
     163                 : /* ==================================================================== */
     164                 : /************************************************************************/
     165                 : 
     166                 : class MrSIDDataset : public GDALPamDataset
     167                 : {
     168                 :     friend class MrSIDRasterBand;
     169                 : 
     170                 :     LTIVSIStream        oStream;
     171                 : 
     172                 : #if defined(LTI_SDK_MAJOR) && LTI_SDK_MAJOR >= 7
     173                 :     LTIImageFilter      *poImageReader;
     174                 : #else
     175                 :     LTIImageReader      *poImageReader;
     176                 : #endif
     177                 : 
     178                 : #ifdef MRSID_ESDK
     179                 :     LTIGeoFileImageWriter *poImageWriter;
     180                 : #endif
     181                 : 
     182                 :     LTIDLLNavigator<LTINavigator>  *poLTINav;
     183                 :     LTIDLLCopy<LTIMetadataDatabase> *poMetadata;
     184                 :     const LTIPixel      *poNDPixel;
     185                 : 
     186                 :     LTIDLLBuffer<LTISceneBuffer>  *poBuffer;
     187                 :     int                 nBlockXSize, nBlockYSize;
     188                 :     int                 bPrevBlockRead;
     189                 :     int                 nPrevBlockXOff, nPrevBlockYOff;
     190                 : 
     191                 :     LTIDataType         eSampleType;
     192                 :     GDALDataType        eDataType;
     193                 :     LTIColorSpace       eColorSpace;
     194                 : 
     195                 :     double              dfCurrentMag;
     196                 : 
     197                 :     int                 bHasGeoTransform;
     198                 :     double              adfGeoTransform[6];
     199                 :     char                *pszProjection;
     200                 :     GTIFDefn            *psDefn;
     201                 : 
     202                 :     MrSIDDataset       *poParentDS;
     203                 :     int                 bIsOverview;
     204                 :     int                 nOverviewCount;
     205                 :     MrSIDDataset        **papoOverviewDS;
     206                 : 
     207                 :     CPLErr              OpenZoomLevel( lt_int32 iZoom );
     208                 :     char                *SerializeMetadataRec( const LTIMetadataRecord* );
     209                 :     int                 GetMetadataElement( const char *, void *, int=0 );
     210                 :     void                FetchProjParms();
     211                 :     void                GetGTIFDefn();
     212                 :     char                *GetOGISDefn( GTIFDefn * );
     213                 : 
     214                 :     virtual CPLErr      IRasterIO( GDALRWFlag, int, int, int, int, void *,
     215                 :                                    int, int, GDALDataType, int, int *,int,
     216                 :                                    int, int );
     217                 : 
     218                 :   public:
     219                 :                 MrSIDDataset(int bIsJPEG2000);
     220                 :                 ~MrSIDDataset();
     221                 : 
     222                 :     static GDALDataset  *Open( GDALOpenInfo * poOpenInfo, int bIsJP2 );
     223                 :     virtual CPLErr      GetGeoTransform( double * padfTransform );
     224                 :     const char          *GetProjectionRef();
     225                 : 
     226                 : #ifdef MRSID_ESDK
     227                 :     static GDALDataset  *Create( const char * pszFilename,
     228                 :                                  int nXSize, int nYSize, int nBands,
     229                 :                                  GDALDataType eType, char ** papszParmList );
     230                 :     virtual void        FlushCache( void );
     231                 : #endif
     232                 : };
     233                 : 
     234                 : /************************************************************************/
     235                 : /* ==================================================================== */
     236                 : /*                           MrSIDRasterBand                            */
     237                 : /* ==================================================================== */
     238                 : /************************************************************************/
     239                 : 
     240                 : class MrSIDRasterBand : public GDALPamRasterBand
     241                 : {
     242                 :     friend class MrSIDDataset;
     243                 : 
     244                 :     LTIPixel        *poPixel;
     245                 : 
     246                 :     int             nBlockSize;
     247                 : 
     248                 :     int             bNoDataSet;
     249                 :     double          dfNoDataValue;
     250                 : 
     251                 :     MrSIDDataset    *poGDS;
     252                 : 
     253                 :     GDALColorInterp eBandInterp;
     254                 : 
     255                 :   public:
     256                 : 
     257                 :                 MrSIDRasterBand( MrSIDDataset *, int );
     258                 :                 ~MrSIDRasterBand();
     259                 : 
     260                 :     virtual CPLErr IRasterIO( GDALRWFlag, int, int, int, int,
     261                 :                               void *, int, int, GDALDataType,
     262                 :                               int, int );
     263                 : 
     264                 :     virtual CPLErr          IReadBlock( int, int, void * );
     265                 :     virtual GDALColorInterp GetColorInterpretation();
     266                 :     CPLErr                  SetColorInterpretation( GDALColorInterp eNewInterp );
     267                 :     virtual double          GetNoDataValue( int * );
     268                 :     virtual int             GetOverviewCount();
     269                 :     virtual GDALRasterBand  *GetOverview( int );
     270                 : 
     271                 :     virtual CPLErr GetStatistics( int bApproxOK, int bForce,
     272                 :                                   double *pdfMin, double *pdfMax, 
     273                 :                                   double *pdfMean, double *pdfStdDev );
     274                 : 
     275                 : #ifdef MRSID_ESDK
     276                 :     virtual CPLErr          IWriteBlock( int, int, void * );
     277                 : #endif
     278                 : };
     279                 : 
     280                 : /************************************************************************/
     281                 : /*                           MrSIDRasterBand()                          */
     282                 : /************************************************************************/
     283                 : 
     284             178 : MrSIDRasterBand::MrSIDRasterBand( MrSIDDataset *poDS, int nBand )
     285                 : {
     286             178 :     this->poDS = poDS;
     287             178 :     poGDS = poDS;
     288             178 :     this->nBand = nBand;
     289             178 :     this->eDataType = poDS->eDataType;
     290                 : 
     291                 : /* -------------------------------------------------------------------- */
     292                 : /*      Set the block sizes and buffer parameters.                      */
     293                 : /* -------------------------------------------------------------------- */
     294             178 :     nBlockXSize = poDS->nBlockXSize;
     295             178 :     nBlockYSize = poDS->nBlockYSize;
     296                 : //#ifdef notdef
     297             178 :     if( poDS->GetRasterXSize() > 2048 )
     298               6 :         nBlockXSize = 1024;
     299             178 :     if( poDS->GetRasterYSize() > 128 )
     300              81 :         nBlockYSize = 128;
     301                 :     else
     302              97 :         nBlockYSize = poDS->GetRasterYSize();
     303                 : //#endif
     304                 : 
     305             178 :     nBlockSize = nBlockXSize * nBlockYSize;
     306                 :     poPixel = new LTIDLLPixel<LTIPixel>( poDS->eColorSpace, poDS->nBands,
     307             178 :                                          poDS->eSampleType );
     308                 : 
     309                 : 
     310                 : /* -------------------------------------------------------------------- */
     311                 : /*      Set NoData values.                                              */
     312                 : /*                                                                      */
     313                 : /*      This logic is disabled for now since the MrSID nodata           */
     314                 : /*      semantics are different than GDAL.  In MrSID all bands must     */
     315                 : /*      match the nodata value for that band in order for the pixel     */
     316                 : /*      to be considered nodata, otherwise all values are valid.        */
     317                 : /* -------------------------------------------------------------------- */
     318                 : #ifdef notdef
     319                 :      if ( poDS->poNDPixel )
     320                 :      {
     321                 :          switch( poDS->eSampleType )
     322                 :          {
     323                 :              case LTI_DATATYPE_UINT8:
     324                 :              case LTI_DATATYPE_SINT8:
     325                 :                  dfNoDataValue = (double)
     326                 :                      poDS->poNDPixel->getSampleValueUint8( nBand - 1 );
     327                 :                  break;
     328                 :              case LTI_DATATYPE_UINT16:
     329                 :                  dfNoDataValue = (double)
     330                 :                      poDS->poNDPixel->getSampleValueUint16( nBand - 1 );
     331                 :                  break;
     332                 :              case LTI_DATATYPE_FLOAT32:
     333                 :                  dfNoDataValue =
     334                 :                      poDS->poNDPixel->getSampleValueFloat32( nBand - 1 );
     335                 :                  break;
     336                 :              case LTI_DATATYPE_SINT16:
     337                 :                  dfNoDataValue = (double)
     338                 :                      *(GInt16 *)poDS->poNDPixel->getSampleValueAddr( nBand - 1 );
     339                 :                  break;
     340                 :              case LTI_DATATYPE_UINT32:
     341                 :                  dfNoDataValue = (double)
     342                 :                      *(GUInt32 *)poDS->poNDPixel->getSampleValueAddr( nBand - 1 );
     343                 :                  break;
     344                 :              case LTI_DATATYPE_SINT32:
     345                 :                  dfNoDataValue = (double)
     346                 :                      *(GInt32 *)poDS->poNDPixel->getSampleValueAddr( nBand - 1 );
     347                 :                  break;
     348                 :              case LTI_DATATYPE_FLOAT64:
     349                 :                  dfNoDataValue =
     350                 :                      *(double *)poDS->poNDPixel->getSampleValueAddr( nBand - 1 );
     351                 :                  break;
     352                 : 
     353                 :              case LTI_DATATYPE_INVALID:
     354                 :                  CPLAssert( FALSE );
     355                 :                  break;
     356                 :          }
     357                 :          bNoDataSet = TRUE;
     358                 :      }
     359                 :      else
     360                 : #endif
     361                 :      {
     362             178 :         dfNoDataValue = 0.0;
     363             178 :         bNoDataSet = FALSE;
     364                 :      }
     365                 : 
     366             178 :     switch( poGDS->eColorSpace )
     367                 :     {
     368                 :         case LTI_COLORSPACE_RGB:
     369             108 :             if( nBand == 1 )
     370              36 :                 eBandInterp = GCI_RedBand;
     371              72 :             else if( nBand == 2 )
     372              36 :                 eBandInterp = GCI_GreenBand;
     373              36 :             else if( nBand == 3 )
     374              36 :                 eBandInterp = GCI_BlueBand;
     375                 :             else
     376               0 :                 eBandInterp = GCI_Undefined;
     377             108 :             break;
     378                 : 
     379                 :         case LTI_COLORSPACE_RGBK:
     380               0 :             if( nBand == 1 )
     381               0 :                 eBandInterp = GCI_RedBand;
     382               0 :             else if( nBand == 2 )
     383               0 :                 eBandInterp = GCI_GreenBand;
     384               0 :             else if( nBand == 3 )
     385               0 :                 eBandInterp = GCI_BlueBand;
     386               0 :             else if( nBand == 4 )
     387               0 :                 eBandInterp = GCI_AlphaBand;
     388                 :             else
     389               0 :                 eBandInterp = GCI_Undefined;
     390               0 :             break;
     391                 : 
     392                 :         case LTI_COLORSPACE_CMYK:
     393               0 :             if( nBand == 1 )
     394               0 :                 eBandInterp = GCI_CyanBand;
     395               0 :             else if( nBand == 2 )
     396               0 :                 eBandInterp = GCI_MagentaBand;
     397               0 :             else if( nBand == 3 )
     398               0 :                 eBandInterp = GCI_YellowBand;
     399               0 :             else if( nBand == 4 )
     400               0 :                 eBandInterp = GCI_BlackBand;
     401                 :             else
     402               0 :                 eBandInterp = GCI_Undefined;
     403               0 :             break;
     404                 : 
     405                 :         case LTI_COLORSPACE_GRAYSCALE:
     406              64 :             eBandInterp = GCI_GrayIndex;
     407              64 :             break;
     408                 : 
     409                 :         default:
     410               6 :             eBandInterp = GCI_Undefined;
     411                 :             break;
     412                 :     }
     413             178 : }
     414                 : 
     415                 : /************************************************************************/
     416                 : /*                            ~MrSIDRasterBand()                        */
     417                 : /************************************************************************/
     418                 : 
     419             178 : MrSIDRasterBand::~MrSIDRasterBand()
     420                 : {
     421             178 :     if ( poPixel )
     422             178 :         delete poPixel;
     423             178 : }
     424                 : 
     425                 : /************************************************************************/
     426                 : /*                             IReadBlock()                             */
     427                 : /************************************************************************/
     428                 : 
     429                 : CPLErr MrSIDRasterBand::IReadBlock( int nBlockXOff, int nBlockYOff,
     430              88 :                                     void * pImage )
     431                 : {
     432                 : #ifdef MRSID_ESDK
     433                 :     if( poGDS->eAccess == GA_Update )
     434                 :     {
     435                 :         CPLDebug( "MrSID", 
     436                 :                   "IReadBlock() - DSDK - read on updatable file fails." );
     437                 :         memset( pImage, 0, nBlockSize * GDALGetDataTypeSize(eDataType) / 8 );
     438                 :         return CE_None;
     439                 :     }
     440                 : #endif /* MRSID_ESDK */
     441                 : 
     442              88 :     CPLDebug( "MrSID", "IReadBlock(%d,%d)", nBlockXOff, nBlockYOff );
     443                 : 
     444              88 :     if ( !poGDS->bPrevBlockRead
     445                 :          || poGDS->nPrevBlockXOff != nBlockXOff
     446                 :          || poGDS->nPrevBlockYOff != nBlockYOff )
     447                 :     {
     448              88 :         GInt32      nLine = nBlockYOff * nBlockYSize;
     449              88 :         GInt32      nCol = nBlockXOff * nBlockXSize;
     450                 : 
     451                 :         // XXX: The scene, passed to LTIImageStage::read() call must be
     452                 :         // inside the image boundaries. So we should detect the last strip and
     453                 :         // form the scene properly.
     454                 :         CPLDebug( "MrSID", 
     455                 :                   "IReadBlock - read() %dx%d block at %d,%d.", 
     456              88 :                   nBlockXSize, nBlockYSize, nCol, nLine );
     457                 :                   
     458              88 :         if(!LT_SUCCESS( poGDS->poLTINav->setSceneAsULWH(
     459                 :                             nCol, nLine,
     460                 :                             (nCol+nBlockXSize>poGDS->GetRasterXSize())?
     461                 :                             (poGDS->GetRasterXSize()-nCol):nBlockXSize,
     462                 :                             (nLine+nBlockYSize>poGDS->GetRasterYSize())?
     463                 :                             (poGDS->GetRasterYSize()-nLine):nBlockYSize,
     464                 :                             poGDS->dfCurrentMag) ))
     465                 :             
     466                 :         {
     467                 :             CPLError( CE_Failure, CPLE_AppDefined,
     468               0 :                       "MrSIDRasterBand::IReadBlock(): Failed to set scene position." );
     469               0 :             return CE_Failure;
     470                 :         }
     471                 : 
     472              88 :         if ( !poGDS->poBuffer )
     473                 :         {
     474                 :             poGDS->poBuffer =
     475              13 :                 new LTIDLLBuffer<LTISceneBuffer>( *poPixel, nBlockXSize, nBlockYSize, NULL );
     476                 : //            poGDS->poBuffer =
     477                 : //                new LTISceneBuffer( *poPixel, nBlockXSize, nBlockYSize, NULL );
     478                 :         }
     479                 : 
     480              88 :         if(!LT_SUCCESS(poGDS->poImageReader->read(poGDS->poLTINav->getScene(),
     481                 :                                                   *poGDS->poBuffer)))
     482                 :         {
     483                 :             CPLError( CE_Failure, CPLE_AppDefined,
     484               0 :                       "MrSIDRasterBand::IReadBlock(): Failed to load image." );
     485               0 :             return CE_Failure;
     486                 :         }
     487                 : 
     488              88 :         poGDS->bPrevBlockRead = TRUE;
     489              88 :         poGDS->nPrevBlockXOff = nBlockXOff;
     490              88 :         poGDS->nPrevBlockYOff = nBlockYOff;
     491                 :     }
     492                 : 
     493                 :     memcpy( pImage, poGDS->poBuffer->getTotalBandData(nBand - 1), 
     494              88 :             nBlockSize * (GDALGetDataTypeSize(poGDS->eDataType) / 8) );
     495                 : 
     496              88 :     return CE_None;
     497                 : }
     498                 : 
     499                 : #ifdef MRSID_ESDK
     500                 : 
     501                 : /************************************************************************/
     502                 : /*                            IWriteBlock()                             */
     503                 : /************************************************************************/
     504                 : 
     505                 : CPLErr MrSIDRasterBand::IWriteBlock( int nBlockXOff, int nBlockYOff,
     506                 :                                      void * pImage )
     507                 : {
     508                 :     CPLAssert( poGDS != NULL
     509                 :                && nBlockXOff >= 0
     510                 :                && nBlockYOff >= 0
     511                 :                && pImage != NULL );
     512                 : 
     513                 : #if DEBUG
     514                 :     CPLDebug( "MrSID", "IWriteBlock(): nBlockXOff=%d, nBlockYOff=%d",
     515                 :               nBlockXOff, nBlockYOff );
     516                 : #endif
     517                 : 
     518                 :     LTIScene        oScene( nBlockXOff * nBlockXSize,
     519                 :                             nBlockYOff * nBlockYSize,
     520                 :                             nBlockXSize, nBlockYSize, 1.0);
     521                 :     LTISceneBuffer  oSceneBuf( *poPixel, poGDS->nBlockXSize,
     522                 :                                poGDS->nBlockYSize, &pImage );
     523                 : 
     524                 :     if( !LT_SUCCESS(poGDS->poImageWriter->writeBegin(oScene)) )
     525                 :     {
     526                 :         CPLError( CE_Failure, CPLE_AppDefined,
     527                 :                   "MrSIDRasterBand::IWriteBlock(): writeBegin failed." );
     528                 :         return CE_Failure;
     529                 :     }
     530                 : 
     531                 :     if( !LT_SUCCESS(poGDS->poImageWriter->writeStrip(oSceneBuf, oScene)) )
     532                 :     {
     533                 :         CPLError( CE_Failure, CPLE_AppDefined,
     534                 :                   "MrSIDRasterBand::IWriteBlock(): writeStrip failed." );
     535                 :         return CE_Failure;
     536                 :     }
     537                 : 
     538                 :     if( !LT_SUCCESS(poGDS->poImageWriter->writeEnd()) )
     539                 :     {
     540                 :         CPLError( CE_Failure, CPLE_AppDefined,
     541                 :                   "MrSIDRasterBand::IWriteBlock(): writeEnd failed." );
     542                 :         return CE_Failure;
     543                 :     }
     544                 : 
     545                 :     return CE_None;
     546                 : }
     547                 : 
     548                 : #endif /* MRSID_ESDK */
     549                 : 
     550                 : /************************************************************************/
     551                 : /*                             IRasterIO()                              */
     552                 : /************************************************************************/
     553                 : 
     554                 : CPLErr MrSIDRasterBand::IRasterIO( GDALRWFlag eRWFlag,
     555                 :                                    int nXOff, int nYOff, int nXSize, int nYSize,
     556                 :                                    void * pData, int nBufXSize, int nBufYSize,
     557                 :                                    GDALDataType eBufType,
     558            5977 :                                    int nPixelSpace, int nLineSpace )
     559                 :     
     560                 : {
     561                 : /* -------------------------------------------------------------------- */
     562                 : /*      Fallback to default implementation if the whole scanline        */
     563                 : /*      without subsampling requested.                                  */
     564                 : /* -------------------------------------------------------------------- */
     565            5977 :     if ( nXSize == poGDS->GetRasterXSize()
     566                 :          && nXSize == nBufXSize
     567                 :          && nYSize == nBufYSize )
     568                 :     {
     569                 :         return GDALRasterBand::IRasterIO( eRWFlag, nXOff, nYOff,
     570                 :                                           nXSize, nYSize, pData,
     571                 :                                           nBufXSize, nBufYSize, eBufType,
     572            5976 :                                           nPixelSpace, nLineSpace );
     573                 :     }
     574                 : 
     575                 : /* -------------------------------------------------------------------- */
     576                 : /*      Handle via the dataset level IRasterIO()                        */
     577                 : /* -------------------------------------------------------------------- */
     578                 :     return poGDS->IRasterIO( eRWFlag, nXOff, nYOff, nXSize, nYSize, pData, 
     579                 :                              nBufXSize, nBufYSize, eBufType, 
     580               1 :                              1, &nBand, nPixelSpace, nLineSpace, 0 );
     581                 : }
     582                 : 
     583                 : /************************************************************************/
     584                 : /*                       GetColorInterpretation()                       */
     585                 : /************************************************************************/
     586                 : 
     587               3 : GDALColorInterp MrSIDRasterBand::GetColorInterpretation()
     588                 : 
     589                 : {
     590               3 :     return eBandInterp;
     591                 : }
     592                 : 
     593                 : /************************************************************************/
     594                 : /*                       SetColorInterpretation()                       */
     595                 : /*                                                                      */
     596                 : /*      This would normally just be used by folks using the MrSID code  */
     597                 : /*      to read JP2 streams in other formats (such as NITF) and         */
     598                 : /*      providing their own color interpretation regardless of what     */
     599                 : /*      MrSID might think the stream itself says.                       */
     600                 : /************************************************************************/
     601                 : 
     602               0 : CPLErr MrSIDRasterBand::SetColorInterpretation( GDALColorInterp eNewInterp )
     603                 : 
     604                 : {
     605               0 :     eBandInterp = eNewInterp;
     606                 : 
     607               0 :     return CE_None;
     608                 : }
     609                 : 
     610                 : /************************************************************************/
     611                 : /*                           GetStatistics()                            */
     612                 : /*                                                                      */
     613                 : /*      We override this method so that we can force generation of      */
     614                 : /*      statistics if approx ok is true since we know that a small      */
     615                 : /*      overview is always available, and that computing statistics     */
     616                 : /*      from it is very fast.                                           */
     617                 : /************************************************************************/
     618                 : 
     619                 : CPLErr MrSIDRasterBand::GetStatistics( int bApproxOK, int bForce,
     620                 :                                        double *pdfMin, double *pdfMax, 
     621               4 :                                        double *pdfMean, double *pdfStdDev )
     622                 : 
     623                 : {
     624               4 :     if( bApproxOK )
     625               2 :         bForce = TRUE;
     626                 : 
     627                 :     return GDALPamRasterBand::GetStatistics( bApproxOK, bForce, 
     628                 :                                              pdfMin, pdfMax, 
     629               4 :                                              pdfMean, pdfStdDev );
     630                 : }
     631                 : 
     632                 : /************************************************************************/
     633                 : /*                           GetNoDataValue()                           */
     634                 : /************************************************************************/
     635                 : 
     636               5 : double MrSIDRasterBand::GetNoDataValue( int * pbSuccess )
     637                 : 
     638                 : {
     639               5 :     if( bNoDataSet )
     640                 :     {
     641               0 :         if( pbSuccess )
     642               0 :             *pbSuccess = bNoDataSet;
     643                 : 
     644               0 :         return dfNoDataValue;
     645                 :     }
     646                 : 
     647               5 :     return GDALPamRasterBand::GetNoDataValue( pbSuccess );
     648                 : }
     649                 : 
     650                 : /************************************************************************/
     651                 : /*                          GetOverviewCount()                          */
     652                 : /************************************************************************/
     653                 : 
     654              15 : int MrSIDRasterBand::GetOverviewCount()
     655                 : 
     656                 : {
     657              15 :     return poGDS->nOverviewCount;
     658                 : }
     659                 : 
     660                 : /************************************************************************/
     661                 : /*                            GetOverview()                             */
     662                 : /************************************************************************/
     663                 : 
     664              11 : GDALRasterBand *MrSIDRasterBand::GetOverview( int i )
     665                 : 
     666                 : {
     667              11 :     if( i < 0 || i >= poGDS->nOverviewCount )
     668               0 :         return NULL;
     669                 :     else
     670              11 :         return poGDS->papoOverviewDS[i]->GetRasterBand( nBand );
     671                 : }
     672                 : 
     673                 : /************************************************************************/
     674                 : /*                           MrSIDDataset()                             */
     675                 : /************************************************************************/
     676                 : 
     677             106 : MrSIDDataset::MrSIDDataset(int bIsJPEG2000)
     678                 : {
     679             106 :     poImageReader = NULL;
     680                 : #ifdef MRSID_ESDK
     681                 :     poImageWriter = NULL;
     682                 : #endif
     683             106 :     poLTINav = NULL;
     684             106 :     poMetadata = NULL;
     685             106 :     poNDPixel = NULL;
     686             106 :     eSampleType = LTI_DATATYPE_UINT8;
     687             106 :     nBands = 0;
     688             106 :     eDataType = GDT_Byte;
     689                 :     
     690             106 :     poBuffer = NULL;
     691             106 :     bPrevBlockRead = FALSE;
     692             106 :     nPrevBlockXOff = 0;
     693             106 :     nPrevBlockYOff = 0;
     694                 :     
     695             106 :     pszProjection = CPLStrdup( "" );
     696             106 :     bHasGeoTransform = FALSE;
     697             106 :     adfGeoTransform[0] = 0.0;
     698             106 :     adfGeoTransform[1] = 1.0;
     699             106 :     adfGeoTransform[2] = 0.0;
     700             106 :     adfGeoTransform[3] = 0.0;
     701             106 :     adfGeoTransform[4] = 0.0;
     702             106 :     adfGeoTransform[5] = 1.0;
     703             106 :     psDefn = NULL;
     704                 :     
     705             106 :     dfCurrentMag = 1.0;
     706             106 :     bIsOverview = FALSE;
     707             106 :     poParentDS = this;
     708             106 :     nOverviewCount = 0;
     709             106 :     papoOverviewDS = NULL;
     710                 :     
     711             106 :     poDriver = (GDALDriver*) GDALGetDriverByName( bIsJPEG2000 ? "JP2MrSID" : "MrSID" );
     712             106 : }
     713                 : 
     714                 : /************************************************************************/
     715                 : /*                            ~MrSIDDataset()                           */
     716                 : /************************************************************************/
     717                 : 
     718             106 : MrSIDDataset::~MrSIDDataset()
     719                 : {
     720             106 :     FlushCache();
     721                 : 
     722                 : #ifdef MRSID_ESDK
     723                 :     if ( poImageWriter )
     724                 :         delete poImageWriter;
     725                 : #endif
     726                 : 
     727             106 :     if ( poBuffer )
     728              13 :         delete poBuffer;
     729             106 :     if ( poMetadata )
     730              19 :         delete poMetadata;
     731             106 :     if ( poLTINav )
     732             106 :         delete poLTINav;
     733             106 :     if ( poImageReader && !bIsOverview )
     734                 : #if defined(LTI_SDK_MAJOR) && LTI_SDK_MAJOR >= 7
     735                 :     {
     736              19 :         poImageReader->release();
     737              19 :         poImageReader = NULL;
     738                 :     }
     739                 : #else
     740                 :         delete poImageReader;
     741                 : #endif
     742                 : 
     743             106 :     if ( pszProjection )
     744             106 :         CPLFree( pszProjection );
     745             106 :     if ( psDefn )
     746              19 :         delete psDefn;
     747             106 :     if ( papoOverviewDS )
     748                 :     {
     749             106 :         for( int i = 0; i < nOverviewCount; i++ )
     750              87 :             delete papoOverviewDS[i];
     751              19 :         CPLFree( papoOverviewDS );
     752                 :     }
     753             106 : }
     754                 : 
     755                 : /************************************************************************/
     756                 : /*                             IRasterIO()                              */
     757                 : /************************************************************************/
     758                 : 
     759                 : CPLErr MrSIDDataset::IRasterIO( GDALRWFlag eRWFlag,
     760                 :                                 int nXOff, int nYOff, int nXSize, int nYSize,
     761                 :                                 void * pData, int nBufXSize, int nBufYSize,
     762                 :                                 GDALDataType eBufType, 
     763                 :                                 int nBandCount, int *panBandMap,
     764               2 :                                 int nPixelSpace, int nLineSpace, int nBandSpace )
     765                 : 
     766                 : {
     767                 : /* -------------------------------------------------------------------- */
     768                 : /*      We need various criteria to skip out to block based methods.    */
     769                 : /* -------------------------------------------------------------------- */
     770               2 :     int bUseBlockedIO = bForceCachedIO;
     771                 : 
     772               2 :     if( nYSize == 1 || nXSize * ((double) nYSize) < 100.0 )
     773               0 :         bUseBlockedIO = TRUE;
     774                 : 
     775               2 :     if( nBufYSize == 1 || nBufXSize * ((double) nBufYSize) < 100.0 )
     776               0 :         bUseBlockedIO = TRUE;
     777                 : 
     778               2 :     if( CSLTestBoolean( CPLGetConfigOption( "GDAL_ONE_BIG_READ", "NO") ) )
     779               0 :         bUseBlockedIO = FALSE;
     780                 : 
     781               2 :     if( bUseBlockedIO )
     782                 :         return GDALDataset::BlockBasedRasterIO( 
     783                 :             eRWFlag, nXOff, nYOff, nXSize, nYSize,
     784                 :             pData, nBufXSize, nBufYSize, eBufType, 
     785               0 :             nBandCount, panBandMap, nPixelSpace, nLineSpace, nBandSpace );
     786               2 :     CPLDebug( "MrSID", "RasterIO() - using optimized dataset level IO." );
     787                 :     
     788                 : /* -------------------------------------------------------------------- */
     789                 : /*      What is our requested window relative to the base dataset.      */
     790                 : /*      We want to operate from here on as if we were operating on      */
     791                 : /*      the full res band.                                              */
     792                 : /* -------------------------------------------------------------------- */
     793               2 :     int nZoomMag = (int) ((1/dfCurrentMag) * 1.0000001);
     794                 : 
     795               2 :     nXOff *= nZoomMag;
     796               2 :     nYOff *= nZoomMag;
     797               2 :     nXSize *= nZoomMag;
     798               2 :     nYSize *= nZoomMag;
     799                 : 
     800                 : /* -------------------------------------------------------------------- */
     801                 : /*      We need to figure out the best zoom level to use for this       */
     802                 : /*      request.  We apply a small fudge factor to make sure that       */
     803                 : /*      request just very, very slightly larger than a zoom level do    */
     804                 : /*      not force us to the next level.                                 */
     805                 : /* -------------------------------------------------------------------- */
     806               2 :     int iOverview = 0;
     807               2 :     double dfZoomMag = MIN((nXSize / (double)nBufXSize), 
     808                 :                            (nYSize / (double)nBufYSize));
     809                 : 
     810               2 :     for( nZoomMag = 1; 
     811                 :          nZoomMag * 2 < (dfZoomMag + 0.1) 
     812                 :              && iOverview < poParentDS->nOverviewCount; 
     813                 :          nZoomMag *= 2, iOverview++ ) {}
     814                 : 
     815                 : /* -------------------------------------------------------------------- */
     816                 : /*      Work out the size of the temporary buffer and allocate it.      */
     817                 : /*      The temporary buffer will generally be at a moderately          */
     818                 : /*      higher resolution than the buffer of data requested.            */
     819                 : /* -------------------------------------------------------------------- */
     820                 :     int  nTmpPixelSize;
     821               2 :     LTIPixel       oPixel( eColorSpace, nBands, eSampleType );
     822                 :     
     823                 :     LT_STATUS eLTStatus;
     824                 :     unsigned int maxWidth;
     825                 :     unsigned int maxHeight;
     826                 : 
     827               2 :     eLTStatus = poImageReader->getDimsAtMag(1.0/nZoomMag,maxWidth,maxHeight);
     828                 : 
     829               2 :     if( !LT_SUCCESS(eLTStatus)) {
     830                 :         CPLError( CE_Failure, CPLE_AppDefined,
     831                 :                   "MrSIDDataset::IRasterIO(): Failed to get zoomed image dimensions.\n%s",
     832               0 :                   getLastStatusString( eLTStatus ) );
     833               2 :         return CE_Failure;
     834                 :     }
     835                 : 
     836               2 :     int maxWidthAtL0 = bIsOverview?poParentDS->GetRasterXSize():this->GetRasterXSize();
     837               2 :     int maxHeightAtL0 = bIsOverview?poParentDS->GetRasterYSize():this->GetRasterYSize();
     838                 : 
     839               2 :     int sceneUlXOff = nXOff / nZoomMag;
     840               2 :     int sceneUlYOff = nYOff / nZoomMag;
     841               2 :     int sceneWidth  = (int)(nXSize * (double) maxWidth / (double)maxWidthAtL0 + 0.99);
     842               2 :     int sceneHeight = (int)(nYSize * (double) maxHeight / (double)maxHeightAtL0 + 0.99);
     843                 : 
     844               2 :     if( (sceneUlXOff + sceneWidth) > (int) maxWidth )
     845               0 :         sceneWidth = maxWidth - sceneUlXOff;
     846                 : 
     847               2 :     if( (sceneUlYOff + sceneHeight) > (int) maxHeight )
     848               0 :         sceneHeight = maxHeight - sceneUlYOff;
     849                 : 
     850               2 :     LTISceneBuffer oLTIBuffer( oPixel, sceneWidth, sceneHeight, NULL );
     851                 : 
     852               2 :     nTmpPixelSize = GDALGetDataTypeSize( eDataType ) / 8;
     853                 : 
     854                 : /* -------------------------------------------------------------------- */
     855                 : /*      Create navigator, and move to the requested scene area.         */
     856                 : /* -------------------------------------------------------------------- */
     857               2 :     LTINavigator oNav( *poImageReader );
     858                 :     
     859               2 :     if( !LT_SUCCESS(oNav.setSceneAsULWH( sceneUlXOff, sceneUlYOff, 
     860                 :                                          sceneWidth, sceneHeight, 
     861                 :                                          1.0 / nZoomMag )) )
     862                 :     {
     863                 :         CPLError( CE_Failure, CPLE_AppDefined,
     864               0 :                   "MrSIDDataset::IRasterIO(): Failed to set scene position." );
     865                 : 
     866               0 :         return CE_Failure;
     867                 :     }
     868                 : 
     869                 :     CPLDebug( "MrSID", 
     870                 :               "Dataset:IRasterIO(%d,%d %dx%d -> %dx%d -> %dx%d, zoom=%d)",
     871                 :               nXOff, nYOff, nXSize, nYSize, 
     872                 :               sceneWidth, sceneHeight,
     873                 :               nBufXSize, nBufYSize, 
     874               2 :               nZoomMag );
     875                 : 
     876               2 :     if( !oNav.isSceneValid() )
     877               0 :         CPLDebug( "MrSID", "LTINavigator in invalid state." );
     878                 : 
     879                 : /* -------------------------------------------------------------------- */
     880                 : /*      Read into the buffer.                                           */
     881                 : /* -------------------------------------------------------------------- */
     882                 : 
     883               2 :     eLTStatus = poImageReader->read(oNav.getScene(),oLTIBuffer);
     884               2 :     if(!LT_SUCCESS(eLTStatus) )
     885                 :     {
     886                 :         CPLError( CE_Failure, CPLE_AppDefined,
     887                 :                   "MrSIDRasterBand::IRasterIO(): Failed to load image.\n%s",
     888               0 :                   getLastStatusString( eLTStatus ) );
     889               0 :         return CE_Failure;
     890                 :     }
     891                 : 
     892                 : /* -------------------------------------------------------------------- */
     893                 : /*      If we are pulling the data at a matching resolution, try to     */
     894                 : /*      do a more direct copy without subsampling.                      */
     895                 : /* -------------------------------------------------------------------- */
     896                 :     int         iBufLine, iBufPixel;
     897                 : 
     898               3 :     if( nBufXSize == sceneWidth && nBufYSize == sceneHeight )
     899                 :     {
     900               2 :         for( int iBand = 0; iBand < nBandCount; iBand++ )
     901                 :         {
     902                 :             GByte *pabySrcBand = (GByte *) 
     903               1 :                 oLTIBuffer.getTotalBandData( panBandMap[iBand] - 1 );
     904                 :     
     905             257 :             for( int iLine = 0; iLine < nBufYSize; iLine++ )
     906                 :       {
     907                 :                 GDALCopyWords( pabySrcBand + iLine*nTmpPixelSize*sceneWidth,
     908                 :                                eDataType, nTmpPixelSize, 
     909                 :                                ((GByte *)pData) + iLine*nLineSpace 
     910                 :                                + iBand * nBandSpace, 
     911                 :                                eBufType, nPixelSpace,
     912             256 :                                nBufXSize );
     913                 :       }
     914                 :   }
     915                 :     }
     916                 : 
     917                 : /* -------------------------------------------------------------------- */
     918                 : /*      Manually resample to our target buffer.                         */
     919                 : /* -------------------------------------------------------------------- */
     920                 :     else
     921                 :     {
     922              11 :         for( iBufLine = 0; iBufLine < nBufYSize; iBufLine++ )
     923                 :   {
     924              10 :             int iTmpLine = (int) floor(((iBufLine+0.5) / nBufYSize)*sceneHeight);
     925                 : 
     926             110 :             for( iBufPixel = 0; iBufPixel < nBufXSize; iBufPixel++ )
     927                 :       {
     928                 :                 int iTmpPixel = (int) 
     929             100 :                     floor(((iBufPixel+0.5) / nBufXSize) * sceneWidth);
     930                 : 
     931             200 :                 for( int iBand = 0; iBand < nBandCount; iBand++ )
     932                 :     {
     933                 :                     GByte *pabySrc, *pabyDst;
     934                 : 
     935                 :                     pabyDst = ((GByte *) pData) 
     936                 :                         + nPixelSpace * iBufPixel
     937                 :                         + nLineSpace * iBufLine
     938             100 :                         + nBandSpace * iBand;
     939                 : 
     940                 :                     pabySrc = (GByte *) oLTIBuffer.getTotalBandData( 
     941             100 :                         panBandMap[iBand] - 1 );
     942             100 :                     pabySrc += (iTmpLine * sceneWidth + iTmpPixel) * nTmpPixelSize;
     943                 : 
     944             100 :                     if( eDataType == eBufType )
     945             100 :                         memcpy( pabyDst, pabySrc, nTmpPixelSize );
     946                 :                     else
     947                 :                         GDALCopyWords( pabySrc, eDataType, 0, 
     948               0 :                                        pabyDst, eBufType, 0, 1 );
     949                 :     }
     950                 :       }
     951                 :   }
     952                 :     }
     953                 : 
     954               2 :     return CE_None;
     955                 : }
     956                 : 
     957                 : /************************************************************************/
     958                 : /*                          GetGeoTransform()                           */
     959                 : /************************************************************************/
     960                 : 
     961               2 : CPLErr MrSIDDataset::GetGeoTransform( double * padfTransform )
     962                 : {
     963               2 :     if( strlen(GDALPamDataset::GetProjectionRef()) > 0
     964                 :         || !bHasGeoTransform )
     965                 :     {
     966               1 :         return GDALPamDataset::GetGeoTransform( padfTransform );
     967                 :     }
     968                 :     else
     969                 :     {
     970               1 :         memcpy( padfTransform, adfGeoTransform, sizeof(double) * 6 );
     971               1 :         return( CE_None );
     972                 :     }
     973                 : }
     974                 : 
     975                 : /************************************************************************/
     976                 : /*                          GetProjectionRef()                          */
     977                 : /************************************************************************/
     978                 : 
     979               4 : const char *MrSIDDataset::GetProjectionRef()
     980                 : {
     981               4 :     const char* pszPamPrj = GDALPamDataset::GetProjectionRef();
     982                 : 
     983               4 :     if( strlen(pszProjection) > 0 && strlen(pszPamPrj) == 0 )
     984               3 :         return pszProjection;
     985                 :     else
     986               1 :         return pszPamPrj;
     987                 : }
     988                 : 
     989                 : /************************************************************************/
     990                 : /*                        SerializeMetadataRec()                        */
     991                 : /************************************************************************/
     992                 : 
     993             244 : char *MrSIDDataset::SerializeMetadataRec( const LTIMetadataRecord *poMetadataRec )
     994                 : {
     995             244 :     GUInt32  iNumDims = 0;
     996             244 :     const GUInt32  *paiDims = NULL;
     997             244 :     const void     *pData = poMetadataRec->getArrayData( iNumDims, paiDims );
     998             244 :     GUInt32        i, j, k = 0, iLength;
     999             244 :     char           *pszMetadata = CPLStrdup( "" );
    1000                 : 
    1001             488 :     for ( i = 0; i < iNumDims; i++ )
    1002                 :     {
    1003                 :         // stops on large binary data
    1004             244 :         if ( poMetadataRec->getDataType() == LTI_METADATA_DATATYPE_UINT8 
    1005                 :              && paiDims[i] > 1024 )
    1006               0 :             return pszMetadata;
    1007                 : 
    1008             620 :         for ( j = 0; j < paiDims[i]; j++ )
    1009                 :         {
    1010             376 :             CPLString osTemp;
    1011                 : 
    1012             376 :             switch( poMetadataRec->getDataType() )
    1013                 :             {
    1014                 :                 case LTI_METADATA_DATATYPE_UINT8:
    1015                 :                 case LTI_METADATA_DATATYPE_SINT8:
    1016               0 :                     osTemp.Printf( "%d", ((GByte *)pData)[k++] );
    1017               0 :                     break;
    1018                 :                 case LTI_METADATA_DATATYPE_UINT16:
    1019              76 :                     osTemp.Printf( "%u", ((GUInt16 *)pData)[k++] );
    1020              76 :                     break;
    1021                 :                 case LTI_METADATA_DATATYPE_SINT16:
    1022               0 :                     osTemp.Printf( "%d", ((GInt16 *)pData)[k++] );
    1023               0 :                     break;
    1024                 :                 case LTI_METADATA_DATATYPE_UINT32:
    1025              12 :                     osTemp.Printf( "%u", ((GUInt32 *)pData)[k++] );
    1026              12 :                     break;
    1027                 :                 case LTI_METADATA_DATATYPE_SINT32:
    1028              18 :                     osTemp.Printf( "%d", ((GInt32 *)pData)[k++] );
    1029              18 :                     break;
    1030                 :                 case LTI_METADATA_DATATYPE_FLOAT32:
    1031              18 :                     osTemp.Printf( "%f", ((float *)pData)[k++] );
    1032              18 :                     break;
    1033                 :                 case LTI_METADATA_DATATYPE_FLOAT64:
    1034             169 :                     osTemp.Printf( "%lf", ((double *)pData)[k++] );
    1035             169 :                     break;
    1036                 :                 case LTI_METADATA_DATATYPE_ASCII:
    1037              83 :                     osTemp = ((const char **)pData)[k++];
    1038              83 :                     break;
    1039                 :                 default:
    1040               0 :                     osTemp = "";
    1041                 :                     break;
    1042                 :             }
    1043                 : 
    1044             376 :             iLength = strlen(pszMetadata) + strlen(osTemp) + 2;
    1045                 : 
    1046             376 :             pszMetadata = (char *)CPLRealloc( pszMetadata, iLength );
    1047             376 :             if ( !EQUAL( pszMetadata, "" ) )
    1048             132 :                 strncat( pszMetadata, ",", 1 );
    1049             376 :             strncat( pszMetadata, osTemp, iLength );
    1050                 :         }
    1051                 :     }
    1052                 : 
    1053             244 :     return pszMetadata;
    1054                 : }
    1055                 : 
    1056                 : /************************************************************************/
    1057                 : /*                          GetMetadataElement()                        */
    1058                 : /************************************************************************/
    1059                 : 
    1060                 : int MrSIDDataset::GetMetadataElement( const char *pszKey, void *pValue,
    1061             337 :                                       int iLength )
    1062                 : {
    1063             337 :     if ( !poMetadata->has( pszKey ) )
    1064             258 :         return FALSE;
    1065                 : 
    1066              79 :     const LTIMetadataRecord *poMetadataRec = NULL;
    1067              79 :     poMetadata->get( pszKey, poMetadataRec );
    1068                 : 
    1069              79 :     if ( !poMetadataRec->isScalar() )
    1070              24 :         return FALSE;
    1071                 : 
    1072                 :     // XXX: return FALSE if we have more than one element in metadata record
    1073                 :     int iSize;
    1074              55 :     switch( poMetadataRec->getDataType() )
    1075                 :     {
    1076                 :          case LTI_METADATA_DATATYPE_UINT8:
    1077                 :          case LTI_METADATA_DATATYPE_SINT8:
    1078               0 :              iSize = 1;
    1079               0 :              break;
    1080                 :          case LTI_METADATA_DATATYPE_UINT16:
    1081                 :          case LTI_METADATA_DATATYPE_SINT16:
    1082              49 :              iSize = 2;
    1083              49 :              break;
    1084                 :          case LTI_METADATA_DATATYPE_UINT32:
    1085                 :          case LTI_METADATA_DATATYPE_SINT32:
    1086                 :          case LTI_METADATA_DATATYPE_FLOAT32:
    1087               0 :              iSize = 4;
    1088               0 :              break;
    1089                 :          case LTI_METADATA_DATATYPE_FLOAT64:
    1090               0 :              iSize = 8;
    1091               0 :              break;
    1092                 :          case LTI_METADATA_DATATYPE_ASCII:
    1093               6 :              iSize = iLength;
    1094               6 :              break;
    1095                 :          default:
    1096               0 :              iSize = 0;
    1097                 :              break;
    1098                 :     }
    1099                 : 
    1100              55 :     if ( poMetadataRec->getDataType() == LTI_METADATA_DATATYPE_ASCII )
    1101                 :     {
    1102                 :         strncpy( (char *)pValue,
    1103               6 :                  ((const char**)poMetadataRec->getScalarData())[0], iSize );
    1104               6 :         ((char *)pValue)[iSize - 1] = '\0';
    1105                 :     }
    1106                 :     else
    1107              49 :         memcpy( pValue, poMetadataRec->getScalarData(), iSize );
    1108                 : 
    1109              55 :     return TRUE;
    1110                 : }
    1111                 : 
    1112                 : /************************************************************************/
    1113                 : /*                             OpenZoomLevel()                          */
    1114                 : /************************************************************************/
    1115                 : 
    1116             106 : CPLErr MrSIDDataset::OpenZoomLevel( lt_int32 iZoom )
    1117                 : {
    1118                 : /* -------------------------------------------------------------------- */
    1119                 : /*      Get image geometry.                                            */
    1120                 : /* -------------------------------------------------------------------- */
    1121             106 :     if ( iZoom != 0 )
    1122                 :     {
    1123                 :         lt_uint32 iWidth, iHeight;
    1124              87 :         dfCurrentMag = LTIUtils::levelToMag( iZoom );
    1125              87 :         poImageReader->getDimsAtMag( dfCurrentMag, iWidth, iHeight );
    1126              87 :         nRasterXSize = iWidth;
    1127              87 :         nRasterYSize = iHeight;
    1128                 :     }
    1129                 :     else
    1130                 :     {
    1131              19 :         dfCurrentMag = 1.0;
    1132              19 :         nRasterXSize = poImageReader->getWidth();
    1133              19 :         nRasterYSize = poImageReader->getHeight();
    1134                 :     }
    1135                 : 
    1136             106 :     nBands = poImageReader->getNumBands();
    1137             106 :     nBlockXSize = nRasterXSize;
    1138             106 :     nBlockYSize = poImageReader->getStripHeight();
    1139                 : 
    1140                 :     CPLDebug( "MrSID", "Opened zoom level %d with size %dx%d.",
    1141             106 :               iZoom, nRasterXSize, nRasterYSize );
    1142                 : 
    1143                 :     try
    1144                 :     {
    1145             106 :         poLTINav = new LTIDLLNavigator<LTINavigator>( *poImageReader );
    1146                 :     }
    1147               0 :     catch ( ... )
    1148                 :     {
    1149                 :         CPLError( CE_Failure, CPLE_AppDefined,
    1150                 :                   "MrSIDDataset::OpenZoomLevel(): "
    1151               0 :                   "Failed to create LTINavigator object." );
    1152               0 :         return CE_Failure;
    1153                 :     }
    1154                 : 
    1155                 : /* -------------------------------------------------------------------- */
    1156                 : /*  Handle sample type and color space.                                 */
    1157                 : /* -------------------------------------------------------------------- */
    1158             106 :     eColorSpace = poImageReader->getColorSpace();
    1159             106 :     eSampleType = poImageReader->getDataType();
    1160             106 :     switch ( eSampleType )
    1161                 :     {
    1162                 :       case LTI_DATATYPE_UINT16:
    1163              12 :         eDataType = GDT_UInt16;
    1164              12 :         break;
    1165                 :       case LTI_DATATYPE_SINT16:
    1166               0 :         eDataType = GDT_Int16;
    1167               0 :         break;
    1168                 :       case LTI_DATATYPE_UINT32:
    1169               0 :         eDataType = GDT_UInt32;
    1170               0 :         break;
    1171                 :       case LTI_DATATYPE_SINT32:
    1172               0 :         eDataType = GDT_Int32;
    1173               0 :         break;
    1174                 :       case LTI_DATATYPE_FLOAT32:
    1175               0 :         eDataType = GDT_Float32;
    1176               0 :         break;
    1177                 :       case LTI_DATATYPE_FLOAT64:
    1178               0 :         eDataType = GDT_Float64;
    1179               0 :         break;
    1180                 :       case LTI_DATATYPE_UINT8:
    1181                 :       case LTI_DATATYPE_SINT8:
    1182                 :       default:
    1183              94 :         eDataType = GDT_Byte;
    1184                 :         break;
    1185                 :     }
    1186                 : 
    1187                 : /* -------------------------------------------------------------------- */
    1188                 : /*      Read georeferencing.                                            */
    1189                 : /* -------------------------------------------------------------------- */
    1190             106 :     if ( !poImageReader->isGeoCoordImplicit() )
    1191                 :     {
    1192              42 :         const LTIGeoCoord& oGeo = poImageReader->getGeoCoord();
    1193                 :         oGeo.get( adfGeoTransform[0], adfGeoTransform[3],
    1194                 :                   adfGeoTransform[1], adfGeoTransform[5],
    1195              42 :                   adfGeoTransform[2], adfGeoTransform[4] );
    1196                 :         
    1197              42 :         adfGeoTransform[0] = adfGeoTransform[0] - adfGeoTransform[1] / 2;
    1198              42 :         adfGeoTransform[3] = adfGeoTransform[3] - adfGeoTransform[5] / 2;
    1199              42 :         bHasGeoTransform = TRUE;
    1200                 :     }
    1201              64 :     else if( iZoom == 0 )
    1202                 :     {
    1203                 :         bHasGeoTransform = 
    1204                 :             GDALReadWorldFile( GetDescription(), ".sdw",  
    1205                 :                                adfGeoTransform )
    1206                 :             || GDALReadWorldFile( GetDescription(), ".sidw", 
    1207                 :                                   adfGeoTransform )
    1208                 :             || GDALReadWorldFile( GetDescription(), ".wld", 
    1209              11 :                                   adfGeoTransform );
    1210                 :     }
    1211                 :     
    1212                 : /* -------------------------------------------------------------------- */
    1213                 : /*      Read wkt.                                                       */
    1214                 : /* -------------------------------------------------------------------- */
    1215                 : #ifdef MRSID_HAVE_GETWKT
    1216             106 :     if( !poImageReader->isGeoCoordImplicit() )
    1217                 :     {
    1218              42 :         const LTIGeoCoord& oGeo = poImageReader->getGeoCoord();
    1219                 :         
    1220              42 :         if( oGeo.getWKT() )
    1221                 :         {
    1222              42 :             CPLFree( pszProjection );
    1223              42 :             pszProjection =  CPLStrdup( oGeo.getWKT() );
    1224                 :         }
    1225                 :     }
    1226                 : #endif // HAVE_MRSID_GETWKT
    1227                 : 
    1228                 : /* -------------------------------------------------------------------- */
    1229                 : /*      Read NoData value.                                              */
    1230                 : /* -------------------------------------------------------------------- */
    1231             106 :     poNDPixel = poImageReader->getNoDataPixel();
    1232                 : 
    1233                 : /* -------------------------------------------------------------------- */
    1234                 : /*      Create band information objects.                                */
    1235                 : /* -------------------------------------------------------------------- */
    1236                 :     int             iBand;
    1237                 : 
    1238             568 :     for( iBand = 1; iBand <= nBands; iBand++ )
    1239             178 :         SetBand( iBand, new MrSIDRasterBand( this, iBand ) );
    1240                 : 
    1241             106 :     return CE_None;
    1242                 : }
    1243                 : 
    1244                 : /************************************************************************/
    1245                 : /*                         MrSIDIdentify()                              */
    1246                 : /*                                                                      */
    1247                 : /*          Identify method that only supports MrSID files.             */
    1248                 : /************************************************************************/
    1249                 : 
    1250           10199 : static int MrSIDIdentify( GDALOpenInfo * poOpenInfo )
    1251                 : {
    1252           10199 :     if( poOpenInfo->nHeaderBytes < 32 )
    1253            9525 :         return FALSE;
    1254                 : 
    1255             674 :     if ( !EQUALN((const char *) poOpenInfo->pabyHeader, "msid", 4) )
    1256             667 :         return FALSE;
    1257                 :         
    1258               7 :     return TRUE;
    1259                 : }
    1260                 : 
    1261                 : /************************************************************************/
    1262                 : /*                          MrSIDOpen()                                 */
    1263                 : /*                                                                      */
    1264                 : /*          Open method that only supports MrSID files.                 */
    1265                 : /************************************************************************/
    1266                 : 
    1267            1954 : static GDALDataset* MrSIDOpen( GDALOpenInfo *poOpenInfo )
    1268                 : {
    1269            1954 :     if (!MrSIDIdentify(poOpenInfo))
    1270            1947 :         return NULL;
    1271                 :         
    1272               7 :     return MrSIDDataset::Open( poOpenInfo, FALSE );
    1273                 : }
    1274                 : 
    1275                 : 
    1276                 : #ifdef MRSID_J2K
    1277                 : 
    1278                 : static const unsigned char jpc_header[] = 
    1279                 : {0xff,0x4f};
    1280                 : 
    1281                 : /************************************************************************/
    1282                 : /*                         JP2Identify()                                */
    1283                 : /*                                                                      */
    1284                 : /*        Identify method that only supports JPEG2000 files.            */
    1285                 : /************************************************************************/
    1286                 : 
    1287            9792 : static int JP2Identify( GDALOpenInfo *poOpenInfo )
    1288                 : {
    1289            9792 :     if( poOpenInfo->nHeaderBytes < 32 )
    1290            9442 :         return FALSE;
    1291                 : 
    1292             350 :     if( memcmp( poOpenInfo->pabyHeader, jpc_header, sizeof(jpc_header) ) == 0 )
    1293                 :     {
    1294                 :         const char *pszExtension;
    1295                 : 
    1296               8 :         pszExtension = CPLGetExtension( poOpenInfo->pszFilename );
    1297                 :         
    1298               8 :         if( !EQUAL(pszExtension,"jpc") && !EQUAL(pszExtension,"j2k") 
    1299                 :             && !EQUAL(pszExtension,"jp2") && !EQUAL(pszExtension,"jpx") 
    1300                 :             && !EQUAL(pszExtension,"j2c") && !EQUAL(pszExtension,"ntf"))
    1301               0 :             return FALSE;
    1302                 :     }
    1303             342 :     else if( !EQUALN((const char *) poOpenInfo->pabyHeader + 4, "jP  ", 4) )
    1304             338 :         return FALSE;
    1305                 : 
    1306              12 :     return TRUE;
    1307                 : }
    1308                 : 
    1309                 : /************************************************************************/
    1310                 : /*                            JP2Open()                                 */
    1311                 : /*                                                                      */
    1312                 : /*      Open method that only supports JPEG2000 files.                  */
    1313                 : /************************************************************************/
    1314                 : 
    1315            1561 : static GDALDataset* JP2Open( GDALOpenInfo *poOpenInfo )
    1316                 : {
    1317            1561 :     if (!JP2Identify(poOpenInfo))
    1318            1549 :         return NULL;
    1319                 :         
    1320              12 :     return MrSIDDataset::Open( poOpenInfo, TRUE );
    1321                 : }
    1322                 : 
    1323                 : #endif // MRSID_J2K
    1324                 : 
    1325                 : /************************************************************************/
    1326                 : /*                                Open()                                */
    1327                 : /************************************************************************/
    1328                 : 
    1329              19 : GDALDataset *MrSIDDataset::Open( GDALOpenInfo * poOpenInfo, int bIsJP2 )
    1330                 : {
    1331              19 :     if(poOpenInfo->fp)
    1332                 :     {
    1333              16 :         VSIFClose( poOpenInfo->fp );
    1334              16 :         poOpenInfo->fp = NULL;
    1335                 :     }
    1336                 : 
    1337                 : /* -------------------------------------------------------------------- */
    1338                 : /*      Create a corresponding GDALDataset.                             */
    1339                 : /* -------------------------------------------------------------------- */
    1340                 :     MrSIDDataset    *poDS;
    1341                 :     LT_STATUS       eStat;
    1342                 : 
    1343              19 :     poDS = new MrSIDDataset(bIsJP2);
    1344              19 :     eStat = poDS->oStream.initialize( poOpenInfo->pszFilename, "rb" );
    1345              19 :     if ( !LT_SUCCESS(eStat) )
    1346                 :     {
    1347                 :         CPLError( CE_Failure, CPLE_AppDefined,
    1348                 :                   "MrSIDStream::initialize(): "
    1349                 :                   "failed to open file \"%s\".\n%s",
    1350               0 :                   poOpenInfo->pszFilename, getLastStatusString( eStat ) );
    1351               0 :         delete poDS;
    1352               0 :         return NULL;
    1353                 :     }
    1354                 : 
    1355              19 :     poDS->oStream.open();
    1356                 : 
    1357                 : #if defined(LTI_SDK_MAJOR) && LTI_SDK_MAJOR >= 7
    1358                 : 
    1359                 : #ifdef MRSID_J2K
    1360              19 :     if ( bIsJP2 )
    1361                 :     {
    1362              12 :         J2KImageReader  *reader = J2KImageReader::create();
    1363              12 :         eStat = reader->initialize( poDS->oStream );
    1364              12 :         poDS->poImageReader = reader;
    1365                 :     }
    1366                 :     else
    1367                 : #endif /* MRSID_J2K */
    1368                 :     {
    1369               7 :         MrSIDImageReader    *reader = MrSIDImageReader::create();
    1370               7 :   eStat = reader->initialize( &poDS->oStream, NULL );
    1371               7 :         poDS->poImageReader = reader;           
    1372                 :     }
    1373                 : 
    1374                 : #else /* LTI_SDK_MAJOR < 7 */
    1375                 : 
    1376                 : #ifdef MRSID_J2K
    1377                 :     if ( bIsJP2 )
    1378                 :     {
    1379                 :         poDS->poImageReader =
    1380                 :             new LTIDLLReader<J2KImageReader>( poDS->oStream, true );
    1381                 :         eStat = poDS->poImageReader->initialize();
    1382                 :     }
    1383                 :     else
    1384                 : #endif /* MRSID_J2K */
    1385                 :     {
    1386                 :         poDS->poImageReader =
    1387                 :             new LTIDLLReader<MrSIDImageReader>( &poDS->oStream, NULL );
    1388                 :         eStat = poDS->poImageReader->initialize();
    1389                 :     }
    1390                 : 
    1391                 : #endif /* LTI_SDK_MAJOR >= 7 */
    1392                 : 
    1393              19 :     if ( !LT_SUCCESS(eStat) )
    1394                 :     {
    1395                 :         CPLError( CE_Failure, CPLE_AppDefined,
    1396                 :                   "LTIImageReader::initialize(): "
    1397                 :                   "failed to initialize reader from the stream \"%s\".\n%s",
    1398               0 :                   poOpenInfo->pszFilename, getLastStatusString( eStat ) );
    1399               0 :         delete poDS;
    1400               0 :         return NULL;
    1401                 :     }
    1402                 : 
    1403                 : /* -------------------------------------------------------------------- */
    1404                 : /*      Read metadata.                                                  */
    1405                 : /* -------------------------------------------------------------------- */
    1406                 :     poDS->poMetadata = new LTIDLLCopy<LTIMetadataDatabase>(
    1407              19 :         poDS->poImageReader->getMetadata() );
    1408              19 :     const GUInt32       iNumRecs = poDS->poMetadata->getIndexCount();
    1409                 :     GUInt32             i;
    1410                 : 
    1411             263 :     for ( i = 0; i < iNumRecs; i++ )
    1412                 :     {
    1413             244 :         const LTIMetadataRecord *poMetadataRec = NULL;
    1414             244 :         if ( LT_SUCCESS(poDS->poMetadata->getDataByIndex(i, poMetadataRec)) )
    1415                 :         {
    1416             244 :             char    *pszElement = poDS->SerializeMetadataRec( poMetadataRec );
    1417             244 :             char    *pszKey = CPLStrdup( poMetadataRec->getTagName() );
    1418             244 :             char    *pszTemp = pszKey;
    1419                 : 
    1420                 :             // GDAL metadata keys should not contain ':' and '=' characters.
    1421                 :             // We will replace them with '_'.
    1422            7925 :             do
    1423                 :             {
    1424            7925 :                 if ( *pszTemp == ':' || *pszTemp == '=' )
    1425             690 :                     *pszTemp = '_';
    1426                 :             }
    1427                 :             while ( *++pszTemp );
    1428                 : 
    1429             244 :             poDS->SetMetadataItem( pszKey, pszElement );
    1430                 : 
    1431             244 :             CPLFree( pszElement );
    1432             244 :             CPLFree( pszKey );
    1433                 :         }
    1434                 :     }
    1435                 : 
    1436                 : /* -------------------------------------------------------------------- */
    1437                 : /*      Add MrSID version.                                              */
    1438                 : /* -------------------------------------------------------------------- */
    1439                 : #ifdef MRSID_J2K
    1440              19 :     if( !bIsJP2 )
    1441                 : #endif
    1442                 :     {
    1443                 :         lt_uint8 major;
    1444                 :         lt_uint8 minor;
    1445                 :         char letter;
    1446               7 :         MrSIDImageReader* poMrSIDImageReader = (MrSIDImageReader*)poDS->poImageReader;
    1447               7 :         poMrSIDImageReader->getVersion(major, minor, minor, letter);
    1448               7 :         if (major < 2) 
    1449               6 :             major = 2;
    1450                 : 
    1451               7 :         poDS->SetMetadataItem( "VERSION", CPLString().Printf("MG%d", major) );
    1452                 :     }
    1453                 : 
    1454              19 :     poDS->GetGTIFDefn();
    1455                 :     
    1456                 : /* -------------------------------------------------------------------- */
    1457                 : /*      Get number of resolution levels (we will use them as overviews).*/
    1458                 : /* -------------------------------------------------------------------- */
    1459                 : #ifdef MRSID_J2K
    1460              19 :     if( bIsJP2 )
    1461                 :         poDS->nOverviewCount
    1462              12 :             = ((J2KImageReader *) (poDS->poImageReader))->getNumLevels();
    1463                 :     else
    1464                 : #endif
    1465                 :         poDS->nOverviewCount
    1466               7 :             = ((MrSIDImageReader *) (poDS->poImageReader))->getNumLevels();
    1467                 : 
    1468              19 :     if ( poDS->nOverviewCount > 0 )
    1469                 :     {
    1470                 :         lt_int32        i;
    1471                 : 
    1472                 :         poDS->papoOverviewDS = (MrSIDDataset **)
    1473              19 :             CPLMalloc( poDS->nOverviewCount * (sizeof(void*)) );
    1474                 : 
    1475             212 :         for ( i = 0; i < poDS->nOverviewCount; i++ )
    1476                 :         {
    1477              87 :             poDS->papoOverviewDS[i] = new MrSIDDataset(bIsJP2);
    1478              87 :             poDS->papoOverviewDS[i]->poImageReader = poDS->poImageReader;
    1479              87 :             poDS->papoOverviewDS[i]->OpenZoomLevel( i + 1 );
    1480              87 :             poDS->papoOverviewDS[i]->bIsOverview = TRUE;
    1481              87 :             poDS->papoOverviewDS[i]->poParentDS = poDS;
    1482                 :         }
    1483                 :     }
    1484                 : 
    1485                 : /* -------------------------------------------------------------------- */
    1486                 : /*      Create object for the whole image.                              */
    1487                 : /* -------------------------------------------------------------------- */
    1488              19 :     poDS->SetDescription( poOpenInfo->pszFilename );
    1489              19 :     poDS->OpenZoomLevel( 0 );
    1490                 : 
    1491                 :     CPLDebug( "MrSID",
    1492                 :               "Opened image: width %d, height %d, bands %d",
    1493              19 :               poDS->nRasterXSize, poDS->nRasterYSize, poDS->nBands );
    1494                 : 
    1495              19 :     if( poDS->nBands > 1 )
    1496               6 :         poDS->SetMetadataItem( "INTERLEAVE", "PIXEL", "IMAGE_STRUCTURE" );
    1497                 : 
    1498                 : /* -------------------------------------------------------------------- */
    1499                 : /*      Initialize any PAM information.                                 */
    1500                 : /* -------------------------------------------------------------------- */
    1501              19 :     poDS->TryLoadXML();
    1502                 : 
    1503              19 :     return( poDS );
    1504                 : }
    1505                 : 
    1506                 : /************************************************************************/
    1507                 : /*                    EPSGProjMethodToCTProjMethod()                    */
    1508                 : /*                                                                      */
    1509                 : /*      Convert between the EPSG enumeration for projection methods,    */
    1510                 : /*      and the GeoTIFF CT codes.                                       */
    1511                 : /*      Explicitly copied from geo_normalize.c of the GeoTIFF package   */
    1512                 : /************************************************************************/
    1513                 : 
    1514               1 : static int EPSGProjMethodToCTProjMethod( int nEPSG )
    1515                 : 
    1516                 : {
    1517                 :     /* see trf_method.csv for list of EPSG codes */
    1518                 :     
    1519               1 :     switch( nEPSG )
    1520                 :     {
    1521                 :       case 9801:
    1522               0 :         return( CT_LambertConfConic_1SP );
    1523                 : 
    1524                 :       case 9802:
    1525               0 :         return( CT_LambertConfConic_2SP );
    1526                 : 
    1527                 :       case 9803:
    1528               0 :         return( CT_LambertConfConic_2SP ); /* Belgian variant not supported */
    1529                 : 
    1530                 :       case 9804:
    1531               0 :         return( CT_Mercator );  /* 1SP and 2SP not differentiated */
    1532                 : 
    1533                 :       case 9805:
    1534               0 :         return( CT_Mercator );  /* 1SP and 2SP not differentiated */
    1535                 : 
    1536                 :       case 9806:
    1537               0 :         return( CT_CassiniSoldner );
    1538                 : 
    1539                 :       case 9807:
    1540               1 :         return( CT_TransverseMercator );
    1541                 : 
    1542                 :       case 9808:
    1543               0 :         return( CT_TransvMercator_SouthOriented );
    1544                 : 
    1545                 :       case 9809:
    1546               0 :         return( CT_ObliqueStereographic );
    1547                 : 
    1548                 :       case 9810:
    1549               0 :         return( CT_PolarStereographic );
    1550                 : 
    1551                 :       case 9811:
    1552               0 :         return( CT_NewZealandMapGrid );
    1553                 : 
    1554                 :       case 9812:
    1555               0 :         return( CT_ObliqueMercator ); /* is hotine actually different? */
    1556                 : 
    1557                 :       case 9813:
    1558               0 :         return( CT_ObliqueMercator_Laborde );
    1559                 : 
    1560                 :       case 9814:
    1561               0 :         return( CT_ObliqueMercator_Rosenmund ); /* swiss  */
    1562                 : 
    1563                 :       case 9815:
    1564               0 :         return( CT_ObliqueMercator );
    1565                 : 
    1566                 :       case 9816: /* tunesia mining grid has no counterpart */
    1567               0 :         return( KvUserDefined );
    1568                 :     }
    1569                 : 
    1570               0 :     return( KvUserDefined );
    1571                 : }
    1572                 : 
    1573                 : /* EPSG Codes for projection parameters.  Unfortunately, these bear no
    1574                 :    relationship to the GeoTIFF codes even though the names are so similar. */
    1575                 : 
    1576                 : #define EPSGNatOriginLat         8801
    1577                 : #define EPSGNatOriginLong        8802
    1578                 : #define EPSGNatOriginScaleFactor 8805
    1579                 : #define EPSGFalseEasting         8806
    1580                 : #define EPSGFalseNorthing        8807
    1581                 : #define EPSGProjCenterLat        8811
    1582                 : #define EPSGProjCenterLong       8812
    1583                 : #define EPSGAzimuth              8813
    1584                 : #define EPSGAngleRectifiedToSkewedGrid 8814
    1585                 : #define EPSGInitialLineScaleFactor 8815
    1586                 : #define EPSGProjCenterEasting    8816
    1587                 : #define EPSGProjCenterNorthing   8817
    1588                 : #define EPSGPseudoStdParallelLat 8818
    1589                 : #define EPSGPseudoStdParallelScaleFactor 8819
    1590                 : #define EPSGFalseOriginLat       8821
    1591                 : #define EPSGFalseOriginLong      8822
    1592                 : #define EPSGStdParallel1Lat      8823
    1593                 : #define EPSGStdParallel2Lat      8824
    1594                 : #define EPSGFalseOriginEasting   8826
    1595                 : #define EPSGFalseOriginNorthing  8827
    1596                 : #define EPSGSphericalOriginLat   8828
    1597                 : #define EPSGSphericalOriginLong  8829
    1598                 : #define EPSGInitialLongitude     8830
    1599                 : #define EPSGZoneWidth            8831
    1600                 : 
    1601                 : /************************************************************************/
    1602                 : /*                            SetGTParmIds()                            */
    1603                 : /*                                                                      */
    1604                 : /*      This is hardcoded logic to set the GeoTIFF parameter            */
    1605                 : /*      identifiers for all the EPSG supported projections.  As the     */
    1606                 : /*      trf_method.csv table grows with new projections, this code      */
    1607                 : /*      will need to be updated.                                        */
    1608                 : /*      Explicitly copied from geo_normalize.c of the GeoTIFF package.  */
    1609                 : /************************************************************************/
    1610                 : 
    1611                 : static int SetGTParmIds( int nCTProjection, 
    1612                 :                          int *panProjParmId, 
    1613               1 :                          int *panEPSGCodes )
    1614                 : 
    1615                 : {
    1616                 :     int anWorkingDummy[7];
    1617                 : 
    1618               1 :     if( panEPSGCodes == NULL )
    1619               1 :         panEPSGCodes = anWorkingDummy;
    1620               1 :     if( panProjParmId == NULL )
    1621               0 :         panProjParmId = anWorkingDummy;
    1622                 : 
    1623               1 :     memset( panEPSGCodes, 0, sizeof(int) * 7 );
    1624                 : 
    1625                 :     /* psDefn->nParms = 7; */
    1626                 :     
    1627               1 :     switch( nCTProjection )
    1628                 :     {
    1629                 :       case CT_CassiniSoldner:
    1630                 :       case CT_NewZealandMapGrid:
    1631               0 :         panProjParmId[0] = ProjNatOriginLatGeoKey;
    1632               0 :         panProjParmId[1] = ProjNatOriginLongGeoKey;
    1633               0 :         panProjParmId[5] = ProjFalseEastingGeoKey;
    1634               0 :         panProjParmId[6] = ProjFalseNorthingGeoKey;
    1635                 : 
    1636               0 :         panEPSGCodes[0] = EPSGNatOriginLat;
    1637               0 :         panEPSGCodes[1] = EPSGNatOriginLong;
    1638               0 :         panEPSGCodes[5] = EPSGFalseEasting;
    1639               0 :         panEPSGCodes[6] = EPSGFalseNorthing;
    1640               0 :         return TRUE;
    1641                 : 
    1642                 :       case CT_ObliqueMercator:
    1643               0 :         panProjParmId[0] = ProjCenterLatGeoKey;
    1644               0 :         panProjParmId[1] = ProjCenterLongGeoKey;
    1645               0 :         panProjParmId[2] = ProjAzimuthAngleGeoKey;
    1646               0 :         panProjParmId[3] = ProjRectifiedGridAngleGeoKey;
    1647               0 :         panProjParmId[4] = ProjScaleAtCenterGeoKey;
    1648               0 :         panProjParmId[5] = ProjFalseEastingGeoKey;
    1649               0 :         panProjParmId[6] = ProjFalseNorthingGeoKey;
    1650                 : 
    1651               0 :         panEPSGCodes[0] = EPSGProjCenterLat;
    1652               0 :         panEPSGCodes[1] = EPSGProjCenterLong;
    1653               0 :         panEPSGCodes[2] = EPSGAzimuth;
    1654               0 :         panEPSGCodes[3] = EPSGAngleRectifiedToSkewedGrid;
    1655               0 :         panEPSGCodes[4] = EPSGInitialLineScaleFactor;
    1656               0 :         panEPSGCodes[5] = EPSGProjCenterEasting;
    1657               0 :         panEPSGCodes[6] = EPSGProjCenterNorthing;
    1658               0 :         return TRUE;
    1659                 : 
    1660                 :       case CT_ObliqueMercator_Laborde:
    1661               0 :         panProjParmId[0] = ProjCenterLatGeoKey;
    1662               0 :         panProjParmId[1] = ProjCenterLongGeoKey;
    1663               0 :         panProjParmId[2] = ProjAzimuthAngleGeoKey;
    1664               0 :         panProjParmId[4] = ProjScaleAtCenterGeoKey;
    1665               0 :         panProjParmId[5] = ProjFalseEastingGeoKey;
    1666               0 :         panProjParmId[6] = ProjFalseNorthingGeoKey;
    1667                 : 
    1668               0 :         panEPSGCodes[0] = EPSGProjCenterLat;
    1669               0 :         panEPSGCodes[1] = EPSGProjCenterLong;
    1670               0 :         panEPSGCodes[2] = EPSGAzimuth;
    1671               0 :         panEPSGCodes[4] = EPSGInitialLineScaleFactor;
    1672               0 :         panEPSGCodes[5] = EPSGProjCenterEasting;
    1673               0 :         panEPSGCodes[6] = EPSGProjCenterNorthing;
    1674               0 :         return TRUE;
    1675                 :         
    1676                 :       case CT_LambertConfConic_1SP:
    1677                 :       case CT_Mercator:
    1678                 :       case CT_ObliqueStereographic:
    1679                 :       case CT_PolarStereographic:
    1680                 :       case CT_TransverseMercator:
    1681                 :       case CT_TransvMercator_SouthOriented:
    1682               1 :         panProjParmId[0] = ProjNatOriginLatGeoKey;
    1683               1 :         panProjParmId[1] = ProjNatOriginLongGeoKey;
    1684               1 :         panProjParmId[4] = ProjScaleAtNatOriginGeoKey;
    1685               1 :         panProjParmId[5] = ProjFalseEastingGeoKey;
    1686               1 :         panProjParmId[6] = ProjFalseNorthingGeoKey;
    1687                 : 
    1688               1 :         panEPSGCodes[0] = EPSGNatOriginLat;
    1689               1 :         panEPSGCodes[1] = EPSGNatOriginLong;
    1690               1 :         panEPSGCodes[4] = EPSGNatOriginScaleFactor;
    1691               1 :         panEPSGCodes[5] = EPSGFalseEasting;
    1692               1 :         panEPSGCodes[6] = EPSGFalseNorthing;
    1693               1 :         return TRUE;
    1694                 : 
    1695                 :       case CT_LambertConfConic_2SP:
    1696               0 :         panProjParmId[0] = ProjFalseOriginLatGeoKey;
    1697               0 :         panProjParmId[1] = ProjFalseOriginLongGeoKey;
    1698               0 :         panProjParmId[2] = ProjStdParallel1GeoKey;
    1699               0 :         panProjParmId[3] = ProjStdParallel2GeoKey;
    1700               0 :         panProjParmId[5] = ProjFalseEastingGeoKey;
    1701               0 :         panProjParmId[6] = ProjFalseNorthingGeoKey;
    1702                 : 
    1703               0 :         panEPSGCodes[0] = EPSGFalseOriginLat;
    1704               0 :         panEPSGCodes[1] = EPSGFalseOriginLong;
    1705               0 :         panEPSGCodes[2] = EPSGStdParallel1Lat;
    1706               0 :         panEPSGCodes[3] = EPSGStdParallel2Lat;
    1707               0 :         panEPSGCodes[5] = EPSGFalseOriginEasting;
    1708               0 :         panEPSGCodes[6] = EPSGFalseOriginNorthing;
    1709               0 :         return TRUE;
    1710                 : 
    1711                 :       case CT_SwissObliqueCylindrical:
    1712               0 :         panProjParmId[0] = ProjCenterLatGeoKey;
    1713               0 :         panProjParmId[1] = ProjCenterLongGeoKey;
    1714               0 :         panProjParmId[5] = ProjFalseEastingGeoKey;
    1715               0 :         panProjParmId[6] = ProjFalseNorthingGeoKey;
    1716                 : 
    1717                 :         /* EPSG codes? */
    1718               0 :         return TRUE;
    1719                 : 
    1720                 :       default:
    1721               0 :         return( FALSE );
    1722                 :     }
    1723                 : }
    1724                 : 
    1725                 : static const char *papszDatumEquiv[] =
    1726                 : {
    1727                 :     "Militar_Geographische_Institut",
    1728                 :     "Militar_Geographische_Institute",
    1729                 :     "World_Geodetic_System_1984",
    1730                 :     "WGS_1984",
    1731                 :     "WGS_72_Transit_Broadcast_Ephemeris",
    1732                 :     "WGS_1972_Transit_Broadcast_Ephemeris",
    1733                 :     "World_Geodetic_System_1972",
    1734                 :     "WGS_1972",
    1735                 :     "European_Terrestrial_Reference_System_89",
    1736                 :     "European_Reference_System_1989",
    1737                 :     NULL
    1738                 : };
    1739                 : 
    1740                 : /************************************************************************/
    1741                 : /*                          WKTMassageDatum()                           */
    1742                 : /*                                                                      */
    1743                 : /*      Massage an EPSG datum name into WMT format.  Also transform     */
    1744                 : /*      specific exception cases into WKT versions.                     */
    1745                 : /*      Explicitly copied from the gt_wkt_srs.cpp.                      */
    1746                 : /************************************************************************/
    1747                 : 
    1748               9 : static void WKTMassageDatum( char ** ppszDatum )
    1749                 : 
    1750                 : {
    1751                 :     int         i, j;
    1752                 :     char        *pszDatum;
    1753                 : 
    1754                 : /* -------------------------------------------------------------------- */
    1755                 : /*      First copy string and allocate with our CPLStrdup() to so we    */
    1756                 : /*      know when we are done this function we will have a CPL          */
    1757                 : /*      string, not a GTIF one.                                         */
    1758                 : /* -------------------------------------------------------------------- */
    1759               9 :     pszDatum = CPLStrdup(*ppszDatum);
    1760               9 :     GTIFFreeMemory( *ppszDatum );
    1761               9 :     *ppszDatum = pszDatum;
    1762               9 :     if (pszDatum[0] == '\0')
    1763               0 :         return;
    1764                 : 
    1765                 : /* -------------------------------------------------------------------- */
    1766                 : /*      Translate non-alphanumeric values to underscores.               */
    1767                 : /* -------------------------------------------------------------------- */
    1768             236 :     for( i = 0; pszDatum[i] != '\0'; i++ )
    1769                 :     {
    1770             227 :         if( !(pszDatum[i] >= 'A' && pszDatum[i] <= 'Z')
    1771                 :             && !(pszDatum[i] >= 'a' && pszDatum[i] <= 'z')
    1772                 :             && !(pszDatum[i] >= '0' && pszDatum[i] <= '9') )
    1773                 :         {
    1774              27 :             pszDatum[i] = '_';
    1775                 :         }
    1776                 :     }
    1777                 : 
    1778                 : /* -------------------------------------------------------------------- */
    1779                 : /*      Remove repeated and trailing underscores.                       */
    1780                 : /* -------------------------------------------------------------------- */
    1781             227 :     for( i = 1, j = 0; pszDatum[i] != '\0'; i++ )
    1782                 :     {
    1783             218 :         if( pszDatum[j] == '_' && pszDatum[i] == '_' )
    1784               0 :             continue;
    1785                 : 
    1786             218 :         pszDatum[++j] = pszDatum[i];
    1787                 :     }
    1788               9 :     if( pszDatum[j] == '_' )
    1789               0 :         pszDatum[j] = '\0';
    1790                 :     else
    1791               9 :         pszDatum[j+1] = '\0';
    1792                 :     
    1793                 : /* -------------------------------------------------------------------- */
    1794                 : /*      Search for datum equivelences.  Specific massaged names get     */
    1795                 : /*      mapped to OpenGIS specified names.                              */
    1796                 : /* -------------------------------------------------------------------- */
    1797              46 :     for( i = 0; papszDatumEquiv[i] != NULL; i += 2 )
    1798                 :     {
    1799              39 :         if( EQUAL(*ppszDatum,papszDatumEquiv[i]) )
    1800                 :         {
    1801               2 :             CPLFree( *ppszDatum );
    1802               2 :             *ppszDatum = CPLStrdup( papszDatumEquiv[i+1] );
    1803               2 :             return;
    1804                 :         }
    1805                 :     }
    1806                 : }
    1807                 : 
    1808                 : /************************************************************************/
    1809                 : /*                           FetchProjParms()                           */
    1810                 : /*                                                                      */
    1811                 : /*      Fetch the projection parameters for a particular projection     */
    1812                 : /*      from MrSID metadata, and fill the GTIFDefn structure out        */
    1813                 : /*      with them.                                                      */
    1814                 : /*      Copied from geo_normalize.c of the GeoTIFF package.             */
    1815                 : /************************************************************************/
    1816                 : 
    1817               6 : void MrSIDDataset::FetchProjParms()
    1818                 : {
    1819               6 :     double dfNatOriginLong = 0.0, dfNatOriginLat = 0.0, dfRectGridAngle = 0.0;
    1820               6 :     double dfFalseEasting = 0.0, dfFalseNorthing = 0.0, dfNatOriginScale = 1.0;
    1821               6 :     double dfStdParallel1 = 0.0, dfStdParallel2 = 0.0, dfAzimuth = 0.0;
    1822                 : 
    1823                 : /* -------------------------------------------------------------------- */
    1824                 : /*      Get the false easting, and northing if available.               */
    1825                 : /* -------------------------------------------------------------------- */
    1826               6 :     if( !GetMetadataElement( "GEOTIFF_NUM::3082::ProjFalseEastingGeoKey",
    1827                 :                              &dfFalseEasting )
    1828                 :         && !GetMetadataElement( "GEOTIFF_NUM::3090:ProjCenterEastingGeoKey",
    1829                 :                                 &dfFalseEasting ) )
    1830               6 :         dfFalseEasting = 0.0;
    1831                 :         
    1832               6 :     if( !GetMetadataElement( "GEOTIFF_NUM::3083::ProjFalseNorthingGeoKey",
    1833                 :                              &dfFalseNorthing )
    1834                 :         && !GetMetadataElement( "GEOTIFF_NUM::3091::ProjCenterNorthingGeoKey",
    1835                 :                                 &dfFalseNorthing ) )
    1836               6 :         dfFalseNorthing = 0.0;
    1837                 : 
    1838               6 :     switch( psDefn->CTProjection )
    1839                 :     {
    1840                 : /* -------------------------------------------------------------------- */
    1841                 :       case CT_Stereographic:
    1842                 : /* -------------------------------------------------------------------- */
    1843               0 :         if( GetMetadataElement( "GEOTIFF_NUM::3080::ProjNatOriginLongGeoKey",
    1844                 :                                 &dfNatOriginLong ) == 0
    1845                 :             && GetMetadataElement( "GEOTIFF_NUM::3084::ProjFalseOriginLongGeoKey",
    1846                 :                                    &dfNatOriginLong ) == 0
    1847                 :             && GetMetadataElement( "GEOTIFF_NUM::3088::ProjCenterLongGeoKey",
    1848                 :                                    &dfNatOriginLong ) == 0 )
    1849               0 :             dfNatOriginLong = 0.0;
    1850                 : 
    1851               0 :         if( GetMetadataElement( "GEOTIFF_NUM::3081::ProjNatOriginLatGeoKey",
    1852                 :                                 &dfNatOriginLat ) == 0
    1853                 :             && GetMetadataElement( "GEOTIFF_NUM::3085::ProjFalseOriginLatGeoKey",
    1854                 :                                    &dfNatOriginLat ) == 0
    1855                 :             && GetMetadataElement( "GEOTIFF_NUM::3089::ProjCenterLatGeoKey",
    1856                 :                                    &dfNatOriginLat ) == 0 )
    1857               0 :             dfNatOriginLat = 0.0;
    1858                 : 
    1859               0 :         if( GetMetadataElement( "GEOTIFF_NUM::3092::ProjScaleAtNatOriginGeoKey",
    1860                 :                                 &dfNatOriginScale ) == 0 )
    1861               0 :             dfNatOriginScale = 1.0;
    1862                 :             
    1863                 :         /* notdef: should transform to decimal degrees at this point */
    1864                 : 
    1865               0 :         psDefn->ProjParm[0] = dfNatOriginLat;
    1866               0 :         psDefn->ProjParmId[0] = ProjCenterLatGeoKey;
    1867               0 :         psDefn->ProjParm[1] = dfNatOriginLong;
    1868               0 :         psDefn->ProjParmId[1] = ProjCenterLongGeoKey;
    1869               0 :         psDefn->ProjParm[4] = dfNatOriginScale;
    1870               0 :         psDefn->ProjParmId[4] = ProjScaleAtNatOriginGeoKey;
    1871               0 :         psDefn->ProjParm[5] = dfFalseEasting;
    1872               0 :         psDefn->ProjParmId[5] = ProjFalseEastingGeoKey;
    1873               0 :         psDefn->ProjParm[6] = dfFalseNorthing;
    1874               0 :         psDefn->ProjParmId[6] = ProjFalseNorthingGeoKey;
    1875                 : 
    1876               0 :         psDefn->nParms = 7;
    1877               0 :         break;
    1878                 : 
    1879                 : /* -------------------------------------------------------------------- */
    1880                 :       case CT_LambertConfConic_1SP:
    1881                 :       case CT_Mercator:
    1882                 :       case CT_ObliqueStereographic:
    1883                 :       case CT_TransverseMercator:
    1884                 :       case CT_TransvMercator_SouthOriented:
    1885                 : /* -------------------------------------------------------------------- */
    1886               6 :         if( GetMetadataElement( "GEOTIFF_NUM::3080::ProjNatOriginLongGeoKey",
    1887                 :                                 &dfNatOriginLong ) == 0
    1888                 :             && GetMetadataElement( "GEOTIFF_NUM::3084::ProjFalseOriginLongGeoKey",
    1889                 :                                    &dfNatOriginLong ) == 0
    1890                 :             && GetMetadataElement( "GEOTIFF_NUM::3088::ProjCenterLongGeoKey", 
    1891                 :                                    &dfNatOriginLong ) == 0 )
    1892               6 :             dfNatOriginLong = 0.0;
    1893                 : 
    1894               6 :         if( GetMetadataElement( "GEOTIFF_NUM::3081::ProjNatOriginLatGeoKey",
    1895                 :                                 &dfNatOriginLat ) == 0
    1896                 :             && GetMetadataElement( "GEOTIFF_NUM::3085::ProjFalseOriginLatGeoKey",
    1897                 :                                    &dfNatOriginLat ) == 0
    1898                 :             && GetMetadataElement( "GEOTIFF_NUM::3089::ProjCenterLatGeoKey",
    1899                 :                                    &dfNatOriginLat ) == 0 )
    1900               6 :             dfNatOriginLat = 0.0;
    1901                 : 
    1902               6 :         if( GetMetadataElement( "GEOTIFF_NUM::3092::ProjScaleAtNatOriginGeoKey",
    1903                 :                                 &dfNatOriginScale ) == 0 )
    1904               6 :             dfNatOriginScale = 1.0;
    1905                 : 
    1906                 :         /* notdef: should transform to decimal degrees at this point */
    1907                 : 
    1908               6 :         psDefn->ProjParm[0] = dfNatOriginLat;
    1909               6 :         psDefn->ProjParmId[0] = ProjNatOriginLatGeoKey;
    1910               6 :         psDefn->ProjParm[1] = dfNatOriginLong;
    1911               6 :         psDefn->ProjParmId[1] = ProjNatOriginLongGeoKey;
    1912               6 :         psDefn->ProjParm[4] = dfNatOriginScale;
    1913               6 :         psDefn->ProjParmId[4] = ProjScaleAtNatOriginGeoKey;
    1914               6 :         psDefn->ProjParm[5] = dfFalseEasting;
    1915               6 :         psDefn->ProjParmId[5] = ProjFalseEastingGeoKey;
    1916               6 :         psDefn->ProjParm[6] = dfFalseNorthing;
    1917               6 :         psDefn->ProjParmId[6] = ProjFalseNorthingGeoKey;
    1918                 : 
    1919               6 :         psDefn->nParms = 7;
    1920               6 :         break;
    1921                 : 
    1922                 : /* -------------------------------------------------------------------- */
    1923                 :       case CT_ObliqueMercator: /* hotine */
    1924                 : /* -------------------------------------------------------------------- */
    1925               0 :         if( GetMetadataElement( "GEOTIFF_NUM::3080::ProjNatOriginLongGeoKey",
    1926                 :                                 &dfNatOriginLong ) == 0
    1927                 :             && GetMetadataElement( "GEOTIFF_NUM::3084::ProjFalseOriginLongGeoKey",
    1928                 :                                    &dfNatOriginLong ) == 0
    1929                 :             && GetMetadataElement( "GEOTIFF_NUM::3088::ProjCenterLongGeoKey", 
    1930                 :                                    &dfNatOriginLong ) == 0 )
    1931               0 :             dfNatOriginLong = 0.0;
    1932                 : 
    1933               0 :         if( GetMetadataElement( "GEOTIFF_NUM::3081::ProjNatOriginLatGeoKey",
    1934                 :                                 &dfNatOriginLat ) == 0
    1935                 :             && GetMetadataElement( "GEOTIFF_NUM::3085::ProjFalseOriginLatGeoKey",
    1936                 :                                    &dfNatOriginLat ) == 0
    1937                 :             && GetMetadataElement( "GEOTIFF_NUM::3089::ProjCenterLatGeoKey",
    1938                 :                                    &dfNatOriginLat ) == 0 )
    1939               0 :             dfNatOriginLat = 0.0;
    1940                 : 
    1941               0 :         if( GetMetadataElement( "GEOTIFF_NUM::3094::ProjAzimuthAngleGeoKey",
    1942                 :                                 &dfAzimuth ) == 0 )
    1943               0 :             dfAzimuth = 0.0;
    1944                 : 
    1945               0 :         if( GetMetadataElement( "GEOTIFF_NUM::3096::ProjRectifiedGridAngleGeoKey",
    1946                 :                                 &dfRectGridAngle ) == 0 )
    1947               0 :             dfRectGridAngle = 90.0;
    1948                 : 
    1949               0 :         if( GetMetadataElement( "GEOTIFF_NUM::3092::ProjScaleAtNatOriginGeoKey",
    1950                 :                                 &dfNatOriginScale ) == 0
    1951                 :             && GetMetadataElement( "GEOTIFF_NUM::3093::ProjScaleAtCenterGeoKey",
    1952                 :                                    &dfNatOriginScale ) == 0 )
    1953               0 :             dfNatOriginScale = 1.0;
    1954                 :             
    1955                 :         /* notdef: should transform to decimal degrees at this point */
    1956                 : 
    1957               0 :         psDefn->ProjParm[0] = dfNatOriginLat;
    1958               0 :         psDefn->ProjParmId[0] = ProjCenterLatGeoKey;
    1959               0 :         psDefn->ProjParm[1] = dfNatOriginLong;
    1960               0 :         psDefn->ProjParmId[1] = ProjCenterLongGeoKey;
    1961               0 :         psDefn->ProjParm[2] = dfAzimuth;
    1962               0 :         psDefn->ProjParmId[2] = ProjAzimuthAngleGeoKey;
    1963               0 :         psDefn->ProjParm[3] = dfRectGridAngle;
    1964               0 :         psDefn->ProjParmId[3] = ProjRectifiedGridAngleGeoKey;
    1965               0 :         psDefn->ProjParm[4] = dfNatOriginScale;
    1966               0 :         psDefn->ProjParmId[4] = ProjScaleAtCenterGeoKey;
    1967               0 :         psDefn->ProjParm[5] = dfFalseEasting;
    1968               0 :         psDefn->ProjParmId[5] = ProjFalseEastingGeoKey;
    1969               0 :         psDefn->ProjParm[6] = dfFalseNorthing;
    1970               0 :         psDefn->ProjParmId[6] = ProjFalseNorthingGeoKey;
    1971                 : 
    1972               0 :         psDefn->nParms = 7;
    1973               0 :         break;
    1974                 : 
    1975                 : /* -------------------------------------------------------------------- */
    1976                 :       case CT_CassiniSoldner:
    1977                 :       case CT_Polyconic:
    1978                 : /* -------------------------------------------------------------------- */
    1979               0 :         if( GetMetadataElement( "GEOTIFF_NUM::3080::ProjNatOriginLongGeoKey",
    1980                 :                                 &dfNatOriginLong ) == 0
    1981                 :             && GetMetadataElement( "GEOTIFF_NUM::3084::ProjFalseOriginLongGeoKey",
    1982                 :                                    &dfNatOriginLong ) == 0
    1983                 :             && GetMetadataElement( "GEOTIFF_NUM::3088::ProjCenterLongGeoKey", 
    1984                 :                                    &dfNatOriginLong ) == 0 )
    1985               0 :             dfNatOriginLong = 0.0;
    1986                 : 
    1987               0 :         if( GetMetadataElement( "GEOTIFF_NUM::3081::ProjNatOriginLatGeoKey",
    1988                 :                                 &dfNatOriginLat ) == 0
    1989                 :             && GetMetadataElement( "GEOTIFF_NUM::3085::ProjFalseOriginLatGeoKey",
    1990                 :                                    &dfNatOriginLat ) == 0
    1991                 :             && GetMetadataElement( "GEOTIFF_NUM::3089::ProjCenterLatGeoKey",
    1992                 :                                    &dfNatOriginLat ) == 0 )
    1993               0 :             dfNatOriginLat = 0.0;
    1994                 : 
    1995                 : 
    1996               0 :         if( GetMetadataElement( "GEOTIFF_NUM::3092::ProjScaleAtNatOriginGeoKey",
    1997                 :                                 &dfNatOriginScale ) == 0
    1998                 :             && GetMetadataElement( "GEOTIFF_NUM::3093::ProjScaleAtCenterGeoKey",
    1999                 :                                    &dfNatOriginScale ) == 0 )
    2000               0 :             dfNatOriginScale = 1.0;
    2001                 :             
    2002                 :         /* notdef: should transform to decimal degrees at this point */
    2003                 : 
    2004               0 :         psDefn->ProjParm[0] = dfNatOriginLat;
    2005               0 :         psDefn->ProjParmId[0] = ProjNatOriginLatGeoKey;
    2006               0 :         psDefn->ProjParm[1] = dfNatOriginLong;
    2007               0 :         psDefn->ProjParmId[1] = ProjNatOriginLongGeoKey;
    2008               0 :         psDefn->ProjParm[4] = dfNatOriginScale;
    2009               0 :         psDefn->ProjParmId[4] = ProjScaleAtNatOriginGeoKey;
    2010               0 :         psDefn->ProjParm[5] = dfFalseEasting;
    2011               0 :         psDefn->ProjParmId[5] = ProjFalseEastingGeoKey;
    2012               0 :         psDefn->ProjParm[6] = dfFalseNorthing;
    2013               0 :         psDefn->ProjParmId[6] = ProjFalseNorthingGeoKey;
    2014                 : 
    2015               0 :         psDefn->nParms = 7;
    2016               0 :         break;
    2017                 : 
    2018                 : /* -------------------------------------------------------------------- */
    2019                 :       case CT_AzimuthalEquidistant:
    2020                 :       case CT_MillerCylindrical:
    2021                 :       case CT_Equirectangular:
    2022                 :       case CT_Gnomonic:
    2023                 :       case CT_LambertAzimEqualArea:
    2024                 :       case CT_Orthographic:
    2025                 : /* -------------------------------------------------------------------- */
    2026               0 :         if( GetMetadataElement( "GEOTIFF_NUM::3080::ProjNatOriginLongGeoKey",
    2027                 :                                 &dfNatOriginLong ) == 0
    2028                 :             && GetMetadataElement( "GEOTIFF_NUM::3084::ProjFalseOriginLongGeoKey",
    2029                 :                                    &dfNatOriginLong ) == 0
    2030                 :             && GetMetadataElement( "GEOTIFF_NUM::3088::ProjCenterLongGeoKey", 
    2031                 :                                    &dfNatOriginLong ) == 0 )
    2032               0 :             dfNatOriginLong = 0.0;
    2033                 : 
    2034               0 :         if( GetMetadataElement( "GEOTIFF_NUM::3081::ProjNatOriginLatGeoKey",
    2035                 :                                 &dfNatOriginLat ) == 0
    2036                 :             && GetMetadataElement( "GEOTIFF_NUM::3085::ProjFalseOriginLatGeoKey",
    2037                 :                                    &dfNatOriginLat ) == 0
    2038                 :             && GetMetadataElement( "GEOTIFF_NUM::3089::ProjCenterLatGeoKey",
    2039                 :                                    &dfNatOriginLat ) == 0 )
    2040               0 :             dfNatOriginLat = 0.0;
    2041                 : 
    2042                 :         /* notdef: should transform to decimal degrees at this point */
    2043                 : 
    2044               0 :         psDefn->ProjParm[0] = dfNatOriginLat;
    2045               0 :         psDefn->ProjParmId[0] = ProjCenterLatGeoKey;
    2046               0 :         psDefn->ProjParm[1] = dfNatOriginLong;
    2047               0 :         psDefn->ProjParmId[1] = ProjCenterLongGeoKey;
    2048               0 :         psDefn->ProjParm[5] = dfFalseEasting;
    2049               0 :         psDefn->ProjParmId[5] = ProjFalseEastingGeoKey;
    2050               0 :         psDefn->ProjParm[6] = dfFalseNorthing;
    2051               0 :         psDefn->ProjParmId[6] = ProjFalseNorthingGeoKey;
    2052                 : 
    2053               0 :         psDefn->nParms = 7;
    2054               0 :         break;
    2055                 : 
    2056                 : /* -------------------------------------------------------------------- */
    2057                 :       case CT_Robinson:
    2058                 :       case CT_Sinusoidal:
    2059                 :       case CT_VanDerGrinten:
    2060                 : /* -------------------------------------------------------------------- */
    2061               0 :         if( GetMetadataElement( "GEOTIFF_NUM::3080::ProjNatOriginLongGeoKey",
    2062                 :                                 &dfNatOriginLong ) == 0
    2063                 :             && GetMetadataElement( "GEOTIFF_NUM::3084::ProjFalseOriginLongGeoKey",
    2064                 :                                    &dfNatOriginLong ) == 0
    2065                 :             && GetMetadataElement( "GEOTIFF_NUM::3088::ProjCenterLongGeoKey", 
    2066                 :                                    &dfNatOriginLong ) == 0 )
    2067               0 :             dfNatOriginLong = 0.0;
    2068                 : 
    2069                 :         /* notdef: should transform to decimal degrees at this point */
    2070                 : 
    2071               0 :         psDefn->ProjParm[1] = dfNatOriginLong;
    2072               0 :         psDefn->ProjParmId[1] = ProjCenterLongGeoKey;
    2073               0 :         psDefn->ProjParm[5] = dfFalseEasting;
    2074               0 :         psDefn->ProjParmId[5] = ProjFalseEastingGeoKey;
    2075               0 :         psDefn->ProjParm[6] = dfFalseNorthing;
    2076               0 :         psDefn->ProjParmId[6] = ProjFalseNorthingGeoKey;
    2077                 : 
    2078               0 :         psDefn->nParms = 7;
    2079               0 :         break;
    2080                 : 
    2081                 : /* -------------------------------------------------------------------- */
    2082                 :       case CT_PolarStereographic:
    2083                 : /* -------------------------------------------------------------------- */
    2084               0 :         if( GetMetadataElement( "GEOTIFF_NUM::3095::ProjStraightVertPoleLongGeoKey",
    2085                 :                                 &dfNatOriginLong ) == 0
    2086                 :             && GetMetadataElement( "GEOTIFF_NUM::3080::ProjNatOriginLongGeoKey",
    2087                 :                                    &dfNatOriginLong ) == 0
    2088                 :             && GetMetadataElement( "GEOTIFF_NUM::3084::ProjFalseOriginLongGeoKey",
    2089                 :                                    &dfNatOriginLong ) == 0
    2090                 :             && GetMetadataElement( "GEOTIFF_NUM::3088::ProjCenterLongGeoKey",
    2091                 :                                    &dfNatOriginLong ) == 0 )
    2092               0 :             dfNatOriginLong = 0.0;
    2093                 : 
    2094               0 :         if( GetMetadataElement( "GEOTIFF_NUM::3081::ProjNatOriginLatGeoKey",
    2095                 :                                 &dfNatOriginLat ) == 0
    2096                 :             && GetMetadataElement( "GEOTIFF_NUM::3085::ProjFalseOriginLatGeoKey",
    2097                 :                                    &dfNatOriginLat ) == 0
    2098                 :             && GetMetadataElement( "GEOTIFF_NUM::3089::ProjCenterLatGeoKey",
    2099                 :                                    &dfNatOriginLat ) == 0 )
    2100               0 :             dfNatOriginLat = 0.0;
    2101                 : 
    2102               0 :         if( GetMetadataElement( "GEOTIFF_NUM::3092::ProjScaleAtNatOriginGeoKey",
    2103                 :                                 &dfNatOriginScale ) == 0
    2104                 :             && GetMetadataElement( "GEOTIFF_NUM::3093::ProjScaleAtCenterGeoKey",
    2105                 :                                    &dfNatOriginScale ) == 0 )
    2106               0 :             dfNatOriginScale = 1.0;
    2107                 :             
    2108                 :         /* notdef: should transform to decimal degrees at this point */
    2109                 : 
    2110               0 :         psDefn->ProjParm[0] = dfNatOriginLat;
    2111               0 :         psDefn->ProjParmId[0] = ProjNatOriginLatGeoKey;;
    2112               0 :         psDefn->ProjParm[1] = dfNatOriginLong;
    2113               0 :         psDefn->ProjParmId[1] = ProjStraightVertPoleLongGeoKey;
    2114               0 :         psDefn->ProjParm[4] = dfNatOriginScale;
    2115               0 :         psDefn->ProjParmId[4] = ProjScaleAtNatOriginGeoKey;
    2116               0 :         psDefn->ProjParm[5] = dfFalseEasting;
    2117               0 :         psDefn->ProjParmId[5] = ProjFalseEastingGeoKey;
    2118               0 :         psDefn->ProjParm[6] = dfFalseNorthing;
    2119               0 :         psDefn->ProjParmId[6] = ProjFalseNorthingGeoKey;
    2120                 : 
    2121               0 :         psDefn->nParms = 7;
    2122               0 :         break;
    2123                 : 
    2124                 : /* -------------------------------------------------------------------- */
    2125                 :       case CT_LambertConfConic_2SP:
    2126                 : /* -------------------------------------------------------------------- */
    2127               0 :         if( GetMetadataElement( "GEOTIFF_NUM::3078::ProjStdParallel1GeoKey",
    2128                 :                                 &dfStdParallel1 ) == 0 )
    2129               0 :             dfStdParallel1 = 0.0;
    2130                 : 
    2131               0 :         if( GetMetadataElement( "GEOTIFF_NUM::3079::ProjStdParallel2GeoKey",
    2132                 :                                 &dfStdParallel2 ) == 0 )
    2133               0 :             dfStdParallel1 = 0.0;
    2134                 : 
    2135               0 :         if( GetMetadataElement( "GEOTIFF_NUM::3080::ProjNatOriginLongGeoKey",
    2136                 :                                 &dfNatOriginLong ) == 0
    2137                 :             && GetMetadataElement( "GEOTIFF_NUM::3084::ProjFalseOriginLongGeoKey",
    2138                 :                                    &dfNatOriginLong ) == 0
    2139                 :             && GetMetadataElement( "GEOTIFF_NUM::3088::ProjCenterLongGeoKey", 
    2140                 :                                    &dfNatOriginLong ) == 0 )
    2141               0 :             dfNatOriginLong = 0.0;
    2142                 : 
    2143               0 :         if( GetMetadataElement( "GEOTIFF_NUM::3081::ProjNatOriginLatGeoKey",
    2144                 :                                 &dfNatOriginLat ) == 0
    2145                 :             && GetMetadataElement( "GEOTIFF_NUM::3085::ProjFalseOriginLatGeoKey",
    2146                 :                                    &dfNatOriginLat ) == 0
    2147                 :             && GetMetadataElement( "GEOTIFF_NUM::3089::ProjCenterLatGeoKey",
    2148                 :                                    &dfNatOriginLat ) == 0 )
    2149               0 :             dfNatOriginLat = 0.0;
    2150                 : 
    2151                 :         /* notdef: should transform to decimal degrees at this point */
    2152                 : 
    2153               0 :         psDefn->ProjParm[0] = dfNatOriginLat;
    2154               0 :         psDefn->ProjParmId[0] = ProjFalseOriginLatGeoKey;
    2155               0 :         psDefn->ProjParm[1] = dfNatOriginLong;
    2156               0 :         psDefn->ProjParmId[1] = ProjFalseOriginLongGeoKey;
    2157               0 :         psDefn->ProjParm[2] = dfStdParallel1;
    2158               0 :         psDefn->ProjParmId[2] = ProjStdParallel1GeoKey;
    2159               0 :         psDefn->ProjParm[3] = dfStdParallel2;
    2160               0 :         psDefn->ProjParmId[3] = ProjStdParallel2GeoKey;
    2161               0 :         psDefn->ProjParm[5] = dfFalseEasting;
    2162               0 :         psDefn->ProjParmId[5] = ProjFalseEastingGeoKey;
    2163               0 :         psDefn->ProjParm[6] = dfFalseNorthing;
    2164               0 :         psDefn->ProjParmId[6] = ProjFalseNorthingGeoKey;
    2165                 : 
    2166               0 :         psDefn->nParms = 7;
    2167               0 :         break;
    2168                 : 
    2169                 : /* -------------------------------------------------------------------- */
    2170                 :       case CT_AlbersEqualArea:
    2171                 :       case CT_EquidistantConic:
    2172                 : /* -------------------------------------------------------------------- */
    2173               0 :         if( GetMetadataElement( "GEOTIFF_NUM::3078::ProjStdParallel1GeoKey",
    2174                 :                                 &dfStdParallel1 ) == 0 )
    2175               0 :             dfStdParallel1 = 0.0;
    2176                 : 
    2177               0 :         if( GetMetadataElement( "GEOTIFF_NUM::3079::ProjStdParallel2GeoKey",
    2178                 :                                 &dfStdParallel2 ) == 0 )
    2179               0 :             dfStdParallel1 = 0.0;
    2180                 : 
    2181               0 :         if( GetMetadataElement( "GEOTIFF_NUM::3080::ProjNatOriginLongGeoKey",
    2182                 :                                 &dfNatOriginLong ) == 0
    2183                 :             && GetMetadataElement( "GEOTIFF_NUM::3084::ProjFalseOriginLongGeoKey",
    2184                 :                                    &dfNatOriginLong ) == 0
    2185                 :             && GetMetadataElement( "GEOTIFF_NUM::3088::ProjCenterLongGeoKey", 
    2186                 :                                    &dfNatOriginLong ) == 0 )
    2187               0 :             dfNatOriginLong = 0.0;
    2188                 : 
    2189               0 :         if( GetMetadataElement( "GEOTIFF_NUM::3081::ProjNatOriginLatGeoKey",
    2190                 :                                 &dfNatOriginLat ) == 0
    2191                 :             && GetMetadataElement( "GEOTIFF_NUM::3085::ProjFalseOriginLatGeoKey",
    2192                 :                                    &dfNatOriginLat ) == 0
    2193                 :             && GetMetadataElement( "GEOTIFF_NUM::3089::ProjCenterLatGeoKey",
    2194                 :                                    &dfNatOriginLat ) == 0 )
    2195               0 :             dfNatOriginLat = 0.0;
    2196                 : 
    2197                 :         /* notdef: should transform to decimal degrees at this point */
    2198                 : 
    2199               0 :         psDefn->ProjParm[0] = dfStdParallel1;
    2200               0 :         psDefn->ProjParmId[0] = ProjStdParallel1GeoKey;
    2201               0 :         psDefn->ProjParm[1] = dfStdParallel2;
    2202               0 :         psDefn->ProjParmId[1] = ProjStdParallel2GeoKey;
    2203               0 :         psDefn->ProjParm[2] = dfNatOriginLat;
    2204               0 :         psDefn->ProjParmId[2] = ProjNatOriginLatGeoKey;
    2205               0 :         psDefn->ProjParm[3] = dfNatOriginLong;
    2206               0 :         psDefn->ProjParmId[3] = ProjNatOriginLongGeoKey;
    2207               0 :         psDefn->ProjParm[5] = dfFalseEasting;
    2208               0 :         psDefn->ProjParmId[5] = ProjFalseEastingGeoKey;
    2209               0 :         psDefn->ProjParm[6] = dfFalseNorthing;
    2210               0 :         psDefn->ProjParmId[6] = ProjFalseNorthingGeoKey;
    2211                 : 
    2212               0 :         psDefn->nParms = 7;
    2213                 :         break;
    2214                 :     }
    2215               6 : }
    2216                 : 
    2217                 : /************************************************************************/
    2218                 : /*                            GetGTIFDefn()                             */
    2219                 : /*      This function borrowed from the GTIFGetDefn() function.         */
    2220                 : /*      See geo_normalize.c from the GeoTIFF package.                   */
    2221                 : /************************************************************************/
    2222                 : 
    2223              19 : void MrSIDDataset::GetGTIFDefn()
    2224                 : {
    2225                 :     double      dfInvFlattening;
    2226                 : 
    2227                 : /* -------------------------------------------------------------------- */
    2228                 : /*      Initially we default all the information we can.                */
    2229                 : /* -------------------------------------------------------------------- */
    2230              19 :     psDefn = new( GTIFDefn );
    2231              19 :     psDefn->Model = KvUserDefined;
    2232              19 :     psDefn->PCS = KvUserDefined;
    2233              19 :     psDefn->GCS = KvUserDefined;
    2234              19 :     psDefn->UOMLength = KvUserDefined;
    2235              19 :     psDefn->UOMLengthInMeters = 1.0;
    2236              19 :     psDefn->UOMAngle = KvUserDefined;
    2237              19 :     psDefn->UOMAngleInDegrees = 1.0;
    2238              19 :     psDefn->Datum = KvUserDefined;
    2239              19 :     psDefn->Ellipsoid = KvUserDefined;
    2240              19 :     psDefn->SemiMajor = 0.0;
    2241              19 :     psDefn->SemiMinor = 0.0;
    2242              19 :     psDefn->PM = KvUserDefined;
    2243              19 :     psDefn->PMLongToGreenwich = 0.0;
    2244                 : 
    2245              19 :     psDefn->ProjCode = KvUserDefined;
    2246              19 :     psDefn->Projection = KvUserDefined;
    2247              19 :     psDefn->CTProjection = KvUserDefined;
    2248                 : 
    2249              19 :     psDefn->nParms = 0;
    2250             209 :     for( int i = 0; i < MAX_GTIF_PROJPARMS; i++ )
    2251                 :     {
    2252             190 :         psDefn->ProjParm[i] = 0.0;
    2253             190 :         psDefn->ProjParmId[i] = 0;
    2254                 :     }
    2255                 : 
    2256              19 :     psDefn->MapSys = KvUserDefined;
    2257              19 :     psDefn->Zone = 0;
    2258                 : 
    2259                 : /* -------------------------------------------------------------------- */
    2260                 : /*      Try to get the overall model type.                              */
    2261                 : /* -------------------------------------------------------------------- */
    2262                 :     GetMetadataElement( "GEOTIFF_NUM::1024::GTModelTypeGeoKey",
    2263              19 :                         &(psDefn->Model) );
    2264                 : 
    2265                 : /* -------------------------------------------------------------------- */
    2266                 : /*      Try to get a PCS.                                               */
    2267                 : /* -------------------------------------------------------------------- */
    2268              19 :     if( GetMetadataElement( "GEOTIFF_NUM::3072::ProjectedCSTypeGeoKey",
    2269                 :                             &(psDefn->PCS) )
    2270                 :         && psDefn->PCS != KvUserDefined )
    2271                 :     {
    2272                 :         /*
    2273                 :          * Translate this into useful information.
    2274                 :          */
    2275                 :         GTIFGetPCSInfo( psDefn->PCS, NULL, &(psDefn->ProjCode),
    2276               1 :                         &(psDefn->UOMLength), &(psDefn->GCS) );
    2277                 :     }
    2278                 : 
    2279                 : /* -------------------------------------------------------------------- */
    2280                 : /*       If we have the PCS code, but didn't find it in the CSV files   */
    2281                 : /*      (likely because we can't find them) we will try some ``jiffy    */
    2282                 : /*      rules'' for UTM and state plane.                                */
    2283                 : /* -------------------------------------------------------------------- */
    2284              19 :     if( psDefn->PCS != KvUserDefined && psDefn->ProjCode == KvUserDefined )
    2285                 :     {
    2286                 :         int     nMapSys, nZone;
    2287               0 :         int     nGCS = psDefn->GCS;
    2288                 : 
    2289               0 :         nMapSys = GTIFPCSToMapSys( psDefn->PCS, &nGCS, &nZone );
    2290               0 :         if( nMapSys != KvUserDefined )
    2291                 :         {
    2292               0 :             psDefn->ProjCode = (short) GTIFMapSysToProj( nMapSys, nZone );
    2293               0 :             psDefn->GCS = (short) nGCS;
    2294                 :         }
    2295                 :     }
    2296                 :    
    2297                 : /* -------------------------------------------------------------------- */
    2298                 : /*      If the Proj_ code is specified directly, use that.              */
    2299                 : /* -------------------------------------------------------------------- */
    2300              19 :     if( psDefn->ProjCode == KvUserDefined )
    2301                 :         GetMetadataElement( "GEOTIFF_NUM::3074::ProjectionGeoKey",
    2302              18 :                             &(psDefn->ProjCode) );
    2303                 :     
    2304              19 :     if( psDefn->ProjCode != KvUserDefined )
    2305                 :     {
    2306                 :         /*
    2307                 :          * We have an underlying projection transformation value.  Look
    2308                 :          * this up.  For a PCS of ``WGS 84 / UTM 11'' the transformation
    2309                 :          * would be Transverse Mercator, with a particular set of options.
    2310                 :          * The nProjTRFCode itself would correspond to the name
    2311                 :          * ``UTM zone 11N'', and doesn't include datum info.
    2312                 :          */
    2313                 :         GTIFGetProjTRFInfo( psDefn->ProjCode, NULL, &(psDefn->Projection),
    2314               1 :                             psDefn->ProjParm );
    2315                 :         
    2316                 :         /*
    2317                 :          * Set the GeoTIFF identity of the parameters.
    2318                 :          */
    2319                 :         psDefn->CTProjection = (short)
    2320               1 :             EPSGProjMethodToCTProjMethod( psDefn->Projection );
    2321                 : 
    2322               1 :         SetGTParmIds( psDefn->CTProjection, psDefn->ProjParmId, NULL);
    2323               1 :         psDefn->nParms = 7;
    2324                 :     }
    2325                 : 
    2326                 : /* -------------------------------------------------------------------- */
    2327                 : /*      Try to get a GCS.  If found, it will override any implied by    */
    2328                 : /*      the PCS.                                                        */
    2329                 : /* -------------------------------------------------------------------- */
    2330                 :     GetMetadataElement( "GEOTIFF_NUM::2048::GeographicTypeGeoKey",
    2331              19 :                         &(psDefn->GCS) );
    2332                 : 
    2333                 : /* -------------------------------------------------------------------- */
    2334                 : /*      Derive the datum, and prime meridian from the GCS.              */
    2335                 : /* -------------------------------------------------------------------- */
    2336              19 :     if( psDefn->GCS != KvUserDefined )
    2337                 :     {
    2338                 :         GTIFGetGCSInfo( psDefn->GCS, NULL, &(psDefn->Datum), &(psDefn->PM),
    2339               9 :                         &(psDefn->UOMAngle) );
    2340                 :     }
    2341                 :     
    2342                 : /* -------------------------------------------------------------------- */
    2343                 : /*      Handle the GCS angular units.  GeogAngularUnitsGeoKey           */
    2344                 : /*      overrides the GCS or PCS setting.                               */
    2345                 : /* -------------------------------------------------------------------- */
    2346                 :     GetMetadataElement( "GEOTIFF_NUM::2054::GeogAngularUnitsGeoKey",
    2347              19 :                         &(psDefn->UOMAngle) );
    2348              19 :     if( psDefn->UOMAngle != KvUserDefined )
    2349                 :     {
    2350                 :         GTIFGetUOMAngleInfo( psDefn->UOMAngle, NULL,
    2351               9 :                              &(psDefn->UOMAngleInDegrees) );
    2352                 :     }
    2353                 : 
    2354                 : /* -------------------------------------------------------------------- */
    2355                 : /*      Check for a datum setting, and then use the datum to derive     */
    2356                 : /*      an ellipsoid.                                                   */
    2357                 : /* -------------------------------------------------------------------- */
    2358                 :     GetMetadataElement( "GEOTIFF_NUM::2050::GeogGeodeticDatumGeoKey",
    2359              19 :                         &(psDefn->Datum) );
    2360                 : 
    2361              19 :     if( psDefn->Datum != KvUserDefined )
    2362                 :     {
    2363               9 :         GTIFGetDatumInfo( psDefn->Datum, NULL, &(psDefn->Ellipsoid) );
    2364                 :     }
    2365                 : 
    2366                 : /* -------------------------------------------------------------------- */
    2367                 : /*      Check for an explicit ellipsoid.  Use the ellipsoid to          */
    2368                 : /*      derive the ellipsoid characteristics, if possible.              */
    2369                 : /* -------------------------------------------------------------------- */
    2370                 :     GetMetadataElement( "GEOTIFF_NUM::2056::GeogEllipsoidGeoKey",
    2371              19 :                         &(psDefn->Ellipsoid) );
    2372                 : 
    2373              19 :     if( psDefn->Ellipsoid != KvUserDefined )
    2374                 :     {
    2375                 :         GTIFGetEllipsoidInfo( psDefn->Ellipsoid, NULL,
    2376               9 :                               &(psDefn->SemiMajor), &(psDefn->SemiMinor) );
    2377                 :     }
    2378                 : 
    2379                 : /* -------------------------------------------------------------------- */
    2380                 : /*      Check for overridden ellipsoid parameters.  It would be nice    */
    2381                 : /*      to warn if they conflict with provided information, but for     */
    2382                 : /*      now we just override.                                           */
    2383                 : /* -------------------------------------------------------------------- */
    2384                 :     GetMetadataElement( "GEOTIFF_NUM::2057::GeogSemiMajorAxisGeoKey",
    2385              19 :                         &(psDefn->SemiMajor) );
    2386                 :     GetMetadataElement( "GEOTIFF_NUM::2058::GeogSemiMinorAxisGeoKey",
    2387              19 :                         &(psDefn->SemiMinor) );
    2388                 :     
    2389              19 :     if( GetMetadataElement( "GEOTIFF_NUM::2059::GeogInvFlatteningGeoKey",
    2390                 :                             &dfInvFlattening ) == 1 )
    2391                 :     {
    2392               0 :         if( dfInvFlattening != 0.0 )
    2393                 :             psDefn->SemiMinor = 
    2394               0 :                 psDefn->SemiMajor * (1 - 1.0/dfInvFlattening);
    2395                 :     }
    2396                 : 
    2397                 : /* -------------------------------------------------------------------- */
    2398                 : /*      Get the prime meridian info.                                    */
    2399                 : /* -------------------------------------------------------------------- */
    2400                 :     GetMetadataElement( "GEOTIFF_NUM::2051::GeogPrimeMeridianGeoKey",
    2401              19 :                         &(psDefn->PM) );
    2402                 : 
    2403              19 :     if( psDefn->PM != KvUserDefined )
    2404                 :     {
    2405               9 :         GTIFGetPMInfo( psDefn->PM, NULL, &(psDefn->PMLongToGreenwich) );
    2406                 :     }
    2407                 :     else
    2408                 :     {
    2409                 :         GetMetadataElement( "GEOTIFF_NUM::2061::GeogPrimeMeridianLongGeoKey",
    2410              10 :                             &(psDefn->PMLongToGreenwich) );
    2411                 : 
    2412                 :         psDefn->PMLongToGreenwich =
    2413                 :             GTIFAngleToDD( psDefn->PMLongToGreenwich,
    2414              10 :                            psDefn->UOMAngle );
    2415                 :     }
    2416                 : 
    2417                 : /* -------------------------------------------------------------------- */
    2418                 : /*      Have the projection units of measure been overridden?  We       */
    2419                 : /*      should likely be doing something about angular units too,       */
    2420                 : /*      but these are very rarely not decimal degrees for actual        */
    2421                 : /*      file coordinates.                                               */
    2422                 : /* -------------------------------------------------------------------- */
    2423                 :     GetMetadataElement( "GEOTIFF_NUM::3076::ProjLinearUnitsGeoKey",
    2424              19 :                         &(psDefn->UOMLength) );
    2425                 : 
    2426              19 :     if( psDefn->UOMLength != KvUserDefined )
    2427                 :     {
    2428                 :         GTIFGetUOMLengthInfo( psDefn->UOMLength, NULL,
    2429               7 :                               &(psDefn->UOMLengthInMeters) );
    2430                 :     }
    2431                 : 
    2432                 : /* -------------------------------------------------------------------- */
    2433                 : /*      Handle a variety of user defined transform types.               */
    2434                 : /* -------------------------------------------------------------------- */
    2435              19 :     if( GetMetadataElement( "GEOTIFF_NUM::3075::ProjCoordTransGeoKey",
    2436                 :                             &(psDefn->CTProjection) ) )
    2437                 :     {
    2438               6 :         FetchProjParms();
    2439                 :     }
    2440                 : 
    2441                 : /* -------------------------------------------------------------------- */
    2442                 : /*      Try to set the zoned map system information.                    */
    2443                 : /* -------------------------------------------------------------------- */
    2444              19 :     psDefn->MapSys = GTIFProjToMapSys( psDefn->ProjCode, &(psDefn->Zone) );
    2445                 : 
    2446                 : /* -------------------------------------------------------------------- */
    2447                 : /*      If this is UTM, and we were unable to extract the projection    */
    2448                 : /*      parameters from the CSV file, just set them directly now,       */
    2449                 : /*      since it's pretty easy, and a common case.                      */
    2450                 : /* -------------------------------------------------------------------- */
    2451              19 :     if( (psDefn->MapSys == MapSys_UTM_North
    2452                 :          || psDefn->MapSys == MapSys_UTM_South)
    2453                 :         && psDefn->CTProjection == KvUserDefined )
    2454                 :     {
    2455               0 :         psDefn->CTProjection = CT_TransverseMercator;
    2456               0 :         psDefn->nParms = 7;
    2457               0 :         psDefn->ProjParmId[0] = ProjNatOriginLatGeoKey;
    2458               0 :         psDefn->ProjParm[0] = 0.0;
    2459                 :             
    2460               0 :         psDefn->ProjParmId[1] = ProjNatOriginLongGeoKey;
    2461               0 :         psDefn->ProjParm[1] = psDefn->Zone*6 - 183.0;
    2462                 :         
    2463               0 :         psDefn->ProjParmId[4] = ProjScaleAtNatOriginGeoKey;
    2464               0 :         psDefn->ProjParm[4] = 0.9996;
    2465                 :         
    2466               0 :         psDefn->ProjParmId[5] = ProjFalseEastingGeoKey;
    2467               0 :         psDefn->ProjParm[5] = 500000.0;
    2468                 :         
    2469               0 :         psDefn->ProjParmId[6] = ProjFalseNorthingGeoKey;
    2470                 : 
    2471               0 :         if( psDefn->MapSys == MapSys_UTM_North )
    2472               0 :             psDefn->ProjParm[6] = 0.0;
    2473                 :         else
    2474               0 :             psDefn->ProjParm[6] = 10000000.0;
    2475                 :     }
    2476                 : 
    2477              19 :     if ( pszProjection )
    2478              19 :         CPLFree( pszProjection );
    2479              19 :     pszProjection = GetOGISDefn( psDefn );
    2480              19 : }
    2481                 : 
    2482                 : /************************************************************************/
    2483                 : /*                          GetOGISDefn()                               */
    2484                 : /*  Copied from the gt_wkt_srs.cpp.                                     */
    2485                 : /************************************************************************/
    2486                 : 
    2487              19 : char *MrSIDDataset::GetOGISDefn( GTIFDefn *psDefn )
    2488                 : {
    2489              19 :     OGRSpatialReference oSRS;
    2490                 : 
    2491              19 :     if( psDefn->Model != ModelTypeProjected 
    2492                 :         && psDefn->Model != ModelTypeGeographic )
    2493              10 :         return CPLStrdup("");
    2494                 :     
    2495                 : /* -------------------------------------------------------------------- */
    2496                 : /*      If this is a projected SRS we set the PROJCS keyword first      */
    2497                 : /*      to ensure that the GEOGCS will be a child.                      */
    2498                 : /* -------------------------------------------------------------------- */
    2499               9 :     if( psDefn->Model == ModelTypeProjected )
    2500                 :     {
    2501                 :         char    *pszPCSName;
    2502               7 :         int     bPCSNameSet = FALSE;
    2503                 : 
    2504               7 :         if( psDefn->PCS != KvUserDefined )
    2505                 :         {
    2506                 : 
    2507               1 :             if( GTIFGetPCSInfo( psDefn->PCS, &pszPCSName, NULL, NULL, NULL ) )
    2508               1 :                 bPCSNameSet = TRUE;
    2509                 :             
    2510               1 :             oSRS.SetNode( "PROJCS", bPCSNameSet ? pszPCSName : "unnamed" );
    2511               1 :             if( bPCSNameSet )
    2512               1 :                 GTIFFreeMemory( pszPCSName );
    2513                 : 
    2514               1 :             oSRS.SetAuthority( "PROJCS", "EPSG", psDefn->PCS );
    2515                 :         }
    2516                 :         else
    2517                 :         {
    2518                 :             char szPCSName[200];
    2519               6 :             strcpy( szPCSName, "unnamed" );
    2520               6 :             if ( GetMetadataElement( "GEOTIFF_NUM::1026::GTCitationGeoKey",
    2521                 :                                      szPCSName, sizeof(szPCSName) ) )
    2522               6 :                 oSRS.SetNode( "PROJCS", szPCSName );
    2523                 :         }
    2524                 :     }
    2525                 :     
    2526                 : /* ==================================================================== */
    2527                 : /*      Setup the GeogCS                                                */
    2528                 : /* ==================================================================== */
    2529               9 :     char        *pszGeogName = NULL;
    2530               9 :     char        *pszDatumName = NULL;
    2531               9 :     char        *pszPMName = NULL;
    2532               9 :     char        *pszSpheroidName = NULL;
    2533               9 :     char        *pszAngularUnits = NULL;
    2534                 :     double      dfInvFlattening, dfSemiMajor;
    2535                 :     char        szGCSName[200];
    2536                 :     
    2537               9 :     if( GetMetadataElement( "GEOTIFF_NUM::2049::GeogCitationGeoKey",
    2538                 :                             szGCSName, sizeof(szGCSName) ) )
    2539               0 :         pszGeogName = CPLStrdup(szGCSName);
    2540               9 :     GTIFGetGCSInfo( psDefn->GCS, &pszGeogName, NULL, NULL, NULL );
    2541               9 :     GTIFGetDatumInfo( psDefn->Datum, &pszDatumName, NULL );
    2542               9 :     GTIFGetPMInfo( psDefn->PM, &pszPMName, NULL );
    2543               9 :     GTIFGetEllipsoidInfo( psDefn->Ellipsoid, &pszSpheroidName, NULL, NULL );
    2544                 :     
    2545               9 :     GTIFGetUOMAngleInfo( psDefn->UOMAngle, &pszAngularUnits, NULL );
    2546               9 :     if( pszAngularUnits == NULL )
    2547               0 :         pszAngularUnits = CPLStrdup("unknown");
    2548                 : 
    2549               9 :     if( pszDatumName != NULL )
    2550               9 :         WKTMassageDatum( &pszDatumName );
    2551                 : 
    2552               9 :     dfSemiMajor = psDefn->SemiMajor;
    2553               9 :     if( psDefn->SemiMajor == 0.0 )
    2554                 :     {
    2555               0 :         pszSpheroidName = CPLStrdup("unretrievable - using WGS84");
    2556               0 :         dfSemiMajor = SRS_WGS84_SEMIMAJOR;
    2557               0 :         dfInvFlattening = SRS_WGS84_INVFLATTENING;
    2558                 :     }
    2559              18 :     else if( (psDefn->SemiMinor / psDefn->SemiMajor) < 0.99999999999999999
    2560                 :              || (psDefn->SemiMinor / psDefn->SemiMajor) > 1.00000000000000001 )
    2561               9 :         dfInvFlattening = -1.0 / (psDefn->SemiMinor/psDefn->SemiMajor - 1.0);
    2562                 :     else
    2563               0 :         dfInvFlattening = 0.0; /* special flag for infinity */
    2564                 : 
    2565                 :     oSRS.SetGeogCS( pszGeogName, pszDatumName, 
    2566                 :                     pszSpheroidName, dfSemiMajor, dfInvFlattening,
    2567                 :                     pszPMName,
    2568                 :                     psDefn->PMLongToGreenwich / psDefn->UOMAngleInDegrees,
    2569                 :                     pszAngularUnits,
    2570               9 :                     psDefn->UOMAngleInDegrees * 0.0174532925199433 );
    2571                 : 
    2572               9 :     if( psDefn->GCS != KvUserDefined )
    2573               9 :         oSRS.SetAuthority( "GEOGCS", "EPSG", psDefn->GCS );
    2574                 : 
    2575               9 :     if( psDefn->Datum != KvUserDefined )
    2576               9 :         oSRS.SetAuthority( "DATUM", "EPSG", psDefn->Datum );
    2577                 : 
    2578               9 :     if( psDefn->Ellipsoid != KvUserDefined )
    2579               9 :         oSRS.SetAuthority( "SPHEROID", "EPSG", psDefn->Ellipsoid );
    2580                 : 
    2581               9 :     GTIFFreeMemory( pszGeogName );
    2582               9 :     CPLFree( pszDatumName );
    2583               9 :     GTIFFreeMemory( pszPMName );
    2584               9 :     GTIFFreeMemory( pszSpheroidName );
    2585               9 :     GTIFFreeMemory( pszAngularUnits );
    2586                 :         
    2587                 : /* ==================================================================== */
    2588                 : /*      Handle projection parameters.                                   */
    2589                 : /* ==================================================================== */
    2590               9 :     if( psDefn->Model == ModelTypeProjected )
    2591                 :     {
    2592                 : /* -------------------------------------------------------------------- */
    2593                 : /*      Make a local copy of parms, and convert back into the           */
    2594                 : /*      angular units of the GEOGCS and the linear units of the         */
    2595                 : /*      projection.                                                     */
    2596                 : /* -------------------------------------------------------------------- */
    2597                 :         double          adfParm[10];
    2598                 :         int             i;
    2599                 : 
    2600              56 :         for( i = 0; i < MIN(10,psDefn->nParms); i++ )
    2601              49 :             adfParm[i] = psDefn->ProjParm[i];
    2602                 : 
    2603               7 :         adfParm[0] /= psDefn->UOMAngleInDegrees;
    2604               7 :         adfParm[1] /= psDefn->UOMAngleInDegrees;
    2605               7 :         adfParm[2] /= psDefn->UOMAngleInDegrees;
    2606               7 :         adfParm[3] /= psDefn->UOMAngleInDegrees;
    2607                 :         
    2608               7 :         adfParm[5] /= psDefn->UOMLengthInMeters;
    2609               7 :         adfParm[6] /= psDefn->UOMLengthInMeters;
    2610                 :         
    2611                 : /* -------------------------------------------------------------------- */
    2612                 : /*      Translation the fundamental projection.                         */
    2613                 : /* -------------------------------------------------------------------- */
    2614               7 :         switch( psDefn->CTProjection )
    2615                 :         {
    2616                 :           case CT_TransverseMercator:
    2617                 :             oSRS.SetTM( adfParm[0], adfParm[1],
    2618                 :                         adfParm[4],
    2619               1 :                         adfParm[5], adfParm[6] );
    2620               1 :             break;
    2621                 : 
    2622                 :           case CT_TransvMercator_SouthOriented:
    2623                 :             oSRS.SetTMSO( adfParm[0], adfParm[1],
    2624                 :                           adfParm[4],
    2625               0 :                           adfParm[5], adfParm[6] );
    2626               0 :             break;
    2627                 : 
    2628                 :           case CT_Mercator:
    2629                 :             oSRS.SetMercator( adfParm[0], adfParm[1],
    2630                 :                               adfParm[4],
    2631               6 :                               adfParm[5], adfParm[6] );
    2632               6 :             break;
    2633                 : 
    2634                 :           case CT_ObliqueStereographic:
    2635                 :             oSRS.SetOS( adfParm[0], adfParm[1],
    2636                 :                         adfParm[4],
    2637               0 :                         adfParm[5], adfParm[6] );
    2638               0 :             break;
    2639                 : 
    2640                 :           case CT_Stereographic:
    2641                 :             oSRS.SetOS( adfParm[0], adfParm[1],
    2642                 :                         adfParm[4],
    2643               0 :                         adfParm[5], adfParm[6] );
    2644               0 :             break;
    2645                 : 
    2646                 :           case CT_ObliqueMercator: /* hotine */
    2647                 :             oSRS.SetHOM( adfParm[0], adfParm[1],
    2648                 :                          adfParm[2], adfParm[3],
    2649                 :                          adfParm[4],
    2650               0 :                          adfParm[5], adfParm[6] );
    2651               0 :             break;
    2652                 :         
    2653                 :           case CT_EquidistantConic: 
    2654                 :             oSRS.SetEC( adfParm[0], adfParm[1],
    2655                 :                         adfParm[2], adfParm[3],
    2656               0 :                         adfParm[5], adfParm[6] );
    2657               0 :             break;
    2658                 :         
    2659                 :           case CT_CassiniSoldner:
    2660                 :             oSRS.SetCS( adfParm[0], adfParm[1],
    2661               0 :                         adfParm[5], adfParm[6] );
    2662               0 :             break;
    2663                 :         
    2664                 :           case CT_Polyconic:
    2665                 :             oSRS.SetPolyconic( adfParm[0], adfParm[1],
    2666               0 :                                adfParm[5], adfParm[6] );
    2667               0 :             break;
    2668                 : 
    2669                 :           case CT_AzimuthalEquidistant:
    2670                 :             oSRS.SetAE( adfParm[0], adfParm[1],
    2671               0 :                         adfParm[5], adfParm[6] );
    2672               0 :             break;
    2673                 :         
    2674                 :           case CT_MillerCylindrical:
    2675                 :             oSRS.SetMC( adfParm[0], adfParm[1],
    2676               0 :                         adfParm[5], adfParm[6] );
    2677               0 :             break;
    2678                 :         
    2679                 :           case CT_Equirectangular:
    2680                 :             oSRS.SetEquirectangular( adfParm[0], adfParm[1],
    2681               0 :                                      adfParm[5], adfParm[6] );
    2682               0 :             break;
    2683                 :         
    2684                 :           case CT_Gnomonic:
    2685                 :             oSRS.SetGnomonic( adfParm[0], adfParm[1],
    2686               0 :                               adfParm[5], adfParm[6] );
    2687               0 :             break;
    2688                 :         
    2689                 :           case CT_LambertAzimEqualArea:
    2690                 :             oSRS.SetLAEA( adfParm[0], adfParm[1],
    2691               0 :                           adfParm[5], adfParm[6] );
    2692               0 :             break;
    2693                 :         
    2694                 :           case CT_Orthographic:
    2695                 :             oSRS.SetOrthographic( adfParm[0], adfParm[1],
    2696               0 :                                   adfParm[5], adfParm[6] );
    2697               0 :             break;
    2698                 :         
    2699                 :           case CT_Robinson:
    2700                 :             oSRS.SetRobinson( adfParm[1],
    2701               0 :                               adfParm[5], adfParm[6] );
    2702               0 :             break;
    2703                 :         
    2704                 :           case CT_Sinusoidal:
    2705                 :             oSRS.SetSinusoidal( adfParm[1],
    2706               0 :                                 adfParm[5], adfParm[6] );
    2707               0 :             break;
    2708                 :         
    2709                 :           case CT_VanDerGrinten:
    2710                 :             oSRS.SetVDG( adfParm[1],
    2711               0 :                          adfParm[5], adfParm[6] );
    2712               0 :             break;
    2713                 : 
    2714                 :           case CT_PolarStereographic:
    2715                 :             oSRS.SetPS( adfParm[0], adfParm[1],
    2716                 :                         adfParm[4],
    2717               0 :                         adfParm[5], adfParm[6] );
    2718               0 :             break;
    2719                 :         
    2720                 :           case CT_LambertConfConic_2SP:
    2721                 :             oSRS.SetLCC( adfParm[2], adfParm[3],
    2722                 :                          adfParm[0], adfParm[1],
    2723               0 :                          adfParm[5], adfParm[6] );
    2724               0 :             break;
    2725                 : 
    2726                 :           case CT_LambertConfConic_1SP:
    2727                 :             oSRS.SetLCC1SP( adfParm[0], adfParm[1],
    2728                 :                             adfParm[4],
    2729               0 :                             adfParm[5], adfParm[6] );
    2730               0 :             break;
    2731                 :         
    2732                 :           case CT_AlbersEqualArea:
    2733                 :             oSRS.SetACEA( adfParm[0], adfParm[1],
    2734                 :                           adfParm[2], adfParm[3],
    2735               0 :                           adfParm[5], adfParm[6] );
    2736               0 :             break;
    2737                 : 
    2738                 :           case CT_NewZealandMapGrid:
    2739                 :             oSRS.SetNZMG( adfParm[0], adfParm[1],
    2740               0 :                           adfParm[5], adfParm[6] );
    2741                 :             break;
    2742                 :         }
    2743                 : 
    2744                 : /* -------------------------------------------------------------------- */
    2745                 : /*      Set projection units.                                           */
    2746                 : /* -------------------------------------------------------------------- */
    2747               7 :         char    *pszUnitsName = NULL;
    2748                 :         
    2749               7 :         GTIFGetUOMLengthInfo( psDefn->UOMLength, &pszUnitsName, NULL );
    2750                 : 
    2751              14 :         if( pszUnitsName != NULL && psDefn->UOMLength != KvUserDefined )
    2752                 :         {
    2753               7 :             oSRS.SetLinearUnits( pszUnitsName, psDefn->UOMLengthInMeters );
    2754               7 :             oSRS.SetAuthority( "PROJCS|UNIT", "EPSG", psDefn->UOMLength );
    2755                 :         }
    2756                 :         else
    2757               0 :             oSRS.SetLinearUnits( "unknown", psDefn->UOMLengthInMeters );
    2758                 : 
    2759               7 :         GTIFFreeMemory( pszUnitsName );
    2760                 :     }
    2761                 :     
    2762                 : /* -------------------------------------------------------------------- */
    2763                 : /*      Return the WKT serialization of the object.                     */
    2764                 : /* -------------------------------------------------------------------- */
    2765                 :     char        *pszWKT;
    2766                 : 
    2767               9 :     oSRS.FixupOrdering();
    2768                 : 
    2769               9 :     if( oSRS.exportToWkt( &pszWKT ) == OGRERR_NONE )
    2770               9 :         return pszWKT;
    2771                 :     else
    2772               0 :         return NULL;
    2773                 : }
    2774                 : 
    2775                 : #ifdef MRSID_ESDK
    2776                 : 
    2777                 : /************************************************************************/
    2778                 : /* ==================================================================== */
    2779                 : /*                        MrSIDDummyImageReader                         */
    2780                 : /*                                                                      */
    2781                 : /*  This is a helper class to wrap GDAL calls in MrSID interface.       */
    2782                 : /* ==================================================================== */
    2783                 : /************************************************************************/
    2784                 : 
    2785                 : class MrSIDDummyImageReader : public LTIImageReader
    2786                 : {
    2787                 :   public:
    2788                 : 
    2789                 :     MrSIDDummyImageReader( GDALDataset *poSrcDS );
    2790                 :     ~MrSIDDummyImageReader();
    2791                 :     LT_STATUS           initialize();
    2792                 :     lt_int64            getPhysicalFileSize(void) const { return 0; };
    2793                 : 
    2794                 :   private:
    2795                 :     GDALDataset         *poDS;
    2796                 :     GDALDataType        eDataType;
    2797                 :     LTIDataType         eSampleType;
    2798                 :     const LTIPixel      *poPixel;
    2799                 :     
    2800                 :     double              adfGeoTransform[6];
    2801                 : 
    2802                 :     virtual LT_STATUS   decodeStrip( LTISceneBuffer& stripBuffer,
    2803                 :                                      const LTIScene& stripScene );
    2804                 :     virtual LT_STATUS   decodeBegin( const LTIScene& scene )
    2805                 :                             { return LT_STS_Success; };
    2806                 :     virtual LT_STATUS   decodeEnd() { return LT_STS_Success; };
    2807                 : };
    2808                 : 
    2809                 : /************************************************************************/
    2810                 : /*                        MrSIDDummyImageReader()                       */
    2811                 : /************************************************************************/
    2812                 : 
    2813                 : MrSIDDummyImageReader::MrSIDDummyImageReader( GDALDataset *poSrcDS ) :
    2814                 :                                             LTIImageReader(), poDS(poSrcDS)
    2815                 : {
    2816                 :     poPixel = NULL;
    2817                 : }
    2818                 : 
    2819                 : /************************************************************************/
    2820                 : /*                        ~MrSIDDummyImageReader()                      */
    2821                 : /************************************************************************/
    2822                 : 
    2823                 : MrSIDDummyImageReader::~MrSIDDummyImageReader()
    2824                 : {
    2825                 :     if ( poPixel )
    2826                 :         delete poPixel;
    2827                 : }
    2828                 : 
    2829                 : /************************************************************************/
    2830                 : /*                             initialize()                             */
    2831                 : /************************************************************************/
    2832                 : 
    2833                 : LT_STATUS MrSIDDummyImageReader::initialize()
    2834                 : {
    2835                 :     if ( !LT_SUCCESS(LTIImageReader::initialize()) )
    2836                 :         return LT_STS_Failure;
    2837                 :     
    2838                 :     lt_uint16 nBands = (lt_uint16)poDS->GetRasterCount();
    2839                 :     LTIColorSpace eColorSpace = LTI_COLORSPACE_RGB;
    2840                 :     switch ( nBands )
    2841                 :     {
    2842                 :         case 1:
    2843                 :             eColorSpace = LTI_COLORSPACE_GRAYSCALE;
    2844                 :             break;
    2845                 :         case 3:
    2846                 :             eColorSpace = LTI_COLORSPACE_RGB;
    2847                 :             break;
    2848                 :         default:
    2849                 :             eColorSpace = LTI_COLORSPACE_MULTISPECTRAL;
    2850                 :             break;
    2851                 :     }
    2852                 :     
    2853                 :     eDataType = poDS->GetRasterBand(1)->GetRasterDataType();
    2854                 :     switch ( eDataType )
    2855                 :     {
    2856                 :         case GDT_UInt16:
    2857                 :             eSampleType = LTI_DATATYPE_UINT16;
    2858                 :             break;
    2859                 :         case GDT_Int16:
    2860                 :             eSampleType = LTI_DATATYPE_SINT16;
    2861                 :             break;
    2862                 :         case GDT_UInt32:
    2863                 :             eSampleType = LTI_DATATYPE_UINT32;
    2864                 :             break;
    2865                 :         case GDT_Int32:
    2866                 :             eSampleType = LTI_DATATYPE_SINT32;
    2867                 :             break;
    2868                 :         case GDT_Float32:
    2869                 :             eSampleType = LTI_DATATYPE_FLOAT32;
    2870                 :             break;
    2871                 :         case GDT_Float64:
    2872                 :             eSampleType = LTI_DATATYPE_FLOAT64;
    2873                 :             break;
    2874                 :         case GDT_Byte:
    2875                 :         default:
    2876                 :             eSampleType = LTI_DATATYPE_UINT8;
    2877                 :             break;
    2878                 :     }
    2879                 : 
    2880                 :     poPixel = new LTIDLLPixel<LTIPixel>( eColorSpace, nBands, eSampleType );
    2881                 :     if ( !LT_SUCCESS(setPixelProps(*poPixel)) )
    2882                 :         return LT_STS_Failure;
    2883                 : 
    2884                 :     if ( !LT_SUCCESS(setDimensions(poDS->GetRasterXSize(),
    2885                 :                                    poDS->GetRasterYSize())) )
    2886                 :         return LT_STS_Failure;
    2887                 : 
    2888                 :     if ( poDS->GetGeoTransform( adfGeoTransform ) == CE_None )
    2889                 :     {
    2890                 : #ifdef MRSID_SDK_40
    2891                 :         LTIGeoCoord oGeo( adfGeoTransform[0] + adfGeoTransform[1] / 2,
    2892                 :                           adfGeoTransform[3] + adfGeoTransform[5] / 2,
    2893                 :                           adfGeoTransform[1], adfGeoTransform[5],
    2894                 :                           adfGeoTransform[2], adfGeoTransform[4], NULL,
    2895                 :                           poDS->GetProjectionRef() );
    2896                 : #else
    2897                 :         LTIGeoCoord oGeo( adfGeoTransform[0] + adfGeoTransform[1] / 2,
    2898                 :                           adfGeoTransform[3] + adfGeoTransform[5] / 2,
    2899                 :                           adfGeoTransform[1], adfGeoTransform[5],
    2900                 :                           adfGeoTransform[2], adfGeoTransform[4], 
    2901                 :                           poDS->GetProjectionRef() );
    2902                 : #endif
    2903                 :         if ( !LT_SUCCESS(setGeoCoord( oGeo )) )
    2904                 :             return LT_STS_Failure;
    2905                 :     }
    2906                 : 
    2907                 :     /*int     bSuccess;
    2908                 :     double  dfNoDataValue = poDS->GetNoDataValue( &bSuccess );
    2909                 :     if ( bSuccess )
    2910                 :     {
    2911                 :         LTIPixel    oNoDataPixel( *poPixel );
    2912                 :         lt_uint16   iBand;
    2913                 : 
    2914                 :         for (iBand = 0; iBand < (lt_uint16)poDS->GetRasterCount(); iBand++)
    2915                 :             oNoDataPixel.setSampleValueFloat32( iBand, dfNoDataValue );
    2916                 :         if ( !LT_SUCCESS(setNoDataPixel( &oNoDataPixel )) )
    2917                 :             return LT_STS_Failure;
    2918                 :     }*/
    2919                 : 
    2920                 :     setDefaultDynamicRange();
    2921                 :     setClassicalMetadata();
    2922                 : 
    2923                 :     return LT_STS_Success;
    2924                 : }
    2925                 : 
    2926                 : /************************************************************************/
    2927                 : /*                             decodeStrip()                            */
    2928                 : /************************************************************************/
    2929                 : 
    2930                 : LT_STATUS MrSIDDummyImageReader::decodeStrip(LTISceneBuffer& stripData,
    2931                 :                                              const LTIScene& stripScene)
    2932                 : 
    2933                 : {
    2934                 :     const lt_int32  nXOff = stripScene.getUpperLeftCol();
    2935                 :     const lt_int32  nYOff = stripScene.getUpperLeftRow();
    2936                 :     const lt_int32  nBufXSize = stripScene.getNumCols();
    2937                 :     const lt_int32  nBufYSize = stripScene.getNumRows();
    2938                 :     const lt_int32  nDataBufXSize = stripData.getTotalNumCols();
    2939                 :     const lt_int32  nDataBufYSize = stripData.getTotalNumRows();
    2940                 :     const lt_uint16 nBands = poPixel->getNumBands();
    2941                 : 
    2942                 :     void *pData = CPLMalloc(nDataBufXSize * nDataBufYSize * poPixel->getNumBytes());
    2943                 :     if ( !pData )
    2944                 :     {
    2945                 :         CPLError( CE_Failure, CPLE_AppDefined,
    2946                 :                   "MrSIDDummyImageReader::decodeStrip(): "
    2947                 :                   "Cannot allocate enough space for scene buffer" );
    2948                 :         return LT_STS_Failure;
    2949                 :     }
    2950                 : 
    2951                 :     poDS->RasterIO( GF_Read, nXOff, nYOff, nBufXSize, nBufYSize, 
    2952                 :                     pData, nBufXSize, nBufYSize, eDataType, nBands, NULL, 
    2953                 :                     0, 0, 0 );
    2954                 : 
    2955                 :     stripData.importDataBSQ( pData );
    2956                 :     CPLFree( pData );
    2957                 :     return LT_STS_Success;
    2958                 : }
    2959                 : 
    2960                 : /************************************************************************/
    2961                 : /*                             FlushCache()                             */
    2962                 : /************************************************************************/
    2963                 : 
    2964                 : void MrSIDDataset::FlushCache()
    2965                 : 
    2966                 : {
    2967                 :     GDALDataset::FlushCache();
    2968                 : }
    2969                 : 
    2970                 : /************************************************************************/
    2971                 : /*                          MrSIDCreateCopy()                           */
    2972                 : /************************************************************************/
    2973                 : 
    2974                 : static GDALDataset *
    2975                 : MrSIDCreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
    2976                 :                  int bStrict, char ** papszOptions, 
    2977                 :                  GDALProgressFunc pfnProgress, void * pProgressData )
    2978                 : 
    2979                 : { 
    2980                 :     const char* pszVersion = CSLFetchNameValue(papszOptions, "VERSION");
    2981                 :     LT_STATUS eStat;
    2982                 : 
    2983                 : #ifdef DEBUG
    2984                 :     bool bMeter = false;
    2985                 : #else
    2986                 :     bool bMeter = true;
    2987                 : #endif    
    2988                 :     
    2989                 :     if (poSrcDS->GetRasterBand(1)->GetColorTable() != NULL)
    2990                 :     {
    2991                 :         CPLError( (bStrict) ? CE_Failure : CE_Warning, CPLE_NotSupported, 
    2992                 :                   "MrSID driver ignores color table. "
    2993                 :                   "The source raster band will be considered as grey level.\n"
    2994                 :                   "Consider using color table expansion (-expand option in gdal_translate)\n");
    2995                 :         if (bStrict)
    2996                 :             return NULL;
    2997                 :     }
    2998                 :     
    2999                 :     // Output Mrsid Version 2 file.
    3000                 :     if( pszVersion && atoi(pszVersion) == 2 )
    3001                 :     {
    3002                 :         int nXSize = poSrcDS->GetRasterXSize();
    3003                 :         int nYSize = poSrcDS->GetRasterYSize();
    3004                 :       
    3005                 :         if( !pfnProgress( 0.0, NULL, pProgressData ) )
    3006                 :             return NULL;
    3007                 :       
    3008                 :         // Create the file.                                               
    3009                 :         MrSIDDummyImageReader oImageReader( poSrcDS );
    3010                 :         eStat = oImageReader.initialize();
    3011                 :         if( eStat != LT_STS_Success )
    3012                 :         {
    3013                 :             CPLError( CE_Failure, CPLE_AppDefined,
    3014                 :                       "MrSIDDummyImageReader.Initialize failed.\n%s",
    3015                 :                       getLastStatusString( eStat ) );
    3016                 :             return NULL;
    3017                 :         }
    3018                 :       
    3019                 :         MG2ImageWriter oImageWriter(&oImageReader);
    3020                 :         eStat = oImageWriter.initialize();
    3021                 :         if( eStat != LT_STS_Success )
    3022                 :         {
    3023                 :             CPLError( CE_Failure, CPLE_AppDefined,
    3024                 :                       "MG3ImageWriter.initialize() failed.\n%s",
    3025                 :                       getLastStatusString( eStat ) );
    3026                 :             return NULL;
    3027                 :         }
    3028                 : 
    3029                 :         oImageWriter.setUsageMeterEnabled(bMeter);
    3030                 :    
    3031                 :         // set output filename
    3032                 :         oImageWriter.setOutputFileSpec( pszFilename );
    3033                 : 
    3034                 :         // Set defaults
    3035                 :         oImageWriter.params().setBlockSize(oImageWriter.params().getBlockSize());
    3036                 :         oImageWriter.setStripHeight(oImageWriter.getStripHeight());
    3037                 : 
    3038                 :         // check for compression option
    3039                 :         const char* pszValue = CSLFetchNameValue(papszOptions, "COMPRESSION");
    3040                 :         if( pszValue != NULL )
    3041                 :             oImageWriter.params().setCompressionRatio( atof(pszValue) );
    3042                 : 
    3043                 :         // set MrSID world file
    3044                 :         if( CSLFetchNameValue(papszOptions, "WORLDFILE") != NULL )
    3045                 :             oImageWriter.setWorldFileSupport( true );
    3046                 :       
    3047                 :         // write the scene
    3048                 :         const LTIScene oScene( 0, 0, nXSize, nYSize, 1.0 );
    3049                 :         eStat = oImageWriter.write( oScene );
    3050                 :         if( eStat != LT_STS_Success )
    3051                 :         {
    3052                 :             CPLError( CE_Failure, CPLE_AppDefined,
    3053                 :                       "MG2ImageWriter.write() failed.\n%s",
    3054                 :                       getLastStatusString( eStat ) );
    3055                 :             return NULL;
    3056                 :         }
    3057                 :     }
    3058                 :     // Output Mrsid Version 3 file.
    3059                 :     else
    3060                 :     {
    3061                 :         int nXSize = poSrcDS->GetRasterXSize();
    3062                 :         int nYSize = poSrcDS->GetRasterYSize();
    3063                 :       
    3064                 :         if( !pfnProgress( 0.0, NULL, pProgressData ) )
    3065                 :             return NULL;
    3066                 :       
    3067                 :         // Create the file.   
    3068                 :         MrSIDDummyImageReader oImageReader( poSrcDS );
    3069                 :         eStat = oImageReader.initialize();
    3070                 :         if( eStat != LT_STS_Success )
    3071                 :         {
    3072                 :             CPLError( CE_Failure, CPLE_AppDefined,
    3073                 :                       "MrSIDDummyImageReader.Initialize failed.\n%s",
    3074                 :                       getLastStatusString( eStat ) );
    3075                 :             return NULL;
    3076                 :         }
    3077                 :       
    3078                 :         MG3ImageWriter oImageWriter(&oImageReader);
    3079                 :         eStat = oImageWriter.initialize();
    3080                 :         if( eStat != LT_STS_Success )
    3081                 :         {
    3082                 :             CPLError( CE_Failure, CPLE_AppDefined,
    3083                 :                       "MG3ImageWriter.initialize() failed.\n%s",
    3084                 :                       getLastStatusString( eStat ) );
    3085                 :             return NULL;
    3086                 :         }
    3087                 :       
    3088                 :         // Set 64-bit Interface for large files.
    3089                 :         oImageWriter.setFileStream64(true);
    3090                 : 
    3091                 :         oImageWriter.setUsageMeterEnabled(bMeter);
    3092                 :       
    3093                 :         // set output filename
    3094                 :         oImageWriter.setOutputFileSpec( pszFilename );
    3095                 : 
    3096                 :         // Set defaults
    3097                 :         oImageWriter.setStripHeight(oImageWriter.getStripHeight());
    3098                 : 
    3099                 :         // set 2 pass optimizer option
    3100                 :         if( CSLFetchNameValue(papszOptions, "TWOPASS") != NULL )
    3101                 :             oImageWriter.params().setTwoPassOptimizer( true );
    3102                 : 
    3103                 :         // set MrSID world file
    3104                 :         if( CSLFetchNameValue(papszOptions, "WORLDFILE") != NULL )
    3105                 :             oImageWriter.setWorldFileSupport( true );
    3106                 :       
    3107                 :         const char* pszValue;
    3108                 :       
    3109                 :         // set filesize in KB
    3110                 :         pszValue = CSLFetchNameValue(papszOptions, "FILESIZE");
    3111                 :         if( pszValue != NULL )
    3112                 :             oImageWriter.params().setTargetFilesize( atoi(pszValue) );
    3113                 :         
    3114                 :         // write the scene
    3115                 :         const LTIScene oScene( 0, 0, nXSize, nYSize, 1.0 );
    3116                 :         eStat = oImageWriter.write( oScene );
    3117                 :         if( eStat != LT_STS_Success )
    3118                 :         {
    3119                 :             CPLError( CE_Failure, CPLE_AppDefined,
    3120                 :                       "MG2ImageWriter.write() failed.\n%s",
    3121                 :                       getLastStatusString( eStat ) );
    3122                 :             return NULL;
    3123                 :         }
    3124                 :     }
    3125                 :   
    3126                 : /* -------------------------------------------------------------------- */
    3127                 : /*      Re-open dataset, and copy any auxilary pam information.         */
    3128                 : /* -------------------------------------------------------------------- */
    3129                 :     GDALPamDataset *poDS = (GDALPamDataset *) 
    3130                 :         GDALOpen( pszFilename, GA_ReadOnly );
    3131                 : 
    3132                 :     if( poDS )
    3133                 :         poDS->CloneInfo( poSrcDS, GCIF_PAM_DEFAULT );
    3134                 : 
    3135                 :     return poDS;
    3136                 : }
    3137                 : 
    3138                 : #ifdef MRSID_J2K
    3139                 : /************************************************************************/
    3140                 : /*                           JP2CreateCopy()                            */
    3141                 : /************************************************************************/
    3142                 : 
    3143                 : static GDALDataset *
    3144                 : JP2CreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
    3145                 :                  int bStrict, char ** papszOptions, 
    3146                 :                  GDALProgressFunc pfnProgress, void * pProgressData )
    3147                 : 
    3148                 : { 
    3149                 : #ifdef DEBUG
    3150                 :     bool bMeter = false;
    3151                 : #else
    3152                 :     bool bMeter = true;
    3153                 : #endif    
    3154                 : 
    3155                 :     int nXSize = poSrcDS->GetRasterXSize();
    3156                 :     int nYSize = poSrcDS->GetRasterYSize();
    3157                 :     LT_STATUS  eStat;
    3158                 :     
    3159                 :     if (poSrcDS->GetRasterBand(1)->GetColorTable() != NULL)
    3160                 :     {
    3161                 :         CPLError( (bStrict) ? CE_Failure : CE_Warning, CPLE_NotSupported, 
    3162                 :                   "MrSID driver ignores color table. "
    3163                 :                   "The source raster band will be considered as grey level.\n"
    3164                 :                   "Consider using color table expansion (-expand option in gdal_translate)\n");
    3165                 :         if (bStrict)
    3166                 :             return NULL;
    3167                 :     }
    3168                 :       
    3169                 :     if( !pfnProgress( 0.0, NULL, pProgressData ) )
    3170                 :         return NULL;
    3171                 :       
    3172                 :     // Create the file.   
    3173                 :     MrSIDDummyImageReader oImageReader( poSrcDS );
    3174                 :     eStat = oImageReader.initialize();
    3175                 :     if( eStat != LT_STS_Success )
    3176                 :     {
    3177                 :         CPLError( CE_Failure, CPLE_AppDefined,
    3178                 :                   "MrSIDDummyImageReader.Initialize failed.\n%s",
    3179                 :                   getLastStatusString( eStat ) );
    3180                 :         return NULL;
    3181                 :     }
    3182                 :       
    3183                 : #ifdef MRSID_POST5
    3184                 :     JP2WriterManager oImageWriter(&oImageReader);
    3185                 : #else
    3186                 :     J2KImageWriter oImageWriter(&oImageReader);
    3187                 : #endif
    3188                 :     eStat = oImageWriter.initialize();
    3189                 :     if( eStat != LT_STS_Success )
    3190                 :     {
    3191                 :         CPLError( CE_Failure, CPLE_AppDefined,
    3192                 :                   "J2KImageWriter.Initialize failed.\n%s",
    3193                 :                   getLastStatusString( eStat ) );
    3194                 :         return NULL;
    3195                 :     }
    3196                 :       
    3197                 :     // Set 64-bit Interface for large files.
    3198                 :     oImageWriter.setFileStream64(true);
    3199                 : 
    3200                 :     oImageWriter.setUsageMeterEnabled(bMeter);
    3201                 :       
    3202                 :     // set output filename
    3203                 :     oImageWriter.setOutputFileSpec( pszFilename );
    3204                 : 
    3205                 :     // Set defaults
    3206                 :     //oImageWriter.setStripHeight(oImageWriter.getStripHeight());
    3207                 : 
    3208                 :     // set MrSID world file
    3209                 :     if( CSLFetchNameValue(papszOptions, "WORLDFILE") != NULL )
    3210                 :         oImageWriter.setWorldFileSupport( true );
    3211                 :       
    3212                 :     // check for compression option
    3213                 :     const char* pszValue = CSLFetchNameValue(papszOptions, "COMPRESSION");
    3214                 :     if( pszValue != NULL )
    3215                 :         oImageWriter.params().setCompressionRatio( atof(pszValue) );
    3216                 :         
    3217                 :     pszValue = CSLFetchNameValue(papszOptions, "XMLPROFILE");
    3218                 :     if( pszValue != NULL )
    3219                 :     {
    3220                 :         LTFileSpec xmlprofile(pszValue);
    3221                 :         eStat = oImageWriter.params().readProfile(xmlprofile);
    3222                 :         if( eStat != LT_STS_Success )
    3223                 :         {
    3224                 :             CPLError( CE_Failure, CPLE_AppDefined,
    3225                 :                       "JPCWriterParams.readProfile failed.\n%s",
    3226                 :                       getLastStatusString( eStat ) );
    3227                 :             return NULL;
    3228                 :         }
    3229                 :     }
    3230                 : 
    3231                 :     // write the scene
    3232                 :     const LTIScene oScene( 0, 0, nXSize, nYSize, 1.0 );
    3233                 :     eStat = oImageWriter.write( oScene );
    3234                 :     if( eStat != LT_STS_Success )
    3235                 :     {
    3236                 :         CPLError( CE_Failure, CPLE_AppDefined,
    3237                 :                   "J2KImageWriter.write() failed.\n%s",
    3238                 :                   getLastStatusString( eStat ) );
    3239                 :         return NULL;
    3240                 :     }
    3241                 :   
    3242                 : /* -------------------------------------------------------------------- */
    3243                 : /*      Re-open dataset, and copy any auxilary pam information.         */
    3244                 : /* -------------------------------------------------------------------- */
    3245                 :     GDALOpenInfo oOpenInfo(pszFilename, GA_ReadOnly);
    3246                 :     GDALPamDataset *poDS = (GDALPamDataset*) JP2Open(&oOpenInfo);
    3247                 : 
    3248                 :     if( poDS )  
    3249                 :         poDS->CloneInfo( poSrcDS, GCIF_PAM_DEFAULT );
    3250                 : 
    3251                 :     return poDS;
    3252                 : }
    3253                 : #endif /* MRSID_J2K */
    3254                 : #endif /* MRSID_ESDK */
    3255                 : 
    3256                 : /************************************************************************/
    3257                 : /*                        GDALRegister_MrSID()                          */
    3258                 : /************************************************************************/
    3259                 : 
    3260             409 : void GDALRegister_MrSID()
    3261                 : 
    3262                 : {
    3263                 :     GDALDriver  *poDriver;
    3264                 :     
    3265             409 :     if (! GDAL_CHECK_VERSION("MrSID driver"))
    3266               0 :         return;
    3267                 : 
    3268                 : /* -------------------------------------------------------------------- */
    3269                 : /*      MrSID driver.                                                   */
    3270                 : /* -------------------------------------------------------------------- */
    3271             409 :     if( GDALGetDriverByName( "MrSID" ) == NULL )
    3272                 :     {
    3273             392 :         poDriver = new GDALDriver();
    3274                 : 
    3275             392 :         poDriver->SetDescription( "MrSID" );
    3276                 :         poDriver->SetMetadataItem( GDAL_DMD_LONGNAME,
    3277             392 :                         "Multi-resolution Seamless Image Database (MrSID)" );
    3278             392 :         poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC, "frmt_mrsid.html" );
    3279             392 :         poDriver->SetMetadataItem( GDAL_DMD_EXTENSION, "sid" );
    3280                 : 
    3281                 : #ifdef MRSID_ESDK
    3282                 :         poDriver->SetMetadataItem( GDAL_DMD_CREATIONDATATYPES, 
    3283                 :                                    "Byte Int16 UInt16 Int32 UInt32 Float32 Float64" );
    3284                 :         poDriver->SetMetadataItem( GDAL_DMD_CREATIONOPTIONLIST,
    3285                 : "<CreationOptionList>"
    3286                 : // Version 2 Options
    3287                 : "   <Option name='COMPRESSION' type='double' description='Set compression ratio (0.0 default is meant to be lossless)'/>"
    3288                 : // Version 3 Options
    3289                 : "   <Option name='TWOPASS' type='int' description='Use twopass optimizer algorithm'/>"
    3290                 : "   <Option name='FILESIZE' type='int' description='Set target file size (0 implies lossless compression)'/>"
    3291                 : // Version 2 and 3 Option
    3292                 : "   <Option name='WORLDFILE' type='boolean' description='Write out world file'/>"
    3293                 : // Version Type
    3294                 : "   <Option name='VERSION' type='int' description='Valid versions are 2 and 3, default = 3'/>"
    3295                 : "</CreationOptionList>" );
    3296                 : 
    3297                 :         poDriver->pfnCreateCopy = MrSIDCreateCopy;
    3298                 : #endif
    3299             392 :         poDriver->pfnIdentify = MrSIDIdentify;
    3300             392 :         poDriver->pfnOpen = MrSIDOpen;
    3301                 : 
    3302             392 :         GetGDALDriverManager()->RegisterDriver( poDriver );
    3303                 :     }
    3304                 : 
    3305                 : /* -------------------------------------------------------------------- */
    3306                 : /*      JP2MRSID driver.                                                */
    3307                 : /* -------------------------------------------------------------------- */
    3308                 : #ifdef MRSID_J2K
    3309             409 :     if( GDALGetDriverByName( "JP2MrSID" ) == NULL )
    3310                 :     {
    3311             392 :         poDriver = new GDALDriver();
    3312                 : 
    3313             392 :         poDriver->SetDescription( "JP2MrSID" );
    3314                 :         poDriver->SetMetadataItem( GDAL_DMD_LONGNAME,
    3315             392 :                         "MrSID JPEG2000" );
    3316             392 :         poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC, "frmt_jp2mrsid.html" );
    3317             392 :         poDriver->SetMetadataItem( GDAL_DMD_EXTENSION, "jp2" );
    3318                 : 
    3319                 : #ifdef MRSID_ESDK
    3320                 :         poDriver->SetMetadataItem( GDAL_DMD_CREATIONDATATYPES, 
    3321                 :                                    "Byte Int16 UInt16" );
    3322                 :         poDriver->SetMetadataItem( GDAL_DMD_CREATIONOPTIONLIST,
    3323                 : "<CreationOptionList>"
    3324                 : "   <Option name='COMPRESSION' type='double' description='Set compression ratio (0.0 default is meant to be lossless)'/>"
    3325                 : "   <Option name='WORLDFILE' type='boolean' description='Write out world file'/>"
    3326                 : "   <Option name='XMLPROFILE' type='string' description='Use named xml profile file'/>"
    3327                 : "</CreationOptionList>" );
    3328                 : 
    3329                 :         poDriver->pfnCreateCopy = JP2CreateCopy;
    3330                 : #endif
    3331             392 :         poDriver->pfnIdentify = JP2Identify;
    3332             392 :         poDriver->pfnOpen = JP2Open;
    3333                 : 
    3334             392 :         GetGDALDriverManager()->RegisterDriver( poDriver );
    3335                 :     }
    3336                 : #endif /* def MRSID_J2K */
    3337                 : }

Generated by: LTP GCOV extension version 1.5