LCOV - code coverage report
Current view: directory - frmts/gtiff - gt_wkt_srs.cpp (source / functions) Found Hit Coverage
Test: gdal_filtered.info Lines: 923 705 76.4 %
Date: 2013-03-30 Functions: 10 10 100.0 %

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

Generated by: LCOV version 1.7