Changeset 945:5df2cac62f01


Ignore:
Timestamp:
02/13/09 18:47:28 (18 months ago)
Author:
Howard Butler <hobu.inc@…>
Branch:
default
Convert:
svn:1766ff46-f334-0410-ab20-d63176f87757/trunk@1020
Message:

more LASSRS stuff, pull in GDAL's code

File:
1 edited

Legend:

Unmodified
Added
Removed
  • src/lassrs.cpp

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