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

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

Generated by: LCOV version 1.7