LCOV - code coverage report
Current view: directory - frmts/gtiff - gt_wkt_srs.cpp (source / functions) Found Hit Coverage
Test: gdal_filtered.info Lines: 805 436 54.2 %
Date: 2010-01-09 Functions: 7 7 100.0 %

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

Generated by: LCOV version 1.7