LCOV - code coverage report
Current view: directory - frmts/gtiff - gt_wkt_srs.cpp (source / functions) Found Hit Coverage
Test: gdal_filtered.info Lines: 910 692 76.0 %
Date: 2012-12-26 Functions: 8 8 100.0 %

       1                 : /******************************************************************************
       2                 :  * $Id: gt_wkt_srs.cpp 25299 2012-12-10 20:58:59Z rouault $
       3                 :  *
       4                 :  * Project:  GeoTIFF Driver
       5                 :  * Purpose:  Implements translation between GeoTIFF normalized projection
       6                 :  *           definitions and OpenGIS WKT SRS format.  This code is
       7                 :  *           deliberately GDAL free, and it is intended to be moved into
       8                 :  *           libgeotiff someday if possible.
       9                 :  * Author:   Frank Warmerdam, warmerdam@pobox.com
      10                 :  *
      11                 :  ******************************************************************************
      12                 :  * Copyright (c) 1999, Frank Warmerdam
      13                 :  *
      14                 :  * Permission is hereby granted, free of charge, to any person obtaining a
      15                 :  * copy of this software and associated documentation files (the "Software"),
      16                 :  * to deal in the Software without restriction, including without limitation
      17                 :  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
      18                 :  * and/or sell copies of the Software, and to permit persons to whom the
      19                 :  * Software is furnished to do so, subject to the following conditions:
      20                 :  *
      21                 :  * The above copyright notice and this permission notice shall be included
      22                 :  * in all copies or substantial portions of the Software.
      23                 :  *
      24                 :  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
      25                 :  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
      26                 :  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
      27                 :  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
      28                 :  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
      29                 :  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
      30                 :  * DEALINGS IN THE SOFTWARE.
      31                 :  ****************************************************************************/
      32                 : 
      33                 : #include "cpl_serv.h"
      34                 : #include "geo_tiffp.h"
      35                 : #define CPL_ERROR_H_INCLUDED
      36                 : 
      37                 : #include "geovalues.h"
      38                 : #include "ogr_spatialref.h"
      39                 : #include "gdal.h"
      40                 : #include "xtiffio.h"
      41                 : #include "cpl_multiproc.h"
      42                 : #include "tifvsi.h"
      43                 : #include "gt_wkt_srs.h"
      44                 : #include "gt_wkt_srs_for_gdal.h"
      45                 : #include "gt_citation.h"
      46                 : 
      47                 : CPL_CVSID("$Id: gt_wkt_srs.cpp 25299 2012-12-10 20:58:59Z rouault $")
      48                 : 
      49                 : #define ProjLinearUnitsInterpCorrectGeoKey   3059
      50                 : 
      51                 : #ifndef CT_HotineObliqueMercatorAzimuthCenter
      52                 : #  define CT_HotineObliqueMercatorAzimuthCenter 9815
      53                 : #endif
      54                 : 
      55                 : 
      56                 : CPL_C_START
      57                 : #ifndef CPL_SERV_H_INTERNAL
      58                 : /* Make VSIL_STRICT_ENFORCE active in DEBUG builds */
      59                 : #ifdef DEBUG
      60                 : #define VSIL_STRICT_ENFORCE
      61                 : #endif
      62                 : 
      63                 : #ifdef VSIL_STRICT_ENFORCE
      64                 : typedef struct _VSILFILE VSILFILE;
      65                 : #else
      66                 : typedef FILE VSILFILE;
      67                 : #endif
      68                 : 
      69                 : // ensure compatability with older libgeotiffs. 
      70                 : #if !defined(GTIFAtof)
      71                 : #  define GTIFAtof atof
      72                 : #endif
      73                 : 
      74                 : int CPL_DLL VSIFCloseL( VSILFILE * );
      75                 : int CPL_DLL VSIUnlink( const char * );
      76                 : VSILFILE CPL_DLL *VSIFileFromMemBuffer( const char *pszFilename,
      77                 :                                     GByte *pabyData, 
      78                 :                                     GUIntBig nDataLength,
      79                 :                                     int bTakeOwnership );
      80                 : GByte CPL_DLL *VSIGetMemFileBuffer( const char *pszFilename, 
      81                 :                                     GUIntBig *pnDataLength, 
      82                 :                                     int bUnlinkAndSeize );
      83                 : 
      84                 : int CPL_DLL CSLTestBoolean( const char *pszValue );
      85                 : const char CPL_DLL * CPL_STDCALL CPLGetConfigOption( const char *, const char * );
      86                 :                   
      87                 : /* Those stuff are redefined in external libgeotiff cpl_serv.h */
      88                 : /* as macros. Let's use GDAL functions instead */
      89                 : /* E.Rouault : I'm wondering why we just don't #define CPL_SERV_H_INCLUDED */
      90                 : /* at the beginning of this file to avoid cpl_serv.h to be used at all ??? */
      91                 : 
      92                 : #undef CSVReadParseLine
      93                 : char CPL_DLL  **CSVReadParseLine( FILE *fp);
      94                 : #undef CSLDestroy
      95                 : void CPL_DLL CPL_STDCALL CSLDestroy(char **papszStrList);
      96                 : #undef VSIFree
      97                 : void CPL_DLL    VSIFree( void * );
      98                 : #undef CPLFree
      99                 : #define CPLFree VSIFree
     100                 : #undef CPLMalloc
     101                 : void CPL_DLL *CPLMalloc( size_t );
     102                 : #undef CPLCalloc
     103                 : void CPL_DLL *CPLCalloc( size_t, size_t );
     104                 : #undef CPLStrdup
     105                 : char CPL_DLL *CPLStrdup( const char * );
     106                 : 
     107                 : #endif /* CPL_SERV_H_INTERNAL */
     108                 : 
     109                 : const char CPL_DLL * CPL_STDCALL CPLGetConfigOption( const char *, const char * );
     110                 : void CPL_DLL CPL_STDCALL CPLDebug( const char *, const char *, ... );
     111                 : 
     112                 : CPL_C_END
     113                 : 
     114                 : // To remind myself not to use CPLString in this file!
     115                 : #define CPLString Please_do_not_use_CPLString_in_this_file
     116                 : 
     117                 : static const char *papszDatumEquiv[] =
     118                 : {
     119                 :     "Militar_Geographische_Institut",
     120                 :     "Militar_Geographische_Institute",
     121                 :     "World_Geodetic_System_1984",
     122                 :     "WGS_1984",
     123                 :     "WGS_72_Transit_Broadcast_Ephemeris",
     124                 :     "WGS_1972_Transit_Broadcast_Ephemeris",
     125                 :     "World_Geodetic_System_1972",
     126                 :     "WGS_1972",
     127                 :     "European_Terrestrial_Reference_System_89",
     128                 :     "European_Reference_System_1989",
     129                 :     NULL
     130                 : };
     131                 : 
     132                 : // older libgeotiff's won't list this.
     133                 : #ifndef CT_CylindricalEqualArea
     134                 : # define CT_CylindricalEqualArea 28
     135                 : #endif
     136                 : 
     137                 : /************************************************************************/
     138                 : /*                       GTIFToCPLRecyleString()                        */
     139                 : /*                                                                      */
     140                 : /*      This changes a string from the libgeotiff heap to the GDAL      */
     141                 : /*      heap.                                                           */
     142                 : /************************************************************************/
     143                 : 
     144            5004 : static void GTIFToCPLRecycleString( char **ppszTarget )
     145                 : 
     146                 : {
     147            5004 :     if( *ppszTarget == NULL )
     148               3 :         return;
     149                 : 
     150            5001 :     char *pszTempString = CPLStrdup(*ppszTarget);
     151            5001 :     GTIFFreeMemory( *ppszTarget );
     152            5001 :     *ppszTarget = pszTempString;
     153                 : }
     154                 : 
     155                 : /************************************************************************/
     156                 : /*                          WKTMassageDatum()                           */
     157                 : /*                                                                      */
     158                 : /*      Massage an EPSG datum name into WMT format.  Also transform     */
     159                 : /*      specific exception cases into WKT versions.                     */
     160                 : /************************************************************************/
     161                 : 
     162           16773 : static void WKTMassageDatum( char ** ppszDatum )
     163                 : 
     164                 : {
     165                 :     int   i, j;
     166                 :     char  *pszDatum;
     167                 : 
     168           16773 :     pszDatum = *ppszDatum;
     169           16773 :     if (pszDatum[0] == '\0')
     170               0 :         return;
     171                 : 
     172                 : /* -------------------------------------------------------------------- */
     173                 : /*      Translate non-alphanumeric values to underscores.               */
     174                 : /* -------------------------------------------------------------------- */
     175          368493 :     for( i = 0; pszDatum[i] != '\0'; i++ )
     176                 :     {
     177         1631966 :         if( pszDatum[i] != '+'
     178          615019 :             && !(pszDatum[i] >= 'A' && pszDatum[i] <= 'Z')
     179          530794 :             && !(pszDatum[i] >= 'a' && pszDatum[i] <= 'z')
     180          134433 :             && !(pszDatum[i] >= '0' && pszDatum[i] <= '9') )
     181                 :         {
     182           42386 :             pszDatum[i] = '_';
     183                 :         }
     184                 :     }
     185                 : 
     186                 : /* -------------------------------------------------------------------- */
     187                 : /*      Remove repeated and trailing underscores.                       */
     188                 : /* -------------------------------------------------------------------- */
     189          351720 :     for( i = 1, j = 0; pszDatum[i] != '\0'; i++ )
     190                 :     {
     191          334947 :         if( pszDatum[j] == '_' && pszDatum[i] == '_' )
     192            2959 :             continue;
     193                 : 
     194          331988 :         pszDatum[++j] = pszDatum[i];
     195                 :     }
     196           16773 :     if( pszDatum[j] == '_' )
     197            2134 :         pszDatum[j] = '\0';
     198                 :     else
     199           14639 :         pszDatum[j+1] = '\0';
     200                 :     
     201                 : /* -------------------------------------------------------------------- */
     202                 : /*      Search for datum equivelences.  Specific massaged names get     */
     203                 : /*      mapped to OpenGIS specified names.                              */
     204                 : /* -------------------------------------------------------------------- */
     205           98338 :     for( i = 0; papszDatumEquiv[i] != NULL; i += 2 )
     206                 :     {
     207           82154 :         if( EQUAL(*ppszDatum,papszDatumEquiv[i]) )
     208                 :         {
     209             589 :             CPLFree( *ppszDatum );
     210             589 :             *ppszDatum = CPLStrdup( papszDatumEquiv[i+1] );
     211             589 :             return;
     212                 :         }
     213                 :     }
     214                 : }
     215                 : 
     216                 : /************************************************************************/
     217                 : /*                      GTIFCleanupImageineNames()                      */
     218                 : /*                                                                      */
     219                 : /*      Erdas Imagine sometimes emits big copyright messages, and       */
     220                 : /*      other stuff into citations.  These can be pretty messy when     */
     221                 : /*      turned into WKT, so we try to trim and clean the strings        */
     222                 : /*      somewhat.                                                       */
     223                 : /************************************************************************/
     224                 : 
     225                 : /* For example:
     226                 :    GTCitationGeoKey (Ascii,215): "IMAGINE GeoTIFF Support\nCopyright 1991 - 2001 by ERDAS, Inc. All Rights Reserved\n@(#)$RCSfile$ $Revision: 25299 $ $Date: 2012-12-10 21:58:59 +0100 (lun. 10 déc. 2012) $\nProjection Name = UTM\nUnits = meters\nGeoTIFF Units = meters"
     227                 : 
     228                 :    GeogCitationGeoKey (Ascii,267): "IMAGINE GeoTIFF Support\nCopyright 1991 - 2001 by ERDAS, Inc. All Rights Reserved\n@(#)$RCSfile$ $Revision: 25299 $ $Date: 2012-12-10 21:58:59 +0100 (lun. 10 déc. 2012) $\nUnable to match Ellipsoid (Datum) to a GeographicTypeGeoKey value\nEllipsoid = Clarke 1866\nDatum = NAD27 (CONUS)"
     229                 : 
     230                 :    PCSCitationGeoKey (Ascii,214): "IMAGINE GeoTIFF Support\nCopyright 1991 - 2001 by ERDAS, Inc. All Rights Reserved\n@(#)$RCSfile$ $Revision: 25299 $ $Date: 2012-12-10 21:58:59 +0100 (lun. 10 déc. 2012) $\nUTM Zone 10N\nEllipsoid = Clarke 1866\nDatum = NAD27 (CONUS)"
     231                 :  
     232                 : */
     233                 : 
     234               5 : static void GTIFCleanupImagineNames( char *pszCitation )
     235                 : 
     236                 : {
     237               5 :     if( strstr(pszCitation,"IMAGINE GeoTIFF") == NULL )
     238               5 :         return;
     239                 : 
     240                 : /* -------------------------------------------------------------------- */
     241                 : /*      First, we skip past all the copyright, and RCS stuff.  We       */
     242                 : /*      assume that this will have a "$" at the end of it all.          */
     243                 : /* -------------------------------------------------------------------- */
     244                 :     char *pszSkip;
     245                 :     
     246               0 :     for( pszSkip = pszCitation + strlen(pszCitation) - 1;
     247                 :          pszSkip != pszCitation && *pszSkip != '$'; 
     248                 :          pszSkip-- ) {}
     249                 : 
     250               0 :     if( *pszSkip == '$' )
     251               0 :         pszSkip++;
     252                 : 
     253               0 :     memmove( pszCitation, pszSkip, strlen(pszSkip)+1 );
     254                 : 
     255                 : /* -------------------------------------------------------------------- */
     256                 : /*      Convert any newlines into spaces, they really gum up the        */
     257                 : /*      WKT.                                                            */
     258                 : /* -------------------------------------------------------------------- */
     259                 :     int i;
     260                 : 
     261               0 :     for( i = 0; pszCitation[i] != '\0'; i++ )
     262                 :     {
     263               0 :         if( pszCitation[i] == '\n' )
     264               0 :             pszCitation[i] = ' ';
     265                 :     }
     266                 : }
     267                 : 
     268                 : /************************************************************************/
     269                 : /*                          GTIFGetOGISDefn()                           */
     270                 : /************************************************************************/
     271                 : 
     272            1029 : char *GTIFGetOGISDefn( GTIF *hGTIF, GTIFDefn * psDefn )
     273                 : 
     274                 : {
     275            1029 :     OGRSpatialReference oSRS;
     276                 : 
     277                 : /* -------------------------------------------------------------------- */
     278                 : /*  Handle non-standard coordinate systems where GTModelTypeGeoKey      */
     279                 : /*  is not defined, but ProjectedCSTypeGeoKey is defined (ticket #3019) */
     280                 : /* -------------------------------------------------------------------- */
     281            1029 :     if( psDefn->Model == KvUserDefined && psDefn->PCS != KvUserDefined)
     282                 :     {
     283               1 :         psDefn->Model = ModelTypeProjected;
     284                 :     }
     285                 : 
     286                 : /* -------------------------------------------------------------------- */
     287                 : /*      Handle non-standard coordinate systems as LOCAL_CS.             */
     288                 : /* -------------------------------------------------------------------- */
     289            1029 :     if( psDefn->Model != ModelTypeProjected 
     290                 :         && psDefn->Model != ModelTypeGeographic 
     291                 :         && psDefn->Model != ModelTypeGeocentric )
     292                 :     {
     293                 :         char  *pszWKT;
     294                 :         char    szPeStr[2400];
     295                 : 
     296                 :         /** check if there is a pe string citation key **/
     297               6 :         if( GTIFKeyGet( hGTIF, PCSCitationGeoKey, szPeStr, 0, sizeof(szPeStr) ) &&
     298                 :             strstr(szPeStr, "ESRI PE String = " ) )
     299                 :         {
     300               1 :             pszWKT = CPLStrdup( szPeStr + strlen("ESRI PE String = ") );
     301               1 :             return pszWKT;
     302                 :         }
     303                 :         else
     304                 :         {
     305               5 :             char  *pszUnitsName = NULL;
     306                 :             char    szPCSName[300];
     307               5 :             int     nKeyCount = 0;
     308                 :             int     anVersion[3];
     309                 : 
     310               5 :             if( hGTIF != NULL )
     311               5 :                 GTIFDirectoryInfo( hGTIF, anVersion, &nKeyCount );
     312                 : 
     313               5 :             if( nKeyCount > 0 ) // Use LOCAL_CS if we have any geokeys at all.
     314                 :             {
     315                 :                 // Handle citation.
     316               5 :                 strcpy( szPCSName, "unnamed" );
     317               5 :                 if( !GTIFKeyGet( hGTIF, GTCitationGeoKey, szPCSName, 
     318                 :                                  0, sizeof(szPCSName) ) )
     319                 :                     GTIFKeyGet( hGTIF, GeogCitationGeoKey, szPCSName, 
     320               0 :                                 0, sizeof(szPCSName) );
     321                 : 
     322               5 :                 GTIFCleanupImagineNames( szPCSName );
     323               5 :                 oSRS.SetLocalCS( szPCSName );
     324                 : 
     325                 :                 // Handle units
     326               5 :                 GTIFGetUOMLengthInfo( psDefn->UOMLength, &pszUnitsName, NULL );
     327                 :               
     328               5 :                 if( pszUnitsName != NULL && psDefn->UOMLength != KvUserDefined )
     329                 :                 {
     330               0 :                     oSRS.SetLinearUnits( pszUnitsName, psDefn->UOMLengthInMeters );
     331               0 :                     oSRS.SetAuthority( "LOCAL_CS|UNIT", "EPSG", psDefn->UOMLength);
     332                 :                 }
     333                 :                 else
     334               5 :                     oSRS.SetLinearUnits( "unknown", psDefn->UOMLengthInMeters );
     335                 : 
     336               5 :                 GTIFFreeMemory( pszUnitsName );
     337                 :             }
     338               5 :             oSRS.exportToWkt( &pszWKT );
     339                 : 
     340               5 :             return pszWKT;
     341                 :         }
     342                 :     }
     343                 : 
     344                 : /* -------------------------------------------------------------------- */
     345                 : /*      Handle Geocentric coordinate systems.                           */
     346                 : /* -------------------------------------------------------------------- */
     347            1023 :     if( psDefn->Model == ModelTypeGeocentric )
     348                 :     {
     349                 :         char    szName[300];
     350                 : 
     351               0 :         strcpy( szName, "unnamed" );
     352               0 :         if( !GTIFKeyGet( hGTIF, GTCitationGeoKey, szName, 
     353                 :                          0, sizeof(szName) ) )
     354                 :             GTIFKeyGet( hGTIF, GeogCitationGeoKey, szName, 
     355               0 :                         0, sizeof(szName) );
     356                 : 
     357               0 :         oSRS.SetGeocCS( szName );
     358                 : 
     359               0 :         char  *pszUnitsName = NULL;
     360                 :           
     361               0 :         GTIFGetUOMLengthInfo( psDefn->UOMLength, &pszUnitsName, NULL );
     362                 :         
     363               0 :         if( pszUnitsName != NULL && psDefn->UOMLength != KvUserDefined )
     364                 :         {
     365               0 :             oSRS.SetLinearUnits( pszUnitsName, psDefn->UOMLengthInMeters );
     366               0 :             oSRS.SetAuthority( "GEOCCS|UNIT", "EPSG", psDefn->UOMLength );
     367                 :         }
     368                 :         else
     369               0 :             oSRS.SetLinearUnits( "unknown", psDefn->UOMLengthInMeters );
     370                 : 
     371               0 :         GTIFFreeMemory( pszUnitsName );
     372                 :     }
     373                 :     
     374                 : /* -------------------------------------------------------------------- */
     375                 : /*      #3901: In libgeotiff 1.3.0 and earlier we incorrectly           */
     376                 : /*      interpreted linear projection parameter geokeys (false          */
     377                 : /*      easting/northing) as being in meters instead of the             */
     378                 : /*      coordinate system of the file.   The following code attempts    */
     379                 : /*      to provide mechanisms for fixing the issue if we are linked     */
     380                 : /*      with an older version of libgeotiff.                            */
     381                 : /* -------------------------------------------------------------------- */
     382                 :     int iParm;
     383                 :     const char *pszLinearUnits = 
     384            1023 :         CPLGetConfigOption( "GTIFF_LINEAR_UNITS", "DEFAULT" );
     385                 : 
     386                 : #if LIBGEOTIFF_VERSION <= 1300
     387                 :     if( EQUAL(pszLinearUnits,"DEFAULT") && psDefn->Projection == KvUserDefined )
     388                 :     {
     389                 :         for( iParm = 0; iParm < psDefn->nParms; iParm++ )
     390                 :         {
     391                 :             switch( psDefn->ProjParmId[iParm] )
     392                 :             {
     393                 :               case ProjFalseEastingGeoKey:
     394                 :               case ProjFalseNorthingGeoKey:
     395                 :               case ProjFalseOriginEastingGeoKey:
     396                 :               case ProjFalseOriginNorthingGeoKey:
     397                 :               case ProjCenterEastingGeoKey:
     398                 :               case ProjCenterNorthingGeoKey:
     399                 :                 if( psDefn->UOMLengthInMeters != 0 
     400                 :                     && psDefn->UOMLengthInMeters != 1.0 )
     401                 :                 {
     402                 :                     psDefn->ProjParm[iParm] *= psDefn->UOMLengthInMeters;
     403                 :                     CPLDebug( "GTIFF", "converting geokey to meters to fix bug in old libgeotiff" );
     404                 :                 }
     405                 :                 break;
     406                 : 
     407                 :               default:
     408                 :                 break;
     409                 :             }
     410                 :         }
     411                 :     }
     412                 : #endif /* LIBGEOTIFF_VERSION <= 1300 */
     413                 : 
     414                 : /* -------------------------------------------------------------------- */
     415                 : /*      #3901: If folks have broken GeoTIFF files generated with        */
     416                 : /*      older versions of GDAL+libgeotiff, then they may need a         */
     417                 : /*      hack to allow them to be read properly.  This is that           */
     418                 : /*      hack.  We basically try to undue the conversion applied by      */
     419                 : /*      libgeotiff to meters (or above) to simulate the old             */
     420                 : /*      behavior.                                                       */
     421                 : /* -------------------------------------------------------------------- */
     422            1023 :     short bLinearUnitsMarkedCorrect = FALSE;
     423                 :     
     424                 :     GTIFKeyGet(hGTIF, (geokey_t) ProjLinearUnitsInterpCorrectGeoKey, 
     425            1023 :                &bLinearUnitsMarkedCorrect, 0, 1);
     426                 : 
     427            1023 :     if( EQUAL(pszLinearUnits,"BROKEN") 
     428                 :         && psDefn->Projection == KvUserDefined 
     429                 :         && !bLinearUnitsMarkedCorrect )
     430                 :     {
     431              16 :         for( iParm = 0; iParm < psDefn->nParms; iParm++ )
     432                 :         {
     433              14 :             switch( psDefn->ProjParmId[iParm] )
     434                 :             {
     435                 :               case ProjFalseEastingGeoKey:
     436                 :               case ProjFalseNorthingGeoKey:
     437                 :               case ProjFalseOriginEastingGeoKey:
     438                 :               case ProjFalseOriginNorthingGeoKey:
     439                 :               case ProjCenterEastingGeoKey:
     440                 :               case ProjCenterNorthingGeoKey:
     441               4 :                 if( psDefn->UOMLengthInMeters != 0 
     442                 :                     && psDefn->UOMLengthInMeters != 1.0 )
     443                 :                 {
     444               4 :                     psDefn->ProjParm[iParm] /= psDefn->UOMLengthInMeters;
     445               4 :                     CPLDebug( "GTIFF", "converting geokey to accomodate old broken file due to GTIFF_LINEAR_UNITS=BROKEN setting." );
     446                 :                 }
     447                 :                 break;
     448                 : 
     449                 :               default:
     450                 :                 break;
     451                 :             }
     452                 :         }
     453                 :     }
     454                 : 
     455                 : /* -------------------------------------------------------------------- */
     456                 : /*      If this is a projected SRS we set the PROJCS keyword first      */
     457                 : /*      to ensure that the GEOGCS will be a child.                      */
     458                 : /* -------------------------------------------------------------------- */
     459            1023 :     OGRBoolean linearUnitIsSet = FALSE;
     460            1023 :     if( psDefn->Model == ModelTypeProjected )
     461                 :     {
     462                 :         char        szCTString[512];
     463             599 :         strcpy( szCTString, "unnamed" );
     464             599 :         if( psDefn->PCS != KvUserDefined )
     465                 :         {
     466             546 :             char    *pszPCSName = NULL;
     467                 : 
     468             546 :             GTIFGetPCSInfo( psDefn->PCS, &pszPCSName, NULL, NULL, NULL );
     469                 :             
     470             546 :             oSRS.SetNode( "PROJCS", pszPCSName ? pszPCSName : "unnamed" );
     471             546 :             if ( pszPCSName )
     472             546 :                 GTIFFreeMemory( pszPCSName );
     473                 : 
     474             546 :             oSRS.SetAuthority( "PROJCS", "EPSG", psDefn->PCS );
     475                 :         }
     476              53 :         else if(hGTIF && GTIFKeyGet( hGTIF, PCSCitationGeoKey, szCTString, 0, 
     477                 :                                      sizeof(szCTString)) )  
     478                 :         {
     479               1 :             if (!SetCitationToSRS(hGTIF, szCTString, sizeof(szCTString),
     480                 :                                   PCSCitationGeoKey, &oSRS, &linearUnitIsSet))
     481               1 :                 oSRS.SetNode("PROJCS",szCTString);
     482                 :         }
     483                 :         else
     484                 :         {
     485              52 :             if( hGTIF )
     486                 :             {
     487              52 :                 GTIFKeyGet( hGTIF, GTCitationGeoKey, szCTString, 0, sizeof(szCTString) );
     488              52 :                 if(!SetCitationToSRS(hGTIF, szCTString, sizeof(szCTString),
     489                 :                                      GTCitationGeoKey, &oSRS, &linearUnitIsSet))
     490               0 :                     oSRS.SetNode( "PROJCS", szCTString );
     491                 :             }
     492                 :             else
     493               0 :                 oSRS.SetNode( "PROJCS", szCTString );
     494                 :         }
     495                 : 
     496                 :         /* Handle ESRI/Erdas style state plane and UTM in citation key */
     497             599 :         if( CheckCitationKeyForStatePlaneUTM(hGTIF, psDefn, &oSRS, &linearUnitIsSet) )
     498                 :         {
     499                 :             char  *pszWKT;
     500               0 :             oSRS.morphFromESRI();
     501               0 :             oSRS.FixupOrdering();
     502               0 :             if( oSRS.exportToWkt( &pszWKT ) == OGRERR_NONE )
     503               0 :                 return pszWKT;
     504                 :         }
     505                 : 
     506                 :         /* Handle ESRI PE string in citation */
     507             599 :         szCTString[0] = '\0';
     508             599 :         if( hGTIF && GTIFKeyGet( hGTIF, GTCitationGeoKey, szCTString, 0, sizeof(szCTString) ) )
     509             596 :             SetCitationToSRS(hGTIF, szCTString, sizeof(szCTString), GTCitationGeoKey, &oSRS, &linearUnitIsSet);
     510                 :     }
     511                 :     
     512                 : /* ==================================================================== */
     513                 : /*      Setup the GeogCS                                                */
     514                 : /* ==================================================================== */
     515            1023 :     char  *pszGeogName = NULL;
     516            1023 :     char  *pszDatumName = NULL;
     517            1023 :     char  *pszPMName = NULL;
     518            1023 :     char  *pszSpheroidName = NULL;
     519            1023 :     char  *pszAngularUnits = NULL;
     520            1023 :     double  dfInvFlattening=0.0, dfSemiMajor=0.0;
     521                 :     char  szGCSName[512];
     522            1023 :     OGRBoolean aUnitGot = FALSE;
     523                 :     
     524            1023 :     if( !GTIFGetGCSInfo( psDefn->GCS, &pszGeogName, NULL, NULL, NULL )
     525                 :         && hGTIF != NULL 
     526                 :         && GTIFKeyGet( hGTIF, GeogCitationGeoKey, szGCSName, 0, 
     527                 :                        sizeof(szGCSName)) )
     528                 :     {
     529                 :         GetGeogCSFromCitation(szGCSName, sizeof(szGCSName),
     530                 :                               GeogCitationGeoKey, 
     531                 :                               &pszGeogName, &pszDatumName,
     532                 :                               &pszPMName, &pszSpheroidName,
     533              30 :                               &pszAngularUnits);
     534                 :     }
     535                 :     else
     536             993 :         GTIFToCPLRecycleString( &pszGeogName );
     537                 :         
     538            1023 :     if( !pszDatumName )
     539                 :     {
     540             996 :         GTIFGetDatumInfo( psDefn->Datum, &pszDatumName, NULL );
     541             996 :         GTIFToCPLRecycleString( &pszDatumName );
     542                 :     }
     543            1023 :     if( !pszSpheroidName )
     544                 :     {
     545             996 :         GTIFGetEllipsoidInfo( psDefn->Ellipsoid, &pszSpheroidName, NULL, NULL );
     546             996 :         GTIFToCPLRecycleString( &pszSpheroidName );
     547                 :     }
     548                 :     else
     549                 :     {
     550              27 :         GTIFKeyGet(hGTIF, GeogSemiMajorAxisGeoKey, &(psDefn->SemiMajor), 0, 1 );
     551              27 :         GTIFKeyGet(hGTIF, GeogInvFlatteningGeoKey, &dfInvFlattening, 0, 1 );
     552                 :     }
     553            1023 :     if( !pszPMName )
     554                 :     {
     555             996 :         GTIFGetPMInfo( psDefn->PM, &pszPMName, NULL );
     556             996 :         GTIFToCPLRecycleString( &pszPMName );
     557                 :     }
     558                 :     else
     559              27 :         GTIFKeyGet(hGTIF, GeogPrimeMeridianLongGeoKey, &(psDefn->PMLongToGreenwich), 0, 1 );
     560                 :     
     561            1023 :     if( !pszAngularUnits )
     562                 :     {
     563            1023 :         GTIFGetUOMAngleInfo( psDefn->UOMAngle, &pszAngularUnits, NULL );
     564            1023 :         if( pszAngularUnits == NULL )
     565               0 :             pszAngularUnits = CPLStrdup("unknown");
     566                 :         else
     567            1023 :             GTIFToCPLRecycleString( &pszAngularUnits );
     568                 :     }
     569                 :     else
     570                 :     {
     571               0 :         GTIFKeyGet(hGTIF, GeogAngularUnitSizeGeoKey, &(psDefn->UOMAngleInDegrees), 0, 1 );
     572               0 :         aUnitGot = TRUE;
     573                 :     }
     574                 : 
     575            1023 :     if( pszDatumName != NULL )
     576            1023 :         WKTMassageDatum( &pszDatumName );
     577                 : 
     578            1023 :     dfSemiMajor = psDefn->SemiMajor;
     579            1023 :     if( dfSemiMajor == 0.0 )
     580                 :     {
     581               0 :         pszSpheroidName = CPLStrdup("unretrievable - using WGS84");
     582               0 :         dfSemiMajor = SRS_WGS84_SEMIMAJOR;
     583               0 :         dfInvFlattening = SRS_WGS84_INVFLATTENING;
     584                 :     }
     585            1023 :     else if( dfInvFlattening == 0.0 && ((psDefn->SemiMinor / psDefn->SemiMajor) < 0.99999999999999999
     586                 :                                         || (psDefn->SemiMinor / psDefn->SemiMajor) > 1.00000000000000001 ) )
     587                 :     {
     588             994 :         dfInvFlattening = -1.0 / (psDefn->SemiMinor/psDefn->SemiMajor - 1.0);
     589                 : 
     590                 :         /* Take official inverse flattening definition in the WGS84 case */
     591             994 :         if (fabs(dfSemiMajor-SRS_WGS84_SEMIMAJOR) < 1e-10 &&
     592                 :             fabs(dfInvFlattening - SRS_WGS84_INVFLATTENING) < 1e-10)
     593             487 :             dfInvFlattening = SRS_WGS84_INVFLATTENING;
     594                 :     }
     595            1023 :     if(!pszGeogName || strlen(pszGeogName) == 0)
     596                 :     {
     597               0 :         CPLFree(pszGeogName);
     598               0 :         pszGeogName = CPLStrdup( pszDatumName ? pszDatumName : "unknown" );
     599                 :     }
     600                 : 
     601            1023 :     if(aUnitGot)
     602                 :         oSRS.SetGeogCS( pszGeogName, pszDatumName, 
     603                 :                         pszSpheroidName, dfSemiMajor, dfInvFlattening,
     604                 :                         pszPMName,
     605                 :                         psDefn->PMLongToGreenwich / psDefn->UOMAngleInDegrees,
     606                 :                         pszAngularUnits,
     607               0 :                         psDefn->UOMAngleInDegrees );
     608                 :     else
     609                 :         oSRS.SetGeogCS( pszGeogName, pszDatumName, 
     610                 :                         pszSpheroidName, dfSemiMajor, dfInvFlattening,
     611                 :                         pszPMName,
     612                 :                         psDefn->PMLongToGreenwich / psDefn->UOMAngleInDegrees,
     613                 :                         pszAngularUnits,
     614            1023 :                         psDefn->UOMAngleInDegrees * 0.0174532925199433 );
     615                 : 
     616            1023 :     if( psDefn->GCS != KvUserDefined && psDefn->GCS > 0 )
     617             993 :         oSRS.SetAuthority( "GEOGCS", "EPSG", psDefn->GCS );
     618                 : 
     619            1023 :     if( psDefn->Datum != KvUserDefined )
     620             996 :         oSRS.SetAuthority( "DATUM", "EPSG", psDefn->Datum );
     621                 : 
     622            1023 :     if( psDefn->Ellipsoid != KvUserDefined )
     623             996 :         oSRS.SetAuthority( "SPHEROID", "EPSG", psDefn->Ellipsoid );
     624                 : 
     625            1023 :     CPLFree( pszGeogName );
     626            1023 :     CPLFree( pszDatumName );
     627            1023 :     CPLFree( pszSpheroidName );
     628            1023 :     CPLFree( pszPMName );
     629            1023 :     CPLFree( pszAngularUnits );
     630                 : 
     631                 : #if LIBGEOTIFF_VERSION >= 1310 && !defined(GEO_NORMALIZE_DISABLE_TOWGS84)
     632            1023 :     if( psDefn->TOWGS84Count > 0 )
     633                 :         oSRS.SetTOWGS84( psDefn->TOWGS84[0],
     634                 :                          psDefn->TOWGS84[1],
     635                 :                          psDefn->TOWGS84[2],
     636                 :                          psDefn->TOWGS84[3],
     637                 :                          psDefn->TOWGS84[4],
     638                 :                          psDefn->TOWGS84[5],
     639              27 :                          psDefn->TOWGS84[6] );
     640                 : #endif
     641                 :         
     642                 : /* ==================================================================== */
     643                 : /*      Handle projection parameters.                                   */
     644                 : /* ==================================================================== */
     645            1023 :     if( psDefn->Model == ModelTypeProjected )
     646                 :     {
     647                 : /* -------------------------------------------------------------------- */
     648                 : /*      Make a local copy of parms, and convert back into the           */
     649                 : /*      angular units of the GEOGCS and the linear units of the         */
     650                 : /*      projection.                                                     */
     651                 : /* -------------------------------------------------------------------- */
     652                 :         double    adfParm[10];
     653                 :         int   i;
     654                 : 
     655            4792 :         for( i = 0; i < MIN(10,psDefn->nParms); i++ )
     656            4193 :             adfParm[i] = psDefn->ProjParm[i];
     657                 : 
     658            2396 :         for( ; i < 10; i++ )
     659            1797 :             adfParm[i] = 0.0;
     660                 : 
     661             599 :         if(!aUnitGot)
     662                 :         {
     663             599 :             adfParm[0] *= psDefn->UOMAngleInDegrees;
     664             599 :             adfParm[1] *= psDefn->UOMAngleInDegrees;
     665             599 :             adfParm[2] *= psDefn->UOMAngleInDegrees;
     666             599 :             adfParm[3] *= psDefn->UOMAngleInDegrees; 
     667                 :         }
     668             599 :         int unitCode = 0;
     669             599 :         GTIFKeyGet(hGTIF, ProjLinearUnitsGeoKey, &unitCode, 0, 1  );
     670             599 :         if(unitCode != KvUserDefined)
     671                 :         {
     672             598 :             adfParm[5] /= psDefn->UOMLengthInMeters;
     673             598 :             adfParm[6] /= psDefn->UOMLengthInMeters;
     674                 :         }
     675                 :         
     676                 : /* -------------------------------------------------------------------- */
     677                 : /*      Translation the fundamental projection.                         */
     678                 : /* -------------------------------------------------------------------- */
     679             599 :         switch( psDefn->CTProjection )
     680                 :         {
     681                 :           case CT_TransverseMercator:
     682                 :             oSRS.SetTM( adfParm[0], adfParm[1],
     683                 :                         adfParm[4],
     684             516 :                         adfParm[5], adfParm[6] );
     685             516 :             break;
     686                 : 
     687                 :           case CT_TransvMercator_SouthOriented:
     688                 :             oSRS.SetTMSO( adfParm[0], adfParm[1],
     689                 :                           adfParm[4],
     690               2 :                           adfParm[5], adfParm[6] );
     691               2 :             break;
     692                 : 
     693                 :           case CT_Mercator:
     694                 :             oSRS.SetMercator( adfParm[0], adfParm[1],
     695                 :                               adfParm[4],
     696              12 :                               adfParm[5], adfParm[6] );
     697                 :                               
     698              12 :             if (psDefn->Projection == 1024 || psDefn->Projection == 9841) // override hack for google mercator. 
     699                 :             {
     700                 :                 oSRS.SetExtension( "PROJCS", "PROJ4",  
     701               8 :                                    "+proj=merc +a=6378137 +b=6378137 +lat_ts=0.0 +lon_0=0.0 +x_0=0.0 +y_0=0 +k=1.0 +units=m +nadgrids=@null +wktext  +no_defs" ); 
     702                 :             }
     703              12 :             break;
     704                 : 
     705                 :           case CT_ObliqueStereographic:
     706                 :             oSRS.SetOS( adfParm[0], adfParm[1],
     707                 :                         adfParm[4],
     708               2 :                         adfParm[5], adfParm[6] );
     709               2 :             break;
     710                 : 
     711                 :           case CT_Stereographic:
     712                 :             oSRS.SetStereographic( adfParm[0], adfParm[1],
     713                 :                         adfParm[4],
     714               2 :                         adfParm[5], adfParm[6] );
     715               2 :             break;
     716                 : 
     717                 :           case CT_ObliqueMercator: /* hotine */
     718                 :             oSRS.SetHOM( adfParm[0], adfParm[1],
     719                 :                          adfParm[2], adfParm[3],
     720                 :                          adfParm[4],
     721               0 :                          adfParm[5], adfParm[6] );
     722               0 :             break;
     723                 :         
     724                 :           case CT_HotineObliqueMercatorAzimuthCenter:
     725                 :             oSRS.SetHOMAC( adfParm[0], adfParm[1],
     726                 :                            adfParm[2], adfParm[3],
     727                 :                            adfParm[4],
     728               4 :                            adfParm[5], adfParm[6] );
     729               4 :             break;
     730                 :         
     731                 :           case CT_EquidistantConic: 
     732                 :             oSRS.SetEC( adfParm[0], adfParm[1],
     733                 :                         adfParm[2], adfParm[3],
     734               0 :                         adfParm[5], adfParm[6] );
     735               0 :             break;
     736                 :         
     737                 :           case CT_CassiniSoldner:
     738                 :             oSRS.SetCS( adfParm[0], adfParm[1],
     739               2 :                         adfParm[5], adfParm[6] );
     740               2 :             break;
     741                 :         
     742                 :           case CT_Polyconic:
     743                 :             oSRS.SetPolyconic( adfParm[0], adfParm[1],
     744               1 :                                adfParm[5], adfParm[6] );
     745               1 :             break;
     746                 : 
     747                 :           case CT_AzimuthalEquidistant:
     748                 :             oSRS.SetAE( adfParm[0], adfParm[1],
     749              11 :                         adfParm[5], adfParm[6] );
     750              11 :             break;
     751                 :         
     752                 :           case CT_MillerCylindrical:
     753                 :             oSRS.SetMC( adfParm[0], adfParm[1],
     754               0 :                         adfParm[5], adfParm[6] );
     755               0 :             break;
     756                 :         
     757                 :           case CT_Equirectangular:
     758                 :             oSRS.SetEquirectangular2( adfParm[0], adfParm[1],
     759                 :                                       adfParm[2],
     760               2 :                                       adfParm[5], adfParm[6] );
     761               2 :             break;
     762                 :         
     763                 :           case CT_Gnomonic:
     764                 :             oSRS.SetGnomonic( adfParm[0], adfParm[1],
     765               0 :                               adfParm[5], adfParm[6] );
     766               0 :             break;
     767                 :         
     768                 :           case CT_LambertAzimEqualArea:
     769                 :             oSRS.SetLAEA( adfParm[0], adfParm[1],
     770               4 :                           adfParm[5], adfParm[6] );
     771               4 :             break;
     772                 :         
     773                 :           case CT_Orthographic:
     774                 :             oSRS.SetOrthographic( adfParm[0], adfParm[1],
     775               2 :                                   adfParm[5], adfParm[6] );
     776               2 :             break;
     777                 :         
     778                 :           case CT_Robinson:
     779                 :             oSRS.SetRobinson( adfParm[1],
     780               0 :                               adfParm[5], adfParm[6] );
     781               0 :             break;
     782                 :         
     783                 :           case CT_Sinusoidal:
     784                 :             oSRS.SetSinusoidal( adfParm[1],
     785               0 :                                 adfParm[5], adfParm[6] );
     786               0 :             break;
     787                 :         
     788                 :           case CT_VanDerGrinten:
     789                 :             oSRS.SetVDG( adfParm[1],
     790               1 :                          adfParm[5], adfParm[6] );
     791               1 :             break;
     792                 : 
     793                 :           case CT_PolarStereographic:
     794                 :             oSRS.SetPS( adfParm[0], adfParm[1],
     795                 :                         adfParm[4],
     796               6 :                         adfParm[5], adfParm[6] );
     797               6 :             break;
     798                 :         
     799                 :           case CT_LambertConfConic_2SP:
     800                 :             oSRS.SetLCC( adfParm[2], adfParm[3],
     801                 :                          adfParm[0], adfParm[1],
     802              14 :                          adfParm[5], adfParm[6] );
     803              14 :             break;
     804                 : 
     805                 :           case CT_LambertConfConic_1SP:
     806                 :             oSRS.SetLCC1SP( adfParm[0], adfParm[1],
     807                 :                             adfParm[4],
     808               5 :                             adfParm[5], adfParm[6] );
     809               5 :             break;
     810                 :         
     811                 :           case CT_AlbersEqualArea:
     812                 :             oSRS.SetACEA( adfParm[0], adfParm[1],
     813                 :                           adfParm[2], adfParm[3],
     814               4 :                           adfParm[5], adfParm[6] );
     815               4 :             break;
     816                 : 
     817                 :           case CT_NewZealandMapGrid:
     818                 :             oSRS.SetNZMG( adfParm[0], adfParm[1],
     819               2 :                           adfParm[5], adfParm[6] );
     820               2 :             break;
     821                 : 
     822                 :           case CT_CylindricalEqualArea:
     823                 :             oSRS.SetCEA( adfParm[0], adfParm[1],
     824               4 :                          adfParm[5], adfParm[6] );
     825               4 :             break;
     826                 :           default:
     827               3 :             if( oSRS.IsProjected() )
     828               3 :                 oSRS.GetRoot()->SetValue( "LOCAL_CS" );
     829                 :             break;
     830                 :         }
     831                 : 
     832                 : /* -------------------------------------------------------------------- */
     833                 : /*      Set projection units.                                           */
     834                 : /* -------------------------------------------------------------------- */
     835             599 :         if(!linearUnitIsSet)
     836                 :         {
     837             599 :             char  *pszUnitsName = NULL;
     838                 :           
     839             599 :             GTIFGetUOMLengthInfo( psDefn->UOMLength, &pszUnitsName, NULL );
     840                 : 
     841            1197 :             if( pszUnitsName != NULL && psDefn->UOMLength != KvUserDefined )
     842                 :             {
     843             598 :                 oSRS.SetLinearUnits( pszUnitsName, psDefn->UOMLengthInMeters );
     844             598 :                 oSRS.SetAuthority( "PROJCS|UNIT", "EPSG", psDefn->UOMLength );
     845                 :             }
     846                 :             else
     847               1 :                 oSRS.SetLinearUnits( "unknown", psDefn->UOMLengthInMeters );
     848                 : 
     849             599 :             GTIFFreeMemory( pszUnitsName );
     850                 :         }
     851                 :     }
     852                 : 
     853                 : /* ==================================================================== */
     854                 : /*      Handle vertical coordinate system information if we have it.    */
     855                 : /* ==================================================================== */
     856            1023 :     short verticalCSType = -1;
     857            1023 :     short verticalDatum = -1;
     858            1023 :     short verticalUnits = -1;
     859            1023 :     const char *pszFilename = NULL;
     860                 :     const char *pszValue;
     861                 :     char szSearchKey[128];
     862            1023 :     bool bNeedManualVertCS = false;
     863                 :     char citation[2048];
     864                 : 
     865                 :     // Don't do anything if there is no apparent vertical information.
     866            1023 :     GTIFKeyGet( hGTIF, VerticalCSTypeGeoKey, &verticalCSType, 0, 1 );
     867            1023 :     GTIFKeyGet( hGTIF, VerticalDatumGeoKey, &verticalDatum, 0, 1 );
     868            1023 :     GTIFKeyGet( hGTIF, VerticalUnitsGeoKey, &verticalUnits, 0, 1 );
     869                 : 
     870            1023 :     if( (verticalCSType != -1 || verticalDatum != -1 || verticalUnits != -1)
     871                 :         && (oSRS.IsGeographic() || oSRS.IsProjected() || oSRS.IsLocal()) )
     872                 :     {
     873               2 :         if( !GTIFKeyGet( hGTIF, VerticalCitationGeoKey, &citation, 
     874                 :                          0, sizeof(citation) ) )
     875               0 :             strcpy( citation, "unknown" );
     876                 : 
     877                 : /* -------------------------------------------------------------------- */
     878                 : /*      The original geotiff specification appears to have              */
     879                 : /*      misconstrued the EPSG codes 5101 to 5106 to be vertical         */
     880                 : /*      coordinate system codes, when in fact they are vertical         */
     881                 : /*      datum codes.  So if these are found in the                      */
     882                 : /*      VerticalCSTypeGeoKey move them to the VerticalDatumGeoKey       */
     883                 : /*      and insert the "normal" corresponding VerticalCSTypeGeoKey      */
     884                 : /*      value.                                                          */
     885                 : /* -------------------------------------------------------------------- */
     886               2 :         if( (verticalCSType >= 5101 && verticalCSType <= 5112)
     887                 :             && verticalDatum == -1 )
     888                 :         {
     889               0 :             verticalDatum = verticalCSType;
     890               0 :             verticalCSType = verticalDatum + 600;
     891                 :         }
     892                 : 
     893                 : /* -------------------------------------------------------------------- */
     894                 : /*      This addresses another case where the EGM96 Vertical Datum code */
     895                 : /*      is mis-used as a Vertical CS code (#4922)                       */
     896                 : /* -------------------------------------------------------------------- */
     897               2 :         if( verticalCSType == 5171 )
     898                 :         {
     899               0 :             verticalDatum = 5171;
     900               0 :             verticalCSType = 5773;
     901                 :         }
     902                 :  
     903                 : /* -------------------------------------------------------------------- */
     904                 : /*      Somewhat similarly, codes 5001 to 5033 were treated as          */
     905                 : /*      vertical coordinate systems based on ellipsoidal heights.       */
     906                 : /*      We use the corresponding 2d geodetic datum as the vertical      */
     907                 : /*      datum and clear the vertical coordinate system code since       */
     908                 : /*      there isn't one in epsg.                                        */
     909                 : /* -------------------------------------------------------------------- */
     910               2 :         if( (verticalCSType >= 5001 && verticalCSType <= 5033)
     911                 :             && verticalDatum == -1 )
     912                 :         {
     913               0 :             verticalDatum = verticalCSType+1000;
     914               0 :             verticalCSType = -1;
     915                 :         }
     916                 : 
     917                 : /* -------------------------------------------------------------------- */
     918                 : /*      Promote to being a compound coordinate system.                  */
     919                 : /* -------------------------------------------------------------------- */
     920               2 :         OGR_SRSNode *poOldRoot = oSRS.GetRoot()->Clone();
     921                 : 
     922               2 :         oSRS.Clear();
     923               2 :         oSRS.SetNode( "COMPD_CS", "unknown" );
     924               2 :         oSRS.GetRoot()->AddChild( poOldRoot );
     925                 : 
     926                 : /* -------------------------------------------------------------------- */
     927                 : /*      If we have the vertical cs, try to look it up using the         */
     928                 : /*      vertcs.csv file, and use the definition provided by that.       */
     929                 : /* -------------------------------------------------------------------- */
     930               2 :         bNeedManualVertCS = true;
     931                 : 
     932               2 :         if( verticalCSType != KvUserDefined && verticalCSType > 0 )
     933                 :         {
     934               2 :             OGRSpatialReference oVertSRS;
     935               2 :             if( oVertSRS.importFromEPSG( verticalCSType ) == OGRERR_NONE )
     936                 :             {
     937               2 :                 oSRS.GetRoot()->AddChild( oVertSRS.GetRoot()->Clone() );
     938               2 :                 bNeedManualVertCS = false;
     939               2 :             }
     940                 :         }
     941                 :     }
     942                 : 
     943                 : /* -------------------------------------------------------------------- */
     944                 : /*      Collect some information from the VerticalCS if not provided    */
     945                 : /*      via geokeys.                                                    */
     946                 : /* -------------------------------------------------------------------- */
     947            1023 :     if( bNeedManualVertCS )
     948                 :     {
     949               0 :         if( verticalCSType > 0 && verticalCSType != KvUserDefined )
     950                 :         {
     951               0 :             pszFilename = CSVFilename( "coordinate_reference_system.csv" );
     952               0 :             sprintf( szSearchKey, "%d", verticalCSType );
     953                 : 
     954               0 :             if( verticalDatum < 1 || verticalDatum == KvUserDefined )
     955                 :             {
     956                 :                 pszValue = CSVGetField( pszFilename, 
     957                 :                                         "coord_ref_sys_code", 
     958                 :                                         szSearchKey, CC_Integer, 
     959               0 :                                         "datum_code" );
     960               0 :                 if( pszValue != NULL )
     961               0 :                     verticalDatum = (short) atoi(pszValue);
     962                 :             }
     963                 : 
     964               0 :             if( EQUAL(citation,"unknown") )
     965                 :             {
     966                 :                 pszValue = CSVGetField( pszFilename, 
     967                 :                                         "coord_ref_sys_code", 
     968                 :                                         szSearchKey, CC_Integer, 
     969               0 :                                         "coord_ref_sys_name" );
     970               0 :                 if( pszValue != NULL && *pszValue != '\0' )
     971               0 :                     strncpy( citation, pszValue, sizeof(citation) );
     972                 :             }
     973                 : 
     974               0 :             if( verticalUnits < 1 || verticalUnits == KvUserDefined )
     975                 :             {
     976                 :                 pszValue = CSVGetField( pszFilename, 
     977                 :                                         "coord_ref_sys_code", 
     978                 :                                         szSearchKey, CC_Integer, 
     979               0 :                                         "coord_sys_code" );
     980               0 :                 if( pszValue != NULL )
     981                 :                 {
     982               0 :                     pszFilename = CSVFilename( "coordinate_axis.csv" );
     983                 :                     pszValue = CSVGetField( pszFilename, 
     984                 :                                             "coord_sys_code", 
     985                 :                                             pszValue, CC_Integer, 
     986               0 :                                             "uom_code" );
     987               0 :                     if( pszValue != NULL )
     988               0 :                         verticalUnits = (short) atoi(pszValue);
     989                 :                 }                
     990                 :             }
     991                 :         }
     992                 : 
     993                 : /* -------------------------------------------------------------------- */
     994                 : /*      Setup VERT_CS with citation if present.                         */
     995                 : /* -------------------------------------------------------------------- */
     996               0 :         oSRS.SetNode( "COMPD_CS|VERT_CS", citation );
     997                 : 
     998                 : /* -------------------------------------------------------------------- */
     999                 : /*      Setup the vertical datum.                                       */
    1000                 : /* -------------------------------------------------------------------- */
    1001               0 :         const char *pszVDatumName = "unknown";
    1002               0 :         const char *pszVDatumType = "2005"; // CS_VD_GeoidModelDerived
    1003                 : 
    1004               0 :         if( verticalDatum > 0 && verticalDatum != KvUserDefined )
    1005                 :         {
    1006               0 :             pszFilename = CSVFilename( "datum.csv" );
    1007               0 :             if( EQUAL(pszFilename,"datum.csv") )
    1008               0 :                 pszFilename = CSVFilename( "gdal_datum.csv" );
    1009                 : 
    1010               0 :             sprintf( szSearchKey, "%d", verticalDatum );
    1011                 : 
    1012                 :             pszValue = CSVGetField( pszFilename,
    1013                 :                                     "DATUM_CODE", szSearchKey, CC_Integer,
    1014               0 :                                     "DATUM_NAME" );
    1015               0 :             if( pszValue != NULL && *pszValue != '\0' )
    1016               0 :                 pszVDatumName = pszValue;
    1017                 : 
    1018                 :             pszValue = CSVGetField( pszFilename,
    1019                 :                                     "DATUM_CODE", szSearchKey, CC_Integer,
    1020               0 :                                     "DATUM_TYPE" );
    1021               0 :             if( pszValue != NULL && EQUALN(pszValue,"geodetic",8) )
    1022               0 :                 pszVDatumType = "2002"; // CS_VD_Ellipsoidal
    1023                 : 
    1024                 :             // We unfortunately don't know how to identify other 
    1025                 :             // vertical datum types, particularly orthometric (2001). 
    1026                 :         }
    1027                 : 
    1028               0 :         oSRS.SetNode( "COMPD_CS|VERT_CS|VERT_DATUM", pszVDatumName );
    1029                 :         oSRS.GetAttrNode( "COMPD_CS|VERT_CS|VERT_DATUM" )
    1030               0 :             ->AddChild( new OGR_SRSNode( pszVDatumType ) );
    1031               0 :         if( verticalDatum > 0 && verticalDatum != KvUserDefined )
    1032                 :             oSRS.SetAuthority( "COMPD_CS|VERT_CS|VERT_DATUM", "EPSG", 
    1033               0 :                                verticalDatum );
    1034                 :     
    1035                 : /* -------------------------------------------------------------------- */
    1036                 : /*      Set the vertical units.                                         */
    1037                 : /* -------------------------------------------------------------------- */
    1038               0 :         if( verticalUnits > 0 && verticalUnits != KvUserDefined 
    1039                 :             && verticalUnits != 9001 )
    1040                 :         {
    1041                 :             char szInMeters[128];
    1042                 : 
    1043               0 :             pszFilename = CSVFilename("unit_of_measure.csv");
    1044                 :             
    1045                 :             // Name
    1046               0 :             sprintf( szSearchKey, "%d", verticalUnits );
    1047                 :             pszValue = CSVGetField( pszFilename,
    1048                 :                                     "uom_code", szSearchKey, CC_Integer,
    1049               0 :                                     "unit_of_meas_name" );
    1050               0 :             if( pszValue == NULL )
    1051               0 :                 pszValue = "unknown";
    1052                 : 
    1053               0 :             oSRS.SetNode( "COMPD_CS|VERT_CS|UNIT", pszValue );
    1054                 : 
    1055                 :             // Value
    1056                 :             double dfFactorB, dfFactorC;
    1057                 :             dfFactorB = GTIFAtof(
    1058                 :                 CSVGetField( pszFilename, 
    1059                 :                              "uom_code", szSearchKey, CC_Integer,
    1060               0 :                              "factor_b" ));
    1061                 :             dfFactorC = GTIFAtof(
    1062                 :                 CSVGetField( pszFilename, 
    1063                 :                              "uom_code", szSearchKey, CC_Integer,
    1064               0 :                              "factor_c" ));
    1065               0 :             if( dfFactorB != 0.0 && dfFactorC != 0.0 )
    1066               0 :                 sprintf( szInMeters, "%.16g", dfFactorB / dfFactorC );
    1067                 :             else
    1068               0 :                 strcpy( szInMeters, "1" );
    1069                 : 
    1070                 : 
    1071                 :             oSRS.GetAttrNode( "COMPD_CS|VERT_CS|UNIT" )
    1072               0 :                 ->AddChild( new OGR_SRSNode( szInMeters ) );
    1073                 : 
    1074               0 :             oSRS.SetAuthority( "COMPD_CS|VERT_CS|UNIT", "EPSG", verticalUnits);
    1075                 :         }
    1076                 :         else
    1077                 :         {
    1078               0 :             oSRS.SetNode( "COMPD_CS|VERT_CS|UNIT", "metre" );
    1079                 :             oSRS.GetAttrNode( "COMPD_CS|VERT_CS|UNIT" )
    1080               0 :                 ->AddChild( new OGR_SRSNode( "1.0" ) );
    1081               0 :             oSRS.SetAuthority( "COMPD_CS|VERT_CS|UNIT", "EPSG", 9001 );
    1082                 :         }
    1083                 : 
    1084                 : /* -------------------------------------------------------------------- */
    1085                 : /*      Set the axis and VERT_CS authority.                             */
    1086                 : /* -------------------------------------------------------------------- */
    1087               0 :         oSRS.SetNode( "COMPD_CS|VERT_CS|AXIS", "Up" );
    1088                 :         oSRS.GetAttrNode( "COMPD_CS|VERT_CS|AXIS" )
    1089               0 :             ->AddChild( new OGR_SRSNode( "UP" ) );
    1090                 :         
    1091               0 :         if( verticalCSType > 0 && verticalCSType != KvUserDefined )
    1092               0 :             oSRS.SetAuthority( "COMPD_CS|VERT_CS", "EPSG", verticalCSType );
    1093                 :     }
    1094                 :     
    1095                 : /* ==================================================================== */
    1096                 : /*      Return the WKT serialization of the object.                     */
    1097                 : /* ==================================================================== */
    1098                 :     char  *pszWKT;
    1099                 : 
    1100            1023 :     oSRS.FixupOrdering();
    1101                 : 
    1102            1023 :     if( oSRS.exportToWkt( &pszWKT ) == OGRERR_NONE )
    1103            1023 :         return pszWKT;
    1104                 :     else
    1105               0 :         return NULL;
    1106                 : }
    1107                 : 
    1108                 : /************************************************************************/
    1109                 : /*                     OGCDatumName2EPSGDatumCode()                     */
    1110                 : /************************************************************************/
    1111                 : 
    1112             375 : static int OGCDatumName2EPSGDatumCode( const char * pszOGCName )
    1113                 : 
    1114                 : {
    1115                 :     FILE  *fp;
    1116                 :     char  **papszTokens;
    1117             375 :     int   nReturn = KvUserDefined;
    1118                 : 
    1119                 : 
    1120                 : /* -------------------------------------------------------------------- */
    1121                 : /*      Do we know it as a built in?                                    */
    1122                 : /* -------------------------------------------------------------------- */
    1123             375 :     if( EQUAL(pszOGCName,"NAD27") 
    1124                 :         || EQUAL(pszOGCName,"North_American_Datum_1927") )
    1125               0 :         return Datum_North_American_Datum_1927;
    1126             375 :     else if( EQUAL(pszOGCName,"NAD83") 
    1127                 :              || EQUAL(pszOGCName,"North_American_Datum_1983") )
    1128               1 :         return Datum_North_American_Datum_1983;
    1129             374 :     else if( EQUAL(pszOGCName,"WGS84") || EQUAL(pszOGCName,"WGS_1984")
    1130                 :              || EQUAL(pszOGCName,"WGS 84"))
    1131             346 :         return Datum_WGS84;
    1132              28 :     else if( EQUAL(pszOGCName,"WGS72") || EQUAL(pszOGCName,"WGS_1972") )
    1133               3 :         return Datum_WGS72;
    1134                 : 
    1135                 : /* -------------------------------------------------------------------- */
    1136                 : /*      Open the table if possible.                                     */
    1137                 : /* -------------------------------------------------------------------- */
    1138              25 :     fp = VSIFOpen( CSVFilename("gdal_datum.csv"), "r" );
    1139              25 :     if( fp == NULL )
    1140               0 :         fp = VSIFOpen( CSVFilename("datum.csv"), "r" );
    1141                 : 
    1142              25 :     if( fp == NULL )
    1143               0 :         return nReturn;
    1144                 : 
    1145                 : /* -------------------------------------------------------------------- */
    1146                 : /*  Discard the first line with field names.      */
    1147                 : /* -------------------------------------------------------------------- */
    1148              25 :     CSLDestroy( CSVReadParseLine( fp ) );
    1149                 : 
    1150                 : /* -------------------------------------------------------------------- */
    1151                 : /*      Read lines looking for our datum.                               */
    1152                 : /* -------------------------------------------------------------------- */
    1153           15775 :     for( papszTokens = CSVReadParseLine( fp );
    1154                 :          CSLCount(papszTokens) > 2 && nReturn == KvUserDefined;
    1155                 :          papszTokens = CSVReadParseLine( fp ) )
    1156                 :     {
    1157           15750 :         WKTMassageDatum( papszTokens + 1 );
    1158                 : 
    1159           15750 :         if( EQUAL(papszTokens[1], pszOGCName) )
    1160               0 :             nReturn = atoi(papszTokens[0]);
    1161                 : 
    1162           15750 :         CSLDestroy( papszTokens );
    1163                 :     }
    1164                 : 
    1165              25 :     CSLDestroy( papszTokens );
    1166              25 :     VSIFClose( fp );
    1167                 : 
    1168              25 :     return nReturn;
    1169                 : }
    1170                 : 
    1171                 : /************************************************************************/
    1172                 : /*                        GTIFSetFromOGISDefn()                         */
    1173                 : /*                                                                      */
    1174                 : /*      Write GeoTIFF projection tags from an OGC WKT definition.       */
    1175                 : /************************************************************************/
    1176                 : 
    1177             930 : int GTIFSetFromOGISDefn( GTIF * psGTIF, const char *pszOGCWKT )
    1178                 : 
    1179                 : {
    1180                 :     OGRSpatialReference *poSRS;
    1181             930 :     int   nPCS = KvUserDefined;
    1182                 :     OGRErr      eErr;
    1183             930 :     OGRBoolean peStrStored = FALSE;    
    1184                 : 
    1185                 :     GTIFKeySet(psGTIF, GTRasterTypeGeoKey, TYPE_SHORT, 1,
    1186             930 :                RasterPixelIsArea);
    1187                 : 
    1188                 : /* -------------------------------------------------------------------- */
    1189                 : /*      Create an OGRSpatialReference object corresponding to the       */
    1190                 : /*      string.                                                         */
    1191                 : /* -------------------------------------------------------------------- */
    1192             930 :     poSRS = new OGRSpatialReference();
    1193             930 :     if( poSRS->importFromWkt((char **) &pszOGCWKT) != OGRERR_NONE )
    1194                 :     {
    1195               2 :         delete poSRS;
    1196               2 :         return FALSE;
    1197                 :     }
    1198                 : 
    1199                 : /* -------------------------------------------------------------------- */
    1200                 : /*      Get the ellipsoid definition.                                   */
    1201                 : /* -------------------------------------------------------------------- */
    1202             928 :     short nSpheroid = KvUserDefined;
    1203                 :     double dfSemiMajor, dfInvFlattening;
    1204                 : 
    1205             928 :     if( poSRS->GetAuthorityName("PROJCS|GEOGCS|DATUM|SPHEROID") != NULL
    1206                 :         && EQUAL(poSRS->GetAuthorityName("PROJCS|GEOGCS|DATUM|SPHEROID"),
    1207                 :                  "EPSG")) 
    1208                 :     {
    1209                 :         nSpheroid = (short)
    1210             239 :             atoi(poSRS->GetAuthorityCode("PROJCS|GEOGCS|DATUM|SPHEROID"));
    1211                 :     }
    1212             689 :     else if( poSRS->GetAuthorityName("GEOGCS|DATUM|SPHEROID") != NULL
    1213                 :              && EQUAL(poSRS->GetAuthorityName("GEOGCS|DATUM|SPHEROID"),"EPSG")) 
    1214                 :     {
    1215                 :         nSpheroid = (short)
    1216             315 :             atoi(poSRS->GetAuthorityCode("GEOGCS|DATUM|SPHEROID"));
    1217                 :     }
    1218                 :     
    1219             928 :     dfSemiMajor = poSRS->GetSemiMajor( &eErr );
    1220             928 :     dfInvFlattening = poSRS->GetInvFlattening( &eErr );
    1221             928 :     if( eErr != OGRERR_NONE )
    1222                 :     {
    1223               3 :         dfSemiMajor = 0.0;
    1224               3 :         dfInvFlattening = 0.0;
    1225                 :     }
    1226                 :     
    1227                 : /* -------------------------------------------------------------------- */
    1228                 : /*      Get the Datum so we can special case a few PCS codes.           */
    1229                 : /* -------------------------------------------------------------------- */
    1230             928 :     int   nDatum = KvUserDefined;
    1231                 : 
    1232             928 :     if( poSRS->GetAuthorityName("PROJCS|GEOGCS|DATUM") != NULL 
    1233                 :         && EQUAL(poSRS->GetAuthorityName("PROJCS|GEOGCS|DATUM"),"EPSG") )
    1234             238 :         nDatum = atoi(poSRS->GetAuthorityCode("PROJCS|GEOGCS|DATUM"));
    1235             690 :     else if( poSRS->GetAuthorityName("GEOGCS|DATUM") != NULL 
    1236                 :              && EQUAL(poSRS->GetAuthorityName("GEOGCS|DATUM"),"EPSG") )
    1237             315 :         nDatum = atoi(poSRS->GetAuthorityCode("GEOGCS|DATUM"));
    1238             375 :     else if( poSRS->GetAttrValue("DATUM") != NULL )
    1239             375 :         nDatum = OGCDatumName2EPSGDatumCode( poSRS->GetAttrValue("DATUM") );
    1240                 : 
    1241                 : /* -------------------------------------------------------------------- */
    1242                 : /*      Get the GCS if possible.                                        */
    1243                 : /* -------------------------------------------------------------------- */
    1244             928 :     int         nGCS = KvUserDefined;
    1245                 : 
    1246             928 :     if( poSRS->GetAuthorityName("PROJCS|GEOGCS") != NULL 
    1247                 :         && EQUAL(poSRS->GetAuthorityName("PROJCS|GEOGCS"),"EPSG") )
    1248             238 :         nGCS = atoi(poSRS->GetAuthorityCode("PROJCS|GEOGCS"));
    1249             690 :     else if( poSRS->GetAuthorityName("GEOGCS") != NULL 
    1250                 :              && EQUAL(poSRS->GetAuthorityName("GEOGCS"),"EPSG") )
    1251             326 :         nGCS = atoi(poSRS->GetAuthorityCode("GEOGCS"));
    1252                 : 
    1253             928 :     if( nGCS > 32767 )
    1254               0 :         nGCS = KvUserDefined;
    1255                 : 
    1256                 : /* -------------------------------------------------------------------- */
    1257                 : /*      Get the linear units.                                           */
    1258                 : /* -------------------------------------------------------------------- */
    1259             928 :     char        *pszLinearUOMName = NULL;
    1260             928 :     double  dfLinearUOM = poSRS->GetLinearUnits( &pszLinearUOMName );
    1261             928 :     int         nUOMLengthCode = 9001; /* meters */
    1262                 : 
    1263             928 :     if( poSRS->GetAuthorityName("PROJCS|UNIT") != NULL 
    1264                 :         && EQUAL(poSRS->GetAuthorityName("PROJCS|UNIT"),"EPSG")
    1265                 :         && poSRS->GetAttrNode( "PROJCS|UNIT" ) != poSRS->GetAttrNode("GEOGCS|UNIT") )
    1266             230 :         nUOMLengthCode = atoi(poSRS->GetAuthorityCode("PROJCS|UNIT"));
    1267             698 :     else if( (pszLinearUOMName != NULL
    1268                 :          && EQUAL(pszLinearUOMName,SRS_UL_FOOT))
    1269                 :         || fabs(dfLinearUOM-GTIFAtof(SRS_UL_FOOT_CONV)) < 0.0000001 )
    1270               0 :         nUOMLengthCode = 9002; /* international foot */
    1271             698 :     else if( (pszLinearUOMName != NULL
    1272                 :               && EQUAL(pszLinearUOMName,SRS_UL_US_FOOT))
    1273                 :              || ABS(dfLinearUOM-GTIFAtof(SRS_UL_US_FOOT_CONV)) < 0.0000001 )
    1274               2 :         nUOMLengthCode = 9003; /* us survey foot */
    1275             696 :     else if( fabs(dfLinearUOM-1.0) > 0.00000001 )
    1276               1 :         nUOMLengthCode = KvUserDefined;
    1277                 : 
    1278                 : /* -------------------------------------------------------------------- */
    1279                 : /*      Get some authority values.                                      */
    1280                 : /* -------------------------------------------------------------------- */
    1281             928 :     if( poSRS->GetAuthorityName("PROJCS") != NULL 
    1282                 :         && EQUAL(poSRS->GetAuthorityName("PROJCS"),"EPSG") )
    1283                 :     {
    1284             225 :         nPCS = atoi(poSRS->GetAuthorityCode("PROJCS"));
    1285             225 :         if( nPCS > 32767 )
    1286               0 :             nPCS = KvUserDefined;
    1287                 :     }
    1288                 : 
    1289                 : /* -------------------------------------------------------------------- */
    1290                 : /*      Handle the projection transformation.                           */
    1291                 : /* -------------------------------------------------------------------- */
    1292             928 :     const char *pszProjection = poSRS->GetAttrValue( "PROJECTION" );
    1293             928 :     int bWritePEString = FALSE;
    1294                 :     
    1295             928 :     if( nPCS != KvUserDefined )
    1296                 :     {
    1297                 :         GTIFKeySet(psGTIF, GTModelTypeGeoKey, TYPE_SHORT, 1,
    1298             225 :                    ModelTypeProjected);
    1299             225 :         GTIFKeySet(psGTIF, ProjectedCSTypeGeoKey, TYPE_SHORT, 1, nPCS );
    1300                 :     }
    1301             703 :     else if( poSRS->IsGeocentric() )
    1302                 :     {
    1303                 :         GTIFKeySet(psGTIF, GTModelTypeGeoKey, TYPE_SHORT, 1, 
    1304               0 :                    ModelTypeGeocentric );
    1305                 :     }
    1306             703 :     else if( pszProjection == NULL )
    1307                 :     {
    1308             665 :         if( poSRS->IsGeographic() )
    1309                 :             GTIFKeySet(psGTIF, GTModelTypeGeoKey, TYPE_SHORT, 1,
    1310             665 :                        ModelTypeGeographic);
    1311                 :         // otherwise, presumably something like LOCAL_CS.
    1312                 :     }
    1313              38 :     else if( EQUAL(pszProjection,SRS_PT_ALBERS_CONIC_EQUAL_AREA) )
    1314                 :     {
    1315                 :         GTIFKeySet(psGTIF, GTModelTypeGeoKey, TYPE_SHORT, 1,
    1316               1 :                    ModelTypeProjected);
    1317                 :         GTIFKeySet(psGTIF, ProjectedCSTypeGeoKey, TYPE_SHORT, 1,
    1318               1 :                    KvUserDefined );
    1319                 :         GTIFKeySet(psGTIF, ProjectionGeoKey, TYPE_SHORT, 1,
    1320               1 :                    KvUserDefined );
    1321                 : 
    1322                 :         GTIFKeySet(psGTIF, ProjCoordTransGeoKey, TYPE_SHORT, 1, 
    1323               1 :                    CT_AlbersEqualArea );
    1324                 : 
    1325                 :         GTIFKeySet(psGTIF, ProjStdParallelGeoKey, TYPE_DOUBLE, 1,
    1326               1 :                    poSRS->GetNormProjParm( SRS_PP_STANDARD_PARALLEL_1, 0.0 ) );
    1327                 : 
    1328                 :         GTIFKeySet(psGTIF, ProjStdParallel2GeoKey, TYPE_DOUBLE, 1,
    1329               1 :                    poSRS->GetNormProjParm( SRS_PP_STANDARD_PARALLEL_2, 0.0 ) );
    1330                 : 
    1331                 :         GTIFKeySet(psGTIF, ProjNatOriginLatGeoKey, TYPE_DOUBLE, 1,
    1332               1 :                    poSRS->GetNormProjParm( SRS_PP_LATITUDE_OF_CENTER, 0.0 ) );
    1333                 : 
    1334                 :         GTIFKeySet(psGTIF, ProjNatOriginLongGeoKey, TYPE_DOUBLE, 1,
    1335               1 :                    poSRS->GetNormProjParm( SRS_PP_LONGITUDE_OF_CENTER, 0.0 ) );
    1336                 :         
    1337                 :         GTIFKeySet(psGTIF, ProjFalseEastingGeoKey, TYPE_DOUBLE, 1,
    1338               1 :                    poSRS->GetProjParm( SRS_PP_FALSE_EASTING, 0.0 ) );
    1339                 :         
    1340                 :         GTIFKeySet(psGTIF, ProjFalseNorthingGeoKey, TYPE_DOUBLE, 1,
    1341               1 :                    poSRS->GetProjParm( SRS_PP_FALSE_NORTHING, 0.0 ) );
    1342                 :     }
    1343                 : 
    1344              37 :     else if( poSRS->GetUTMZone() != 0 )
    1345                 :     {
    1346                 :         int   bNorth, nZone, nProjection;
    1347                 : 
    1348                 :         GTIFKeySet(psGTIF, GTModelTypeGeoKey, TYPE_SHORT, 1,
    1349               2 :                    ModelTypeProjected);
    1350                 : 
    1351               2 :         nZone = poSRS->GetUTMZone( &bNorth );
    1352                 : 
    1353               2 :         if( nDatum == Datum_North_American_Datum_1983 && nZone >= 3
    1354                 :             && nZone <= 22 && bNorth && nUOMLengthCode == 9001 )
    1355                 :         {
    1356               0 :             nPCS = 26900 + nZone;
    1357                 : 
    1358               0 :             GTIFKeySet(psGTIF, ProjectedCSTypeGeoKey, TYPE_SHORT, 1, nPCS );
    1359                 :         }
    1360               2 :         else if( nDatum == Datum_North_American_Datum_1927 && nZone >= 3
    1361                 :                  && nZone <= 22 && bNorth && nUOMLengthCode == 9001 )
    1362                 :         {
    1363               0 :             nPCS = 26700 + nZone;
    1364                 : 
    1365               0 :             GTIFKeySet(psGTIF, ProjectedCSTypeGeoKey, TYPE_SHORT, 1, nPCS );
    1366                 :         }
    1367               2 :         else if( nDatum == Datum_WGS84 && nUOMLengthCode == 9001 )
    1368                 :         {
    1369               0 :             if( bNorth )
    1370               0 :                 nPCS = 32600 + nZone;
    1371                 :             else
    1372               0 :                 nPCS = 32700 + nZone;
    1373                 : 
    1374               0 :             GTIFKeySet(psGTIF, ProjectedCSTypeGeoKey, TYPE_SHORT, 1, nPCS );
    1375                 :         }
    1376                 :         else
    1377                 :         {
    1378               2 :             if( bNorth )
    1379               2 :                 nProjection = 16000 + nZone;
    1380                 :             else
    1381               0 :                 nProjection = 16100 + nZone;
    1382                 : 
    1383                 :         
    1384                 :             GTIFKeySet(psGTIF, ProjectedCSTypeGeoKey, TYPE_SHORT, 1,
    1385               2 :                        KvUserDefined );
    1386                 :             
    1387               2 :             GTIFKeySet(psGTIF, ProjectionGeoKey, TYPE_SHORT, 1, nProjection );
    1388                 :         }
    1389                 :     }
    1390                 : 
    1391              35 :     else if( EQUAL(pszProjection,SRS_PT_TRANSVERSE_MERCATOR) )
    1392                 :     {
    1393                 :         GTIFKeySet(psGTIF, GTModelTypeGeoKey, TYPE_SHORT, 1,
    1394               1 :                    ModelTypeProjected);
    1395                 :         GTIFKeySet(psGTIF, ProjectedCSTypeGeoKey, TYPE_SHORT, 1,
    1396               1 :                    KvUserDefined );
    1397                 :         GTIFKeySet(psGTIF, ProjectionGeoKey, TYPE_SHORT, 1,
    1398               1 :                    KvUserDefined );
    1399                 : 
    1400                 :         GTIFKeySet(psGTIF, ProjCoordTransGeoKey, TYPE_SHORT, 1, 
    1401               1 :                    CT_TransverseMercator );
    1402                 : 
    1403                 :         GTIFKeySet(psGTIF, ProjNatOriginLatGeoKey, TYPE_DOUBLE, 1,
    1404               1 :                    poSRS->GetNormProjParm( SRS_PP_LATITUDE_OF_ORIGIN, 0.0 ) );
    1405                 : 
    1406                 :         GTIFKeySet(psGTIF, ProjNatOriginLongGeoKey, TYPE_DOUBLE, 1,
    1407               1 :                    poSRS->GetNormProjParm( SRS_PP_CENTRAL_MERIDIAN, 0.0 ) );
    1408                 :         
    1409                 :         GTIFKeySet(psGTIF, ProjScaleAtNatOriginGeoKey, TYPE_DOUBLE, 1,
    1410               1 :                    poSRS->GetNormProjParm( SRS_PP_SCALE_FACTOR, 1.0 ) );
    1411                 :         
    1412                 :         GTIFKeySet(psGTIF, ProjFalseEastingGeoKey, TYPE_DOUBLE, 1,
    1413               1 :                    poSRS->GetProjParm( SRS_PP_FALSE_EASTING, 0.0 ) );
    1414                 :         
    1415                 :         GTIFKeySet(psGTIF, ProjFalseNorthingGeoKey, TYPE_DOUBLE, 1,
    1416               1 :                    poSRS->GetProjParm( SRS_PP_FALSE_NORTHING, 0.0 ) );
    1417                 :     }
    1418                 :     
    1419              34 :     else if( EQUAL(pszProjection,SRS_PT_TRANSVERSE_MERCATOR_SOUTH_ORIENTED) )
    1420                 :     {
    1421                 :         GTIFKeySet(psGTIF, GTModelTypeGeoKey, TYPE_SHORT, 1,
    1422               1 :                    ModelTypeProjected);
    1423                 :         GTIFKeySet(psGTIF, ProjectedCSTypeGeoKey, TYPE_SHORT, 1,
    1424               1 :                    KvUserDefined );
    1425                 :         GTIFKeySet(psGTIF, ProjectionGeoKey, TYPE_SHORT, 1,
    1426               1 :                    KvUserDefined );
    1427                 : 
    1428                 :         GTIFKeySet(psGTIF, ProjCoordTransGeoKey, TYPE_SHORT, 1, 
    1429               1 :                    CT_TransvMercator_SouthOriented );
    1430                 : 
    1431                 :         GTIFKeySet(psGTIF, ProjNatOriginLatGeoKey, TYPE_DOUBLE, 1,
    1432               1 :                    poSRS->GetNormProjParm( SRS_PP_LATITUDE_OF_ORIGIN, 0.0 ) );
    1433                 : 
    1434                 :         GTIFKeySet(psGTIF, ProjNatOriginLongGeoKey, TYPE_DOUBLE, 1,
    1435               1 :                    poSRS->GetNormProjParm( SRS_PP_CENTRAL_MERIDIAN, 0.0 ) );
    1436                 :         
    1437                 :         GTIFKeySet(psGTIF, ProjScaleAtNatOriginGeoKey, TYPE_DOUBLE, 1,
    1438               1 :                    poSRS->GetNormProjParm( SRS_PP_SCALE_FACTOR, 1.0 ) );
    1439                 :         
    1440                 :         GTIFKeySet(psGTIF, ProjFalseEastingGeoKey, TYPE_DOUBLE, 1,
    1441               1 :                    poSRS->GetProjParm( SRS_PP_FALSE_EASTING, 0.0 ) );
    1442                 :         
    1443                 :         GTIFKeySet(psGTIF, ProjFalseNorthingGeoKey, TYPE_DOUBLE, 1,
    1444               1 :                    poSRS->GetProjParm( SRS_PP_FALSE_NORTHING, 0.0 ) );
    1445                 :     }
    1446                 :     
    1447              35 :     else if( EQUAL(pszProjection,SRS_PT_MERCATOR_2SP) 
    1448                 :              || EQUAL(pszProjection,SRS_PT_MERCATOR_1SP) )
    1449                 : 
    1450                 :     {
    1451                 :         GTIFKeySet(psGTIF, GTModelTypeGeoKey, TYPE_SHORT, 1,
    1452               2 :                    ModelTypeProjected);
    1453                 :         GTIFKeySet(psGTIF, ProjectedCSTypeGeoKey, TYPE_SHORT, 1,
    1454               2 :                    KvUserDefined );
    1455                 :         GTIFKeySet(psGTIF, ProjectionGeoKey, TYPE_SHORT, 1,
    1456               2 :                    KvUserDefined );
    1457                 : 
    1458                 :         GTIFKeySet(psGTIF, ProjCoordTransGeoKey, TYPE_SHORT, 1, 
    1459               2 :                    CT_Mercator );
    1460                 : 
    1461                 :         GTIFKeySet(psGTIF, ProjNatOriginLatGeoKey, TYPE_DOUBLE, 1,
    1462               2 :                    poSRS->GetNormProjParm( SRS_PP_LATITUDE_OF_ORIGIN, 0.0 ) );
    1463                 : 
    1464                 :         GTIFKeySet(psGTIF, ProjNatOriginLongGeoKey, TYPE_DOUBLE, 1,
    1465               2 :                    poSRS->GetNormProjParm( SRS_PP_CENTRAL_MERIDIAN, 0.0 ) );
    1466                 :         
    1467                 :         GTIFKeySet(psGTIF, ProjScaleAtNatOriginGeoKey, TYPE_DOUBLE, 1,
    1468               2 :                    poSRS->GetNormProjParm( SRS_PP_SCALE_FACTOR, 1.0 ) );
    1469                 :         
    1470                 :         GTIFKeySet(psGTIF, ProjFalseEastingGeoKey, TYPE_DOUBLE, 1,
    1471               2 :                    poSRS->GetProjParm( SRS_PP_FALSE_EASTING, 0.0 ) );
    1472                 :         
    1473                 :         GTIFKeySet(psGTIF, ProjFalseNorthingGeoKey, TYPE_DOUBLE, 1,
    1474               2 :                    poSRS->GetProjParm( SRS_PP_FALSE_NORTHING, 0.0 ) );
    1475                 :     }
    1476                 :     
    1477              31 :     else if( EQUAL(pszProjection,SRS_PT_OBLIQUE_STEREOGRAPHIC) )
    1478                 :     {
    1479                 :         GTIFKeySet(psGTIF, GTModelTypeGeoKey, TYPE_SHORT, 1,
    1480               1 :                    ModelTypeProjected);
    1481                 :         GTIFKeySet(psGTIF, ProjectedCSTypeGeoKey, TYPE_SHORT, 1,
    1482               1 :                    KvUserDefined );
    1483                 :         GTIFKeySet(psGTIF, ProjectionGeoKey, TYPE_SHORT, 1,
    1484               1 :                    KvUserDefined );
    1485                 : 
    1486                 :         GTIFKeySet(psGTIF, ProjCoordTransGeoKey, TYPE_SHORT, 1, 
    1487               1 :                    CT_ObliqueStereographic );
    1488                 : 
    1489                 :         GTIFKeySet(psGTIF, ProjNatOriginLatGeoKey, TYPE_DOUBLE, 1,
    1490               1 :                    poSRS->GetNormProjParm( SRS_PP_LATITUDE_OF_ORIGIN, 0.0 ) );
    1491                 : 
    1492                 :         GTIFKeySet(psGTIF, ProjNatOriginLongGeoKey, TYPE_DOUBLE, 1,
    1493               1 :                    poSRS->GetNormProjParm( SRS_PP_CENTRAL_MERIDIAN, 0.0 ) );
    1494                 :         
    1495                 :         GTIFKeySet(psGTIF, ProjScaleAtNatOriginGeoKey, TYPE_DOUBLE, 1,
    1496               1 :                    poSRS->GetNormProjParm( SRS_PP_SCALE_FACTOR, 1.0 ) );
    1497                 :         
    1498                 :         GTIFKeySet(psGTIF, ProjFalseEastingGeoKey, TYPE_DOUBLE, 1,
    1499               1 :                    poSRS->GetProjParm( SRS_PP_FALSE_EASTING, 0.0 ) );
    1500                 :         
    1501                 :         GTIFKeySet(psGTIF, ProjFalseNorthingGeoKey, TYPE_DOUBLE, 1,
    1502               1 :                    poSRS->GetProjParm( SRS_PP_FALSE_NORTHING, 0.0 ) );
    1503                 :     }
    1504                 :     
    1505              30 :     else if( EQUAL(pszProjection,SRS_PT_STEREOGRAPHIC) )
    1506                 :     {
    1507                 :         GTIFKeySet(psGTIF, GTModelTypeGeoKey, TYPE_SHORT, 1,
    1508               1 :                    ModelTypeProjected);
    1509                 :         GTIFKeySet(psGTIF, ProjectedCSTypeGeoKey, TYPE_SHORT, 1,
    1510               1 :                    KvUserDefined );
    1511                 :         GTIFKeySet(psGTIF, ProjectionGeoKey, TYPE_SHORT, 1,
    1512               1 :                    KvUserDefined );
    1513                 : 
    1514                 :         GTIFKeySet(psGTIF, ProjCoordTransGeoKey, TYPE_SHORT, 1, 
    1515               1 :                    CT_Stereographic );
    1516                 : 
    1517                 :         GTIFKeySet(psGTIF, ProjCenterLatGeoKey, TYPE_DOUBLE, 1,
    1518               1 :                    poSRS->GetNormProjParm( SRS_PP_LATITUDE_OF_ORIGIN, 0.0 ) );
    1519                 : 
    1520                 :         GTIFKeySet(psGTIF, ProjCenterLongGeoKey, TYPE_DOUBLE, 1,
    1521               1 :                    poSRS->GetNormProjParm( SRS_PP_CENTRAL_MERIDIAN, 0.0 ) );
    1522                 :         
    1523                 :         GTIFKeySet(psGTIF, ProjScaleAtNatOriginGeoKey, TYPE_DOUBLE, 1,
    1524               1 :                    poSRS->GetNormProjParm( SRS_PP_SCALE_FACTOR, 1.0 ) );
    1525                 :         
    1526                 :         GTIFKeySet(psGTIF, ProjFalseEastingGeoKey, TYPE_DOUBLE, 1,
    1527               1 :                    poSRS->GetProjParm( SRS_PP_FALSE_EASTING, 0.0 ) );
    1528                 :         
    1529                 :         GTIFKeySet(psGTIF, ProjFalseNorthingGeoKey, TYPE_DOUBLE, 1,
    1530               1 :                    poSRS->GetProjParm( SRS_PP_FALSE_NORTHING, 0.0 ) );
    1531                 :     }
    1532                 :     
    1533              29 :     else if( EQUAL(pszProjection,SRS_PT_POLAR_STEREOGRAPHIC) )
    1534                 :     {
    1535                 :         GTIFKeySet(psGTIF, GTModelTypeGeoKey, TYPE_SHORT, 1,
    1536               3 :                    ModelTypeProjected);
    1537                 :         GTIFKeySet(psGTIF, ProjectedCSTypeGeoKey, TYPE_SHORT, 1,
    1538               3 :                    KvUserDefined );
    1539                 :         GTIFKeySet(psGTIF, ProjectionGeoKey, TYPE_SHORT, 1,
    1540               3 :                    KvUserDefined );
    1541                 : 
    1542                 :         GTIFKeySet(psGTIF, ProjCoordTransGeoKey, TYPE_SHORT, 1, 
    1543               3 :                    CT_PolarStereographic );
    1544                 : 
    1545                 :         GTIFKeySet(psGTIF, ProjNatOriginLatGeoKey, TYPE_DOUBLE, 1,
    1546               3 :                    poSRS->GetNormProjParm( SRS_PP_LATITUDE_OF_ORIGIN, 0.0 ) );
    1547                 : 
    1548                 :         GTIFKeySet(psGTIF, ProjStraightVertPoleLongGeoKey, TYPE_DOUBLE, 1,
    1549               3 :                    poSRS->GetNormProjParm( SRS_PP_CENTRAL_MERIDIAN, 0.0 ) );
    1550                 :         
    1551                 :         GTIFKeySet(psGTIF, ProjScaleAtNatOriginGeoKey, TYPE_DOUBLE, 1,
    1552               3 :                    poSRS->GetNormProjParm( SRS_PP_SCALE_FACTOR, 1.0 ) );
    1553                 :         
    1554                 :         GTIFKeySet(psGTIF, ProjFalseEastingGeoKey, TYPE_DOUBLE, 1,
    1555               3 :                    poSRS->GetProjParm( SRS_PP_FALSE_EASTING, 0.0 ) );
    1556                 :         
    1557                 :         GTIFKeySet(psGTIF, ProjFalseNorthingGeoKey, TYPE_DOUBLE, 1,
    1558               3 :                    poSRS->GetProjParm( SRS_PP_FALSE_NORTHING, 0.0 ) );
    1559                 :     }
    1560                 :     
    1561              26 :     else if( EQUAL(pszProjection,SRS_PT_HOTINE_OBLIQUE_MERCATOR) )
    1562                 :     {
    1563                 :         GTIFKeySet(psGTIF, GTModelTypeGeoKey, TYPE_SHORT, 1,
    1564               0 :                    ModelTypeProjected);
    1565                 :         GTIFKeySet(psGTIF, ProjectedCSTypeGeoKey, TYPE_SHORT, 1,
    1566               0 :                    KvUserDefined );
    1567                 :         GTIFKeySet(psGTIF, ProjectionGeoKey, TYPE_SHORT, 1,
    1568               0 :                    KvUserDefined );
    1569                 : 
    1570                 :         GTIFKeySet(psGTIF, ProjCoordTransGeoKey, TYPE_SHORT, 1, 
    1571               0 :                    CT_ObliqueMercator );
    1572                 : 
    1573                 :         GTIFKeySet(psGTIF, ProjCenterLatGeoKey, TYPE_DOUBLE, 1,
    1574               0 :                    poSRS->GetNormProjParm( SRS_PP_LATITUDE_OF_CENTER, 0.0 ) );
    1575                 : 
    1576                 :         GTIFKeySet(psGTIF, ProjCenterLongGeoKey, TYPE_DOUBLE, 1,
    1577               0 :                    poSRS->GetNormProjParm( SRS_PP_LONGITUDE_OF_CENTER, 0.0 ) );
    1578                 :         
    1579                 :         GTIFKeySet(psGTIF, ProjAzimuthAngleGeoKey, TYPE_DOUBLE, 1,
    1580               0 :                    poSRS->GetNormProjParm( SRS_PP_AZIMUTH, 0.0 ) );
    1581                 :         
    1582                 :         GTIFKeySet(psGTIF, ProjRectifiedGridAngleGeoKey, TYPE_DOUBLE, 1,
    1583               0 :                    poSRS->GetNormProjParm( SRS_PP_RECTIFIED_GRID_ANGLE, 0.0 ) );
    1584                 :         
    1585                 :         GTIFKeySet(psGTIF, ProjScaleAtCenterGeoKey, TYPE_DOUBLE, 1,
    1586               0 :                    poSRS->GetNormProjParm( SRS_PP_SCALE_FACTOR, 1.0 ) );
    1587                 :         
    1588                 :         GTIFKeySet(psGTIF, ProjFalseEastingGeoKey, TYPE_DOUBLE, 1,
    1589               0 :                    poSRS->GetProjParm( SRS_PP_FALSE_EASTING, 0.0 ) );
    1590                 :         
    1591                 :         GTIFKeySet(psGTIF, ProjFalseNorthingGeoKey, TYPE_DOUBLE, 1,
    1592               0 :                    poSRS->GetProjParm( SRS_PP_FALSE_NORTHING, 0.0 ) );
    1593                 :     }
    1594                 :     
    1595              26 :     else if( EQUAL(pszProjection,SRS_PT_HOTINE_OBLIQUE_MERCATOR_AZIMUTH_CENTER) )
    1596                 :     {
    1597                 :         GTIFKeySet(psGTIF, GTModelTypeGeoKey, TYPE_SHORT, 1,
    1598               2 :                    ModelTypeProjected);
    1599                 :         GTIFKeySet(psGTIF, ProjectedCSTypeGeoKey, TYPE_SHORT, 1,
    1600               2 :                    KvUserDefined );
    1601                 :         GTIFKeySet(psGTIF, ProjectionGeoKey, TYPE_SHORT, 1,
    1602               2 :                    KvUserDefined );
    1603                 : 
    1604                 :         GTIFKeySet(psGTIF, ProjCoordTransGeoKey, TYPE_SHORT, 1, 
    1605               2 :                    CT_HotineObliqueMercatorAzimuthCenter );
    1606                 : 
    1607                 :         GTIFKeySet(psGTIF, ProjCenterLatGeoKey, TYPE_DOUBLE, 1,
    1608               2 :                    poSRS->GetNormProjParm( SRS_PP_LATITUDE_OF_CENTER, 0.0 ) );
    1609                 : 
    1610                 :         GTIFKeySet(psGTIF, ProjCenterLongGeoKey, TYPE_DOUBLE, 1,
    1611               2 :                    poSRS->GetNormProjParm( SRS_PP_LONGITUDE_OF_CENTER, 0.0 ) );
    1612                 :         
    1613                 :         GTIFKeySet(psGTIF, ProjAzimuthAngleGeoKey, TYPE_DOUBLE, 1,
    1614               2 :                    poSRS->GetNormProjParm( SRS_PP_AZIMUTH, 0.0 ) );
    1615                 :         
    1616                 :         GTIFKeySet(psGTIF, ProjRectifiedGridAngleGeoKey, TYPE_DOUBLE, 1,
    1617               2 :                    poSRS->GetNormProjParm( SRS_PP_RECTIFIED_GRID_ANGLE, 0.0 ) );
    1618                 :         
    1619                 :         GTIFKeySet(psGTIF, ProjScaleAtCenterGeoKey, TYPE_DOUBLE, 1,
    1620               2 :                    poSRS->GetNormProjParm( SRS_PP_SCALE_FACTOR, 1.0 ) );
    1621                 :         
    1622                 :         GTIFKeySet(psGTIF, ProjFalseEastingGeoKey, TYPE_DOUBLE, 1,
    1623               2 :                    poSRS->GetProjParm( SRS_PP_FALSE_EASTING, 0.0 ) );
    1624                 :         
    1625                 :         GTIFKeySet(psGTIF, ProjFalseNorthingGeoKey, TYPE_DOUBLE, 1,
    1626               2 :                    poSRS->GetProjParm( SRS_PP_FALSE_NORTHING, 0.0 ) );
    1627                 :     }
    1628                 :     
    1629              24 :     else if( EQUAL(pszProjection,SRS_PT_CASSINI_SOLDNER) )
    1630                 :     {
    1631                 :         GTIFKeySet(psGTIF, GTModelTypeGeoKey, TYPE_SHORT, 1,
    1632               1 :                    ModelTypeProjected);
    1633                 :         GTIFKeySet(psGTIF, ProjectedCSTypeGeoKey, TYPE_SHORT, 1,
    1634               1 :                    KvUserDefined );
    1635                 :         GTIFKeySet(psGTIF, ProjectionGeoKey, TYPE_SHORT, 1,
    1636               1 :                    KvUserDefined );
    1637                 : 
    1638                 :         GTIFKeySet(psGTIF, ProjCoordTransGeoKey, TYPE_SHORT, 1, 
    1639               1 :                    CT_CassiniSoldner );
    1640                 : 
    1641                 :         GTIFKeySet(psGTIF, ProjNatOriginLatGeoKey, TYPE_DOUBLE, 1,
    1642               1 :                    poSRS->GetNormProjParm( SRS_PP_LATITUDE_OF_ORIGIN, 0.0 ) );
    1643                 : 
    1644                 :         GTIFKeySet(psGTIF, ProjNatOriginLongGeoKey, TYPE_DOUBLE, 1,
    1645               1 :                    poSRS->GetNormProjParm( SRS_PP_CENTRAL_MERIDIAN, 0.0 ) );
    1646                 :         
    1647                 :         GTIFKeySet(psGTIF, ProjFalseEastingGeoKey, TYPE_DOUBLE, 1,
    1648               1 :                    poSRS->GetProjParm( SRS_PP_FALSE_EASTING, 0.0 ) );
    1649                 :         
    1650                 :         GTIFKeySet(psGTIF, ProjFalseNorthingGeoKey, TYPE_DOUBLE, 1,
    1651               1 :                    poSRS->GetProjParm( SRS_PP_FALSE_NORTHING, 0.0 ) );
    1652                 :     }
    1653                 :     
    1654              23 :     else if( EQUAL(pszProjection,SRS_PT_EQUIDISTANT_CONIC) )
    1655                 :     {
    1656                 :         GTIFKeySet(psGTIF, GTModelTypeGeoKey, TYPE_SHORT, 1,
    1657               0 :                    ModelTypeProjected);
    1658                 :         GTIFKeySet(psGTIF, ProjectedCSTypeGeoKey, TYPE_SHORT, 1,
    1659               0 :                    KvUserDefined );
    1660                 :         GTIFKeySet(psGTIF, ProjectionGeoKey, TYPE_SHORT, 1,
    1661               0 :                    KvUserDefined );
    1662                 : 
    1663                 :         GTIFKeySet(psGTIF, ProjCoordTransGeoKey, TYPE_SHORT, 1, 
    1664               0 :                    CT_EquidistantConic );
    1665                 : 
    1666                 :         GTIFKeySet(psGTIF, ProjStdParallel1GeoKey, TYPE_DOUBLE, 1,
    1667               0 :                    poSRS->GetNormProjParm( SRS_PP_STANDARD_PARALLEL_1, 0.0 ) );
    1668                 : 
    1669                 :         GTIFKeySet(psGTIF, ProjStdParallel2GeoKey, TYPE_DOUBLE, 1,
    1670               0 :                    poSRS->GetNormProjParm( SRS_PP_STANDARD_PARALLEL_2, 0.0 ) );
    1671                 : 
    1672                 :         GTIFKeySet(psGTIF, ProjNatOriginLatGeoKey, TYPE_DOUBLE, 1,
    1673               0 :                    poSRS->GetNormProjParm( SRS_PP_LATITUDE_OF_CENTER, 0.0 ) );
    1674                 : 
    1675                 :         GTIFKeySet(psGTIF, ProjNatOriginLongGeoKey, TYPE_DOUBLE, 1,
    1676               0 :                    poSRS->GetNormProjParm( SRS_PP_LONGITUDE_OF_CENTER, 0.0 ) );
    1677                 :         
    1678                 :         GTIFKeySet(psGTIF, ProjFalseEastingGeoKey, TYPE_DOUBLE, 1,
    1679               0 :                    poSRS->GetProjParm( SRS_PP_FALSE_EASTING, 0.0 ) );
    1680                 :         
    1681                 :         GTIFKeySet(psGTIF, ProjFalseNorthingGeoKey, TYPE_DOUBLE, 1,
    1682               0 :                    poSRS->GetProjParm( SRS_PP_FALSE_NORTHING, 0.0 ) );
    1683                 :     }
    1684                 :     
    1685              23 :     else if( EQUAL(pszProjection,SRS_PT_POLYCONIC) )
    1686                 :     {
    1687                 :         GTIFKeySet(psGTIF, GTModelTypeGeoKey, TYPE_SHORT, 1,
    1688               1 :                    ModelTypeProjected);
    1689                 :         GTIFKeySet(psGTIF, ProjectedCSTypeGeoKey, TYPE_SHORT, 1,
    1690               1 :                    KvUserDefined );
    1691                 :         GTIFKeySet(psGTIF, ProjectionGeoKey, TYPE_SHORT, 1,
    1692               1 :                    KvUserDefined );
    1693                 : 
    1694                 :         GTIFKeySet(psGTIF, ProjCoordTransGeoKey, TYPE_SHORT, 1, 
    1695               1 :                    CT_Polyconic );
    1696                 : 
    1697                 :         GTIFKeySet(psGTIF, ProjNatOriginLatGeoKey, TYPE_DOUBLE, 1,
    1698               1 :                    poSRS->GetNormProjParm( SRS_PP_LATITUDE_OF_ORIGIN, 0.0 ) );
    1699                 : 
    1700                 :         GTIFKeySet(psGTIF, ProjNatOriginLongGeoKey, TYPE_DOUBLE, 1,
    1701               1 :                    poSRS->GetNormProjParm( SRS_PP_CENTRAL_MERIDIAN, 0.0 ) );
    1702                 :         
    1703                 :         GTIFKeySet(psGTIF, ProjScaleAtNatOriginGeoKey, TYPE_DOUBLE, 1,
    1704               1 :                    poSRS->GetNormProjParm( SRS_PP_SCALE_FACTOR, 1.0 ) );
    1705                 :         
    1706                 :         GTIFKeySet(psGTIF, ProjFalseEastingGeoKey, TYPE_DOUBLE, 1,
    1707               1 :                    poSRS->GetProjParm( SRS_PP_FALSE_EASTING, 0.0 ) );
    1708                 :         
    1709                 :         GTIFKeySet(psGTIF, ProjFalseNorthingGeoKey, TYPE_DOUBLE, 1,
    1710               1 :                    poSRS->GetProjParm( SRS_PP_FALSE_NORTHING, 0.0 ) );
    1711                 :     }
    1712                 :     
    1713              22 :     else if( EQUAL(pszProjection,SRS_PT_AZIMUTHAL_EQUIDISTANT) )
    1714                 :     {
    1715                 :         GTIFKeySet(psGTIF, GTModelTypeGeoKey, TYPE_SHORT, 1,
    1716               4 :                    ModelTypeProjected);
    1717                 :         GTIFKeySet(psGTIF, ProjectedCSTypeGeoKey, TYPE_SHORT, 1,
    1718               4 :                    KvUserDefined );
    1719                 :         GTIFKeySet(psGTIF, ProjectionGeoKey, TYPE_SHORT, 1,
    1720               4 :                    KvUserDefined );
    1721                 : 
    1722                 :         GTIFKeySet(psGTIF, ProjCoordTransGeoKey, TYPE_SHORT, 1, 
    1723               4 :                    CT_AzimuthalEquidistant );
    1724                 : 
    1725                 :         GTIFKeySet(psGTIF, ProjCenterLatGeoKey, TYPE_DOUBLE, 1,
    1726               4 :                    poSRS->GetNormProjParm( SRS_PP_LATITUDE_OF_CENTER, 0.0 ) );
    1727                 : 
    1728                 :         GTIFKeySet(psGTIF, ProjCenterLongGeoKey, TYPE_DOUBLE, 1,
    1729               4 :                    poSRS->GetNormProjParm( SRS_PP_LONGITUDE_OF_CENTER, 0.0 ) );
    1730                 :         
    1731                 :         GTIFKeySet(psGTIF, ProjFalseEastingGeoKey, TYPE_DOUBLE, 1,
    1732               4 :                    poSRS->GetProjParm( SRS_PP_FALSE_EASTING, 0.0 ) );
    1733                 :         
    1734                 :         GTIFKeySet(psGTIF, ProjFalseNorthingGeoKey, TYPE_DOUBLE, 1,
    1735               4 :                    poSRS->GetProjParm( SRS_PP_FALSE_NORTHING, 0.0 ) );
    1736                 :     }
    1737                 :     
    1738              18 :     else if( EQUAL(pszProjection,SRS_PT_MILLER_CYLINDRICAL) )
    1739                 :     {
    1740                 :         GTIFKeySet(psGTIF, GTModelTypeGeoKey, TYPE_SHORT, 1,
    1741               0 :                    ModelTypeProjected);
    1742                 :         GTIFKeySet(psGTIF, ProjectedCSTypeGeoKey, TYPE_SHORT, 1,
    1743               0 :                    KvUserDefined );
    1744                 :         GTIFKeySet(psGTIF, ProjectionGeoKey, TYPE_SHORT, 1,
    1745               0 :                    KvUserDefined );
    1746                 : 
    1747                 :         GTIFKeySet(psGTIF, ProjCoordTransGeoKey, TYPE_SHORT, 1, 
    1748               0 :                    CT_MillerCylindrical );
    1749                 : 
    1750                 :         GTIFKeySet(psGTIF, ProjCenterLatGeoKey, TYPE_DOUBLE, 1,
    1751               0 :                    poSRS->GetNormProjParm( SRS_PP_LATITUDE_OF_CENTER, 0.0 ) );
    1752                 : 
    1753                 :         GTIFKeySet(psGTIF, ProjCenterLongGeoKey, TYPE_DOUBLE, 1,
    1754               0 :                    poSRS->GetNormProjParm( SRS_PP_LONGITUDE_OF_CENTER, 0.0 ) );
    1755                 :         
    1756                 :         GTIFKeySet(psGTIF, ProjFalseEastingGeoKey, TYPE_DOUBLE, 1,
    1757               0 :                    poSRS->GetProjParm( SRS_PP_FALSE_EASTING, 0.0 ) );
    1758                 :         
    1759                 :         GTIFKeySet(psGTIF, ProjFalseNorthingGeoKey, TYPE_DOUBLE, 1,
    1760               0 :                    poSRS->GetProjParm( SRS_PP_FALSE_NORTHING, 0.0 ) );
    1761                 :     }
    1762                 :     
    1763              18 :     else if( EQUAL(pszProjection,SRS_PT_EQUIRECTANGULAR) )
    1764                 :     {
    1765                 :         GTIFKeySet(psGTIF, GTModelTypeGeoKey, TYPE_SHORT, 1,
    1766               2 :                    ModelTypeProjected);
    1767                 :         GTIFKeySet(psGTIF, ProjectedCSTypeGeoKey, TYPE_SHORT, 1,
    1768               2 :                    KvUserDefined );
    1769                 :         GTIFKeySet(psGTIF, ProjectionGeoKey, TYPE_SHORT, 1,
    1770               2 :                    KvUserDefined );
    1771                 : 
    1772                 :         GTIFKeySet(psGTIF, ProjCoordTransGeoKey, TYPE_SHORT, 1, 
    1773               2 :                    CT_Equirectangular );
    1774                 : 
    1775                 :         GTIFKeySet(psGTIF, ProjCenterLatGeoKey, TYPE_DOUBLE, 1,
    1776               2 :                    poSRS->GetNormProjParm( SRS_PP_LATITUDE_OF_ORIGIN, 0.0 ) );
    1777                 : 
    1778                 :         GTIFKeySet(psGTIF, ProjCenterLongGeoKey, TYPE_DOUBLE, 1,
    1779               2 :                    poSRS->GetNormProjParm( SRS_PP_CENTRAL_MERIDIAN, 0.0 ) );
    1780                 :         
    1781                 :         GTIFKeySet(psGTIF, ProjStdParallel1GeoKey, TYPE_DOUBLE, 1,
    1782               2 :                    poSRS->GetNormProjParm( SRS_PP_STANDARD_PARALLEL_1, 0.0 ) );
    1783                 :         
    1784                 :         GTIFKeySet(psGTIF, ProjFalseEastingGeoKey, TYPE_DOUBLE, 1,
    1785               2 :                    poSRS->GetProjParm( SRS_PP_FALSE_EASTING, 0.0 ) );
    1786                 :         
    1787                 :         GTIFKeySet(psGTIF, ProjFalseNorthingGeoKey, TYPE_DOUBLE, 1,
    1788               2 :                    poSRS->GetProjParm( SRS_PP_FALSE_NORTHING, 0.0 ) );
    1789                 :     }
    1790                 :     
    1791              16 :     else if( EQUAL(pszProjection,SRS_PT_GNOMONIC) )
    1792                 :     {
    1793                 :         GTIFKeySet(psGTIF, GTModelTypeGeoKey, TYPE_SHORT, 1,
    1794               0 :                    ModelTypeProjected);
    1795                 :         GTIFKeySet(psGTIF, ProjectedCSTypeGeoKey, TYPE_SHORT, 1,
    1796               0 :                    KvUserDefined );
    1797                 :         GTIFKeySet(psGTIF, ProjectionGeoKey, TYPE_SHORT, 1,
    1798               0 :                    KvUserDefined );
    1799                 : 
    1800                 :         GTIFKeySet(psGTIF, ProjCoordTransGeoKey, TYPE_SHORT, 1, 
    1801               0 :                    CT_Gnomonic );
    1802                 : 
    1803                 :         GTIFKeySet(psGTIF, ProjCenterLatGeoKey, TYPE_DOUBLE, 1,
    1804               0 :                    poSRS->GetNormProjParm( SRS_PP_LATITUDE_OF_ORIGIN, 0.0 ) );
    1805                 : 
    1806                 :         GTIFKeySet(psGTIF, ProjCenterLongGeoKey, TYPE_DOUBLE, 1,
    1807               0 :                    poSRS->GetNormProjParm( SRS_PP_CENTRAL_MERIDIAN, 0.0 ) );
    1808                 :         
    1809                 :         GTIFKeySet(psGTIF, ProjFalseEastingGeoKey, TYPE_DOUBLE, 1,
    1810               0 :                    poSRS->GetProjParm( SRS_PP_FALSE_EASTING, 0.0 ) );
    1811                 :         
    1812                 :         GTIFKeySet(psGTIF, ProjFalseNorthingGeoKey, TYPE_DOUBLE, 1,
    1813               0 :                    poSRS->GetProjParm( SRS_PP_FALSE_NORTHING, 0.0 ) );
    1814                 :     }
    1815                 :     
    1816              16 :     else if( EQUAL(pszProjection,SRS_PT_LAMBERT_AZIMUTHAL_EQUAL_AREA) )
    1817                 :     {
    1818                 :         GTIFKeySet(psGTIF, GTModelTypeGeoKey, TYPE_SHORT, 1,
    1819               2 :                    ModelTypeProjected);
    1820                 :         GTIFKeySet(psGTIF, ProjectedCSTypeGeoKey, TYPE_SHORT, 1,
    1821               2 :                    KvUserDefined );
    1822                 :         GTIFKeySet(psGTIF, ProjectionGeoKey, TYPE_SHORT, 1,
    1823               2 :                    KvUserDefined );
    1824                 : 
    1825                 :         GTIFKeySet(psGTIF, ProjCoordTransGeoKey, TYPE_SHORT, 1, 
    1826               2 :                    CT_LambertAzimEqualArea );
    1827                 : 
    1828                 :         GTIFKeySet(psGTIF, ProjCenterLatGeoKey, TYPE_DOUBLE, 1,
    1829               2 :                    poSRS->GetNormProjParm( SRS_PP_LATITUDE_OF_CENTER, 0.0 ) );
    1830                 : 
    1831                 :         GTIFKeySet(psGTIF, ProjCenterLongGeoKey, TYPE_DOUBLE, 1,
    1832               2 :                    poSRS->GetNormProjParm( SRS_PP_LONGITUDE_OF_CENTER, 0.0 ) );
    1833                 :         
    1834                 :         GTIFKeySet(psGTIF, ProjFalseEastingGeoKey, TYPE_DOUBLE, 1,
    1835               2 :                    poSRS->GetProjParm( SRS_PP_FALSE_EASTING, 0.0 ) );
    1836                 :         
    1837                 :         GTIFKeySet(psGTIF, ProjFalseNorthingGeoKey, TYPE_DOUBLE, 1,
    1838               2 :                    poSRS->GetProjParm( SRS_PP_FALSE_NORTHING, 0.0 ) );
    1839                 :     }
    1840                 :     
    1841              14 :     else if( EQUAL(pszProjection,SRS_PT_ORTHOGRAPHIC) )
    1842                 :     {
    1843                 :         GTIFKeySet(psGTIF, GTModelTypeGeoKey, TYPE_SHORT, 1,
    1844               1 :                    ModelTypeProjected);
    1845                 :         GTIFKeySet(psGTIF, ProjectedCSTypeGeoKey, TYPE_SHORT, 1,
    1846               1 :                    KvUserDefined );
    1847                 :         GTIFKeySet(psGTIF, ProjectionGeoKey, TYPE_SHORT, 1,
    1848               1 :                    KvUserDefined );
    1849                 : 
    1850                 :         GTIFKeySet(psGTIF, ProjCoordTransGeoKey, TYPE_SHORT, 1, 
    1851               1 :                    CT_Orthographic );
    1852                 : 
    1853                 :         GTIFKeySet(psGTIF, ProjCenterLatGeoKey, TYPE_DOUBLE, 1,
    1854               1 :                    poSRS->GetNormProjParm( SRS_PP_LATITUDE_OF_ORIGIN, 0.0 ) );
    1855                 : 
    1856                 :         GTIFKeySet(psGTIF, ProjCenterLongGeoKey, TYPE_DOUBLE, 1,
    1857               1 :                    poSRS->GetNormProjParm( SRS_PP_CENTRAL_MERIDIAN, 0.0 ) );
    1858                 :         
    1859                 :         GTIFKeySet(psGTIF, ProjFalseEastingGeoKey, TYPE_DOUBLE, 1,
    1860               1 :                    poSRS->GetProjParm( SRS_PP_FALSE_EASTING, 0.0 ) );
    1861                 :         
    1862                 :         GTIFKeySet(psGTIF, ProjFalseNorthingGeoKey, TYPE_DOUBLE, 1,
    1863               1 :                    poSRS->GetProjParm( SRS_PP_FALSE_NORTHING, 0.0 ) );
    1864                 :     }
    1865                 :     
    1866              13 :     else if( EQUAL(pszProjection,SRS_PT_NEW_ZEALAND_MAP_GRID) )
    1867                 :     {
    1868                 :         GTIFKeySet(psGTIF, GTModelTypeGeoKey, TYPE_SHORT, 1,
    1869               1 :                    ModelTypeProjected);
    1870                 :         GTIFKeySet(psGTIF, ProjectedCSTypeGeoKey, TYPE_SHORT, 1,
    1871               1 :                    KvUserDefined );
    1872                 :         GTIFKeySet(psGTIF, ProjectionGeoKey, TYPE_SHORT, 1,
    1873               1 :                    KvUserDefined );
    1874                 : 
    1875                 :         GTIFKeySet(psGTIF, ProjCoordTransGeoKey, TYPE_SHORT, 1, 
    1876               1 :                    CT_NewZealandMapGrid );
    1877                 : 
    1878                 :         GTIFKeySet(psGTIF, ProjNatOriginLatGeoKey, TYPE_DOUBLE, 1,
    1879               1 :                    poSRS->GetNormProjParm( SRS_PP_LATITUDE_OF_ORIGIN, 0.0 ) );
    1880                 : 
    1881                 :         GTIFKeySet(psGTIF, ProjNatOriginLongGeoKey, TYPE_DOUBLE, 1,
    1882               1 :                    poSRS->GetNormProjParm( SRS_PP_CENTRAL_MERIDIAN, 0.0 ) );
    1883                 :         
    1884                 :         GTIFKeySet(psGTIF, ProjFalseEastingGeoKey, TYPE_DOUBLE, 1,
    1885               1 :                    poSRS->GetProjParm( SRS_PP_FALSE_EASTING, 0.0 ) );
    1886                 :         
    1887                 :         GTIFKeySet(psGTIF, ProjFalseNorthingGeoKey, TYPE_DOUBLE, 1,
    1888               1 :                    poSRS->GetProjParm( SRS_PP_FALSE_NORTHING, 0.0 ) );
    1889                 :     }
    1890                 :     
    1891              12 :     else if( EQUAL(pszProjection,SRS_PT_ROBINSON) )
    1892                 :     {
    1893                 :         GTIFKeySet(psGTIF, GTModelTypeGeoKey, TYPE_SHORT, 1,
    1894               0 :                    ModelTypeProjected);
    1895                 :         GTIFKeySet(psGTIF, ProjectedCSTypeGeoKey, TYPE_SHORT, 1,
    1896               0 :                    KvUserDefined );
    1897                 :         GTIFKeySet(psGTIF, ProjectionGeoKey, TYPE_SHORT, 1,
    1898               0 :                    KvUserDefined );
    1899                 : 
    1900                 :         GTIFKeySet(psGTIF, ProjCoordTransGeoKey, TYPE_SHORT, 1, 
    1901               0 :                    CT_Robinson );
    1902                 : 
    1903                 :         GTIFKeySet(psGTIF, ProjCenterLongGeoKey, TYPE_DOUBLE, 1,
    1904               0 :                    poSRS->GetNormProjParm( SRS_PP_LONGITUDE_OF_CENTER, 0.0 ) );
    1905                 :         
    1906                 :         GTIFKeySet(psGTIF, ProjFalseEastingGeoKey, TYPE_DOUBLE, 1,
    1907               0 :                    poSRS->GetProjParm( SRS_PP_FALSE_EASTING, 0.0 ) );
    1908                 :         
    1909                 :         GTIFKeySet(psGTIF, ProjFalseNorthingGeoKey, TYPE_DOUBLE, 1,
    1910               0 :                    poSRS->GetProjParm( SRS_PP_FALSE_NORTHING, 0.0 ) );
    1911                 :     }
    1912                 :     
    1913              12 :     else if( EQUAL(pszProjection,SRS_PT_SINUSOIDAL) )
    1914                 :     {
    1915                 :         GTIFKeySet(psGTIF, GTModelTypeGeoKey, TYPE_SHORT, 1,
    1916               1 :                    ModelTypeProjected);
    1917                 :         GTIFKeySet(psGTIF, ProjectedCSTypeGeoKey, TYPE_SHORT, 1,
    1918               1 :                    KvUserDefined );
    1919                 :         GTIFKeySet(psGTIF, ProjectionGeoKey, TYPE_SHORT, 1,
    1920               1 :                    KvUserDefined );
    1921                 : 
    1922                 :         GTIFKeySet(psGTIF, ProjCoordTransGeoKey, TYPE_SHORT, 1, 
    1923               1 :                    CT_Sinusoidal );
    1924                 : 
    1925                 :         GTIFKeySet(psGTIF, ProjCenterLongGeoKey, TYPE_DOUBLE, 1,
    1926               1 :                    poSRS->GetNormProjParm( SRS_PP_LONGITUDE_OF_CENTER, 0.0 ) );
    1927                 :         
    1928                 :         GTIFKeySet(psGTIF, ProjFalseEastingGeoKey, TYPE_DOUBLE, 1,
    1929               1 :                    poSRS->GetProjParm( SRS_PP_FALSE_EASTING, 0.0 ) );
    1930                 :         
    1931                 :         GTIFKeySet(psGTIF, ProjFalseNorthingGeoKey, TYPE_DOUBLE, 1,
    1932               1 :                    poSRS->GetProjParm( SRS_PP_FALSE_NORTHING, 0.0 ) );
    1933                 :     }
    1934                 :     
    1935              11 :     else if( EQUAL(pszProjection,SRS_PT_VANDERGRINTEN) )
    1936                 :     {
    1937                 :         GTIFKeySet(psGTIF, GTModelTypeGeoKey, TYPE_SHORT, 1,
    1938               2 :                    ModelTypeProjected);
    1939                 :         GTIFKeySet(psGTIF, ProjectedCSTypeGeoKey, TYPE_SHORT, 1,
    1940               2 :                    KvUserDefined );
    1941                 :         GTIFKeySet(psGTIF, ProjectionGeoKey, TYPE_SHORT, 1,
    1942               2 :                    KvUserDefined );
    1943                 : 
    1944                 :         GTIFKeySet(psGTIF, ProjCoordTransGeoKey, TYPE_SHORT, 1, 
    1945               2 :                    CT_VanDerGrinten );
    1946                 : 
    1947                 :         GTIFKeySet(psGTIF, ProjCenterLongGeoKey, TYPE_DOUBLE, 1,
    1948               2 :                    poSRS->GetNormProjParm( SRS_PP_CENTRAL_MERIDIAN, 0.0 ) );
    1949                 :         
    1950                 :         GTIFKeySet(psGTIF, ProjFalseEastingGeoKey, TYPE_DOUBLE, 1,
    1951               2 :                    poSRS->GetProjParm( SRS_PP_FALSE_EASTING, 0.0 ) );
    1952                 :         
    1953                 :         GTIFKeySet(psGTIF, ProjFalseNorthingGeoKey, TYPE_DOUBLE, 1,
    1954               2 :                    poSRS->GetProjParm( SRS_PP_FALSE_NORTHING, 0.0 ) );
    1955                 :     }
    1956                 :     
    1957               9 :     else if( EQUAL(pszProjection,SRS_PT_ALBERS_CONIC_EQUAL_AREA) )
    1958                 :     {
    1959                 :         GTIFKeySet(psGTIF, GTModelTypeGeoKey, TYPE_SHORT, 1,
    1960               0 :                    ModelTypeProjected);
    1961                 :         GTIFKeySet(psGTIF, ProjectedCSTypeGeoKey, TYPE_SHORT, 1,
    1962               0 :                    KvUserDefined );
    1963                 :         GTIFKeySet(psGTIF, ProjectionGeoKey, TYPE_SHORT, 1,
    1964               0 :                    KvUserDefined );
    1965                 : 
    1966                 :         GTIFKeySet(psGTIF, ProjCoordTransGeoKey, TYPE_SHORT, 1, 
    1967               0 :                    CT_AlbersEqualArea );
    1968                 : 
    1969                 :         GTIFKeySet(psGTIF, ProjNatOriginLatGeoKey, TYPE_DOUBLE, 1,
    1970               0 :                    poSRS->GetNormProjParm( SRS_PP_LATITUDE_OF_CENTER, 0.0 ) );
    1971                 : 
    1972                 :         GTIFKeySet(psGTIF, ProjNatOriginLongGeoKey, TYPE_DOUBLE, 1,
    1973               0 :                    poSRS->GetNormProjParm( SRS_PP_LONGITUDE_OF_CENTER, 0.0 ) );
    1974                 :         
    1975                 :         GTIFKeySet(psGTIF, ProjStdParallel1GeoKey, TYPE_DOUBLE, 1,
    1976               0 :                    poSRS->GetNormProjParm( SRS_PP_STANDARD_PARALLEL_1, 0.0 ) );
    1977                 :         
    1978                 :         GTIFKeySet(psGTIF, ProjStdParallel2GeoKey, TYPE_DOUBLE, 1,
    1979               0 :                    poSRS->GetNormProjParm( SRS_PP_STANDARD_PARALLEL_2, 0.0 ) );
    1980                 :         
    1981                 :         GTIFKeySet(psGTIF, ProjFalseEastingGeoKey, TYPE_DOUBLE, 1,
    1982               0 :                    poSRS->GetProjParm( SRS_PP_FALSE_EASTING, 0.0 ) );
    1983                 :         
    1984                 :         GTIFKeySet(psGTIF, ProjFalseNorthingGeoKey, TYPE_DOUBLE, 1,
    1985               0 :                    poSRS->GetProjParm( SRS_PP_FALSE_NORTHING, 0.0 ) );
    1986                 :     }
    1987                 :     
    1988               9 :     else if( EQUAL(pszProjection,SRS_PT_LAMBERT_CONFORMAL_CONIC_2SP) )
    1989                 :     {
    1990                 :         GTIFKeySet(psGTIF, GTModelTypeGeoKey, TYPE_SHORT, 1,
    1991               4 :                    ModelTypeProjected);
    1992                 :         GTIFKeySet(psGTIF, ProjectedCSTypeGeoKey, TYPE_SHORT, 1,
    1993               4 :                    KvUserDefined );
    1994                 :         GTIFKeySet(psGTIF, ProjectionGeoKey, TYPE_SHORT, 1,
    1995               4 :                    KvUserDefined );
    1996                 : 
    1997                 :         GTIFKeySet(psGTIF, ProjCoordTransGeoKey, TYPE_SHORT, 1, 
    1998               4 :                    CT_LambertConfConic_2SP );
    1999                 : 
    2000                 :         GTIFKeySet(psGTIF, ProjFalseOriginLatGeoKey, TYPE_DOUBLE, 1,
    2001               4 :                    poSRS->GetNormProjParm( SRS_PP_LATITUDE_OF_ORIGIN, 0.0 ) );
    2002                 : 
    2003                 :         GTIFKeySet(psGTIF, ProjFalseOriginLongGeoKey, TYPE_DOUBLE, 1,
    2004               4 :                    poSRS->GetNormProjParm( SRS_PP_CENTRAL_MERIDIAN, 0.0 ) );
    2005                 :         
    2006                 :         GTIFKeySet(psGTIF, ProjStdParallel1GeoKey, TYPE_DOUBLE, 1,
    2007               4 :                    poSRS->GetNormProjParm( SRS_PP_STANDARD_PARALLEL_1, 0.0 ) );
    2008                 :         
    2009                 :         GTIFKeySet(psGTIF, ProjStdParallel2GeoKey, TYPE_DOUBLE, 1,
    2010               4 :                    poSRS->GetNormProjParm( SRS_PP_STANDARD_PARALLEL_2, 0.0 ) );
    2011                 :         
    2012                 :         GTIFKeySet(psGTIF, ProjFalseOriginEastingGeoKey, TYPE_DOUBLE, 1,
    2013               4 :                    poSRS->GetProjParm( SRS_PP_FALSE_EASTING, 0.0 ) );
    2014                 :         
    2015                 :         GTIFKeySet(psGTIF, ProjFalseOriginNorthingGeoKey, TYPE_DOUBLE, 1,
    2016               4 :                    poSRS->GetProjParm( SRS_PP_FALSE_NORTHING, 0.0 ) );
    2017                 :     }
    2018                 :     
    2019               5 :     else if( EQUAL(pszProjection,SRS_PT_LAMBERT_CONFORMAL_CONIC_1SP) )
    2020                 :     {
    2021                 :         GTIFKeySet(psGTIF, GTModelTypeGeoKey, TYPE_SHORT, 1,
    2022               1 :                    ModelTypeProjected);
    2023                 :         GTIFKeySet(psGTIF, ProjectedCSTypeGeoKey, TYPE_SHORT, 1,
    2024               1 :                    KvUserDefined );
    2025                 :         GTIFKeySet(psGTIF, ProjectionGeoKey, TYPE_SHORT, 1,
    2026               1 :                    KvUserDefined );
    2027                 : 
    2028                 :         GTIFKeySet(psGTIF, ProjCoordTransGeoKey, TYPE_SHORT, 1, 
    2029               1 :                    CT_LambertConfConic_1SP );
    2030                 : 
    2031                 :         GTIFKeySet(psGTIF, ProjNatOriginLatGeoKey, TYPE_DOUBLE, 1,
    2032               1 :                    poSRS->GetNormProjParm( SRS_PP_LATITUDE_OF_ORIGIN, 0.0 ) );
    2033                 : 
    2034                 :         GTIFKeySet(psGTIF, ProjNatOriginLongGeoKey, TYPE_DOUBLE, 1,
    2035               1 :                    poSRS->GetNormProjParm( SRS_PP_CENTRAL_MERIDIAN, 0.0 ) );
    2036                 :         
    2037                 :         GTIFKeySet(psGTIF, ProjScaleAtNatOriginGeoKey, TYPE_DOUBLE, 1,
    2038               1 :                    poSRS->GetNormProjParm( SRS_PP_SCALE_FACTOR, 1.0 ) );
    2039                 :         
    2040                 :         GTIFKeySet(psGTIF, ProjFalseEastingGeoKey, TYPE_DOUBLE, 1,
    2041               1 :                    poSRS->GetProjParm( SRS_PP_FALSE_EASTING, 0.0 ) );
    2042                 :         
    2043                 :         GTIFKeySet(psGTIF, ProjFalseNorthingGeoKey, TYPE_DOUBLE, 1,
    2044               1 :                    poSRS->GetProjParm( SRS_PP_FALSE_NORTHING, 0.0 ) );
    2045                 :     }
    2046                 : 
    2047               4 :     else if( EQUAL(pszProjection,SRS_PT_CYLINDRICAL_EQUAL_AREA) )
    2048                 :     {
    2049                 :         GTIFKeySet(psGTIF, GTModelTypeGeoKey, TYPE_SHORT, 1,
    2050               2 :                    ModelTypeProjected);
    2051                 :         GTIFKeySet(psGTIF, ProjectedCSTypeGeoKey, TYPE_SHORT, 1,
    2052               2 :                    KvUserDefined );
    2053                 :         GTIFKeySet(psGTIF, ProjectionGeoKey, TYPE_SHORT, 1,
    2054               2 :                    KvUserDefined );
    2055                 : 
    2056                 :         GTIFKeySet(psGTIF, ProjCoordTransGeoKey, TYPE_SHORT, 1, 
    2057               2 :                    CT_CylindricalEqualArea );
    2058                 : 
    2059                 :         GTIFKeySet(psGTIF, ProjNatOriginLongGeoKey, TYPE_DOUBLE, 1,
    2060               2 :                    poSRS->GetNormProjParm( SRS_PP_CENTRAL_MERIDIAN, 0.0 ) );
    2061                 :         
    2062                 :         GTIFKeySet(psGTIF, ProjStdParallel1GeoKey, TYPE_DOUBLE, 1,
    2063               2 :                    poSRS->GetNormProjParm( SRS_PP_STANDARD_PARALLEL_1, 0.0 ) );
    2064                 :         
    2065                 :         GTIFKeySet(psGTIF, ProjFalseEastingGeoKey, TYPE_DOUBLE, 1,
    2066               2 :                    poSRS->GetProjParm( SRS_PP_FALSE_EASTING, 0.0 ) );
    2067                 :         
    2068                 :         GTIFKeySet(psGTIF, ProjFalseNorthingGeoKey, TYPE_DOUBLE, 1,
    2069               2 :                    poSRS->GetProjParm( SRS_PP_FALSE_NORTHING, 0.0 ) );
    2070                 :     }
    2071                 : 
    2072                 :     else
    2073                 :     {
    2074               2 :         bWritePEString = TRUE;
    2075                 :     }
    2076                 : 
    2077                 :     // Note that VERTCS is an ESRI "spelling" of VERT_CS so we assume if
    2078                 :     // we find it that we should try to treat this as a PE string.
    2079             928 :     bWritePEString |= (poSRS->GetAttrValue("VERTCS") != NULL);
    2080                 : 
    2081             928 :     if( bWritePEString 
    2082                 :         && CSLTestBoolean( CPLGetConfigOption("GTIFF_ESRI_CITATION",
    2083                 :                                               "YES") ) )
    2084                 :     {
    2085                 :         /* Anyhing we can't map, we store as an ESRI PE string with a citation key */
    2086               2 :         char *pszPEString = NULL;
    2087               2 :         poSRS->morphToESRI();
    2088               2 :         poSRS->exportToWkt( &pszPEString );
    2089               2 :         int peStrLen = strlen(pszPEString);
    2090               2 :         if(peStrLen > 0)
    2091                 :         {
    2092               2 :             char *outPeStr = (char *) CPLMalloc( peStrLen + strlen("ESRI PE String = ")+1 );
    2093               2 :             strcpy(outPeStr, "ESRI PE String = "); 
    2094               2 :             strcat(outPeStr, pszPEString); 
    2095               2 :             GTIFKeySet( psGTIF, PCSCitationGeoKey, TYPE_ASCII, 0, outPeStr ); 
    2096               2 :             peStrStored = TRUE;
    2097               2 :             CPLFree( outPeStr );
    2098                 :         }
    2099               2 :         if(pszPEString)
    2100               2 :             CPLFree( pszPEString );
    2101                 :         GTIFKeySet(psGTIF, GTModelTypeGeoKey, TYPE_SHORT, 1,
    2102               2 :                    KvUserDefined );
    2103                 :     }
    2104                 :     
    2105                 : /* -------------------------------------------------------------------- */
    2106                 : /*      Is there a false easting/northing set?  If so, write out a      */
    2107                 : /*      special geokey tag to indicate that GDAL has written these      */
    2108                 : /*      with the proper interpretation of the linear units.             */
    2109                 : /* -------------------------------------------------------------------- */
    2110             928 :     double dfFE = 0.0, dfFN = 0.0;
    2111                 : 
    2112             928 :     if( (GTIFKeyGet(psGTIF, ProjFalseEastingGeoKey, &dfFE, 0, 1)
    2113                 :          || GTIFKeyGet(psGTIF, ProjFalseNorthingGeoKey, &dfFN, 0, 1)
    2114                 :          || GTIFKeyGet(psGTIF, ProjFalseOriginEastingGeoKey, &dfFE, 0, 1)
    2115                 :          || GTIFKeyGet(psGTIF, ProjFalseOriginNorthingGeoKey, &dfFN, 0, 1))
    2116                 :         && (dfFE != 0.0 || dfFN != 0.0) 
    2117                 :         && nUOMLengthCode != 9001 )
    2118                 :     {
    2119                 :         GTIFKeySet(psGTIF, (geokey_t) ProjLinearUnitsInterpCorrectGeoKey, 
    2120               3 :                    TYPE_SHORT, 1, (short) 1 );
    2121                 :     }
    2122                 : 
    2123                 : /* -------------------------------------------------------------------- */
    2124                 : /*      Write linear units information.                                 */
    2125                 : /* -------------------------------------------------------------------- */
    2126             928 :     if( poSRS->IsGeocentric() )
    2127                 :     {
    2128                 :         GTIFKeySet(psGTIF, GeogLinearUnitsGeoKey, TYPE_SHORT, 1, 
    2129               0 :                    nUOMLengthCode );
    2130               0 :         if( nUOMLengthCode == KvUserDefined )
    2131                 :             GTIFKeySet( psGTIF, GeogLinearUnitSizeGeoKey, TYPE_DOUBLE, 1, 
    2132               0 :                         dfLinearUOM);
    2133                 :     }
    2134             928 :     else if( !poSRS->IsGeographic() )
    2135                 :     {
    2136                 :         GTIFKeySet(psGTIF, ProjLinearUnitsGeoKey, TYPE_SHORT, 1, 
    2137             263 :                    nUOMLengthCode );
    2138             263 :         if( nUOMLengthCode == KvUserDefined )
    2139                 :             GTIFKeySet( psGTIF, ProjLinearUnitSizeGeoKey, TYPE_DOUBLE, 1, 
    2140               1 :                         dfLinearUOM);
    2141                 : 
    2142                 :         /* if linear units name is available and user defined, store it as citation */
    2143             263 :         if(!peStrStored 
    2144                 :            && nUOMLengthCode == KvUserDefined 
    2145                 :            && pszLinearUOMName 
    2146                 :            && strlen(pszLinearUOMName)>0
    2147                 :            && CSLTestBoolean( CPLGetConfigOption("GTIFF_ESRI_CITATION",
    2148                 :                                                  "YES") ) )
    2149                 :         {
    2150               1 :             SetLinearUnitCitation(psGTIF, pszLinearUOMName);
    2151                 :         }
    2152                 :     }
    2153                 :     
    2154                 : /* -------------------------------------------------------------------- */
    2155                 : /*      Write angular units.  Always Degrees for now.                   */
    2156                 : /*   Changed to support different angular units                         */
    2157                 : /* -------------------------------------------------------------------- */
    2158                 : 
    2159             928 :     char* angUnitName = NULL;
    2160             928 :     double angUnitValue = poSRS->GetAngularUnits(&angUnitName);
    2161             928 :     if(EQUAL(angUnitName, "Degree"))
    2162                 :         GTIFKeySet(psGTIF, GeogAngularUnitsGeoKey, TYPE_SHORT, 1, 
    2163             927 :                    Angular_Degree );
    2164               1 :     else if(angUnitName)
    2165                 :     {
    2166                 :         GTIFKeySet(psGTIF, GeogCitationGeoKey, TYPE_ASCII, 0, 
    2167               1 :                    angUnitName ); // it may be rewritten if the gcs is userdefined 
    2168                 :         GTIFKeySet(psGTIF, GeogAngularUnitSizeGeoKey, TYPE_DOUBLE, 1, 
    2169               1 :                    angUnitValue );
    2170                 :     }
    2171                 : 
    2172                 : /* -------------------------------------------------------------------- */
    2173                 : /*      Try to write a citation from the main coordinate system         */
    2174                 : /*      name.                                                           */
    2175                 : /* -------------------------------------------------------------------- */
    2176             928 :     if( poSRS->GetRoot() != NULL
    2177                 :         && poSRS->GetRoot()->GetChild(0) != NULL 
    2178                 :         && (poSRS->IsProjected() || poSRS->IsLocal() || poSRS->IsGeocentric()) )
    2179                 :     {
    2180                 :         GTIFKeySet( psGTIF, GTCitationGeoKey, TYPE_ASCII, 0, 
    2181             263 :                     poSRS->GetRoot()->GetChild(0)->GetValue() );
    2182                 :     }
    2183                 : 
    2184                 : /* -------------------------------------------------------------------- */
    2185                 : /*      Try to write a GCS citation.                                    */
    2186                 : /* -------------------------------------------------------------------- */
    2187             928 :     OGR_SRSNode *poGCS = poSRS->GetAttrNode( "GEOGCS" );
    2188                 : 
    2189             928 :     if( poGCS != NULL && poGCS->GetChild(0) != NULL )
    2190                 :     {
    2191                 :         GTIFKeySet( psGTIF, GeogCitationGeoKey, TYPE_ASCII, 0, 
    2192             928 :                     poGCS->GetChild(0)->GetValue() );
    2193                 :     }
    2194                 : 
    2195                 : /* -------------------------------------------------------------------- */
    2196                 : /*      Try to identify the GCS/datum, scanning the EPSG datum file for */
    2197                 : /*      a match.                                                        */
    2198                 : /* -------------------------------------------------------------------- */
    2199             928 :     if( nPCS == KvUserDefined )
    2200                 :     {
    2201             703 :         if( nGCS == KvUserDefined )
    2202                 :         {
    2203             364 :             if( nDatum == Datum_North_American_Datum_1927 )
    2204               0 :                 nGCS = GCS_NAD27;
    2205             364 :             else if( nDatum == Datum_North_American_Datum_1983 )
    2206               1 :                 nGCS = GCS_NAD83;
    2207             363 :             else if( nDatum == Datum_WGS84 || nDatum == DatumE_WGS84 )
    2208             335 :                 nGCS = GCS_WGS_84;
    2209                 :         }
    2210                 :             
    2211             703 :         if( nGCS != KvUserDefined )
    2212                 :         {
    2213                 :             GTIFKeySet( psGTIF, GeographicTypeGeoKey, TYPE_SHORT,
    2214             675 :                         1, nGCS );
    2215                 :         }
    2216              28 :         else if( nDatum != KvUserDefined )
    2217                 :         {
    2218                 :             GTIFKeySet( psGTIF, GeographicTypeGeoKey, TYPE_SHORT, 1, 
    2219               3 :                         KvUserDefined );
    2220                 :             GTIFKeySet( psGTIF, GeogGeodeticDatumGeoKey, TYPE_SHORT,
    2221               3 :                         1, nDatum );
    2222                 :         }
    2223              25 :         else if( nSpheroid != KvUserDefined )
    2224                 :         {
    2225                 :             GTIFKeySet( psGTIF, GeographicTypeGeoKey, TYPE_SHORT, 1, 
    2226               0 :                         KvUserDefined );
    2227                 :             GTIFKeySet( psGTIF, GeogGeodeticDatumGeoKey, TYPE_SHORT,
    2228               0 :                         1, KvUserDefined );
    2229                 :             GTIFKeySet( psGTIF, GeogEllipsoidGeoKey, TYPE_SHORT, 1, 
    2230               0 :                         nSpheroid );
    2231                 :         }
    2232              25 :         else if( dfSemiMajor != 0.0 )
    2233                 :         {
    2234                 :             GTIFKeySet( psGTIF, GeographicTypeGeoKey, TYPE_SHORT, 1, 
    2235              25 :                         KvUserDefined );
    2236                 :             GTIFKeySet( psGTIF, GeogGeodeticDatumGeoKey, TYPE_SHORT,
    2237              25 :                         1, KvUserDefined );
    2238                 :             GTIFKeySet( psGTIF, GeogEllipsoidGeoKey, TYPE_SHORT, 1, 
    2239              25 :                         KvUserDefined );
    2240                 :             GTIFKeySet( psGTIF, GeogSemiMajorAxisGeoKey, TYPE_DOUBLE, 1,
    2241              25 :                         dfSemiMajor );
    2242              25 :             if( dfInvFlattening == 0.0 )
    2243                 :                 GTIFKeySet( psGTIF, GeogSemiMinorAxisGeoKey, TYPE_DOUBLE, 1,
    2244               3 :                             dfSemiMajor );
    2245                 :             else
    2246                 :                 GTIFKeySet( psGTIF, GeogInvFlatteningGeoKey, TYPE_DOUBLE, 1,
    2247              22 :                             dfInvFlattening );
    2248                 :         }
    2249               0 :         else if( poSRS->GetAttrValue("DATUM") != NULL
    2250                 :                  && strstr(poSRS->GetAttrValue("DATUM"),"unknown") == NULL
    2251                 :                  && strstr(poSRS->GetAttrValue("DATUM"),"unnamed") == NULL )
    2252                 :                  
    2253                 :         {
    2254                 :             CPLError( CE_Warning, CPLE_AppDefined,
    2255                 :                       "Couldn't translate `%s' to a GeoTIFF datum.\n",
    2256               0 :                       poSRS->GetAttrValue("DATUM") );
    2257                 :         }
    2258                 : 
    2259                 :         /* Always set InvFlattening if it is avaliable.  */
    2260                 :         /* So that it doesn'tneed to calculate from SemiMinor */
    2261             703 :         if( dfInvFlattening != 0.0 )
    2262                 :             GTIFKeySet( psGTIF, GeogInvFlatteningGeoKey, TYPE_DOUBLE, 1,
    2263             697 :                         dfInvFlattening );
    2264                 :         /* Always set SemiMajor to keep the precision and in case of editing */
    2265             703 :         if( dfSemiMajor != 0.0 )
    2266                 :             GTIFKeySet( psGTIF, GeogSemiMajorAxisGeoKey, TYPE_DOUBLE, 1,
    2267             700 :                         dfSemiMajor );
    2268                 : 
    2269             703 :         if( nGCS == KvUserDefined 
    2270                 :             && CSLTestBoolean( CPLGetConfigOption("GTIFF_ESRI_CITATION",
    2271                 :                                                   "YES") ) )
    2272              28 :             SetGeogCSCitation(psGTIF, poSRS, angUnitName, nDatum, nSpheroid);
    2273                 :     }
    2274                 : 
    2275                 : /* -------------------------------------------------------------------- */
    2276                 : /*      Do we have TOWGS84 parameters?                                  */
    2277                 : /* -------------------------------------------------------------------- */
    2278                 : 
    2279                 : #if LIBGEOTIFF_VERSION >= 1310 && !defined(GEO_NORMALIZE_DISABLE_TOWGS84)
    2280                 :     double adfTOWGS84[7];
    2281                 : 
    2282             928 :     if( poSRS->GetTOWGS84( adfTOWGS84 ) == OGRERR_NONE )
    2283                 :     {
    2284             218 :         if( adfTOWGS84[3] == 0.0 && adfTOWGS84[4] == 0.0
    2285             108 :             && adfTOWGS84[5] == 0.0 && adfTOWGS84[6] == 0.0 )
    2286                 :         {
    2287             111 :             if( nGCS == GCS_WGS_84 && adfTOWGS84[0] == 0.0
    2288              58 :                 && adfTOWGS84[1] == 0.0 && adfTOWGS84[2] == 0.0 )
    2289                 :             {
    2290                 :                 ; /* do nothing */
    2291                 :             }
    2292                 :             else
    2293                 :                 GTIFKeySet( psGTIF, GeogTOWGS84GeoKey, TYPE_DOUBLE, 3,
    2294              24 :                             adfTOWGS84 );
    2295                 :         }
    2296                 :         else
    2297                 :             GTIFKeySet( psGTIF, GeogTOWGS84GeoKey, TYPE_DOUBLE, 7, 
    2298               4 :                         adfTOWGS84 );
    2299                 :     }
    2300                 : #endif
    2301                 : 
    2302                 : /* -------------------------------------------------------------------- */
    2303                 : /*      Do we have vertical datum information to set?                   */
    2304                 : /* -------------------------------------------------------------------- */
    2305             928 :     if( poSRS->GetAttrValue( "COMPD_CS|VERT_CS" ) != NULL )
    2306                 :     {
    2307                 :         const char *pszValue;
    2308                 : 
    2309                 :         GTIFKeySet( psGTIF, VerticalCitationGeoKey, TYPE_ASCII, 0, 
    2310               1 :                     poSRS->GetAttrValue( "COMPD_CS|VERT_CS" ) );
    2311                 : 
    2312               1 :         pszValue = poSRS->GetAuthorityCode( "COMPD_CS|VERT_CS" );
    2313               1 :         if( pszValue && atoi(pszValue) )
    2314                 :             GTIFKeySet( psGTIF, VerticalCSTypeGeoKey, TYPE_SHORT, 1,
    2315               1 :                         atoi(pszValue) );
    2316                 :         
    2317               1 :         pszValue = poSRS->GetAuthorityCode( "COMPD_CS|VERT_CS|VERT_DATUM" );
    2318               1 :         if( pszValue && atoi(pszValue) )
    2319                 :             GTIFKeySet( psGTIF, VerticalDatumGeoKey, TYPE_SHORT, 1,
    2320               1 :                         atoi(pszValue) );
    2321                 :         
    2322               1 :         pszValue = poSRS->GetAuthorityCode( "COMPD_CS|VERT_CS|UNIT" );
    2323               1 :         if( pszValue && atoi(pszValue) )
    2324                 :             GTIFKeySet( psGTIF, VerticalUnitsGeoKey, TYPE_SHORT, 1,
    2325               1 :                         atoi(pszValue) );
    2326                 :     }
    2327                 : 
    2328                 : /* -------------------------------------------------------------------- */
    2329                 : /*      Cleanup                                                         */
    2330                 : /* -------------------------------------------------------------------- */
    2331             928 :     delete poSRS;
    2332             928 :     return TRUE;
    2333                 : }
    2334                 : 
    2335                 : /************************************************************************/
    2336                 : /*                         GTIFWktFromMemBuf()                          */
    2337                 : /************************************************************************/
    2338                 : 
    2339              74 : CPLErr GTIFWktFromMemBuf( int nSize, unsigned char *pabyBuffer, 
    2340                 :                           char **ppszWKT, double *padfGeoTransform,
    2341                 :                           int *pnGCPCount, GDAL_GCP **ppasGCPList )
    2342                 : 
    2343                 : {
    2344                 :     char szFilename[100];
    2345                 : 
    2346                 :     sprintf( szFilename, "/vsimem/wkt_from_mem_buf_%ld.tif",
    2347              74 :              (long) CPLGetPID() );
    2348                 : 
    2349                 : /* -------------------------------------------------------------------- */
    2350                 : /*      Create a memory file from the buffer.                           */
    2351                 : /* -------------------------------------------------------------------- */
    2352              74 :     VSILFILE *fp = VSIFileFromMemBuffer( szFilename, pabyBuffer, nSize, FALSE );
    2353              74 :     if( fp == NULL )
    2354               0 :         return CE_Failure;
    2355              74 :     VSIFCloseL( fp );
    2356                 : 
    2357                 : /* -------------------------------------------------------------------- */
    2358                 : /*      Initialize access to the memory geotiff structure.              */
    2359                 : /* -------------------------------------------------------------------- */
    2360                 :     TIFF        *hTIFF;
    2361              74 :     hTIFF = VSI_TIFFOpen( szFilename, "rc" );
    2362                 : 
    2363              74 :     if( hTIFF == NULL )
    2364                 :     {
    2365                 :         CPLError( CE_Failure, CPLE_AppDefined,
    2366               0 :                   "TIFF/GeoTIFF structure is corrupt." );
    2367               0 :         VSIUnlink( szFilename );
    2368               0 :         return CE_Failure;
    2369                 :     }
    2370                 :     
    2371                 : /* -------------------------------------------------------------------- */
    2372                 : /*      Get the projection definition.                                  */
    2373                 : /* -------------------------------------------------------------------- */
    2374                 :     GTIF  *hGTIF;
    2375                 :     GTIFDefn    *psGTIFDefn;
    2376                 : 
    2377              74 :     hGTIF = GTIFNew(hTIFF);
    2378                 : 
    2379                 : #if LIBGEOTIFF_VERSION >= 1410
    2380                 :     psGTIFDefn = GTIFAllocDefn();
    2381                 : #else
    2382              74 :     psGTIFDefn = (GTIFDefn *) CPLCalloc(1,sizeof(GTIFDefn));
    2383                 : #endif    
    2384                 : 
    2385              74 :     if( hGTIF != NULL && GTIFGetDefn( hGTIF, psGTIFDefn ) )
    2386              74 :         *ppszWKT = GTIFGetOGISDefn( hGTIF, psGTIFDefn );
    2387                 :     else
    2388               0 :         *ppszWKT = NULL;
    2389                 :     
    2390              74 :     if( hGTIF )
    2391              74 :         GTIFFree( hGTIF );
    2392                 :     
    2393                 : #if LIBGEOTIFF_VERSION >= 1410
    2394                 :     GTIFFreeDefn(psGTIFDefn);
    2395                 : #else
    2396              74 :     CPLFree(psGTIFDefn);
    2397                 : #endif    
    2398                 : 
    2399                 : /* -------------------------------------------------------------------- */
    2400                 : /*      Get geotransform or tiepoints.                                  */
    2401                 : /* -------------------------------------------------------------------- */
    2402                 :     double  *padfTiePoints, *padfScale, *padfMatrix;
    2403                 :     int16 nCount;
    2404                 : 
    2405              74 :     padfGeoTransform[0] = 0.0;
    2406              74 :     padfGeoTransform[1] = 1.0;
    2407              74 :     padfGeoTransform[2] = 0.0;
    2408              74 :     padfGeoTransform[3] = 0.0;
    2409              74 :     padfGeoTransform[4] = 0.0;
    2410              74 :     padfGeoTransform[5] = 1.0;
    2411                 : 
    2412              74 :     *pnGCPCount = 0;
    2413              74 :     *ppasGCPList = NULL;
    2414                 :     
    2415              74 :     if( TIFFGetField(hTIFF,TIFFTAG_GEOPIXELSCALE,&nCount,&padfScale )
    2416                 :         && nCount >= 2 )
    2417                 :     {
    2418              64 :         padfGeoTransform[1] = padfScale[0];
    2419              64 :         padfGeoTransform[5] = - ABS(padfScale[1]);
    2420                 : 
    2421              64 :         if( TIFFGetField(hTIFF,TIFFTAG_GEOTIEPOINTS,&nCount,&padfTiePoints )
    2422                 :             && nCount >= 6 )
    2423                 :         {
    2424                 :             padfGeoTransform[0] =
    2425              64 :                 padfTiePoints[3] - padfTiePoints[0] * padfGeoTransform[1];
    2426              64 :             padfGeoTransform[3] =
    2427              64 :                 padfTiePoints[4] - padfTiePoints[1] * padfGeoTransform[5];
    2428                 :         }
    2429                 :     }
    2430                 : 
    2431              10 :     else if( TIFFGetField(hTIFF,TIFFTAG_GEOTIEPOINTS,&nCount,&padfTiePoints )
    2432                 :              && nCount >= 6 )
    2433                 :     {
    2434              10 :         *pnGCPCount = nCount / 6;
    2435              10 :         *ppasGCPList = (GDAL_GCP *) CPLCalloc(sizeof(GDAL_GCP),*pnGCPCount);
    2436                 :         
    2437             138 :         for( int iGCP = 0; iGCP < *pnGCPCount; iGCP++ )
    2438                 :         {
    2439                 :             char  szID[32];
    2440             128 :             GDAL_GCP  *psGCP = *ppasGCPList + iGCP;
    2441                 : 
    2442             128 :             sprintf( szID, "%d", iGCP+1 );
    2443             128 :             psGCP->pszId = CPLStrdup( szID );
    2444             128 :             psGCP->pszInfo = CPLStrdup("");
    2445             128 :             psGCP->dfGCPPixel = padfTiePoints[iGCP*6+0];
    2446             128 :             psGCP->dfGCPLine = padfTiePoints[iGCP*6+1];
    2447             128 :             psGCP->dfGCPX = padfTiePoints[iGCP*6+3];
    2448             128 :             psGCP->dfGCPY = padfTiePoints[iGCP*6+4];
    2449             128 :             psGCP->dfGCPZ = padfTiePoints[iGCP*6+5];
    2450                 :         }
    2451                 :     }
    2452                 : 
    2453               0 :     else if( TIFFGetField(hTIFF,TIFFTAG_GEOTRANSMATRIX,&nCount,&padfMatrix ) 
    2454                 :              && nCount == 16 )
    2455                 :     {
    2456               0 :         padfGeoTransform[0] = padfMatrix[3];
    2457               0 :         padfGeoTransform[1] = padfMatrix[0];
    2458               0 :         padfGeoTransform[2] = padfMatrix[1];
    2459               0 :         padfGeoTransform[3] = padfMatrix[7];
    2460               0 :         padfGeoTransform[4] = padfMatrix[4];
    2461               0 :         padfGeoTransform[5] = padfMatrix[5];
    2462                 :     }
    2463                 : 
    2464                 : /* -------------------------------------------------------------------- */
    2465                 : /*      Cleanup.                                                        */
    2466                 : /* -------------------------------------------------------------------- */
    2467              74 :     XTIFFClose( hTIFF );
    2468                 : 
    2469              74 :     VSIUnlink( szFilename );
    2470                 : 
    2471              74 :     if( *ppszWKT == NULL )
    2472               0 :         return CE_Failure;
    2473                 :     else
    2474              74 :         return CE_None;
    2475                 : }
    2476                 : 
    2477                 : /************************************************************************/
    2478                 : /*                         GTIFMemBufFromWkt()                          */
    2479                 : /************************************************************************/
    2480                 : 
    2481              32 : CPLErr GTIFMemBufFromWkt( const char *pszWKT, const double *padfGeoTransform,
    2482                 :                           int nGCPCount, const GDAL_GCP *pasGCPList,
    2483                 :                           int *pnSize, unsigned char **ppabyBuffer )
    2484                 : 
    2485                 : {
    2486                 :     TIFF        *hTIFF;
    2487                 :     GTIF  *hGTIF;
    2488                 :     char        szFilename[100];
    2489                 : 
    2490                 :     sprintf( szFilename, "/vsimem/wkt_from_mem_buf_%ld.tif", 
    2491              32 :              (long) CPLGetPID() );
    2492                 : 
    2493                 : /* -------------------------------------------------------------------- */
    2494                 : /*      Initialize access to the memory geotiff structure.              */
    2495                 : /* -------------------------------------------------------------------- */
    2496              32 :     hTIFF = VSI_TIFFOpen( szFilename, "w" );
    2497                 : 
    2498              32 :     if( hTIFF == NULL )
    2499                 :     {
    2500                 :         CPLError( CE_Failure, CPLE_AppDefined,
    2501               0 :                   "TIFF/GeoTIFF structure is corrupt." );
    2502               0 :         return CE_Failure;
    2503                 :     }
    2504                 : 
    2505                 : /* -------------------------------------------------------------------- */
    2506                 : /*      Write some minimal set of image parameters.                     */
    2507                 : /* -------------------------------------------------------------------- */
    2508              32 :     TIFFSetField( hTIFF, TIFFTAG_IMAGEWIDTH, 1 );
    2509              32 :     TIFFSetField( hTIFF, TIFFTAG_IMAGELENGTH, 1 );
    2510              32 :     TIFFSetField( hTIFF, TIFFTAG_BITSPERSAMPLE, 8 );
    2511              32 :     TIFFSetField( hTIFF, TIFFTAG_SAMPLESPERPIXEL, 1 );
    2512              32 :     TIFFSetField( hTIFF, TIFFTAG_ROWSPERSTRIP, 1 );
    2513              32 :     TIFFSetField( hTIFF, TIFFTAG_PLANARCONFIG, PLANARCONFIG_CONTIG );
    2514              32 :     TIFFSetField( hTIFF, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_MINISBLACK );
    2515                 :     
    2516                 : /* -------------------------------------------------------------------- */
    2517                 : /*      Get the projection definition.                                  */
    2518                 : /* -------------------------------------------------------------------- */
    2519                 : 
    2520              32 :     if( pszWKT != NULL )
    2521                 :     {
    2522              32 :         hGTIF = GTIFNew(hTIFF);
    2523              32 :         GTIFSetFromOGISDefn( hGTIF, pszWKT );
    2524              32 :         GTIFWriteKeys( hGTIF );
    2525              32 :         GTIFFree( hGTIF );
    2526                 :     }
    2527                 : 
    2528                 : /* -------------------------------------------------------------------- */
    2529                 : /*      Set the geotransform, or GCPs.                                  */
    2530                 : /* -------------------------------------------------------------------- */
    2531              72 :     if( padfGeoTransform[0] != 0.0 || padfGeoTransform[1] != 1.0
    2532               4 :         || padfGeoTransform[2] != 0.0 || padfGeoTransform[3] != 0.0
    2533               6 :         || padfGeoTransform[4] != 0.0 || ABS(padfGeoTransform[5]) != 1.0 )
    2534                 :     {
    2535                 : 
    2536              60 :         if( padfGeoTransform[2] == 0.0 && padfGeoTransform[4] == 0.0 )
    2537                 :         {
    2538                 :             double  adfPixelScale[3], adfTiePoints[6];
    2539                 : 
    2540              30 :             adfPixelScale[0] = padfGeoTransform[1];
    2541              30 :             adfPixelScale[1] = fabs(padfGeoTransform[5]);
    2542              30 :             adfPixelScale[2] = 0.0;
    2543                 : 
    2544              30 :             TIFFSetField( hTIFF, TIFFTAG_GEOPIXELSCALE, 3, adfPixelScale );
    2545                 :             
    2546              30 :             adfTiePoints[0] = 0.0;
    2547              30 :             adfTiePoints[1] = 0.0;
    2548              30 :             adfTiePoints[2] = 0.0;
    2549              30 :             adfTiePoints[3] = padfGeoTransform[0];
    2550              30 :             adfTiePoints[4] = padfGeoTransform[3];
    2551              30 :             adfTiePoints[5] = 0.0;
    2552                 :         
    2553              30 :             TIFFSetField( hTIFF, TIFFTAG_GEOTIEPOINTS, 6, adfTiePoints );
    2554                 :         }
    2555                 :         else
    2556                 :         {
    2557                 :             double  adfMatrix[16];
    2558                 : 
    2559               0 :             memset(adfMatrix,0,sizeof(double) * 16);
    2560                 : 
    2561               0 :             adfMatrix[0] = padfGeoTransform[1];
    2562               0 :             adfMatrix[1] = padfGeoTransform[2];
    2563               0 :             adfMatrix[3] = padfGeoTransform[0];
    2564               0 :             adfMatrix[4] = padfGeoTransform[4];
    2565               0 :             adfMatrix[5] = padfGeoTransform[5];
    2566               0 :             adfMatrix[7] = padfGeoTransform[3];
    2567               0 :             adfMatrix[15] = 1.0;
    2568                 : 
    2569               0 :             TIFFSetField( hTIFF, TIFFTAG_GEOTRANSMATRIX, 16, adfMatrix );
    2570                 :         }
    2571                 :     }
    2572                 : 
    2573                 : /* -------------------------------------------------------------------- */
    2574                 : /*      Otherwise write tiepoints if they are available.                */
    2575                 : /* -------------------------------------------------------------------- */
    2576               2 :     else if( nGCPCount > 0 )
    2577                 :     {
    2578                 :         double  *padfTiePoints;
    2579                 : 
    2580               1 :         padfTiePoints = (double *) CPLMalloc(6*sizeof(double)*nGCPCount);
    2581                 : 
    2582               5 :         for( int iGCP = 0; iGCP < nGCPCount; iGCP++ )
    2583                 :         {
    2584                 : 
    2585               4 :             padfTiePoints[iGCP*6+0] = pasGCPList[iGCP].dfGCPPixel;
    2586               4 :             padfTiePoints[iGCP*6+1] = pasGCPList[iGCP].dfGCPLine;
    2587               4 :             padfTiePoints[iGCP*6+2] = 0;
    2588               4 :             padfTiePoints[iGCP*6+3] = pasGCPList[iGCP].dfGCPX;
    2589               4 :             padfTiePoints[iGCP*6+4] = pasGCPList[iGCP].dfGCPY;
    2590               4 :             padfTiePoints[iGCP*6+5] = pasGCPList[iGCP].dfGCPZ;
    2591                 :         }
    2592                 : 
    2593               1 :         TIFFSetField( hTIFF, TIFFTAG_GEOTIEPOINTS, 6*nGCPCount, padfTiePoints);
    2594               1 :         CPLFree( padfTiePoints );
    2595                 :     } 
    2596                 : 
    2597                 : /* -------------------------------------------------------------------- */
    2598                 : /*      Cleanup and return the created memory buffer.                   */
    2599                 : /* -------------------------------------------------------------------- */
    2600              32 :     GByte bySmallImage = 0;
    2601                 : 
    2602              32 :     TIFFWriteEncodedStrip( hTIFF, 0, (char *) &bySmallImage, 1 );
    2603              32 :     TIFFWriteCheck( hTIFF, TIFFIsTiled(hTIFF), "GTIFMemBufFromWkt");
    2604              32 :     TIFFWriteDirectory( hTIFF );
    2605                 : 
    2606              32 :     XTIFFClose( hTIFF );
    2607                 : 
    2608                 : /* -------------------------------------------------------------------- */
    2609                 : /*      Read back from the memory buffer.  It would be preferrable      */
    2610                 : /*      to be able to "steal" the memory buffer, but there isn't        */
    2611                 : /*      currently any support for this.                                 */
    2612                 : /* -------------------------------------------------------------------- */
    2613                 :     GUIntBig nBigLength;
    2614                 : 
    2615              32 :     *ppabyBuffer = VSIGetMemFileBuffer( szFilename, &nBigLength, TRUE );
    2616              32 :     *pnSize = (int) nBigLength;
    2617                 : 
    2618              32 :     return CE_None;
    2619                 : }

Generated by: LCOV version 1.7