LTP GCOV extension - code coverage report
Current view: directory - frmts/gtiff - gt_wkt_srs.cpp
Test: gdal_filtered.info
Date: 2010-07-12 Instrumented lines: 811
Code covered: 47.6 % Executed lines: 386

       1                 : /******************************************************************************
       2                 :  * $Id: gt_wkt_srs.cpp 18584 2010-01-19 04:24:54Z 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 18584 2010-01-19 04:24:54Z 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            5057 : 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            5057 :     pszDatum = CPLStrdup(*ppszDatum);
     124            5057 :     GTIFFreeMemory( *ppszDatum );
     125            5057 :     *ppszDatum = pszDatum;
     126            5057 :     if (pszDatum[0] == '\0')
     127               0 :         return;
     128                 : 
     129                 : /* -------------------------------------------------------------------- */
     130                 : /*      Translate non-alphanumeric values to underscores.               */
     131                 : /* -------------------------------------------------------------------- */
     132          112846 :     for( i = 0; pszDatum[i] != '\0'; i++ )
     133                 :     {
     134          107789 :         if( pszDatum[i] != '+'
     135                 :             && !(pszDatum[i] >= 'A' && pszDatum[i] <= 'Z')
     136                 :             && !(pszDatum[i] >= 'a' && pszDatum[i] <= 'z')
     137                 :             && !(pszDatum[i] >= '0' && pszDatum[i] <= '9') )
     138                 :         {
     139           12992 :             pszDatum[i] = '_';
     140                 :         }
     141                 :     }
     142                 : 
     143                 : /* -------------------------------------------------------------------- */
     144                 : /*      Remove repeated and trailing underscores.                       */
     145                 : /* -------------------------------------------------------------------- */
     146          107789 :     for( i = 1, j = 0; pszDatum[i] != '\0'; i++ )
     147                 :     {
     148          102732 :         if( pszDatum[j] == '_' && pszDatum[i] == '_' )
     149             806 :             continue;
     150                 : 
     151          101926 :         pszDatum[++j] = pszDatum[i];
     152                 :     }
     153            5057 :     if( pszDatum[j] == '_' )
     154             582 :         pszDatum[j] = '\0';
     155                 :     else
     156            4475 :         pszDatum[j+1] = '\0';
     157                 :     
     158                 : /* -------------------------------------------------------------------- */
     159                 : /*      Search for datum equivelences.  Specific massaged names get     */
     160                 : /*      mapped to OpenGIS specified names.                              */
     161                 : /* -------------------------------------------------------------------- */
     162           27656 :     for( i = 0; papszDatumEquiv[i] != NULL; i += 2 )
     163                 :     {
     164           23275 :         if( EQUAL(*ppszDatum,papszDatumEquiv[i]) )
     165                 :         {
     166             676 :             CPLFree( *ppszDatum );
     167             676 :             *ppszDatum = CPLStrdup( papszDatumEquiv[i+1] );
     168             676 :             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: 18584 $ $Date: 2010-01-19 05:24:54 +0100 (mar 19 jan 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: 18584 $ $Date: 2010-01-19 05:24:54 +0100 (mar 19 jan 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: 18584 $ $Date: 2010-01-19 05:24:54 +0100 (mar 19 jan 2010) $\nUTM Zone 10N\nEllipsoid = Clarke 1866\nDatum = NAD27 (CONUS)"
     188                 :  
     189                 : */
     190                 : 
     191               8 : static void GTIFCleanupImagineNames( char *pszCitation )
     192                 : 
     193                 : {
     194               8 :     if( strstr(pszCitation,"IMAGINE GeoTIFF") == NULL )
     195               8 :         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             998 : char *GTIFGetOGISDefn( GTIF *hGTIF, GTIFDefn * psDefn )
     230                 : 
     231                 : {
     232             998 :     OGRSpatialReference oSRS;
     233                 : 
     234                 : /* -------------------------------------------------------------------- */
     235                 : /*  Handle non-standard coordinate systems where GTModelTypeGeoKey      */
     236                 : /*  is not defined, but ProjectedCSTypeGeoKey is defined (ticket #3019) */
     237                 : /* -------------------------------------------------------------------- */
     238             998 :     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             998 :     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               8 :         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               8 :           char  *pszUnitsName = NULL;
     262                 :           char    szPCSName[300];
     263               8 :           int     nKeyCount = 0;
     264                 :           int     anVersion[3];
     265                 : 
     266               8 :           if( hGTIF != NULL )
     267               8 :               GTIFDirectoryInfo( hGTIF, anVersion, &nKeyCount );
     268                 : 
     269               8 :           if( nKeyCount > 0 ) // Use LOCAL_CS if we have any geokeys at all.
     270                 :           {
     271                 :               // Handle citation.
     272               8 :               strcpy( szPCSName, "unnamed" );
     273               8 :               if( !GTIFKeyGet( hGTIF, GTCitationGeoKey, szPCSName, 
     274                 :                                0, sizeof(szPCSName) ) )
     275                 :                   GTIFKeyGet( hGTIF, GeogCitationGeoKey, szPCSName, 
     276               0 :                               0, sizeof(szPCSName) );
     277                 : 
     278               8 :               GTIFCleanupImagineNames( szPCSName );
     279               8 :               oSRS.SetLocalCS( szPCSName );
     280                 : 
     281                 :               // Handle units
     282               8 :               GTIFGetUOMLengthInfo( psDefn->UOMLength, &pszUnitsName, NULL );
     283                 :               
     284               8 :               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               8 :                   oSRS.SetLinearUnits( "unknown", psDefn->UOMLengthInMeters );
     291                 : 
     292               8 :               GTIFFreeMemory( pszUnitsName );
     293                 :           }
     294               8 :           oSRS.exportToWkt( &pszWKT );
     295                 : 
     296               8 :           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             990 :     OGRBoolean linearUnitIsSet = FALSE;
     305             990 :     if( psDefn->Model == ModelTypeProjected )
     306                 :     {
     307                 :         char        szCTString[512];
     308             375 :         strcpy( szCTString, "unnamed" );
     309             375 :         if( psDefn->PCS != KvUserDefined )
     310                 :         {
     311             371 :             char    *pszPCSName = NULL;
     312                 : 
     313             371 :             GTIFGetPCSInfo( psDefn->PCS, &pszPCSName, NULL, NULL, NULL );
     314                 :             
     315             371 :             oSRS.SetNode( "PROJCS", pszPCSName ? pszPCSName : "unnamed" );
     316             371 :             if ( pszPCSName )
     317             371 :                 GTIFFreeMemory( pszPCSName );
     318                 : 
     319             371 :             oSRS.SetAuthority( "PROJCS", "EPSG", psDefn->PCS );
     320                 :         }
     321               4 :         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               4 :           if( hGTIF )
     331                 :           {
     332               4 :             GTIFKeyGet( hGTIF, GTCitationGeoKey, szCTString, 0, sizeof(szCTString) );
     333               4 :             if(!SetCitationToSRS(hGTIF, szCTString, sizeof(szCTString),
     334                 :                                  GTCitationGeoKey, &oSRS, &linearUnitIsSet))
     335               4 :               oSRS.SetNode( "PROJCS", szCTString );
     336                 :           }
     337                 :           else
     338               0 :             oSRS.SetNode( "PROJCS", szCTString );
     339                 :         }
     340                 :     }
     341                 :     
     342                 : /* ==================================================================== */
     343                 : /*      Setup the GeogCS                                                */
     344                 : /* ==================================================================== */
     345             990 :     char  *pszGeogName = NULL;
     346             990 :     char  *pszDatumName = NULL;
     347             990 :     char  *pszPMName = NULL;
     348             990 :     char  *pszSpheroidName = NULL;
     349             990 :     char  *pszAngularUnits = NULL;
     350             990 :     double  dfInvFlattening=0.0, dfSemiMajor=0.0;
     351                 :     char  szGCSName[512];
     352             990 :     OGRBoolean aUnitGot = FALSE;
     353                 :     
     354             990 :     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               7 :                           &pszAngularUnits);
     363                 : 
     364             990 :     if( !pszDatumName )
     365             985 :       GTIFGetDatumInfo( psDefn->Datum, &pszDatumName, NULL );
     366             990 :     if( !pszSpheroidName )
     367             985 :       GTIFGetEllipsoidInfo( psDefn->Ellipsoid, &pszSpheroidName, NULL, NULL );
     368                 :     else
     369                 :     {
     370               5 :       GTIFKeyGet(hGTIF, GeogSemiMajorAxisGeoKey, &(psDefn->SemiMajor), 0, 1 );
     371               5 :       GTIFKeyGet(hGTIF, GeogInvFlatteningGeoKey, &dfInvFlattening, 0, 1 );
     372                 :     }
     373             990 :     if( !pszPMName )
     374             985 :       GTIFGetPMInfo( psDefn->PM, &pszPMName, NULL );
     375                 :     else
     376               5 :       GTIFKeyGet(hGTIF, GeogPrimeMeridianLongGeoKey, &(psDefn->PMLongToGreenwich), 0, 1 );
     377                 :     
     378             990 :     if( !pszAngularUnits )
     379                 :     {
     380             990 :       GTIFGetUOMAngleInfo( psDefn->UOMAngle, &pszAngularUnits, NULL );
     381             990 :       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             990 :     if( pszDatumName != NULL )            /* was a GTIFFreeMemory'able string */
     391             990 :         WKTMassageDatum( &pszDatumName ); /* now a CPLFree'able string */
     392                 : 
     393             990 :     dfSemiMajor = psDefn->SemiMajor;
     394             990 :     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             990 :     else if( dfInvFlattening == 0.0 && ((psDefn->SemiMinor / psDefn->SemiMajor) < 0.99999999999999999
     401                 :              || (psDefn->SemiMinor / psDefn->SemiMajor) > 1.00000000000000001 ) )
     402                 :     {
     403             985 :           dfInvFlattening = -1.0 / (psDefn->SemiMinor/psDefn->SemiMajor - 1.0);
     404                 : 
     405                 :           /* Take official inverse flattening definition in the WGS84 case */
     406             985 :           if (dfSemiMajor == SRS_WGS84_SEMIMAJOR &&
     407                 :               fabs(dfInvFlattening - SRS_WGS84_INVFLATTENING) < 1e-10)
     408             646 :               dfInvFlattening = SRS_WGS84_INVFLATTENING;
     409                 :     }
     410             990 :     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             990 :     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             990 :                       psDefn->UOMAngleInDegrees * 0.0174532925199433 );
     429                 : 
     430             990 :     if( psDefn->GCS != KvUserDefined && psDefn->GCS > 0 )
     431             983 :         oSRS.SetAuthority( "GEOGCS", "EPSG", psDefn->GCS );
     432                 : 
     433             990 :     if( psDefn->Datum != KvUserDefined )
     434             985 :         oSRS.SetAuthority( "DATUM", "EPSG", psDefn->Datum );
     435                 : 
     436             990 :     if( psDefn->Ellipsoid != KvUserDefined )
     437             985 :         oSRS.SetAuthority( "SPHEROID", "EPSG", psDefn->Ellipsoid );
     438                 : 
     439             990 :     CPLFree( pszGeogName );
     440             990 :     CPLFree( pszDatumName );
     441             990 :     GTIFFreeMemory( pszPMName );
     442             990 :     GTIFFreeMemory( pszSpheroidName );
     443             990 :     GTIFFreeMemory( pszAngularUnits );
     444                 :         
     445                 : /* ==================================================================== */
     446                 : /*      Handle projection parameters.                                   */
     447                 : /* ==================================================================== */
     448             990 :     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            3000 :         for( i = 0; i < MIN(10,psDefn->nParms); i++ )
     459            2625 :             adfParm[i] = psDefn->ProjParm[i];
     460                 : 
     461            1500 :         for( ; i < 10; i++ )
     462            1125 :             adfParm[i] = 0.0;
     463                 : 
     464             375 :         if(!aUnitGot)
     465                 :         {
     466             375 :           adfParm[0] *= psDefn->UOMAngleInDegrees;
     467             375 :           adfParm[1] *= psDefn->UOMAngleInDegrees;
     468             375 :           adfParm[2] *= psDefn->UOMAngleInDegrees;
     469             375 :           adfParm[3] *= psDefn->UOMAngleInDegrees; 
     470                 :         }
     471             375 :         int unitCode = 0;
     472             375 :         GTIFKeyGet(hGTIF, ProjLinearUnitsGeoKey, &unitCode, 0, 1  );
     473             375 :         if(unitCode != KvUserDefined)
     474                 :         {
     475             375 :           adfParm[5] /= psDefn->UOMLengthInMeters;
     476             375 :           adfParm[6] /= psDefn->UOMLengthInMeters;
     477                 :         }
     478                 :         
     479                 : /* -------------------------------------------------------------------- */
     480                 : /*      Translation the fundamental projection.                         */
     481                 : /* -------------------------------------------------------------------- */
     482             375 :         switch( psDefn->CTProjection )
     483                 :         {
     484                 :           case CT_TransverseMercator:
     485                 :             oSRS.SetTM( adfParm[0], adfParm[1],
     486                 :                         adfParm[4],
     487             372 :                         adfParm[5], adfParm[6] );
     488             372 :             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               0 :                               adfParm[5], adfParm[6] );
     500                 :                               
     501               0 :             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               0 :             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             375 :        if(!linearUnitIsSet)
     628                 :        {
     629             375 :           char  *pszUnitsName = NULL;
     630                 :           
     631             375 :           GTIFGetUOMLengthInfo( psDefn->UOMLength, &pszUnitsName, NULL );
     632                 : 
     633             750 :           if( pszUnitsName != NULL && psDefn->UOMLength != KvUserDefined )
     634                 :           {
     635             375 :               oSRS.SetLinearUnits( pszUnitsName, psDefn->UOMLengthInMeters );
     636             375 :               oSRS.SetAuthority( "PROJCS|UNIT", "EPSG", psDefn->UOMLength );
     637                 :           }
     638                 :           else
     639               0 :               oSRS.SetLinearUnits( "unknown", psDefn->UOMLengthInMeters );
     640                 : 
     641             375 :           GTIFFreeMemory( pszUnitsName );
     642                 :        }
     643                 :     }
     644                 : 
     645                 : /* ==================================================================== */
     646                 : /*      Handle vertical coordinate system information if we have it.    */
     647                 : /* ==================================================================== */
     648             990 :     short verticalCSType = -1;
     649             990 :     short verticalDatum = -1;
     650             990 :     short verticalUnits = -1;
     651             990 :     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             990 :     GTIFKeyGet( hGTIF, VerticalCSTypeGeoKey, &verticalCSType, 0, 1 );
     657             990 :     GTIFKeyGet( hGTIF, VerticalDatumGeoKey, &verticalDatum, 0, 1 );
     658             990 :     GTIFKeyGet( hGTIF, VerticalUnitsGeoKey, &verticalUnits, 0, 1 );
     659                 : 
     660             990 :     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                 : /*      The original geotiff specification appears to have              */
     671                 : /*      misconstrued the EPSG codes 5101 to 5106 to be vertical         */
     672                 : /*      coordinate system codes, when in fact they are vertical         */
     673                 : /*      datum codes.  So if these are found in the                      */
     674                 : /*      VerticalCSTypeGeoKey move them to the VerticalDatumGeoKey       */
     675                 : /*      and insert the "normal" corresponding VerticalCSTypeGeoKey      */
     676                 : /*      value.                                                          */
     677                 : /* -------------------------------------------------------------------- */
     678               0 :         if( (verticalCSType >= 5101 && verticalCSType <= 5112)
     679                 :             && verticalDatum == -1 )
     680                 :         {
     681               0 :             verticalDatum = verticalCSType;
     682               0 :             verticalCSType = verticalDatum + 600;
     683                 :         }
     684                 : 
     685                 : /* -------------------------------------------------------------------- */
     686                 : /*      Somewhat similarly, codes 5001 to 5033 were treated as          */
     687                 : /*      vertical coordinate systems based on ellipsoidal heights.       */
     688                 : /*      We use the corresponding 2d geodetic datum as the vertical      */
     689                 : /*      datum and clear the vertical coordinate system code since       */
     690                 : /*      there isn't one in epsg.                                        */
     691                 : /* -------------------------------------------------------------------- */
     692               0 :         if( (verticalCSType >= 5001 && verticalCSType <= 5033)
     693                 :             && verticalDatum == -1 )
     694                 :         {
     695               0 :             verticalDatum = verticalCSType+1000;
     696               0 :             verticalCSType = -1;
     697                 :         }
     698                 : 
     699                 : /* -------------------------------------------------------------------- */
     700                 : /*      Promote to being a compound coordinate system.                  */
     701                 : /* -------------------------------------------------------------------- */
     702               0 :         OGR_SRSNode *poOldRoot = oSRS.GetRoot()->Clone();
     703                 : 
     704               0 :         oSRS.Clear();
     705               0 :         oSRS.SetNode( "COMPD_CS", "unknown" );
     706               0 :         oSRS.GetRoot()->AddChild( poOldRoot );
     707                 :         
     708                 : /* -------------------------------------------------------------------- */
     709                 : /*      Collect some information from the VerticalCS if not provided    */
     710                 : /*      via geokeys.                                                    */
     711                 : /* -------------------------------------------------------------------- */
     712               0 :         if( verticalCSType > 0 && verticalCSType != KvUserDefined )
     713                 :         {
     714               0 :             pszFilename = CSVFilename( "coordinate_reference_system.csv" );
     715               0 :             sprintf( szSearchKey, "%d", verticalCSType );
     716                 : 
     717               0 :             if( verticalDatum < 1 || verticalDatum == KvUserDefined )
     718                 :             {
     719                 :                 pszValue = CSVGetField( pszFilename, 
     720                 :                                         "coord_ref_sys_code", 
     721                 :                                         szSearchKey, CC_Integer, 
     722               0 :                                         "datum_code" );
     723               0 :                 if( pszValue != NULL )
     724               0 :                     verticalDatum = atoi(pszValue);
     725                 :             }
     726                 : 
     727               0 :             if( EQUAL(citation,"unknown") )
     728                 :             {
     729                 :                 pszValue = CSVGetField( pszFilename, 
     730                 :                                         "coord_ref_sys_code", 
     731                 :                                         szSearchKey, CC_Integer, 
     732               0 :                                         "coord_ref_sys_name" );
     733               0 :                 if( pszValue != NULL && *pszValue != '\0' )
     734               0 :                     strncpy( citation, pszValue, sizeof(citation) );
     735                 :             }
     736                 : 
     737               0 :             if( verticalUnits < 1 || verticalUnits == KvUserDefined )
     738                 :             {
     739                 :                 pszValue = CSVGetField( pszFilename, 
     740                 :                                         "coord_ref_sys_code", 
     741                 :                                         szSearchKey, CC_Integer, 
     742               0 :                                         "coord_sys_code" );
     743               0 :                 if( pszValue != NULL )
     744                 :                 {
     745               0 :                     pszFilename = CSVFilename( "coordinate_axis.csv" );
     746                 :                     pszValue = CSVGetField( pszFilename, 
     747                 :                                             "coord_sys_code", 
     748                 :                                             pszValue, CC_Integer, 
     749               0 :                                             "uom_code" );
     750               0 :                     if( pszValue != NULL )
     751               0 :                         verticalUnits = atoi(pszValue);
     752                 :                 }                
     753                 :             }
     754                 :         }
     755                 : 
     756                 : /* -------------------------------------------------------------------- */
     757                 : /*      Setup VERT_CS with citation if present.                         */
     758                 : /* -------------------------------------------------------------------- */
     759               0 :         oSRS.SetNode( "COMPD_CS|VERT_CS", citation );
     760                 : 
     761                 : /* -------------------------------------------------------------------- */
     762                 : /*      Setup the vertical datum.                                       */
     763                 : /* -------------------------------------------------------------------- */
     764               0 :         const char *pszVDatumName = "unknown";
     765               0 :         const char *pszVDatumType = "2005"; // CS_VD_GeoidModelDerived
     766                 : 
     767               0 :         if( verticalDatum > 0 && verticalDatum != KvUserDefined )
     768                 :         {
     769               0 :             pszFilename = CSVFilename( "datum.csv" );
     770               0 :             if( EQUAL(pszFilename,"datum.csv") )
     771               0 :                 pszFilename = CSVFilename( "gdal_datum.csv" );
     772                 : 
     773               0 :             sprintf( szSearchKey, "%d", verticalDatum );
     774                 : 
     775                 :             pszValue = CSVGetField( pszFilename,
     776                 :                                     "DATUM_CODE", szSearchKey, CC_Integer,
     777               0 :                                     "DATUM_NAME" );
     778               0 :             if( pszValue != NULL && *pszValue != '\0' )
     779               0 :                 pszVDatumName = pszValue;
     780                 : 
     781                 :             pszValue = CSVGetField( pszFilename,
     782                 :                                     "DATUM_CODE", szSearchKey, CC_Integer,
     783               0 :                                     "DATUM_TYPE" );
     784               0 :             if( pszValue != NULL && EQUALN(pszValue,"geodetic",8) )
     785               0 :                 pszVDatumType = "2002"; // CS_VD_Ellipsoidal
     786                 : 
     787                 :             // We unfortunately don't know how to identify other 
     788                 :             // vertical datum types, particularly orthometric (2001). 
     789                 :         }
     790                 : 
     791               0 :         oSRS.SetNode( "COMPD_CS|VERT_CS|VERT_DATUM", pszVDatumName );
     792                 :         oSRS.GetAttrNode( "COMPD_CS|VERT_CS|VERT_DATUM" )
     793               0 :             ->AddChild( new OGR_SRSNode( pszVDatumType ) );
     794               0 :         if( verticalDatum > 0 && verticalDatum != KvUserDefined )
     795                 :             oSRS.SetAuthority( "COMPD_CS|VERT_CS|VERT_DATUM", "EPSG", 
     796               0 :                                   verticalDatum );
     797                 :     
     798                 : /* -------------------------------------------------------------------- */
     799                 : /*      Set the vertical units.                                         */
     800                 : /* -------------------------------------------------------------------- */
     801               0 :         if( verticalUnits > 0 && verticalUnits != KvUserDefined 
     802                 :             && verticalUnits != 9001 )
     803                 :         {
     804                 :             char szInMeters[128];
     805                 : 
     806               0 :             pszFilename = CSVFilename("unit_of_measure.csv");
     807                 :             
     808                 :             // Name
     809               0 :             sprintf( szSearchKey, "%d", verticalUnits );
     810                 :             pszValue = CSVGetField( pszFilename,
     811                 :                                     "uom_code", szSearchKey, CC_Integer,
     812               0 :                                     "unit_of_meas_name" );
     813               0 :             if( pszValue == NULL )
     814               0 :                 pszValue = "unknown";
     815                 : 
     816               0 :             oSRS.SetNode( "COMPD_CS|VERT_CS|UNIT", pszValue );
     817                 : 
     818                 :             // Value
     819                 :             double dfFactorB, dfFactorC;
     820                 :             dfFactorB = atof(CSVGetField( pszFilename, 
     821                 :                                           "uom_code", szSearchKey, CC_Integer,
     822               0 :                                           "factor_b" ));
     823                 :             dfFactorC = atof(CSVGetField( pszFilename, 
     824                 :                                           "uom_code", szSearchKey, CC_Integer,
     825               0 :                                           "factor_b" ));
     826               0 :             if( dfFactorB != 0.0 && dfFactorC != 0.0 )
     827               0 :                 sprintf( szInMeters, "%.16g", dfFactorB / dfFactorC );
     828                 :             else
     829               0 :                 strcpy( szInMeters, "1" );
     830                 : 
     831                 : 
     832                 :             oSRS.GetAttrNode( "COMPD_CS|VERT_CS|UNIT" )
     833               0 :                 ->AddChild( new OGR_SRSNode( szInMeters ) );
     834                 : 
     835               0 :             oSRS.SetAuthority( "COMPD_CS|VERT_CS|UNIT", "EPSG", verticalUnits);
     836                 :         }
     837                 :         else
     838                 :         {
     839               0 :             oSRS.SetNode( "COMPD_CS|VERT_CS|UNIT", "metre" );
     840                 :             oSRS.GetAttrNode( "COMPD_CS|VERT_CS|UNIT" )
     841               0 :                 ->AddChild( new OGR_SRSNode( "1.0" ) );
     842               0 :             oSRS.SetAuthority( "COMPD_CS|VERT_CS|UNIT", "EPSG", 9001 );
     843                 :         }
     844                 : 
     845                 : /* -------------------------------------------------------------------- */
     846                 : /*      Set the axis and VERT_CS authority.                             */
     847                 : /* -------------------------------------------------------------------- */
     848               0 :         oSRS.SetNode( "COMPD_CS|VERT_CS|AXIS", "Up" );
     849                 :         oSRS.GetAttrNode( "COMPD_CS|VERT_CS|AXIS" )
     850               0 :             ->AddChild( new OGR_SRSNode( "UP" ) );
     851                 :         
     852               0 :         if( verticalCSType > 0 && verticalCSType != KvUserDefined )
     853               0 :             oSRS.SetAuthority( "COMPD_CS|VERT_CS", "EPSG", verticalCSType );
     854                 :     }
     855                 :     
     856                 : /* ==================================================================== */
     857                 : /*      Return the WKT serialization of the object.                     */
     858                 : /* ==================================================================== */
     859                 :     char  *pszWKT;
     860                 : 
     861             990 :     oSRS.FixupOrdering();
     862                 : 
     863             990 :     if( oSRS.exportToWkt( &pszWKT ) == OGRERR_NONE )
     864             990 :         return pszWKT;
     865                 :     else
     866               0 :         return NULL;
     867                 : }
     868                 : 
     869                 : /************************************************************************/
     870                 : /*                     OGCDatumName2EPSGDatumCode()                     */
     871                 : /************************************************************************/
     872                 : 
     873             283 : static int OGCDatumName2EPSGDatumCode( const char * pszOGCName )
     874                 : 
     875                 : {
     876                 :     FILE  *fp;
     877                 :     char  **papszTokens;
     878             283 :     int   nReturn = KvUserDefined;
     879                 : 
     880                 : /* -------------------------------------------------------------------- */
     881                 : /*      Do we know it as a built in?                                    */
     882                 : /* -------------------------------------------------------------------- */
     883             283 :     if( EQUAL(pszOGCName,"NAD27") 
     884                 :         || EQUAL(pszOGCName,"North_American_Datum_1927") )
     885               0 :         return Datum_North_American_Datum_1927;
     886             283 :     else if( EQUAL(pszOGCName,"NAD83") 
     887                 :         || EQUAL(pszOGCName,"North_American_Datum_1983") )
     888               0 :         return Datum_North_American_Datum_1983;
     889             283 :     else if( EQUAL(pszOGCName,"WGS84") || EQUAL(pszOGCName,"WGS_1984")
     890                 :              || EQUAL(pszOGCName,"WGS 84"))
     891             274 :         return Datum_WGS84;
     892               9 :     else if( EQUAL(pszOGCName,"WGS72") || EQUAL(pszOGCName,"WGS_1972") )
     893               2 :         return Datum_WGS72;
     894                 :     
     895                 : /* -------------------------------------------------------------------- */
     896                 : /*      Open the table if possible.                                     */
     897                 : /* -------------------------------------------------------------------- */
     898               7 :     fp = VSIFOpen( CSVFilename("gdal_datum.csv"), "r" );
     899               7 :     if( fp == NULL )
     900               0 :         fp = VSIFOpen( CSVFilename("datum.csv"), "r" );
     901                 : 
     902               7 :     if( fp == NULL )
     903               0 :         return nReturn;
     904                 : 
     905                 : /* -------------------------------------------------------------------- */
     906                 : /*  Discard the first line with field names.      */
     907                 : /* -------------------------------------------------------------------- */
     908               7 :     CSLDestroy( CSVReadParseLine( fp ) );
     909                 : 
     910                 : /* -------------------------------------------------------------------- */
     911                 : /*      Read lines looking for our datum.                               */
     912                 : /* -------------------------------------------------------------------- */
     913            4074 :     for( papszTokens = CSVReadParseLine( fp );
     914                 :          CSLCount(papszTokens) > 2 && nReturn == KvUserDefined;
     915                 :          papszTokens = CSVReadParseLine( fp ) )
     916                 :     {
     917            4067 :         WKTMassageDatum( papszTokens + 1 );
     918                 : 
     919            4067 :         if( EQUAL(papszTokens[1], pszOGCName) )
     920               0 :             nReturn = atoi(papszTokens[0]);
     921                 : 
     922            4067 :         CSLDestroy( papszTokens );
     923                 :     }
     924                 : 
     925               7 :     CSLDestroy( papszTokens );
     926               7 :     VSIFClose( fp );
     927                 : 
     928               7 :     return nReturn;
     929                 : }
     930                 : 
     931                 : /************************************************************************/
     932                 : /*                        GTIFSetFromOGISDefn()                         */
     933                 : /*                                                                      */
     934                 : /*      Write GeoTIFF projection tags from an OGC WKT definition.       */
     935                 : /************************************************************************/
     936                 : 
     937             701 : int GTIFSetFromOGISDefn( GTIF * psGTIF, const char *pszOGCWKT )
     938                 : 
     939                 : {
     940                 :     OGRSpatialReference *poSRS;
     941             701 :     int   nPCS = KvUserDefined;
     942                 :     OGRErr      eErr;
     943             701 :     OGRBoolean peStrStored = FALSE;    
     944                 : 
     945                 :     GTIFKeySet(psGTIF, GTRasterTypeGeoKey, TYPE_SHORT, 1,
     946             701 :                RasterPixelIsArea);
     947                 : 
     948                 : /* -------------------------------------------------------------------- */
     949                 : /*      Create an OGRSpatialReference object corresponding to the       */
     950                 : /*      string.                                                         */
     951                 : /* -------------------------------------------------------------------- */
     952             701 :     poSRS = new OGRSpatialReference();
     953             701 :     if( poSRS->importFromWkt((char **) &pszOGCWKT) != OGRERR_NONE )
     954                 :     {
     955               0 :         delete poSRS;
     956               0 :         return FALSE;
     957                 :     }
     958                 : 
     959                 : /* -------------------------------------------------------------------- */
     960                 : /*      Get the ellipsoid definition.                                   */
     961                 : /* -------------------------------------------------------------------- */
     962             701 :     short nSpheroid = KvUserDefined;
     963                 :     double dfSemiMajor, dfInvFlattening;
     964                 : 
     965             701 :     if( poSRS->GetAuthorityName("PROJCS|GEOGCS|DATUM|SPHEROID") != NULL
     966                 :         && EQUAL(poSRS->GetAuthorityName("PROJCS|GEOGCS|DATUM|SPHEROID"),
     967                 :                  "EPSG")) 
     968                 :     {
     969                 :         nSpheroid = (short)
     970             129 :             atoi(poSRS->GetAuthorityCode("PROJCS|GEOGCS|DATUM|SPHEROID"));
     971                 :     }
     972             572 :     else if( poSRS->GetAuthorityName("GEOGCS|DATUM|SPHEROID") != NULL
     973                 :              && EQUAL(poSRS->GetAuthorityName("GEOGCS|DATUM|SPHEROID"),"EPSG")) 
     974                 :     {
     975                 :         nSpheroid = (short)
     976             289 :             atoi(poSRS->GetAuthorityCode("GEOGCS|DATUM|SPHEROID"));
     977                 :     }
     978                 :     
     979             701 :     dfSemiMajor = poSRS->GetSemiMajor( &eErr );
     980             701 :     dfInvFlattening = poSRS->GetInvFlattening( &eErr );
     981             701 :     if( eErr != OGRERR_NONE )
     982                 :     {
     983               2 :         dfSemiMajor = 0.0;
     984               2 :         dfInvFlattening = 0.0;
     985                 :     }
     986                 :     
     987                 : /* -------------------------------------------------------------------- */
     988                 : /*      Get the Datum so we can special case a few PCS codes.           */
     989                 : /* -------------------------------------------------------------------- */
     990             701 :     int   nDatum = KvUserDefined;
     991                 : 
     992             701 :     if( poSRS->GetAuthorityName("PROJCS|GEOGCS|DATUM") != NULL 
     993                 :         && EQUAL(poSRS->GetAuthorityName("PROJCS|GEOGCS|DATUM"),"EPSG") )
     994             129 :         nDatum = atoi(poSRS->GetAuthorityCode("PROJCS|GEOGCS|DATUM"));
     995             572 :     else if( poSRS->GetAuthorityName("GEOGCS|DATUM") != NULL 
     996                 :              && EQUAL(poSRS->GetAuthorityName("GEOGCS|DATUM"),"EPSG") )
     997             289 :         nDatum = atoi(poSRS->GetAuthorityCode("GEOGCS|DATUM"));
     998             283 :     else if( poSRS->GetAttrValue("DATUM") != NULL )
     999             283 :         nDatum = OGCDatumName2EPSGDatumCode( poSRS->GetAttrValue("DATUM") );
    1000                 : 
    1001                 : /* -------------------------------------------------------------------- */
    1002                 : /*      Get the GCS if possible.                                        */
    1003                 : /* -------------------------------------------------------------------- */
    1004             701 :     int         nGCS = KvUserDefined;
    1005                 : 
    1006             701 :     if( poSRS->GetAuthorityName("PROJCS|GEOGCS") != NULL 
    1007                 :         && EQUAL(poSRS->GetAuthorityName("PROJCS|GEOGCS"),"EPSG") )
    1008             129 :         nGCS = atoi(poSRS->GetAuthorityCode("PROJCS|GEOGCS"));
    1009             572 :     else if( poSRS->GetAuthorityName("GEOGCS") != NULL 
    1010                 :              && EQUAL(poSRS->GetAuthorityName("GEOGCS"),"EPSG") )
    1011             298 :         nGCS = atoi(poSRS->GetAuthorityCode("GEOGCS"));
    1012                 : 
    1013             701 :     if( nGCS > 32767 )
    1014               0 :         nGCS = KvUserDefined;
    1015                 : 
    1016                 : /* -------------------------------------------------------------------- */
    1017                 : /*      Get the linear units.                                           */
    1018                 : /* -------------------------------------------------------------------- */
    1019             701 :     char        *pszLinearUOMName = NULL;
    1020             701 :     double  dfLinearUOM = poSRS->GetLinearUnits( &pszLinearUOMName );
    1021             701 :     int         nUOMLengthCode = 9001; /* meters */
    1022                 : 
    1023             701 :     if( (pszLinearUOMName != NULL
    1024                 :          && EQUAL(pszLinearUOMName,SRS_UL_FOOT))
    1025                 :         || dfLinearUOM == atof(SRS_UL_FOOT_CONV) )
    1026               0 :         nUOMLengthCode = 9002; /* international foot */
    1027             702 :     else if( (pszLinearUOMName != NULL
    1028                 :               && EQUAL(pszLinearUOMName,SRS_UL_US_FOOT))
    1029                 :              || ABS(dfLinearUOM-atof(SRS_UL_US_FOOT_CONV)) < 0.0000001 )
    1030               1 :         nUOMLengthCode = 9003; /* us survey foot */
    1031             700 :     else if( dfLinearUOM != 1.0 )
    1032               0 :         nUOMLengthCode = KvUserDefined;
    1033                 : 
    1034                 : /* -------------------------------------------------------------------- */
    1035                 : /*      Get some authority values.                                      */
    1036                 : /* -------------------------------------------------------------------- */
    1037             701 :     if( poSRS->GetAuthorityName("PROJCS") != NULL 
    1038                 :         && EQUAL(poSRS->GetAuthorityName("PROJCS"),"EPSG") )
    1039                 :     {
    1040             128 :         nPCS = atoi(poSRS->GetAuthorityCode("PROJCS"));
    1041             128 :         if( nPCS > 32767 )
    1042               0 :             nPCS = KvUserDefined;
    1043                 :     }
    1044                 : 
    1045                 : /* -------------------------------------------------------------------- */
    1046                 : /*      Handle the projection transformation.                           */
    1047                 : /* -------------------------------------------------------------------- */
    1048             701 :     const char *pszProjection = poSRS->GetAttrValue( "PROJECTION" );
    1049                 : 
    1050             701 :     if( nPCS != KvUserDefined )
    1051                 :     {
    1052                 :         GTIFKeySet(psGTIF, GTModelTypeGeoKey, TYPE_SHORT, 1,
    1053             128 :                    ModelTypeProjected);
    1054             128 :         GTIFKeySet(psGTIF, ProjectedCSTypeGeoKey, TYPE_SHORT, 1, nPCS );
    1055                 :     }
    1056             573 :     else if( pszProjection == NULL )
    1057                 :     {
    1058             566 :         if( poSRS->IsGeographic() )
    1059                 :             GTIFKeySet(psGTIF, GTModelTypeGeoKey, TYPE_SHORT, 1,
    1060             566 :                        ModelTypeGeographic);
    1061                 :         // otherwise, presumably something like LOCAL_CS.
    1062                 :     }
    1063               7 :     else if( EQUAL(pszProjection,SRS_PT_ALBERS_CONIC_EQUAL_AREA) )
    1064                 :     {
    1065                 :   GTIFKeySet(psGTIF, GTModelTypeGeoKey, TYPE_SHORT, 1,
    1066               0 :                    ModelTypeProjected);
    1067                 :   GTIFKeySet(psGTIF, ProjectedCSTypeGeoKey, TYPE_SHORT, 1,
    1068               0 :                    KvUserDefined );
    1069                 :   GTIFKeySet(psGTIF, ProjectionGeoKey, TYPE_SHORT, 1,
    1070               0 :                    KvUserDefined );
    1071                 : 
    1072                 :   GTIFKeySet(psGTIF, ProjCoordTransGeoKey, TYPE_SHORT, 1, 
    1073               0 :        CT_AlbersEqualArea );
    1074                 : 
    1075                 :         GTIFKeySet(psGTIF, ProjStdParallelGeoKey, TYPE_DOUBLE, 1,
    1076               0 :                    poSRS->GetNormProjParm( SRS_PP_STANDARD_PARALLEL_1, 0.0 ) );
    1077                 : 
    1078                 :         GTIFKeySet(psGTIF, ProjStdParallel2GeoKey, TYPE_DOUBLE, 1,
    1079               0 :                    poSRS->GetNormProjParm( SRS_PP_STANDARD_PARALLEL_2, 0.0 ) );
    1080                 : 
    1081                 :         GTIFKeySet(psGTIF, ProjNatOriginLatGeoKey, TYPE_DOUBLE, 1,
    1082               0 :                    poSRS->GetNormProjParm( SRS_PP_LATITUDE_OF_CENTER, 0.0 ) );
    1083                 : 
    1084                 :         GTIFKeySet(psGTIF, ProjNatOriginLongGeoKey, TYPE_DOUBLE, 1,
    1085               0 :                    poSRS->GetNormProjParm( SRS_PP_LONGITUDE_OF_CENTER, 0.0 ) );
    1086                 :         
    1087                 :         GTIFKeySet(psGTIF, ProjFalseEastingGeoKey, TYPE_DOUBLE, 1,
    1088               0 :                    poSRS->GetNormProjParm( SRS_PP_FALSE_EASTING, 0.0 ) );
    1089                 :         
    1090                 :         GTIFKeySet(psGTIF, ProjFalseNorthingGeoKey, TYPE_DOUBLE, 1,
    1091               0 :                    poSRS->GetNormProjParm( SRS_PP_FALSE_NORTHING, 0.0 ) );
    1092                 :     }
    1093                 : 
    1094               7 :     else if( poSRS->GetUTMZone() != 0 )
    1095                 :     {
    1096                 :         int   bNorth, nZone, nProjection;
    1097                 : 
    1098                 :   GTIFKeySet(psGTIF, GTModelTypeGeoKey, TYPE_SHORT, 1,
    1099               1 :                    ModelTypeProjected);
    1100                 : 
    1101               1 :         nZone = poSRS->GetUTMZone( &bNorth );
    1102                 : 
    1103               1 :         if( nDatum == Datum_North_American_Datum_1983 && nZone >= 3
    1104                 :             && nZone <= 22 && bNorth && nUOMLengthCode == 9001 )
    1105                 :         {
    1106               0 :             nPCS = 26900 + nZone;
    1107                 : 
    1108               0 :             GTIFKeySet(psGTIF, ProjectedCSTypeGeoKey, TYPE_SHORT, 1, nPCS );
    1109                 :         }
    1110               1 :         else if( nDatum == Datum_North_American_Datum_1927 && nZone >= 3
    1111                 :                  && nZone <= 22 && bNorth && nUOMLengthCode == 9001 )
    1112                 :         {
    1113               0 :             nPCS = 26700 + nZone;
    1114                 : 
    1115               0 :             GTIFKeySet(psGTIF, ProjectedCSTypeGeoKey, TYPE_SHORT, 1, nPCS );
    1116                 :         }
    1117               1 :         else if( nDatum == Datum_WGS84 && nUOMLengthCode == 9001 )
    1118                 :         {
    1119               0 :             if( bNorth )
    1120               0 :                 nPCS = 32600 + nZone;
    1121                 :             else
    1122               0 :                 nPCS = 32700 + nZone;
    1123                 : 
    1124               0 :             GTIFKeySet(psGTIF, ProjectedCSTypeGeoKey, TYPE_SHORT, 1, nPCS );
    1125                 :         }
    1126                 :         else
    1127                 :         {
    1128               1 :             if( bNorth )
    1129               1 :                 nProjection = 16000 + nZone;
    1130                 :             else
    1131               0 :                 nProjection = 16100 + nZone;
    1132                 : 
    1133                 :         
    1134                 :             GTIFKeySet(psGTIF, ProjectedCSTypeGeoKey, TYPE_SHORT, 1,
    1135               1 :                        KvUserDefined );
    1136                 :             
    1137               1 :             GTIFKeySet(psGTIF, ProjectionGeoKey, TYPE_SHORT, 1, nProjection );
    1138                 :         }
    1139                 :     }
    1140                 : 
    1141               6 :     else if( EQUAL(pszProjection,SRS_PT_TRANSVERSE_MERCATOR) )
    1142                 :     {
    1143                 :   GTIFKeySet(psGTIF, GTModelTypeGeoKey, TYPE_SHORT, 1,
    1144               0 :                    ModelTypeProjected);
    1145                 :   GTIFKeySet(psGTIF, ProjectedCSTypeGeoKey, TYPE_SHORT, 1,
    1146               0 :                    KvUserDefined );
    1147                 :   GTIFKeySet(psGTIF, ProjectionGeoKey, TYPE_SHORT, 1,
    1148               0 :                    KvUserDefined );
    1149                 : 
    1150                 :   GTIFKeySet(psGTIF, ProjCoordTransGeoKey, TYPE_SHORT, 1, 
    1151               0 :        CT_TransverseMercator );
    1152                 : 
    1153                 :         GTIFKeySet(psGTIF, ProjNatOriginLatGeoKey, TYPE_DOUBLE, 1,
    1154               0 :                    poSRS->GetNormProjParm( SRS_PP_LATITUDE_OF_ORIGIN, 0.0 ) );
    1155                 : 
    1156                 :         GTIFKeySet(psGTIF, ProjNatOriginLongGeoKey, TYPE_DOUBLE, 1,
    1157               0 :                    poSRS->GetNormProjParm( SRS_PP_CENTRAL_MERIDIAN, 0.0 ) );
    1158                 :         
    1159                 :         GTIFKeySet(psGTIF, ProjScaleAtNatOriginGeoKey, TYPE_DOUBLE, 1,
    1160               0 :                    poSRS->GetNormProjParm( SRS_PP_SCALE_FACTOR, 1.0 ) );
    1161                 :         
    1162                 :         GTIFKeySet(psGTIF, ProjFalseEastingGeoKey, TYPE_DOUBLE, 1,
    1163               0 :                    poSRS->GetNormProjParm( SRS_PP_FALSE_EASTING, 0.0 ) );
    1164                 :         
    1165                 :         GTIFKeySet(psGTIF, ProjFalseNorthingGeoKey, TYPE_DOUBLE, 1,
    1166               0 :                    poSRS->GetNormProjParm( SRS_PP_FALSE_NORTHING, 0.0 ) );
    1167                 :     }
    1168                 :     
    1169               6 :     else if( EQUAL(pszProjection,SRS_PT_TRANSVERSE_MERCATOR_SOUTH_ORIENTED) )
    1170                 :     {
    1171                 :   GTIFKeySet(psGTIF, GTModelTypeGeoKey, TYPE_SHORT, 1,
    1172               0 :                    ModelTypeProjected);
    1173                 :   GTIFKeySet(psGTIF, ProjectedCSTypeGeoKey, TYPE_SHORT, 1,
    1174               0 :                    KvUserDefined );
    1175                 :   GTIFKeySet(psGTIF, ProjectionGeoKey, TYPE_SHORT, 1,
    1176               0 :                    KvUserDefined );
    1177                 : 
    1178                 :   GTIFKeySet(psGTIF, ProjCoordTransGeoKey, TYPE_SHORT, 1, 
    1179               0 :        CT_TransvMercator_SouthOriented );
    1180                 : 
    1181                 :         GTIFKeySet(psGTIF, ProjNatOriginLatGeoKey, TYPE_DOUBLE, 1,
    1182               0 :                    poSRS->GetNormProjParm( SRS_PP_LATITUDE_OF_ORIGIN, 0.0 ) );
    1183                 : 
    1184                 :         GTIFKeySet(psGTIF, ProjNatOriginLongGeoKey, TYPE_DOUBLE, 1,
    1185               0 :                    poSRS->GetNormProjParm( SRS_PP_CENTRAL_MERIDIAN, 0.0 ) );
    1186                 :         
    1187                 :         GTIFKeySet(psGTIF, ProjScaleAtNatOriginGeoKey, TYPE_DOUBLE, 1,
    1188               0 :                    poSRS->GetNormProjParm( SRS_PP_SCALE_FACTOR, 1.0 ) );
    1189                 :         
    1190                 :         GTIFKeySet(psGTIF, ProjFalseEastingGeoKey, TYPE_DOUBLE, 1,
    1191               0 :                    poSRS->GetNormProjParm( SRS_PP_FALSE_EASTING, 0.0 ) );
    1192                 :         
    1193                 :         GTIFKeySet(psGTIF, ProjFalseNorthingGeoKey, TYPE_DOUBLE, 1,
    1194               0 :                    poSRS->GetNormProjParm( SRS_PP_FALSE_NORTHING, 0.0 ) );
    1195                 :     }
    1196                 :     
    1197               6 :     else if( EQUAL(pszProjection,SRS_PT_MERCATOR_2SP) 
    1198                 :              || EQUAL(pszProjection,SRS_PT_MERCATOR_1SP) )
    1199                 : 
    1200                 :     {
    1201                 :   GTIFKeySet(psGTIF, GTModelTypeGeoKey, TYPE_SHORT, 1,
    1202               0 :                    ModelTypeProjected);
    1203                 :   GTIFKeySet(psGTIF, ProjectedCSTypeGeoKey, TYPE_SHORT, 1,
    1204               0 :                    KvUserDefined );
    1205                 :   GTIFKeySet(psGTIF, ProjectionGeoKey, TYPE_SHORT, 1,
    1206               0 :                    KvUserDefined );
    1207                 : 
    1208                 :   GTIFKeySet(psGTIF, ProjCoordTransGeoKey, TYPE_SHORT, 1, 
    1209               0 :        CT_Mercator );
    1210                 : 
    1211                 :         GTIFKeySet(psGTIF, ProjNatOriginLatGeoKey, TYPE_DOUBLE, 1,
    1212               0 :                    poSRS->GetNormProjParm( SRS_PP_LATITUDE_OF_ORIGIN, 0.0 ) );
    1213                 : 
    1214                 :         GTIFKeySet(psGTIF, ProjNatOriginLongGeoKey, TYPE_DOUBLE, 1,
    1215               0 :                    poSRS->GetNormProjParm( SRS_PP_CENTRAL_MERIDIAN, 0.0 ) );
    1216                 :         
    1217                 :         GTIFKeySet(psGTIF, ProjScaleAtNatOriginGeoKey, TYPE_DOUBLE, 1,
    1218               0 :                    poSRS->GetNormProjParm( SRS_PP_SCALE_FACTOR, 1.0 ) );
    1219                 :         
    1220                 :         GTIFKeySet(psGTIF, ProjFalseEastingGeoKey, TYPE_DOUBLE, 1,
    1221               0 :                    poSRS->GetNormProjParm( SRS_PP_FALSE_EASTING, 0.0 ) );
    1222                 :         
    1223                 :         GTIFKeySet(psGTIF, ProjFalseNorthingGeoKey, TYPE_DOUBLE, 1,
    1224               0 :                    poSRS->GetNormProjParm( SRS_PP_FALSE_NORTHING, 0.0 ) );
    1225                 :     }
    1226                 :     
    1227               6 :     else if( EQUAL(pszProjection,SRS_PT_OBLIQUE_STEREOGRAPHIC) )
    1228                 :     {
    1229                 :   GTIFKeySet(psGTIF, GTModelTypeGeoKey, TYPE_SHORT, 1,
    1230               0 :                    ModelTypeProjected);
    1231                 :   GTIFKeySet(psGTIF, ProjectedCSTypeGeoKey, TYPE_SHORT, 1,
    1232               0 :                    KvUserDefined );
    1233                 :   GTIFKeySet(psGTIF, ProjectionGeoKey, TYPE_SHORT, 1,
    1234               0 :                    KvUserDefined );
    1235                 : 
    1236                 :   GTIFKeySet(psGTIF, ProjCoordTransGeoKey, TYPE_SHORT, 1, 
    1237               0 :        CT_ObliqueStereographic );
    1238                 : 
    1239                 :         GTIFKeySet(psGTIF, ProjNatOriginLatGeoKey, TYPE_DOUBLE, 1,
    1240               0 :                    poSRS->GetNormProjParm( SRS_PP_LATITUDE_OF_ORIGIN, 0.0 ) );
    1241                 : 
    1242                 :         GTIFKeySet(psGTIF, ProjNatOriginLongGeoKey, TYPE_DOUBLE, 1,
    1243               0 :                    poSRS->GetNormProjParm( SRS_PP_CENTRAL_MERIDIAN, 0.0 ) );
    1244                 :         
    1245                 :         GTIFKeySet(psGTIF, ProjScaleAtNatOriginGeoKey, TYPE_DOUBLE, 1,
    1246               0 :                    poSRS->GetNormProjParm( SRS_PP_SCALE_FACTOR, 1.0 ) );
    1247                 :         
    1248                 :         GTIFKeySet(psGTIF, ProjFalseEastingGeoKey, TYPE_DOUBLE, 1,
    1249               0 :                    poSRS->GetNormProjParm( SRS_PP_FALSE_EASTING, 0.0 ) );
    1250                 :         
    1251                 :         GTIFKeySet(psGTIF, ProjFalseNorthingGeoKey, TYPE_DOUBLE, 1,
    1252               0 :                    poSRS->GetNormProjParm( SRS_PP_FALSE_NORTHING, 0.0 ) );
    1253                 :     }
    1254                 :     
    1255               6 :     else if( EQUAL(pszProjection,SRS_PT_STEREOGRAPHIC) )
    1256                 :     {
    1257                 :   GTIFKeySet(psGTIF, GTModelTypeGeoKey, TYPE_SHORT, 1,
    1258               0 :                    ModelTypeProjected);
    1259                 :   GTIFKeySet(psGTIF, ProjectedCSTypeGeoKey, TYPE_SHORT, 1,
    1260               0 :                    KvUserDefined );
    1261                 :   GTIFKeySet(psGTIF, ProjectionGeoKey, TYPE_SHORT, 1,
    1262               0 :                    KvUserDefined );
    1263                 : 
    1264                 :   GTIFKeySet(psGTIF, ProjCoordTransGeoKey, TYPE_SHORT, 1, 
    1265               0 :        CT_Stereographic );
    1266                 : 
    1267                 :         GTIFKeySet(psGTIF, ProjCenterLatGeoKey, TYPE_DOUBLE, 1,
    1268               0 :                    poSRS->GetNormProjParm( SRS_PP_LATITUDE_OF_ORIGIN, 0.0 ) );
    1269                 : 
    1270                 :         GTIFKeySet(psGTIF, ProjCenterLongGeoKey, TYPE_DOUBLE, 1,
    1271               0 :                    poSRS->GetNormProjParm( SRS_PP_CENTRAL_MERIDIAN, 0.0 ) );
    1272                 :         
    1273                 :         GTIFKeySet(psGTIF, ProjScaleAtNatOriginGeoKey, TYPE_DOUBLE, 1,
    1274               0 :                    poSRS->GetNormProjParm( SRS_PP_SCALE_FACTOR, 1.0 ) );
    1275                 :         
    1276                 :         GTIFKeySet(psGTIF, ProjFalseEastingGeoKey, TYPE_DOUBLE, 1,
    1277               0 :                    poSRS->GetNormProjParm( SRS_PP_FALSE_EASTING, 0.0 ) );
    1278                 :         
    1279                 :         GTIFKeySet(psGTIF, ProjFalseNorthingGeoKey, TYPE_DOUBLE, 1,
    1280               0 :                    poSRS->GetNormProjParm( SRS_PP_FALSE_NORTHING, 0.0 ) );
    1281                 :     }
    1282                 :     
    1283               6 :     else if( EQUAL(pszProjection,SRS_PT_POLAR_STEREOGRAPHIC) )
    1284                 :     {
    1285                 :   GTIFKeySet(psGTIF, GTModelTypeGeoKey, TYPE_SHORT, 1,
    1286               0 :                    ModelTypeProjected);
    1287                 :   GTIFKeySet(psGTIF, ProjectedCSTypeGeoKey, TYPE_SHORT, 1,
    1288               0 :                    KvUserDefined );
    1289                 :   GTIFKeySet(psGTIF, ProjectionGeoKey, TYPE_SHORT, 1,
    1290               0 :                    KvUserDefined );
    1291                 : 
    1292                 :   GTIFKeySet(psGTIF, ProjCoordTransGeoKey, TYPE_SHORT, 1, 
    1293               0 :        CT_PolarStereographic );
    1294                 : 
    1295                 :         GTIFKeySet(psGTIF, ProjNatOriginLatGeoKey, TYPE_DOUBLE, 1,
    1296               0 :                    poSRS->GetNormProjParm( SRS_PP_LATITUDE_OF_ORIGIN, 0.0 ) );
    1297                 : 
    1298                 :         GTIFKeySet(psGTIF, ProjStraightVertPoleLongGeoKey, TYPE_DOUBLE, 1,
    1299               0 :                    poSRS->GetNormProjParm( SRS_PP_CENTRAL_MERIDIAN, 0.0 ) );
    1300                 :         
    1301                 :         GTIFKeySet(psGTIF, ProjScaleAtNatOriginGeoKey, TYPE_DOUBLE, 1,
    1302               0 :                    poSRS->GetNormProjParm( SRS_PP_SCALE_FACTOR, 1.0 ) );
    1303                 :         
    1304                 :         GTIFKeySet(psGTIF, ProjFalseEastingGeoKey, TYPE_DOUBLE, 1,
    1305               0 :                    poSRS->GetNormProjParm( SRS_PP_FALSE_EASTING, 0.0 ) );
    1306                 :         
    1307                 :         GTIFKeySet(psGTIF, ProjFalseNorthingGeoKey, TYPE_DOUBLE, 1,
    1308               0 :                    poSRS->GetNormProjParm( SRS_PP_FALSE_NORTHING, 0.0 ) );
    1309                 :     }
    1310                 :     
    1311               6 :     else if( EQUAL(pszProjection,SRS_PT_HOTINE_OBLIQUE_MERCATOR) )
    1312                 :     {
    1313                 :   GTIFKeySet(psGTIF, GTModelTypeGeoKey, TYPE_SHORT, 1,
    1314               0 :                    ModelTypeProjected);
    1315                 :   GTIFKeySet(psGTIF, ProjectedCSTypeGeoKey, TYPE_SHORT, 1,
    1316               0 :                    KvUserDefined );
    1317                 :   GTIFKeySet(psGTIF, ProjectionGeoKey, TYPE_SHORT, 1,
    1318               0 :                    KvUserDefined );
    1319                 : 
    1320                 :   GTIFKeySet(psGTIF, ProjCoordTransGeoKey, TYPE_SHORT, 1, 
    1321               0 :        CT_ObliqueMercator );
    1322                 : 
    1323                 :         GTIFKeySet(psGTIF, ProjCenterLatGeoKey, TYPE_DOUBLE, 1,
    1324               0 :                    poSRS->GetNormProjParm( SRS_PP_LATITUDE_OF_CENTER, 0.0 ) );
    1325                 : 
    1326                 :         GTIFKeySet(psGTIF, ProjCenterLongGeoKey, TYPE_DOUBLE, 1,
    1327               0 :                    poSRS->GetNormProjParm( SRS_PP_LONGITUDE_OF_CENTER, 0.0 ) );
    1328                 :         
    1329                 :         GTIFKeySet(psGTIF, ProjAzimuthAngleGeoKey, TYPE_DOUBLE, 1,
    1330               0 :                    poSRS->GetNormProjParm( SRS_PP_AZIMUTH, 0.0 ) );
    1331                 :         
    1332                 :         GTIFKeySet(psGTIF, ProjRectifiedGridAngleGeoKey, TYPE_DOUBLE, 1,
    1333               0 :                    poSRS->GetNormProjParm( SRS_PP_RECTIFIED_GRID_ANGLE, 0.0 ) );
    1334                 :         
    1335                 :         GTIFKeySet(psGTIF, ProjScaleAtCenterGeoKey, TYPE_DOUBLE, 1,
    1336               0 :                    poSRS->GetNormProjParm( SRS_PP_SCALE_FACTOR, 1.0 ) );
    1337                 :         
    1338                 :         GTIFKeySet(psGTIF, ProjFalseEastingGeoKey, TYPE_DOUBLE, 1,
    1339               0 :                    poSRS->GetNormProjParm( SRS_PP_FALSE_EASTING, 0.0 ) );
    1340                 :         
    1341                 :         GTIFKeySet(psGTIF, ProjFalseNorthingGeoKey, TYPE_DOUBLE, 1,
    1342               0 :                    poSRS->GetNormProjParm( SRS_PP_FALSE_NORTHING, 0.0 ) );
    1343                 :     }
    1344                 :     
    1345               6 :     else if( EQUAL(pszProjection,SRS_PT_CASSINI_SOLDNER) )
    1346                 :     {
    1347                 :   GTIFKeySet(psGTIF, GTModelTypeGeoKey, TYPE_SHORT, 1,
    1348               0 :                    ModelTypeProjected);
    1349                 :   GTIFKeySet(psGTIF, ProjectedCSTypeGeoKey, TYPE_SHORT, 1,
    1350               0 :                    KvUserDefined );
    1351                 :   GTIFKeySet(psGTIF, ProjectionGeoKey, TYPE_SHORT, 1,
    1352               0 :                    KvUserDefined );
    1353                 : 
    1354                 :   GTIFKeySet(psGTIF, ProjCoordTransGeoKey, TYPE_SHORT, 1, 
    1355               0 :        CT_CassiniSoldner );
    1356                 : 
    1357                 :         GTIFKeySet(psGTIF, ProjNatOriginLatGeoKey, TYPE_DOUBLE, 1,
    1358               0 :                    poSRS->GetNormProjParm( SRS_PP_LATITUDE_OF_ORIGIN, 0.0 ) );
    1359                 : 
    1360                 :         GTIFKeySet(psGTIF, ProjNatOriginLongGeoKey, TYPE_DOUBLE, 1,
    1361               0 :                    poSRS->GetNormProjParm( SRS_PP_CENTRAL_MERIDIAN, 0.0 ) );
    1362                 :         
    1363                 :         GTIFKeySet(psGTIF, ProjFalseEastingGeoKey, TYPE_DOUBLE, 1,
    1364               0 :                    poSRS->GetNormProjParm( SRS_PP_FALSE_EASTING, 0.0 ) );
    1365                 :         
    1366                 :         GTIFKeySet(psGTIF, ProjFalseNorthingGeoKey, TYPE_DOUBLE, 1,
    1367               0 :                    poSRS->GetNormProjParm( SRS_PP_FALSE_NORTHING, 0.0 ) );
    1368                 :     }
    1369                 :     
    1370               6 :     else if( EQUAL(pszProjection,SRS_PT_EQUIDISTANT_CONIC) )
    1371                 :     {
    1372                 :   GTIFKeySet(psGTIF, GTModelTypeGeoKey, TYPE_SHORT, 1,
    1373               0 :                    ModelTypeProjected);
    1374                 :   GTIFKeySet(psGTIF, ProjectedCSTypeGeoKey, TYPE_SHORT, 1,
    1375               0 :                    KvUserDefined );
    1376                 :   GTIFKeySet(psGTIF, ProjectionGeoKey, TYPE_SHORT, 1,
    1377               0 :                    KvUserDefined );
    1378                 : 
    1379                 :   GTIFKeySet(psGTIF, ProjCoordTransGeoKey, TYPE_SHORT, 1, 
    1380               0 :        CT_EquidistantConic );
    1381                 : 
    1382                 :         GTIFKeySet(psGTIF, ProjStdParallel1GeoKey, TYPE_DOUBLE, 1,
    1383               0 :                    poSRS->GetNormProjParm( SRS_PP_STANDARD_PARALLEL_1, 0.0 ) );
    1384                 : 
    1385                 :         GTIFKeySet(psGTIF, ProjStdParallel2GeoKey, TYPE_DOUBLE, 1,
    1386               0 :                    poSRS->GetNormProjParm( SRS_PP_STANDARD_PARALLEL_2, 0.0 ) );
    1387                 : 
    1388                 :         GTIFKeySet(psGTIF, ProjNatOriginLatGeoKey, TYPE_DOUBLE, 1,
    1389               0 :                    poSRS->GetNormProjParm( SRS_PP_LATITUDE_OF_CENTER, 0.0 ) );
    1390                 : 
    1391                 :         GTIFKeySet(psGTIF, ProjNatOriginLongGeoKey, TYPE_DOUBLE, 1,
    1392               0 :                    poSRS->GetNormProjParm( SRS_PP_LONGITUDE_OF_CENTER, 0.0 ) );
    1393                 :         
    1394                 :         GTIFKeySet(psGTIF, ProjFalseEastingGeoKey, TYPE_DOUBLE, 1,
    1395               0 :                    poSRS->GetNormProjParm( SRS_PP_FALSE_EASTING, 0.0 ) );
    1396                 :         
    1397                 :         GTIFKeySet(psGTIF, ProjFalseNorthingGeoKey, TYPE_DOUBLE, 1,
    1398               0 :                    poSRS->GetNormProjParm( SRS_PP_FALSE_NORTHING, 0.0 ) );
    1399                 :     }
    1400                 :     
    1401               6 :     else if( EQUAL(pszProjection,SRS_PT_POLYCONIC) )
    1402                 :     {
    1403                 :   GTIFKeySet(psGTIF, GTModelTypeGeoKey, TYPE_SHORT, 1,
    1404               0 :                    ModelTypeProjected);
    1405                 :   GTIFKeySet(psGTIF, ProjectedCSTypeGeoKey, TYPE_SHORT, 1,
    1406               0 :                    KvUserDefined );
    1407                 :   GTIFKeySet(psGTIF, ProjectionGeoKey, TYPE_SHORT, 1,
    1408               0 :                    KvUserDefined );
    1409                 : 
    1410                 :   GTIFKeySet(psGTIF, ProjCoordTransGeoKey, TYPE_SHORT, 1, 
    1411               0 :        CT_Polyconic );
    1412                 : 
    1413                 :         GTIFKeySet(psGTIF, ProjNatOriginLatGeoKey, TYPE_DOUBLE, 1,
    1414               0 :                    poSRS->GetNormProjParm( SRS_PP_LATITUDE_OF_ORIGIN, 0.0 ) );
    1415                 : 
    1416                 :         GTIFKeySet(psGTIF, ProjNatOriginLongGeoKey, TYPE_DOUBLE, 1,
    1417               0 :                    poSRS->GetNormProjParm( SRS_PP_CENTRAL_MERIDIAN, 0.0 ) );
    1418                 :         
    1419                 :         GTIFKeySet(psGTIF, ProjScaleAtNatOriginGeoKey, TYPE_DOUBLE, 1,
    1420               0 :                    poSRS->GetNormProjParm( SRS_PP_SCALE_FACTOR, 1.0 ) );
    1421                 :         
    1422                 :         GTIFKeySet(psGTIF, ProjFalseEastingGeoKey, TYPE_DOUBLE, 1,
    1423               0 :                    poSRS->GetNormProjParm( SRS_PP_FALSE_EASTING, 0.0 ) );
    1424                 :         
    1425                 :         GTIFKeySet(psGTIF, ProjFalseNorthingGeoKey, TYPE_DOUBLE, 1,
    1426               0 :                    poSRS->GetNormProjParm( SRS_PP_FALSE_NORTHING, 0.0 ) );
    1427                 :     }
    1428                 :     
    1429               6 :     else if( EQUAL(pszProjection,SRS_PT_AZIMUTHAL_EQUIDISTANT) )
    1430                 :     {
    1431                 :   GTIFKeySet(psGTIF, GTModelTypeGeoKey, TYPE_SHORT, 1,
    1432               1 :                    ModelTypeProjected);
    1433                 :   GTIFKeySet(psGTIF, ProjectedCSTypeGeoKey, TYPE_SHORT, 1,
    1434               1 :                    KvUserDefined );
    1435                 :   GTIFKeySet(psGTIF, ProjectionGeoKey, TYPE_SHORT, 1,
    1436               1 :                    KvUserDefined );
    1437                 : 
    1438                 :   GTIFKeySet(psGTIF, ProjCoordTransGeoKey, TYPE_SHORT, 1, 
    1439               1 :        CT_AzimuthalEquidistant );
    1440                 : 
    1441                 :         GTIFKeySet(psGTIF, ProjCenterLatGeoKey, TYPE_DOUBLE, 1,
    1442               1 :                    poSRS->GetNormProjParm( SRS_PP_LATITUDE_OF_CENTER, 0.0 ) );
    1443                 : 
    1444                 :         GTIFKeySet(psGTIF, ProjCenterLongGeoKey, TYPE_DOUBLE, 1,
    1445               1 :                    poSRS->GetNormProjParm( SRS_PP_LONGITUDE_OF_CENTER, 0.0 ) );
    1446                 :         
    1447                 :         GTIFKeySet(psGTIF, ProjFalseEastingGeoKey, TYPE_DOUBLE, 1,
    1448               1 :                    poSRS->GetNormProjParm( SRS_PP_FALSE_EASTING, 0.0 ) );
    1449                 :         
    1450                 :         GTIFKeySet(psGTIF, ProjFalseNorthingGeoKey, TYPE_DOUBLE, 1,
    1451               1 :                    poSRS->GetNormProjParm( SRS_PP_FALSE_NORTHING, 0.0 ) );
    1452                 :     }
    1453                 :     
    1454               5 :     else if( EQUAL(pszProjection,SRS_PT_MILLER_CYLINDRICAL) )
    1455                 :     {
    1456                 :   GTIFKeySet(psGTIF, GTModelTypeGeoKey, TYPE_SHORT, 1,
    1457               0 :                    ModelTypeProjected);
    1458                 :   GTIFKeySet(psGTIF, ProjectedCSTypeGeoKey, TYPE_SHORT, 1,
    1459               0 :                    KvUserDefined );
    1460                 :   GTIFKeySet(psGTIF, ProjectionGeoKey, TYPE_SHORT, 1,
    1461               0 :                    KvUserDefined );
    1462                 : 
    1463                 :   GTIFKeySet(psGTIF, ProjCoordTransGeoKey, TYPE_SHORT, 1, 
    1464               0 :        CT_MillerCylindrical );
    1465                 : 
    1466                 :         GTIFKeySet(psGTIF, ProjCenterLatGeoKey, TYPE_DOUBLE, 1,
    1467               0 :                    poSRS->GetNormProjParm( SRS_PP_LATITUDE_OF_CENTER, 0.0 ) );
    1468                 : 
    1469                 :         GTIFKeySet(psGTIF, ProjCenterLongGeoKey, TYPE_DOUBLE, 1,
    1470               0 :                    poSRS->GetNormProjParm( SRS_PP_LONGITUDE_OF_CENTER, 0.0 ) );
    1471                 :         
    1472                 :         GTIFKeySet(psGTIF, ProjFalseEastingGeoKey, TYPE_DOUBLE, 1,
    1473               0 :                    poSRS->GetNormProjParm( SRS_PP_FALSE_EASTING, 0.0 ) );
    1474                 :         
    1475                 :         GTIFKeySet(psGTIF, ProjFalseNorthingGeoKey, TYPE_DOUBLE, 1,
    1476               0 :                    poSRS->GetNormProjParm( SRS_PP_FALSE_NORTHING, 0.0 ) );
    1477                 :     }
    1478                 :     
    1479               5 :     else if( EQUAL(pszProjection,SRS_PT_EQUIRECTANGULAR) )
    1480                 :     {
    1481                 :   GTIFKeySet(psGTIF, GTModelTypeGeoKey, TYPE_SHORT, 1,
    1482               1 :                    ModelTypeProjected);
    1483                 :   GTIFKeySet(psGTIF, ProjectedCSTypeGeoKey, TYPE_SHORT, 1,
    1484               1 :                    KvUserDefined );
    1485                 :   GTIFKeySet(psGTIF, ProjectionGeoKey, TYPE_SHORT, 1,
    1486               1 :                    KvUserDefined );
    1487                 : 
    1488                 :   GTIFKeySet(psGTIF, ProjCoordTransGeoKey, TYPE_SHORT, 1, 
    1489               1 :        CT_Equirectangular );
    1490                 : 
    1491                 :         GTIFKeySet(psGTIF, ProjCenterLatGeoKey, TYPE_DOUBLE, 1,
    1492               1 :                    poSRS->GetNormProjParm( SRS_PP_LATITUDE_OF_ORIGIN, 0.0 ) );
    1493                 : 
    1494                 :         GTIFKeySet(psGTIF, ProjCenterLongGeoKey, TYPE_DOUBLE, 1,
    1495               1 :                    poSRS->GetNormProjParm( SRS_PP_CENTRAL_MERIDIAN, 0.0 ) );
    1496                 :         
    1497                 :         GTIFKeySet(psGTIF, ProjStdParallel1GeoKey, TYPE_DOUBLE, 1,
    1498               1 :                    poSRS->GetNormProjParm( SRS_PP_STANDARD_PARALLEL_1, 0.0 ) );
    1499                 :         
    1500                 :         GTIFKeySet(psGTIF, ProjFalseEastingGeoKey, TYPE_DOUBLE, 1,
    1501               1 :                    poSRS->GetNormProjParm( SRS_PP_FALSE_EASTING, 0.0 ) );
    1502                 :         
    1503                 :         GTIFKeySet(psGTIF, ProjFalseNorthingGeoKey, TYPE_DOUBLE, 1,
    1504               1 :                    poSRS->GetNormProjParm( SRS_PP_FALSE_NORTHING, 0.0 ) );
    1505                 :     }
    1506                 :     
    1507               4 :     else if( EQUAL(pszProjection,SRS_PT_GNOMONIC) )
    1508                 :     {
    1509                 :   GTIFKeySet(psGTIF, GTModelTypeGeoKey, TYPE_SHORT, 1,
    1510               0 :                    ModelTypeProjected);
    1511                 :   GTIFKeySet(psGTIF, ProjectedCSTypeGeoKey, TYPE_SHORT, 1,
    1512               0 :                    KvUserDefined );
    1513                 :   GTIFKeySet(psGTIF, ProjectionGeoKey, TYPE_SHORT, 1,
    1514               0 :                    KvUserDefined );
    1515                 : 
    1516                 :   GTIFKeySet(psGTIF, ProjCoordTransGeoKey, TYPE_SHORT, 1, 
    1517               0 :        CT_Gnomonic );
    1518                 : 
    1519                 :         GTIFKeySet(psGTIF, ProjCenterLatGeoKey, TYPE_DOUBLE, 1,
    1520               0 :                    poSRS->GetNormProjParm( SRS_PP_LATITUDE_OF_ORIGIN, 0.0 ) );
    1521                 : 
    1522                 :         GTIFKeySet(psGTIF, ProjCenterLongGeoKey, TYPE_DOUBLE, 1,
    1523               0 :                    poSRS->GetNormProjParm( SRS_PP_CENTRAL_MERIDIAN, 0.0 ) );
    1524                 :         
    1525                 :         GTIFKeySet(psGTIF, ProjFalseEastingGeoKey, TYPE_DOUBLE, 1,
    1526               0 :                    poSRS->GetNormProjParm( SRS_PP_FALSE_EASTING, 0.0 ) );
    1527                 :         
    1528                 :         GTIFKeySet(psGTIF, ProjFalseNorthingGeoKey, TYPE_DOUBLE, 1,
    1529               0 :                    poSRS->GetNormProjParm( SRS_PP_FALSE_NORTHING, 0.0 ) );
    1530                 :     }
    1531                 :     
    1532               4 :     else if( EQUAL(pszProjection,SRS_PT_LAMBERT_AZIMUTHAL_EQUAL_AREA) )
    1533                 :     {
    1534                 :   GTIFKeySet(psGTIF, GTModelTypeGeoKey, TYPE_SHORT, 1,
    1535               0 :                    ModelTypeProjected);
    1536                 :   GTIFKeySet(psGTIF, ProjectedCSTypeGeoKey, TYPE_SHORT, 1,
    1537               0 :                    KvUserDefined );
    1538                 :   GTIFKeySet(psGTIF, ProjectionGeoKey, TYPE_SHORT, 1,
    1539               0 :                    KvUserDefined );
    1540                 : 
    1541                 :   GTIFKeySet(psGTIF, ProjCoordTransGeoKey, TYPE_SHORT, 1, 
    1542               0 :        CT_LambertAzimEqualArea );
    1543                 : 
    1544                 :         GTIFKeySet(psGTIF, ProjCenterLatGeoKey, TYPE_DOUBLE, 1,
    1545               0 :                    poSRS->GetNormProjParm( SRS_PP_LATITUDE_OF_CENTER, 0.0 ) );
    1546                 : 
    1547                 :         GTIFKeySet(psGTIF, ProjCenterLongGeoKey, TYPE_DOUBLE, 1,
    1548               0 :                    poSRS->GetNormProjParm( SRS_PP_LONGITUDE_OF_CENTER, 0.0 ) );
    1549                 :         
    1550                 :         GTIFKeySet(psGTIF, ProjFalseEastingGeoKey, TYPE_DOUBLE, 1,
    1551               0 :                    poSRS->GetNormProjParm( SRS_PP_FALSE_EASTING, 0.0 ) );
    1552                 :         
    1553                 :         GTIFKeySet(psGTIF, ProjFalseNorthingGeoKey, TYPE_DOUBLE, 1,
    1554               0 :                    poSRS->GetNormProjParm( SRS_PP_FALSE_NORTHING, 0.0 ) );
    1555                 :     }
    1556                 :     
    1557               4 :     else if( EQUAL(pszProjection,SRS_PT_ORTHOGRAPHIC) )
    1558                 :     {
    1559                 :   GTIFKeySet(psGTIF, GTModelTypeGeoKey, TYPE_SHORT, 1,
    1560               0 :                    ModelTypeProjected);
    1561                 :   GTIFKeySet(psGTIF, ProjectedCSTypeGeoKey, TYPE_SHORT, 1,
    1562               0 :                    KvUserDefined );
    1563                 :   GTIFKeySet(psGTIF, ProjectionGeoKey, TYPE_SHORT, 1,
    1564               0 :                    KvUserDefined );
    1565                 : 
    1566                 :   GTIFKeySet(psGTIF, ProjCoordTransGeoKey, TYPE_SHORT, 1, 
    1567               0 :        CT_Orthographic );
    1568                 : 
    1569                 :         GTIFKeySet(psGTIF, ProjCenterLatGeoKey, TYPE_DOUBLE, 1,
    1570               0 :                    poSRS->GetNormProjParm( SRS_PP_LATITUDE_OF_ORIGIN, 0.0 ) );
    1571                 : 
    1572                 :         GTIFKeySet(psGTIF, ProjCenterLongGeoKey, TYPE_DOUBLE, 1,
    1573               0 :                    poSRS->GetNormProjParm( SRS_PP_CENTRAL_MERIDIAN, 0.0 ) );
    1574                 :         
    1575                 :         GTIFKeySet(psGTIF, ProjFalseEastingGeoKey, TYPE_DOUBLE, 1,
    1576               0 :                    poSRS->GetNormProjParm( SRS_PP_FALSE_EASTING, 0.0 ) );
    1577                 :         
    1578                 :         GTIFKeySet(psGTIF, ProjFalseNorthingGeoKey, TYPE_DOUBLE, 1,
    1579               0 :                    poSRS->GetNormProjParm( SRS_PP_FALSE_NORTHING, 0.0 ) );
    1580                 :     }
    1581                 :     
    1582               4 :     else if( EQUAL(pszProjection,SRS_PT_NEW_ZEALAND_MAP_GRID) )
    1583                 :     {
    1584                 :   GTIFKeySet(psGTIF, GTModelTypeGeoKey, TYPE_SHORT, 1,
    1585               0 :                    ModelTypeProjected);
    1586                 :   GTIFKeySet(psGTIF, ProjectedCSTypeGeoKey, TYPE_SHORT, 1,
    1587               0 :                    KvUserDefined );
    1588                 :   GTIFKeySet(psGTIF, ProjectionGeoKey, TYPE_SHORT, 1,
    1589               0 :                    KvUserDefined );
    1590                 : 
    1591                 :   GTIFKeySet(psGTIF, ProjCoordTransGeoKey, TYPE_SHORT, 1, 
    1592               0 :        CT_NewZealandMapGrid );
    1593                 : 
    1594                 :         GTIFKeySet(psGTIF, ProjNatOriginLatGeoKey, TYPE_DOUBLE, 1,
    1595               0 :                    poSRS->GetNormProjParm( SRS_PP_LATITUDE_OF_ORIGIN, 0.0 ) );
    1596                 : 
    1597                 :         GTIFKeySet(psGTIF, ProjNatOriginLongGeoKey, TYPE_DOUBLE, 1,
    1598               0 :                    poSRS->GetNormProjParm( SRS_PP_CENTRAL_MERIDIAN, 0.0 ) );
    1599                 :         
    1600                 :         GTIFKeySet(psGTIF, ProjFalseEastingGeoKey, TYPE_DOUBLE, 1,
    1601               0 :                    poSRS->GetNormProjParm( SRS_PP_FALSE_EASTING, 0.0 ) );
    1602                 :         
    1603                 :         GTIFKeySet(psGTIF, ProjFalseNorthingGeoKey, TYPE_DOUBLE, 1,
    1604               0 :                    poSRS->GetNormProjParm( SRS_PP_FALSE_NORTHING, 0.0 ) );
    1605                 :     }
    1606                 :     
    1607               4 :     else if( EQUAL(pszProjection,SRS_PT_ROBINSON) )
    1608                 :     {
    1609                 :   GTIFKeySet(psGTIF, GTModelTypeGeoKey, TYPE_SHORT, 1,
    1610               0 :                    ModelTypeProjected);
    1611                 :   GTIFKeySet(psGTIF, ProjectedCSTypeGeoKey, TYPE_SHORT, 1,
    1612               0 :                    KvUserDefined );
    1613                 :   GTIFKeySet(psGTIF, ProjectionGeoKey, TYPE_SHORT, 1,
    1614               0 :                    KvUserDefined );
    1615                 : 
    1616                 :   GTIFKeySet(psGTIF, ProjCoordTransGeoKey, TYPE_SHORT, 1, 
    1617               0 :        CT_Robinson );
    1618                 : 
    1619                 :         GTIFKeySet(psGTIF, ProjCenterLongGeoKey, TYPE_DOUBLE, 1,
    1620               0 :                    poSRS->GetNormProjParm( SRS_PP_LONGITUDE_OF_CENTER, 0.0 ) );
    1621                 :         
    1622                 :         GTIFKeySet(psGTIF, ProjFalseEastingGeoKey, TYPE_DOUBLE, 1,
    1623               0 :                    poSRS->GetNormProjParm( SRS_PP_FALSE_EASTING, 0.0 ) );
    1624                 :         
    1625                 :         GTIFKeySet(psGTIF, ProjFalseNorthingGeoKey, TYPE_DOUBLE, 1,
    1626               0 :                    poSRS->GetNormProjParm( SRS_PP_FALSE_NORTHING, 0.0 ) );
    1627                 :     }
    1628                 :     
    1629               4 :     else if( EQUAL(pszProjection,SRS_PT_SINUSOIDAL) )
    1630                 :     {
    1631                 :   GTIFKeySet(psGTIF, GTModelTypeGeoKey, TYPE_SHORT, 1,
    1632               1 :                    ModelTypeProjected);
    1633                 :   GTIFKeySet(psGTIF, ProjectedCSTypeGeoKey, TYPE_SHORT, 1,
    1634               1 :                    KvUserDefined );
    1635                 :   GTIFKeySet(psGTIF, ProjectionGeoKey, TYPE_SHORT, 1,
    1636               1 :                    KvUserDefined );
    1637                 : 
    1638                 :   GTIFKeySet(psGTIF, ProjCoordTransGeoKey, TYPE_SHORT, 1, 
    1639               1 :        CT_Sinusoidal );
    1640                 : 
    1641                 :         GTIFKeySet(psGTIF, ProjCenterLongGeoKey, TYPE_DOUBLE, 1,
    1642               1 :                    poSRS->GetNormProjParm( SRS_PP_LONGITUDE_OF_CENTER, 0.0 ) );
    1643                 :         
    1644                 :         GTIFKeySet(psGTIF, ProjFalseEastingGeoKey, TYPE_DOUBLE, 1,
    1645               1 :                    poSRS->GetNormProjParm( SRS_PP_FALSE_EASTING, 0.0 ) );
    1646                 :         
    1647                 :         GTIFKeySet(psGTIF, ProjFalseNorthingGeoKey, TYPE_DOUBLE, 1,
    1648               1 :                    poSRS->GetNormProjParm( SRS_PP_FALSE_NORTHING, 0.0 ) );
    1649                 :     }
    1650                 :     
    1651               3 :     else if( EQUAL(pszProjection,SRS_PT_VANDERGRINTEN) )
    1652                 :     {
    1653                 :   GTIFKeySet(psGTIF, GTModelTypeGeoKey, TYPE_SHORT, 1,
    1654               1 :                    ModelTypeProjected);
    1655                 :   GTIFKeySet(psGTIF, ProjectedCSTypeGeoKey, TYPE_SHORT, 1,
    1656               1 :                    KvUserDefined );
    1657                 :   GTIFKeySet(psGTIF, ProjectionGeoKey, TYPE_SHORT, 1,
    1658               1 :                    KvUserDefined );
    1659                 : 
    1660                 :   GTIFKeySet(psGTIF, ProjCoordTransGeoKey, TYPE_SHORT, 1, 
    1661               1 :        CT_VanDerGrinten );
    1662                 : 
    1663                 :         GTIFKeySet(psGTIF, ProjCenterLongGeoKey, TYPE_DOUBLE, 1,
    1664               1 :                    poSRS->GetNormProjParm( SRS_PP_CENTRAL_MERIDIAN, 0.0 ) );
    1665                 :         
    1666                 :         GTIFKeySet(psGTIF, ProjFalseEastingGeoKey, TYPE_DOUBLE, 1,
    1667               1 :                    poSRS->GetNormProjParm( SRS_PP_FALSE_EASTING, 0.0 ) );
    1668                 :         
    1669                 :         GTIFKeySet(psGTIF, ProjFalseNorthingGeoKey, TYPE_DOUBLE, 1,
    1670               1 :                    poSRS->GetNormProjParm( SRS_PP_FALSE_NORTHING, 0.0 ) );
    1671                 :     }
    1672                 :     
    1673               2 :     else if( EQUAL(pszProjection,SRS_PT_ALBERS_CONIC_EQUAL_AREA) )
    1674                 :     {
    1675                 :   GTIFKeySet(psGTIF, GTModelTypeGeoKey, TYPE_SHORT, 1,
    1676               0 :                    ModelTypeProjected);
    1677                 :   GTIFKeySet(psGTIF, ProjectedCSTypeGeoKey, TYPE_SHORT, 1,
    1678               0 :                    KvUserDefined );
    1679                 :   GTIFKeySet(psGTIF, ProjectionGeoKey, TYPE_SHORT, 1,
    1680               0 :                    KvUserDefined );
    1681                 : 
    1682                 :   GTIFKeySet(psGTIF, ProjCoordTransGeoKey, TYPE_SHORT, 1, 
    1683               0 :        CT_AlbersEqualArea );
    1684                 : 
    1685                 :         GTIFKeySet(psGTIF, ProjNatOriginLatGeoKey, TYPE_DOUBLE, 1,
    1686               0 :                    poSRS->GetNormProjParm( SRS_PP_LATITUDE_OF_CENTER, 0.0 ) );
    1687                 : 
    1688                 :         GTIFKeySet(psGTIF, ProjNatOriginLongGeoKey, TYPE_DOUBLE, 1,
    1689               0 :                    poSRS->GetNormProjParm( SRS_PP_LONGITUDE_OF_CENTER, 0.0 ) );
    1690                 :         
    1691                 :         GTIFKeySet(psGTIF, ProjStdParallel1GeoKey, TYPE_DOUBLE, 1,
    1692               0 :                    poSRS->GetNormProjParm( SRS_PP_STANDARD_PARALLEL_1, 0.0 ) );
    1693                 :         
    1694                 :         GTIFKeySet(psGTIF, ProjStdParallel2GeoKey, TYPE_DOUBLE, 1,
    1695               0 :                    poSRS->GetNormProjParm( SRS_PP_STANDARD_PARALLEL_2, 0.0 ) );
    1696                 :         
    1697                 :         GTIFKeySet(psGTIF, ProjFalseEastingGeoKey, TYPE_DOUBLE, 1,
    1698               0 :                    poSRS->GetNormProjParm( SRS_PP_FALSE_EASTING, 0.0 ) );
    1699                 :         
    1700                 :         GTIFKeySet(psGTIF, ProjFalseNorthingGeoKey, TYPE_DOUBLE, 1,
    1701               0 :                    poSRS->GetNormProjParm( SRS_PP_FALSE_NORTHING, 0.0 ) );
    1702                 :     }
    1703                 :     
    1704               2 :     else if( EQUAL(pszProjection,SRS_PT_LAMBERT_CONFORMAL_CONIC_2SP) )
    1705                 :     {
    1706                 :   GTIFKeySet(psGTIF, GTModelTypeGeoKey, TYPE_SHORT, 1,
    1707               1 :                    ModelTypeProjected);
    1708                 :   GTIFKeySet(psGTIF, ProjectedCSTypeGeoKey, TYPE_SHORT, 1,
    1709               1 :                    KvUserDefined );
    1710                 :   GTIFKeySet(psGTIF, ProjectionGeoKey, TYPE_SHORT, 1,
    1711               1 :                    KvUserDefined );
    1712                 : 
    1713                 :   GTIFKeySet(psGTIF, ProjCoordTransGeoKey, TYPE_SHORT, 1, 
    1714               1 :        CT_LambertConfConic_2SP );
    1715                 : 
    1716                 :         GTIFKeySet(psGTIF, ProjFalseOriginLatGeoKey, TYPE_DOUBLE, 1,
    1717               1 :                    poSRS->GetNormProjParm( SRS_PP_LATITUDE_OF_ORIGIN, 0.0 ) );
    1718                 : 
    1719                 :         GTIFKeySet(psGTIF, ProjFalseOriginLongGeoKey, TYPE_DOUBLE, 1,
    1720               1 :                    poSRS->GetNormProjParm( SRS_PP_CENTRAL_MERIDIAN, 0.0 ) );
    1721                 :         
    1722                 :         GTIFKeySet(psGTIF, ProjStdParallel1GeoKey, TYPE_DOUBLE, 1,
    1723               1 :                    poSRS->GetNormProjParm( SRS_PP_STANDARD_PARALLEL_1, 0.0 ) );
    1724                 :         
    1725                 :         GTIFKeySet(psGTIF, ProjStdParallel2GeoKey, TYPE_DOUBLE, 1,
    1726               1 :                    poSRS->GetNormProjParm( SRS_PP_STANDARD_PARALLEL_2, 0.0 ) );
    1727                 :         
    1728                 :         GTIFKeySet(psGTIF, ProjFalseOriginEastingGeoKey, TYPE_DOUBLE, 1,
    1729               1 :                    poSRS->GetNormProjParm( SRS_PP_FALSE_EASTING, 0.0 ) );
    1730                 :         
    1731                 :         GTIFKeySet(psGTIF, ProjFalseOriginNorthingGeoKey, TYPE_DOUBLE, 1,
    1732               1 :                    poSRS->GetNormProjParm( SRS_PP_FALSE_NORTHING, 0.0 ) );
    1733                 :     }
    1734                 :     
    1735               1 :     else if( EQUAL(pszProjection,SRS_PT_LAMBERT_CONFORMAL_CONIC_1SP) )
    1736                 :     {
    1737                 :   GTIFKeySet(psGTIF, GTModelTypeGeoKey, TYPE_SHORT, 1,
    1738               0 :                    ModelTypeProjected);
    1739                 :   GTIFKeySet(psGTIF, ProjectedCSTypeGeoKey, TYPE_SHORT, 1,
    1740               0 :                    KvUserDefined );
    1741                 :   GTIFKeySet(psGTIF, ProjectionGeoKey, TYPE_SHORT, 1,
    1742               0 :                    KvUserDefined );
    1743                 : 
    1744                 :   GTIFKeySet(psGTIF, ProjCoordTransGeoKey, TYPE_SHORT, 1, 
    1745               0 :        CT_LambertConfConic_1SP );
    1746                 : 
    1747                 :         GTIFKeySet(psGTIF, ProjNatOriginLatGeoKey, TYPE_DOUBLE, 1,
    1748               0 :                    poSRS->GetNormProjParm( SRS_PP_LATITUDE_OF_ORIGIN, 0.0 ) );
    1749                 : 
    1750                 :         GTIFKeySet(psGTIF, ProjNatOriginLongGeoKey, TYPE_DOUBLE, 1,
    1751               0 :                    poSRS->GetNormProjParm( SRS_PP_CENTRAL_MERIDIAN, 0.0 ) );
    1752                 :         
    1753                 :         GTIFKeySet(psGTIF, ProjScaleAtNatOriginGeoKey, TYPE_DOUBLE, 1,
    1754               0 :                    poSRS->GetNormProjParm( SRS_PP_SCALE_FACTOR, 1.0 ) );
    1755                 :         
    1756                 :         GTIFKeySet(psGTIF, ProjFalseEastingGeoKey, TYPE_DOUBLE, 1,
    1757               0 :                    poSRS->GetNormProjParm( SRS_PP_FALSE_EASTING, 0.0 ) );
    1758                 :         
    1759                 :         GTIFKeySet(psGTIF, ProjFalseNorthingGeoKey, TYPE_DOUBLE, 1,
    1760               0 :                    poSRS->GetNormProjParm( SRS_PP_FALSE_NORTHING, 0.0 ) );
    1761                 :     }
    1762                 : 
    1763               1 :     else if( EQUAL(pszProjection,SRS_PT_CYLINDRICAL_EQUAL_AREA) )
    1764                 :     {
    1765                 :   GTIFKeySet(psGTIF, GTModelTypeGeoKey, TYPE_SHORT, 1,
    1766               0 :                    ModelTypeProjected);
    1767                 :   GTIFKeySet(psGTIF, ProjectedCSTypeGeoKey, TYPE_SHORT, 1,
    1768               0 :                    KvUserDefined );
    1769                 :   GTIFKeySet(psGTIF, ProjectionGeoKey, TYPE_SHORT, 1,
    1770               0 :                    KvUserDefined );
    1771                 : 
    1772                 :   GTIFKeySet(psGTIF, ProjCoordTransGeoKey, TYPE_SHORT, 1, 
    1773               0 :        CT_CylindricalEqualArea );
    1774                 : 
    1775                 :         GTIFKeySet(psGTIF, ProjNatOriginLongGeoKey, TYPE_DOUBLE, 1,
    1776               0 :                    poSRS->GetNormProjParm( SRS_PP_CENTRAL_MERIDIAN, 0.0 ) );
    1777                 :         
    1778                 :         GTIFKeySet(psGTIF, ProjStdParallel1GeoKey, TYPE_DOUBLE, 1,
    1779               0 :                    poSRS->GetNormProjParm( SRS_PP_STANDARD_PARALLEL_1, 0.0 ) );
    1780                 :         
    1781                 :         GTIFKeySet(psGTIF, ProjFalseEastingGeoKey, TYPE_DOUBLE, 1,
    1782               0 :                    poSRS->GetNormProjParm( SRS_PP_FALSE_EASTING, 0.0 ) );
    1783                 :         
    1784                 :         GTIFKeySet(psGTIF, ProjFalseNorthingGeoKey, TYPE_DOUBLE, 1,
    1785               0 :                    poSRS->GetNormProjParm( SRS_PP_FALSE_NORTHING, 0.0 ) );
    1786                 :     }
    1787                 :     
    1788                 :     else
    1789                 :     {
    1790                 :         /* Anyhing we can't map, we store as an ESRI PE string with a citation key */
    1791               1 :         char *pszPEString = NULL;
    1792               1 :         poSRS->morphToESRI();
    1793               1 :         poSRS->exportToWkt( &pszPEString );
    1794               1 :         int peStrLen = strlen(pszPEString);
    1795               1 :         if(peStrLen > 0)
    1796                 :         {
    1797               1 :             char *outPeStr = new char[peStrLen + strlen("ESRI PE String = ")+1];
    1798               1 :             strcpy(outPeStr, "ESRI PE String = "); 
    1799               1 :             strcat(outPeStr, pszPEString); 
    1800               1 :             GTIFKeySet( psGTIF, PCSCitationGeoKey, TYPE_ASCII, 0, outPeStr ); 
    1801               1 :             peStrStored = TRUE;
    1802               1 :             delete[] outPeStr; 
    1803                 :         }
    1804               1 :         if(pszPEString)
    1805               1 :             CPLFree( pszPEString );
    1806                 :         GTIFKeySet(psGTIF, GTModelTypeGeoKey, TYPE_SHORT, 1,
    1807               1 :                    KvUserDefined );
    1808                 :     }
    1809                 :     
    1810                 : /* -------------------------------------------------------------------- */
    1811                 : /*      Write linear units information.                                 */
    1812                 : /* -------------------------------------------------------------------- */
    1813             701 :     if( !poSRS->IsGeographic() )
    1814                 :     {
    1815                 :         GTIFKeySet(psGTIF, ProjLinearUnitsGeoKey, TYPE_SHORT, 1, 
    1816             135 :                    nUOMLengthCode );
    1817             135 :         if( nUOMLengthCode == KvUserDefined )
    1818                 :             GTIFKeySet( psGTIF, ProjLinearUnitSizeGeoKey, TYPE_DOUBLE, 1, 
    1819               0 :                         dfLinearUOM);
    1820                 : 
    1821                 :         /* if linear units name is available and user defined, store it as citation */
    1822             135 :         if(!peStrStored && nUOMLengthCode == KvUserDefined && pszLinearUOMName && strlen(pszLinearUOMName)>0)
    1823               0 :             SetLinearUnitCitation(psGTIF, pszLinearUOMName);
    1824                 :     }
    1825                 :     
    1826                 : /* -------------------------------------------------------------------- */
    1827                 : /*      Write angular units.  Always Degrees for now.                   */
    1828                 : /*   Changed to support different angular units                         */
    1829                 : /* -------------------------------------------------------------------- */
    1830                 : 
    1831             701 :     char* angUnitName = NULL;
    1832             701 :     double angUnitValue = poSRS->GetAngularUnits(&angUnitName);
    1833             701 :     if(EQUAL(angUnitName, "Degree"))
    1834                 :         GTIFKeySet(psGTIF, GeogAngularUnitsGeoKey, TYPE_SHORT, 1, 
    1835             701 :                    Angular_Degree );
    1836               0 :     else if(angUnitName)
    1837                 :     {
    1838                 :         GTIFKeySet(psGTIF, GeogCitationGeoKey, TYPE_ASCII, 0, 
    1839               0 :                    angUnitName ); // it may be rewritten if the gcs is userdefined 
    1840                 :         GTIFKeySet(psGTIF, GeogAngularUnitSizeGeoKey, TYPE_DOUBLE, 1, 
    1841               0 :                    angUnitValue );
    1842                 :     }
    1843                 : 
    1844                 : /* -------------------------------------------------------------------- */
    1845                 : /*      Try to write a citation from the main coordinate system         */
    1846                 : /*      name.                                                           */
    1847                 : /* -------------------------------------------------------------------- */
    1848             701 :     if( poSRS->GetRoot() != NULL
    1849                 :         && poSRS->GetRoot()->GetChild(0) != NULL 
    1850                 :         && (poSRS->IsProjected() || poSRS->IsLocal()) )
    1851                 :     {
    1852                 :         GTIFKeySet( psGTIF, GTCitationGeoKey, TYPE_ASCII, 0, 
    1853             135 :                     poSRS->GetRoot()->GetChild(0)->GetValue() );
    1854                 :     }
    1855                 : 
    1856                 : /* -------------------------------------------------------------------- */
    1857                 : /*      Try to write a GCS citation.                                    */
    1858                 : /* -------------------------------------------------------------------- */
    1859             701 :     OGR_SRSNode *poGCS = poSRS->GetAttrNode( "GEOGCS" );
    1860                 : 
    1861             701 :     if( poGCS != NULL && poGCS->GetChild(0) != NULL )
    1862                 :     {
    1863                 :         GTIFKeySet( psGTIF, GeogCitationGeoKey, TYPE_ASCII, 0, 
    1864             701 :                     poGCS->GetChild(0)->GetValue() );
    1865                 :     }
    1866                 : 
    1867                 : /* -------------------------------------------------------------------- */
    1868                 : /*      Try to identify the GCS/datum, scanning the EPSG datum file for */
    1869                 : /*      a match.                                                        */
    1870                 : /* -------------------------------------------------------------------- */
    1871             701 :     if( nPCS == KvUserDefined )
    1872                 :     {
    1873             573 :         if( nGCS == KvUserDefined )
    1874                 :         {
    1875             274 :             if( nDatum == Datum_North_American_Datum_1927 )
    1876               0 :                 nGCS = GCS_NAD27;
    1877             274 :             else if( nDatum == Datum_North_American_Datum_1983 )
    1878               0 :                 nGCS = GCS_NAD83;
    1879             274 :             else if( nDatum == Datum_WGS84 || nDatum == DatumE_WGS84 )
    1880             265 :                 nGCS = GCS_WGS_84;
    1881                 :         }
    1882                 :             
    1883             573 :         if( nGCS != KvUserDefined )
    1884                 :         {
    1885                 :             GTIFKeySet( psGTIF, GeographicTypeGeoKey, TYPE_SHORT,
    1886             564 :                         1, nGCS );
    1887                 :         }
    1888               9 :         else if( nDatum != KvUserDefined )
    1889                 :         {
    1890                 :             GTIFKeySet( psGTIF, GeographicTypeGeoKey, TYPE_SHORT, 1, 
    1891               2 :                         KvUserDefined );
    1892                 :             GTIFKeySet( psGTIF, GeogGeodeticDatumGeoKey, TYPE_SHORT,
    1893               2 :                         1, nDatum );
    1894                 :         }
    1895               7 :         else if( nSpheroid != KvUserDefined )
    1896                 :         {
    1897                 :             GTIFKeySet( psGTIF, GeographicTypeGeoKey, TYPE_SHORT, 1, 
    1898               0 :                         KvUserDefined );
    1899                 :             GTIFKeySet( psGTIF, GeogGeodeticDatumGeoKey, TYPE_SHORT,
    1900               0 :                         1, KvUserDefined );
    1901                 :             GTIFKeySet( psGTIF, GeogEllipsoidGeoKey, TYPE_SHORT, 1, 
    1902               0 :                         nSpheroid );
    1903                 :         }
    1904               7 :         else if( dfSemiMajor != 0.0 )
    1905                 :         {
    1906                 :             GTIFKeySet( psGTIF, GeographicTypeGeoKey, TYPE_SHORT, 1, 
    1907               7 :                         KvUserDefined );
    1908                 :             GTIFKeySet( psGTIF, GeogGeodeticDatumGeoKey, TYPE_SHORT,
    1909               7 :                         1, KvUserDefined );
    1910                 :             GTIFKeySet( psGTIF, GeogEllipsoidGeoKey, TYPE_SHORT, 1, 
    1911               7 :                         KvUserDefined );
    1912                 :             GTIFKeySet( psGTIF, GeogSemiMajorAxisGeoKey, TYPE_DOUBLE, 1,
    1913               7 :                         dfSemiMajor );
    1914               7 :             if( dfInvFlattening == 0.0 )
    1915                 :                 GTIFKeySet( psGTIF, GeogSemiMinorAxisGeoKey, TYPE_DOUBLE, 1,
    1916               1 :                             dfSemiMajor );
    1917                 :             else
    1918                 :                 GTIFKeySet( psGTIF, GeogInvFlatteningGeoKey, TYPE_DOUBLE, 1,
    1919               6 :                             dfInvFlattening );
    1920                 :         }
    1921               0 :         else if( poSRS->GetAttrValue("DATUM") != NULL
    1922                 :                  && strstr(poSRS->GetAttrValue("DATUM"),"unknown") == NULL
    1923                 :                  && strstr(poSRS->GetAttrValue("DATUM"),"unnamed") == NULL )
    1924                 :                  
    1925                 :         {
    1926                 :             CPLError( CE_Warning, CPLE_AppDefined,
    1927                 :                       "Couldn't translate `%s' to a GeoTIFF datum.\n",
    1928               0 :                       poSRS->GetAttrValue("DATUM") );
    1929                 :         }
    1930                 : 
    1931                 :         /* Always set InvFlattening if it is avaliable.  */
    1932                 :         /* So that it doesn'tneed to calculate from SemiMinor */
    1933             573 :         if( dfInvFlattening != 0.0 )
    1934                 :             GTIFKeySet( psGTIF, GeogInvFlatteningGeoKey, TYPE_DOUBLE, 1,
    1935             570 :                         dfInvFlattening );
    1936                 :         /* Always set SemiMajor to keep the precision and in case of editing */
    1937             573 :         if( dfSemiMajor != 0.0 )
    1938                 :             GTIFKeySet( psGTIF, GeogSemiMajorAxisGeoKey, TYPE_DOUBLE, 1,
    1939             571 :                         dfSemiMajor );
    1940                 : 
    1941             573 :         if( nGCS == KvUserDefined )
    1942               9 :             SetGeogCSCitation(psGTIF, poSRS, angUnitName, nDatum, nSpheroid);
    1943                 :     }
    1944                 : 
    1945                 : /* -------------------------------------------------------------------- */
    1946                 : /*      Do we have vertical datum information to set?                   */
    1947                 : /* -------------------------------------------------------------------- */
    1948             701 :     if( poSRS->GetAttrValue( "COMPD_CS|VERT_CS" ) != NULL )
    1949                 :     {
    1950                 :         const char *pszValue;
    1951                 : 
    1952                 :         GTIFKeySet( psGTIF, VerticalCitationGeoKey, TYPE_ASCII, 0, 
    1953               0 :                     poSRS->GetAttrValue( "COMPD_CS|VERT_CS" ) );
    1954                 : 
    1955               0 :         pszValue = poSRS->GetAuthorityCode( "COMPD_CS|VERT_CS" );
    1956               0 :         if( pszValue && atoi(pszValue) )
    1957                 :             GTIFKeySet( psGTIF, VerticalCSTypeGeoKey, TYPE_SHORT, 1,
    1958               0 :                         atoi(pszValue) );
    1959                 :         
    1960               0 :         pszValue = poSRS->GetAuthorityCode( "COMPD_CS|VERT_CS|VERT_DATUM" );
    1961               0 :         if( pszValue && atoi(pszValue) )
    1962                 :             GTIFKeySet( psGTIF, VerticalDatumGeoKey, TYPE_SHORT, 1,
    1963               0 :                         atoi(pszValue) );
    1964                 :         
    1965               0 :         pszValue = poSRS->GetAuthorityCode( "COMPD_CS|VERT_CS|UNIT" );
    1966               0 :         if( pszValue && atoi(pszValue) )
    1967                 :             GTIFKeySet( psGTIF, VerticalUnitsGeoKey, TYPE_SHORT, 1,
    1968               0 :                         atoi(pszValue) );
    1969                 :     }
    1970                 : 
    1971                 : /* -------------------------------------------------------------------- */
    1972                 : /*      Cleanup                                                         */
    1973                 : /* -------------------------------------------------------------------- */
    1974             701 :     delete poSRS;
    1975             701 :     return TRUE;
    1976                 : }
    1977                 : 
    1978                 : /************************************************************************/
    1979                 : /*                         GTIFWktFromMemBuf()                          */
    1980                 : /************************************************************************/
    1981                 : 
    1982                 : CPLErr GTIFWktFromMemBuf( int nSize, unsigned char *pabyBuffer, 
    1983                 :                           char **ppszWKT, double *padfGeoTransform,
    1984              15 :                           int *pnGCPCount, GDAL_GCP **ppasGCPList )
    1985                 : 
    1986                 : {
    1987                 :     TIFF        *hTIFF;
    1988                 :     GTIF  *hGTIF;
    1989                 :     GTIFDefn  sGTIFDefn;
    1990                 :     char        szFilename[100];
    1991                 : 
    1992                 :     sprintf( szFilename, "/vsimem/wkt_from_mem_buf_%ld.tif", 
    1993              15 :              (long) CPLGetPID() );
    1994                 : 
    1995                 : /* -------------------------------------------------------------------- */
    1996                 : /*      Create a memory file from the buffer.                           */
    1997                 : /* -------------------------------------------------------------------- */
    1998              15 :     FILE *fp = VSIFileFromMemBuffer( szFilename, pabyBuffer, nSize, FALSE );
    1999              15 :     if( fp == NULL )
    2000               0 :         return CE_Failure;
    2001              15 :     VSIFCloseL( fp );
    2002                 : 
    2003                 : /* -------------------------------------------------------------------- */
    2004                 : /*      Initialize access to the memory geotiff structure.              */
    2005                 : /* -------------------------------------------------------------------- */
    2006              15 :     hTIFF = VSI_TIFFOpen( szFilename, "r" );
    2007                 : 
    2008              15 :     if( hTIFF == NULL )
    2009                 :     {
    2010                 :         CPLError( CE_Failure, CPLE_AppDefined,
    2011               0 :                   "TIFF/GeoTIFF structure is corrupt." );
    2012               0 :         VSIUnlink( szFilename );
    2013               0 :         return CE_Failure;
    2014                 :     }
    2015                 :     
    2016                 : /* -------------------------------------------------------------------- */
    2017                 : /*      Get the projection definition.                                  */
    2018                 : /* -------------------------------------------------------------------- */
    2019              15 :     hGTIF = GTIFNew(hTIFF);
    2020                 : 
    2021              15 :     if( hGTIF != NULL && GTIFGetDefn( hGTIF, &sGTIFDefn ) )
    2022              15 :         *ppszWKT = GTIFGetOGISDefn( hGTIF, &sGTIFDefn );
    2023                 :     else
    2024               0 :         *ppszWKT = NULL;
    2025                 :     
    2026              15 :     if( hGTIF )
    2027              15 :         GTIFFree( hGTIF );
    2028                 : 
    2029                 : /* -------------------------------------------------------------------- */
    2030                 : /*      Get geotransform or tiepoints.                                  */
    2031                 : /* -------------------------------------------------------------------- */
    2032                 :     double  *padfTiePoints, *padfScale, *padfMatrix;
    2033                 :     int16 nCount;
    2034                 : 
    2035              15 :     padfGeoTransform[0] = 0.0;
    2036              15 :     padfGeoTransform[1] = 1.0;
    2037              15 :     padfGeoTransform[2] = 0.0;
    2038              15 :     padfGeoTransform[3] = 0.0;
    2039              15 :     padfGeoTransform[4] = 0.0;
    2040              15 :     padfGeoTransform[5] = 1.0;
    2041                 : 
    2042              15 :     *pnGCPCount = 0;
    2043              15 :     *ppasGCPList = NULL;
    2044                 :     
    2045              15 :     if( TIFFGetField(hTIFF,TIFFTAG_GEOPIXELSCALE,&nCount,&padfScale )
    2046                 :         && nCount >= 2 )
    2047                 :     {
    2048              11 :         padfGeoTransform[1] = padfScale[0];
    2049              11 :         padfGeoTransform[5] = - ABS(padfScale[1]);
    2050                 : 
    2051              11 :         if( TIFFGetField(hTIFF,TIFFTAG_GEOTIEPOINTS,&nCount,&padfTiePoints )
    2052                 :             && nCount >= 6 )
    2053                 :         {
    2054                 :             padfGeoTransform[0] =
    2055              11 :                 padfTiePoints[3] - padfTiePoints[0] * padfGeoTransform[1];
    2056                 :             padfGeoTransform[3] =
    2057              11 :                 padfTiePoints[4] - padfTiePoints[1] * padfGeoTransform[5];
    2058                 :         }
    2059                 :     }
    2060                 : 
    2061               4 :     else if( TIFFGetField(hTIFF,TIFFTAG_GEOTIEPOINTS,&nCount,&padfTiePoints )
    2062                 :             && nCount >= 6 )
    2063                 :     {
    2064               4 :         *pnGCPCount = nCount / 6;
    2065               4 :         *ppasGCPList = (GDAL_GCP *) CPLCalloc(sizeof(GDAL_GCP),*pnGCPCount);
    2066                 :         
    2067              64 :         for( int iGCP = 0; iGCP < *pnGCPCount; iGCP++ )
    2068                 :         {
    2069                 :             char  szID[32];
    2070              60 :             GDAL_GCP  *psGCP = *ppasGCPList + iGCP;
    2071                 : 
    2072              60 :             sprintf( szID, "%d", iGCP+1 );
    2073              60 :             psGCP->pszId = CPLStrdup( szID );
    2074              60 :             psGCP->pszInfo = CPLStrdup("");
    2075              60 :             psGCP->dfGCPPixel = padfTiePoints[iGCP*6+0];
    2076              60 :             psGCP->dfGCPLine = padfTiePoints[iGCP*6+1];
    2077              60 :             psGCP->dfGCPX = padfTiePoints[iGCP*6+3];
    2078              60 :             psGCP->dfGCPY = padfTiePoints[iGCP*6+4];
    2079              60 :             psGCP->dfGCPZ = padfTiePoints[iGCP*6+5];
    2080                 :         }
    2081                 :     }
    2082                 : 
    2083               0 :     else if( TIFFGetField(hTIFF,TIFFTAG_GEOTRANSMATRIX,&nCount,&padfMatrix ) 
    2084                 :              && nCount == 16 )
    2085                 :     {
    2086               0 :         padfGeoTransform[0] = padfMatrix[3];
    2087               0 :         padfGeoTransform[1] = padfMatrix[0];
    2088               0 :         padfGeoTransform[2] = padfMatrix[1];
    2089               0 :         padfGeoTransform[3] = padfMatrix[7];
    2090               0 :         padfGeoTransform[4] = padfMatrix[4];
    2091               0 :         padfGeoTransform[5] = padfMatrix[5];
    2092                 :     }
    2093                 : 
    2094                 : /* -------------------------------------------------------------------- */
    2095                 : /*      Cleanup.                                                        */
    2096                 : /* -------------------------------------------------------------------- */
    2097              15 :     XTIFFClose( hTIFF );
    2098                 : 
    2099              15 :     VSIUnlink( szFilename );
    2100                 : 
    2101              15 :     if( *ppszWKT == NULL )
    2102               0 :         return CE_Failure;
    2103                 :     else
    2104              15 :         return CE_None;
    2105                 : }
    2106                 : 
    2107                 : /************************************************************************/
    2108                 : /*                         GTIFMemBufFromWkt()                          */
    2109                 : /************************************************************************/
    2110                 : 
    2111                 : CPLErr GTIFMemBufFromWkt( const char *pszWKT, const double *padfGeoTransform,
    2112                 :                           int nGCPCount, const GDAL_GCP *pasGCPList,
    2113               0 :                           int *pnSize, unsigned char **ppabyBuffer )
    2114                 : 
    2115                 : {
    2116                 :     TIFF        *hTIFF;
    2117                 :     GTIF  *hGTIF;
    2118                 :     char        szFilename[100];
    2119                 : 
    2120                 :     sprintf( szFilename, "/vsimem/wkt_from_mem_buf_%ld.tif", 
    2121               0 :              (long) CPLGetPID() );
    2122                 : 
    2123                 : /* -------------------------------------------------------------------- */
    2124                 : /*      Initialize access to the memory geotiff structure.              */
    2125                 : /* -------------------------------------------------------------------- */
    2126               0 :     hTIFF = VSI_TIFFOpen( szFilename, "w" );
    2127                 : 
    2128               0 :     if( hTIFF == NULL )
    2129                 :     {
    2130                 :         CPLError( CE_Failure, CPLE_AppDefined,
    2131               0 :                   "TIFF/GeoTIFF structure is corrupt." );
    2132               0 :         return CE_Failure;
    2133                 :     }
    2134                 : 
    2135                 : /* -------------------------------------------------------------------- */
    2136                 : /*      Write some minimal set of image parameters.                     */
    2137                 : /* -------------------------------------------------------------------- */
    2138               0 :     TIFFSetField( hTIFF, TIFFTAG_IMAGEWIDTH, 1 );
    2139               0 :     TIFFSetField( hTIFF, TIFFTAG_IMAGELENGTH, 1 );
    2140               0 :     TIFFSetField( hTIFF, TIFFTAG_BITSPERSAMPLE, 8 );
    2141               0 :     TIFFSetField( hTIFF, TIFFTAG_SAMPLESPERPIXEL, 1 );
    2142               0 :     TIFFSetField( hTIFF, TIFFTAG_ROWSPERSTRIP, 1 );
    2143               0 :     TIFFSetField( hTIFF, TIFFTAG_PLANARCONFIG, PLANARCONFIG_CONTIG );
    2144               0 :     TIFFSetField( hTIFF, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_MINISBLACK );
    2145                 :     
    2146                 : /* -------------------------------------------------------------------- */
    2147                 : /*      Get the projection definition.                                  */
    2148                 : /* -------------------------------------------------------------------- */
    2149                 : 
    2150               0 :     if( pszWKT != NULL )
    2151                 :     {
    2152               0 :         hGTIF = GTIFNew(hTIFF);
    2153               0 :         GTIFSetFromOGISDefn( hGTIF, pszWKT );
    2154               0 :         GTIFWriteKeys( hGTIF );
    2155               0 :         GTIFFree( hGTIF );
    2156                 :     }
    2157                 : 
    2158                 : /* -------------------------------------------------------------------- */
    2159                 : /*      Set the geotransform, or GCPs.                                  */
    2160                 : /* -------------------------------------------------------------------- */
    2161               0 :     if( padfGeoTransform[0] != 0.0 || padfGeoTransform[1] != 1.0
    2162                 :         || padfGeoTransform[2] != 0.0 || padfGeoTransform[3] != 0.0
    2163                 :         || padfGeoTransform[4] != 0.0 || ABS(padfGeoTransform[5]) != 1.0 )
    2164                 :     {
    2165                 : 
    2166               0 :         if( padfGeoTransform[2] == 0.0 && padfGeoTransform[4] == 0.0 )
    2167                 :         {
    2168                 :             double  adfPixelScale[3], adfTiePoints[6];
    2169                 : 
    2170               0 :             adfPixelScale[0] = padfGeoTransform[1];
    2171               0 :             adfPixelScale[1] = fabs(padfGeoTransform[5]);
    2172               0 :             adfPixelScale[2] = 0.0;
    2173                 : 
    2174               0 :             TIFFSetField( hTIFF, TIFFTAG_GEOPIXELSCALE, 3, adfPixelScale );
    2175                 :             
    2176               0 :             adfTiePoints[0] = 0.0;
    2177               0 :             adfTiePoints[1] = 0.0;
    2178               0 :             adfTiePoints[2] = 0.0;
    2179               0 :             adfTiePoints[3] = padfGeoTransform[0];
    2180               0 :             adfTiePoints[4] = padfGeoTransform[3];
    2181               0 :             adfTiePoints[5] = 0.0;
    2182                 :         
    2183               0 :             TIFFSetField( hTIFF, TIFFTAG_GEOTIEPOINTS, 6, adfTiePoints );
    2184                 :         }
    2185                 :         else
    2186                 :         {
    2187                 :             double  adfMatrix[16];
    2188                 : 
    2189               0 :             memset(adfMatrix,0,sizeof(double) * 16);
    2190                 : 
    2191               0 :             adfMatrix[0] = padfGeoTransform[1];
    2192               0 :             adfMatrix[1] = padfGeoTransform[2];
    2193               0 :             adfMatrix[3] = padfGeoTransform[0];
    2194               0 :             adfMatrix[4] = padfGeoTransform[4];
    2195               0 :             adfMatrix[5] = padfGeoTransform[5];
    2196               0 :             adfMatrix[7] = padfGeoTransform[3];
    2197               0 :             adfMatrix[15] = 1.0;
    2198                 : 
    2199               0 :             TIFFSetField( hTIFF, TIFFTAG_GEOTRANSMATRIX, 16, adfMatrix );
    2200                 :         }
    2201                 :     }
    2202                 : 
    2203                 : /* -------------------------------------------------------------------- */
    2204                 : /*      Otherwise write tiepoints if they are available.                */
    2205                 : /* -------------------------------------------------------------------- */
    2206               0 :     else if( nGCPCount > 0 )
    2207                 :     {
    2208                 :         double  *padfTiePoints;
    2209                 : 
    2210               0 :         padfTiePoints = (double *) CPLMalloc(6*sizeof(double)*nGCPCount);
    2211                 : 
    2212               0 :         for( int iGCP = 0; iGCP < nGCPCount; iGCP++ )
    2213                 :         {
    2214                 : 
    2215               0 :             padfTiePoints[iGCP*6+0] = pasGCPList[iGCP].dfGCPPixel;
    2216               0 :             padfTiePoints[iGCP*6+1] = pasGCPList[iGCP].dfGCPLine;
    2217               0 :             padfTiePoints[iGCP*6+2] = 0;
    2218               0 :             padfTiePoints[iGCP*6+3] = pasGCPList[iGCP].dfGCPX;
    2219               0 :             padfTiePoints[iGCP*6+4] = pasGCPList[iGCP].dfGCPY;
    2220               0 :             padfTiePoints[iGCP*6+5] = pasGCPList[iGCP].dfGCPZ;
    2221                 :         }
    2222                 : 
    2223               0 :         TIFFSetField( hTIFF, TIFFTAG_GEOTIEPOINTS, 6*nGCPCount, padfTiePoints);
    2224               0 :         CPLFree( padfTiePoints );
    2225                 :     } 
    2226                 : 
    2227                 : /* -------------------------------------------------------------------- */
    2228                 : /*      Cleanup and return the created memory buffer.                   */
    2229                 : /* -------------------------------------------------------------------- */
    2230               0 :     GByte bySmallImage = 0;
    2231                 : 
    2232               0 :     TIFFWriteEncodedStrip( hTIFF, 0, (char *) &bySmallImage, 1 );
    2233               0 :     TIFFWriteCheck( hTIFF, TIFFIsTiled(hTIFF), "GTIFMemBufFromWkt");
    2234               0 :     TIFFWriteDirectory( hTIFF );
    2235                 : 
    2236               0 :     XTIFFClose( hTIFF );
    2237                 : 
    2238                 : /* -------------------------------------------------------------------- */
    2239                 : /*      Read back from the memory buffer.  It would be preferrable      */
    2240                 : /*      to be able to "steal" the memory buffer, but there isn't        */
    2241                 : /*      currently any support for this.                                 */
    2242                 : /* -------------------------------------------------------------------- */
    2243                 :     GUIntBig nBigLength;
    2244                 : 
    2245               0 :     *ppabyBuffer = VSIGetMemFileBuffer( szFilename, &nBigLength, TRUE );
    2246               0 :     *pnSize = (int) nBigLength;
    2247                 : 
    2248               0 :     return CE_None;
    2249                 : }
    2250                 : 

Generated by: LTP GCOV extension version 1.5