LCOV - code coverage report
Current view: directory - frmts/mrsid - mrsiddataset.cpp (source / functions) Found Hit Coverage
Test: gdal_filtered.info Lines: 1019 615 60.4 %
Date: 2013-03-30 Functions: 52 40 76.9 %

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

Generated by: LCOV version 1.7