/****************************************************************************** * $Id: gt_wkt_srs.cpp 15825 2008-11-27 22:26:58Z warmerdam $ * * Project: GeoTIFF Driver * Purpose: Implements translation between GeoTIFF normalized projection * definitions and OpenGIS WKT SRS format. This code is * deliberately GDAL free, and it is intended to be moved into * libgeotiff someday if possible. * Author: Frank Warmerdam, warmerdam@pobox.com * ****************************************************************************** * Copyright (c) 1999, Frank Warmerdam * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included * in all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. ****************************************************************************/ #include "libgeotiff/port/cpl_port.h" #include "libgeotiff/cpl_serv.h" #include "libgeotiff/geo_tiffp.h" #define CPL_ERROR_H_INCLUDED #include "libgeotiff/geo_normalize.h" #include "libgeotiff/geovalues.h" #include "libgeotiff/ogr/ogr_spatialref.h" #include "libgeotiff/gcore/gdal.h" #include "libgeotiff/xtiffio.h" #include "libgeotiff/port/cpl_multiproc.h" CPL_CVSID("$Id: gt_wkt_srs.cpp 15825 2008-11-27 22:26:58Z warmerdam $"); CPL_C_START void GTiffOneTimeInit(); int CPL_DLL VSIFCloseL( FILE * ); int CPL_DLL VSIUnlink( const char * ); FILE CPL_DLL *VSIFileFromMemBuffer( const char *pszFilename, GByte *pabyData, GUIntBig nDataLength, int bTakeOwnership ); GByte CPL_DLL *VSIGetMemFileBuffer( const char *pszFilename, GUIntBig *pnDataLength, int bUnlinkAndSeize ); char CPL_DLL * GTIFGetOGISDefn( GTIF *, GTIFDefn * ); int CPL_DLL GTIFSetFromOGISDefn( GTIF *, const char * ); CPLErr CPL_DLL GTIFMemBufFromWkt( const char *pszWKT, const double *padfGeoTransform, int nGCPCount, const GDAL_GCP *pasGCPList, int *pnSize, unsigned char **ppabyBuffer ); CPLErr CPL_DLL GTIFWktFromMemBuf( int nSize, unsigned char *pabyBuffer, char **ppszWKT, double *padfGeoTransform, int *pnGCPCount, GDAL_GCP **ppasGCPList ); CPL_C_END TIFF* VSI_TIFFOpen(const char* name, const char* mode); static const char *papszDatumEquiv[] = { "Militar_Geographische_Institut", "Militar_Geographische_Institute", "World_Geodetic_System_1984", "WGS_1984", "WGS_72_Transit_Broadcast_Ephemeris", "WGS_1972_Transit_Broadcast_Ephemeris", "World_Geodetic_System_1972", "WGS_1972", "European_Terrestrial_Reference_System_89", "European_Reference_System_1989", NULL }; // older libgeotiff's won't list this. #ifndef CT_CylindricalEqualArea # define CT_CylindricalEqualArea 28 #endif /************************************************************************/ /* WKTMassageDatum() */ /* */ /* Massage an EPSG datum name into WMT format. Also transform */ /* specific exception cases into WKT versions. */ /************************************************************************/ static void WKTMassageDatum( char ** ppszDatum ) { int i, j; char *pszDatum; /* -------------------------------------------------------------------- */ /* First copy string and allocate with our CPLStrdup() to so we */ /* know when we are done this function we will have a CPL */ /* string, not a GTIF one. */ /* -------------------------------------------------------------------- */ pszDatum = CPLStrdup(*ppszDatum); GTIFFreeMemory( *ppszDatum ); *ppszDatum = pszDatum; /* -------------------------------------------------------------------- */ /* Translate non-alphanumeric values to underscores. */ /* -------------------------------------------------------------------- */ for( i = 0; pszDatum[i] != '\0'; i++ ) { if( !(pszDatum[i] >= 'A' && pszDatum[i] <= 'Z') && !(pszDatum[i] >= 'a' && pszDatum[i] <= 'z') && !(pszDatum[i] >= '0' && pszDatum[i] <= '9') ) { pszDatum[i] = '_'; } } /* -------------------------------------------------------------------- */ /* Remove repeated and trailing underscores. */ /* -------------------------------------------------------------------- */ for( i = 1, j = 0; pszDatum[i] != '\0'; i++ ) { if( pszDatum[j] == '_' && pszDatum[i] == '_' ) continue; pszDatum[++j] = pszDatum[i]; } if( pszDatum[j] == '_' ) pszDatum[j] = '\0'; else pszDatum[j+1] = '\0'; /* -------------------------------------------------------------------- */ /* Search for datum equivelences. Specific massaged names get */ /* mapped to OpenGIS specified names. */ /* -------------------------------------------------------------------- */ for( i = 0; papszDatumEquiv[i] != NULL; i += 2 ) { if( EQUAL(*ppszDatum,papszDatumEquiv[i]) ) { CPLFree( *ppszDatum ); *ppszDatum = CPLStrdup( papszDatumEquiv[i+1] ); return; } } } /************************************************************************/ /* GTIFCleanupImageineNames() */ /* */ /* Erdas Imagine sometimes emits big copyright messages, and */ /* other stuff into citations. These can be pretty messy when */ /* turned into WKT, so we try to trim and clean the strings */ /* somewhat. */ /************************************************************************/ /* For example: GTCitationGeoKey (Ascii,215): "IMAGINE GeoTIFF Support\nCopyright 1991 - 2001 by ERDAS, Inc. All Rights Reserved\n@(#)$RCSfile$ $Revision: 15825 $ $Date: 2008-11-27 14:26:58 -0800 (Thu, 27 Nov 2008) $\nProjection Name = UTM\nUnits = meters\nGeoTIFF Units = meters" GeogCitationGeoKey (Ascii,267): "IMAGINE GeoTIFF Support\nCopyright 1991 - 2001 by ERDAS, Inc. All Rights Reserved\n@(#)$RCSfile$ $Revision: 15825 $ $Date: 2008-11-27 14:26:58 -0800 (Thu, 27 Nov 2008) $\nUnable to match Ellipsoid (Datum) to a GeographicTypeGeoKey value\nEllipsoid = Clarke 1866\nDatum = NAD27 (CONUS)" PCSCitationGeoKey (Ascii,214): "IMAGINE GeoTIFF Support\nCopyright 1991 - 2001 by ERDAS, Inc. All Rights Reserved\n@(#)$RCSfile$ $Revision: 15825 $ $Date: 2008-11-27 14:26:58 -0800 (Thu, 27 Nov 2008) $\nUTM Zone 10N\nEllipsoid = Clarke 1866\nDatum = NAD27 (CONUS)" */ static void GTIFCleanupImagineNames( char *pszCitation ) { if( strstr(pszCitation,"IMAGINE GeoTIFF") == NULL ) return; /* -------------------------------------------------------------------- */ /* First, we skip past all the copyright, and RCS stuff. We */ /* assume that this will have a "$" at the end of it all. */ /* -------------------------------------------------------------------- */ char *pszSkip; for( pszSkip = pszCitation + strlen(pszCitation) - 1; pszSkip != pszCitation && *pszSkip != '$'; pszSkip-- ) {} if( *pszSkip == '$' ) pszSkip++; memmove( pszCitation, pszSkip, strlen(pszSkip)+1 ); /* -------------------------------------------------------------------- */ /* Convert any newlines into spaces, they really gum up the */ /* WKT. */ /* -------------------------------------------------------------------- */ int i; for( i = 0; pszCitation[i] != '\0'; i++ ) { if( pszCitation[i] == '\n' ) pszCitation[i] = ' '; } } /************************************************************************/ /* GTIFGetOGISDefn() */ /************************************************************************/ char *GTIFGetOGISDefn( GTIF *hGTIF, GTIFDefn * psDefn ) { OGRSpatialReference oSRS; /* -------------------------------------------------------------------- */ /* Handle non-standard coordinate systems as LOCAL_CS. */ /* -------------------------------------------------------------------- */ if( psDefn->Model != ModelTypeProjected && psDefn->Model != ModelTypeGeographic ) { char *pszWKT; char *pszUnitsName = NULL; char szPCSName[300]; int nKeyCount = 0; int anVersion[3]; if( hGTIF != NULL ) GTIFDirectoryInfo( hGTIF, anVersion, &nKeyCount ); if( nKeyCount > 0 ) // Use LOCAL_CS if we have any geokeys at all. { // Handle citation. strcpy( szPCSName, "unnamed" ); if( !GTIFKeyGet( hGTIF, GTCitationGeoKey, szPCSName, 0, sizeof(szPCSName) ) ) GTIFKeyGet( hGTIF, GeogCitationGeoKey, szPCSName, 0, sizeof(szPCSName) ); GTIFCleanupImagineNames( szPCSName ); oSRS.SetLocalCS( szPCSName ); // Handle units GTIFGetUOMLengthInfo( psDefn->UOMLength, &pszUnitsName, NULL ); if( pszUnitsName != NULL && psDefn->UOMLength != KvUserDefined ) { oSRS.SetLinearUnits( pszUnitsName, psDefn->UOMLengthInMeters ); oSRS.SetAuthority( "LOCAL_CS|UNIT", "EPSG", psDefn->UOMLength); } else oSRS.SetLinearUnits( "unknown", psDefn->UOMLengthInMeters ); GTIFFreeMemory( pszUnitsName ); } oSRS.exportToWkt( &pszWKT ); return pszWKT; } /* -------------------------------------------------------------------- */ /* If this is a projected SRS we set the PROJCS keyword first */ /* to ensure that the GEOGCS will be a child. */ /* -------------------------------------------------------------------- */ if( psDefn->Model == ModelTypeProjected ) { if( psDefn->PCS != KvUserDefined ) { char *pszPCSName = NULL; GTIFGetPCSInfo( psDefn->PCS, &pszPCSName, NULL, NULL, NULL ); oSRS.SetNode( "PROJCS", pszPCSName ? pszPCSName : "unnamed" ); if ( pszPCSName ) GTIFFreeMemory( pszPCSName ); oSRS.SetAuthority( "PROJCS", "EPSG", psDefn->PCS ); } else { char szPCSName[300]; strcpy( szPCSName, "unnamed" ); if( hGTIF != NULL ) { GTIFKeyGet( hGTIF, GTCitationGeoKey, szPCSName, 0, sizeof(szPCSName) ); GTIFCleanupImagineNames( szPCSName ); } oSRS.SetNode( "PROJCS", szPCSName ); } } /* ==================================================================== */ /* Setup the GeogCS */ /* ==================================================================== */ char *pszGeogName = NULL; char *pszDatumName = NULL; char *pszPMName = NULL; char *pszSpheroidName = NULL; char *pszAngularUnits = NULL; double dfInvFlattening, dfSemiMajor; char szGCSName[300]; if( !GTIFGetGCSInfo( psDefn->GCS, &pszGeogName, NULL, NULL, NULL ) && hGTIF != NULL && GTIFKeyGet( hGTIF, GeogCitationGeoKey, szGCSName, 0, sizeof(szGCSName)) ) { GTIFCleanupImagineNames( szGCSName ); pszGeogName = CPLStrdup(szGCSName); } GTIFGetDatumInfo( psDefn->Datum, &pszDatumName, NULL ); GTIFGetPMInfo( psDefn->PM, &pszPMName, NULL ); GTIFGetEllipsoidInfo( psDefn->Ellipsoid, &pszSpheroidName, NULL, NULL ); GTIFGetUOMAngleInfo( psDefn->UOMAngle, &pszAngularUnits, NULL ); if( pszAngularUnits == NULL ) pszAngularUnits = CPLStrdup("unknown"); if( pszDatumName != NULL ) WKTMassageDatum( &pszDatumName ); dfSemiMajor = psDefn->SemiMajor; if( psDefn->SemiMajor == 0.0 ) { pszSpheroidName = CPLStrdup("unretrievable - using WGS84"); dfSemiMajor = SRS_WGS84_SEMIMAJOR; dfInvFlattening = SRS_WGS84_INVFLATTENING; } else if( (psDefn->SemiMinor / psDefn->SemiMajor) < 0.99999999999999999 || (psDefn->SemiMinor / psDefn->SemiMajor) > 1.00000000000000001 ) dfInvFlattening = -1.0 / (psDefn->SemiMinor/psDefn->SemiMajor - 1.0); else dfInvFlattening = 0.0; /* special flag for infinity */ oSRS.SetGeogCS( pszGeogName, pszDatumName, pszSpheroidName, dfSemiMajor, dfInvFlattening, pszPMName, psDefn->PMLongToGreenwich / psDefn->UOMAngleInDegrees, pszAngularUnits, psDefn->UOMAngleInDegrees * 0.0174532925199433 ); if( psDefn->GCS != KvUserDefined && psDefn->GCS > 0 ) oSRS.SetAuthority( "GEOGCS", "EPSG", psDefn->GCS ); if( psDefn->Datum != KvUserDefined ) oSRS.SetAuthority( "DATUM", "EPSG", psDefn->Datum ); if( psDefn->Ellipsoid != KvUserDefined ) oSRS.SetAuthority( "SPHEROID", "EPSG", psDefn->Ellipsoid ); CPLFree( pszGeogName ); CPLFree( pszDatumName ); GTIFFreeMemory( pszPMName ); GTIFFreeMemory( pszSpheroidName ); GTIFFreeMemory( pszAngularUnits ); /* ==================================================================== */ /* Handle projection parameters. */ /* ==================================================================== */ if( psDefn->Model == ModelTypeProjected ) { /* -------------------------------------------------------------------- */ /* Make a local copy of parms, and convert back into the */ /* angular units of the GEOGCS and the linear units of the */ /* projection. */ /* -------------------------------------------------------------------- */ double adfParm[10]; int i; for( i = 0; i < MIN(10,psDefn->nParms); i++ ) adfParm[i] = psDefn->ProjParm[i]; for( ; i < 10; i++ ) adfParm[i] = 0.0; adfParm[0] *= psDefn->UOMAngleInDegrees; adfParm[1] *= psDefn->UOMAngleInDegrees; adfParm[2] *= psDefn->UOMAngleInDegrees; adfParm[3] *= psDefn->UOMAngleInDegrees; adfParm[5] /= psDefn->UOMLengthInMeters; adfParm[6] /= psDefn->UOMLengthInMeters; /* -------------------------------------------------------------------- */ /* Translation the fundamental projection. */ /* -------------------------------------------------------------------- */ switch( psDefn->CTProjection ) { case CT_TransverseMercator: oSRS.SetTM( adfParm[0], adfParm[1], adfParm[4], adfParm[5], adfParm[6] ); break; case CT_TransvMercator_SouthOriented: oSRS.SetTMSO( adfParm[0], adfParm[1], adfParm[4], adfParm[5], adfParm[6] ); break; case CT_Mercator: oSRS.SetMercator( adfParm[0], adfParm[1], adfParm[4], adfParm[5], adfParm[6] ); break; case CT_ObliqueStereographic: oSRS.SetOS( adfParm[0], adfParm[1], adfParm[4], adfParm[5], adfParm[6] ); break; case CT_Stereographic: oSRS.SetOS( adfParm[0], adfParm[1], adfParm[4], adfParm[5], adfParm[6] ); break; case CT_ObliqueMercator: /* hotine */ oSRS.SetHOM( adfParm[0], adfParm[1], adfParm[2], adfParm[3], adfParm[4], adfParm[5], adfParm[6] ); break; case CT_EquidistantConic: oSRS.SetEC( adfParm[0], adfParm[1], adfParm[2], adfParm[3], adfParm[5], adfParm[6] ); break; case CT_CassiniSoldner: oSRS.SetCS( adfParm[0], adfParm[1], adfParm[5], adfParm[6] ); break; case CT_Polyconic: oSRS.SetPolyconic( adfParm[0], adfParm[1], adfParm[5], adfParm[6] ); break; case CT_AzimuthalEquidistant: oSRS.SetAE( adfParm[0], adfParm[1], adfParm[5], adfParm[6] ); break; case CT_MillerCylindrical: oSRS.SetMC( adfParm[0], adfParm[1], adfParm[5], adfParm[6] ); break; case CT_Equirectangular: oSRS.SetEquirectangular2( adfParm[0], adfParm[1], adfParm[2], adfParm[5], adfParm[6] ); break; case CT_Gnomonic: oSRS.SetGnomonic( adfParm[0], adfParm[1], adfParm[5], adfParm[6] ); break; case CT_LambertAzimEqualArea: oSRS.SetLAEA( adfParm[0], adfParm[1], adfParm[5], adfParm[6] ); break; case CT_Orthographic: oSRS.SetOrthographic( adfParm[0], adfParm[1], adfParm[5], adfParm[6] ); break; case CT_Robinson: oSRS.SetRobinson( adfParm[1], adfParm[5], adfParm[6] ); break; case CT_Sinusoidal: oSRS.SetSinusoidal( adfParm[1], adfParm[5], adfParm[6] ); break; case CT_VanDerGrinten: oSRS.SetVDG( adfParm[1], adfParm[5], adfParm[6] ); break; case CT_PolarStereographic: oSRS.SetPS( adfParm[0], adfParm[1], adfParm[4], adfParm[5], adfParm[6] ); break; case CT_LambertConfConic_2SP: oSRS.SetLCC( adfParm[2], adfParm[3], adfParm[0], adfParm[1], adfParm[5], adfParm[6] ); break; case CT_LambertConfConic_1SP: oSRS.SetLCC1SP( adfParm[0], adfParm[1], adfParm[4], adfParm[5], adfParm[6] ); break; case CT_AlbersEqualArea: oSRS.SetACEA( adfParm[0], adfParm[1], adfParm[2], adfParm[3], adfParm[5], adfParm[6] ); break; case CT_NewZealandMapGrid: oSRS.SetNZMG( adfParm[0], adfParm[1], adfParm[5], adfParm[6] ); break; case CT_CylindricalEqualArea: oSRS.SetCEA( adfParm[0], adfParm[1], adfParm[5], adfParm[6] ); break; } /* -------------------------------------------------------------------- */ /* Set projection units. */ /* -------------------------------------------------------------------- */ char *pszUnitsName = NULL; GTIFGetUOMLengthInfo( psDefn->UOMLength, &pszUnitsName, NULL ); if( pszUnitsName != NULL && psDefn->UOMLength != KvUserDefined ) { oSRS.SetLinearUnits( pszUnitsName, psDefn->UOMLengthInMeters ); oSRS.SetAuthority( "PROJCS|UNIT", "EPSG", psDefn->UOMLength ); } else oSRS.SetLinearUnits( "unknown", psDefn->UOMLengthInMeters ); GTIFFreeMemory( pszUnitsName ); } /* -------------------------------------------------------------------- */ /* Return the WKT serialization of the object. */ /* -------------------------------------------------------------------- */ char *pszWKT; oSRS.FixupOrdering(); if( oSRS.exportToWkt( &pszWKT ) == OGRERR_NONE ) return pszWKT; else return NULL; } /************************************************************************/ /* OGCDatumName2EPSGDatumCode() */ /************************************************************************/ static int OGCDatumName2EPSGDatumCode( const char * pszOGCName ) { FILE *fp; char **papszTokens; int nReturn = KvUserDefined; /* -------------------------------------------------------------------- */ /* Do we know it as a built in? */ /* -------------------------------------------------------------------- */ if( EQUAL(pszOGCName,"NAD27") || EQUAL(pszOGCName,"North_American_Datum_1927") ) return Datum_North_American_Datum_1927; else if( EQUAL(pszOGCName,"NAD83") || EQUAL(pszOGCName,"North_American_Datum_1983") ) return Datum_North_American_Datum_1983; else if( EQUAL(pszOGCName,"WGS84") || EQUAL(pszOGCName,"WGS_1984") || EQUAL(pszOGCName,"WGS 84")) return Datum_WGS84; else if( EQUAL(pszOGCName,"WGS72") || EQUAL(pszOGCName,"WGS_1972") ) return Datum_WGS72; /* -------------------------------------------------------------------- */ /* Open the table if possible. */ /* -------------------------------------------------------------------- */ fp = VSIFOpen( CSVFilename("gdal_datum.csv"), "r" ); if( fp == NULL ) fp = VSIFOpen( CSVFilename("datum.csv"), "r" ); if( fp == NULL ) return nReturn; /* -------------------------------------------------------------------- */ /* Discard the first line with field names. */ /* -------------------------------------------------------------------- */ CSLDestroy( CSVReadParseLine( fp ) ); /* -------------------------------------------------------------------- */ /* Read lines looking for our datum. */ /* -------------------------------------------------------------------- */ for( papszTokens = CSVReadParseLine( fp ); CSLCount(papszTokens) > 2 && nReturn == KvUserDefined; papszTokens = CSVReadParseLine( fp ) ) { WKTMassageDatum( papszTokens + 1 ); if( EQUAL(papszTokens[1], pszOGCName) ) nReturn = atoi(papszTokens[0]); CSLDestroy( papszTokens ); } CSLDestroy( papszTokens ); VSIFClose( fp ); return nReturn; } /************************************************************************/ /* GTIFSetFromOGISDefn() */ /* */ /* Write GeoTIFF projection tags from an OGC WKT definition. */ /************************************************************************/ int GTIFSetFromOGISDefn( GTIF * psGTIF, const char *pszOGCWKT ) { OGRSpatialReference *poSRS; int nPCS = KvUserDefined; OGRErr eErr; GTIFKeySet(psGTIF, GTRasterTypeGeoKey, TYPE_SHORT, 1, RasterPixelIsArea); /* -------------------------------------------------------------------- */ /* Create an OGRSpatialReference object corresponding to the */ /* string. */ /* -------------------------------------------------------------------- */ poSRS = new OGRSpatialReference(); if( poSRS->importFromWkt((char **) &pszOGCWKT) != OGRERR_NONE ) { delete poSRS; return FALSE; } /* -------------------------------------------------------------------- */ /* Get the ellipsoid definition. */ /* -------------------------------------------------------------------- */ short nSpheroid = KvUserDefined; double dfSemiMajor, dfInvFlattening; if( poSRS->GetAuthorityName("PROJCS|GEOGCS|DATUM|SPHEROID") != NULL && EQUAL(poSRS->GetAuthorityName("PROJCS|GEOGCS|DATUM|SPHEROID"), "EPSG")) { nSpheroid = (short) atoi(poSRS->GetAuthorityCode("PROJCS|GEOGCS|DATUM|SPHEROID")); } else if( poSRS->GetAuthorityName("GEOGCS|DATUM|SPHEROID") != NULL && EQUAL(poSRS->GetAuthorityName("GEOGCS|DATUM|SPHEROID"),"EPSG")) { nSpheroid = (short) atoi(poSRS->GetAuthorityCode("GEOGCS|DATUM|SPHEROID")); } dfSemiMajor = poSRS->GetSemiMajor( &eErr ); dfInvFlattening = poSRS->GetInvFlattening( &eErr ); if( eErr != OGRERR_NONE ) { dfSemiMajor = 0.0; dfInvFlattening = 0.0; } /* -------------------------------------------------------------------- */ /* Get the Datum so we can special case a few PCS codes. */ /* -------------------------------------------------------------------- */ int nDatum = KvUserDefined; if( poSRS->GetAuthorityName("PROJCS|GEOGCS|DATUM") != NULL && EQUAL(poSRS->GetAuthorityName("PROJCS|GEOGCS|DATUM"),"EPSG") ) nDatum = atoi(poSRS->GetAuthorityCode("PROJCS|GEOGCS|DATUM")); else if( poSRS->GetAuthorityName("GEOGCS|DATUM") != NULL && EQUAL(poSRS->GetAuthorityName("GEOGCS|DATUM"),"EPSG") ) nDatum = atoi(poSRS->GetAuthorityCode("GEOGCS|DATUM")); else if( poSRS->GetAttrValue("DATUM") != NULL ) nDatum = OGCDatumName2EPSGDatumCode( poSRS->GetAttrValue("DATUM") ); /* -------------------------------------------------------------------- */ /* Get the GCS if possible. */ /* -------------------------------------------------------------------- */ int nGCS = KvUserDefined; if( poSRS->GetAuthorityName("PROJCS|GEOGCS") != NULL && EQUAL(poSRS->GetAuthorityName("PROJCS|GEOGCS"),"EPSG") ) nGCS = atoi(poSRS->GetAuthorityCode("PROJCS|GEOGCS")); else if( poSRS->GetAuthorityName("GEOGCS") != NULL && EQUAL(poSRS->GetAuthorityName("GEOGCS"),"EPSG") ) nGCS = atoi(poSRS->GetAuthorityCode("GEOGCS")); if( nGCS > 32767 ) nGCS = KvUserDefined; /* -------------------------------------------------------------------- */ /* Get the linear units. */ /* -------------------------------------------------------------------- */ char *pszLinearUOMName = NULL; double dfLinearUOM = poSRS->GetLinearUnits( &pszLinearUOMName ); int nUOMLengthCode = 9001; /* meters */ if( (pszLinearUOMName != NULL && EQUAL(pszLinearUOMName,SRS_UL_FOOT)) || dfLinearUOM == atof(SRS_UL_FOOT_CONV) ) nUOMLengthCode = 9002; /* international foot */ else if( (pszLinearUOMName != NULL && EQUAL(pszLinearUOMName,SRS_UL_US_FOOT)) || ABS(dfLinearUOM-atof(SRS_UL_US_FOOT_CONV)) < 0.0000001 ) nUOMLengthCode = 9003; /* us survey foot */ else if( dfLinearUOM != 1.0 ) nUOMLengthCode = KvUserDefined; /* -------------------------------------------------------------------- */ /* Get some authority values. */ /* -------------------------------------------------------------------- */ if( poSRS->GetAuthorityName("PROJCS") != NULL && EQUAL(poSRS->GetAuthorityName("PROJCS"),"EPSG") ) { nPCS = atoi(poSRS->GetAuthorityCode("PROJCS")); if( nPCS > 32767 ) nPCS = KvUserDefined; } /* -------------------------------------------------------------------- */ /* Handle the projection transformation. */ /* -------------------------------------------------------------------- */ const char *pszProjection = poSRS->GetAttrValue( "PROJECTION" ); if( nPCS != KvUserDefined ) { GTIFKeySet(psGTIF, GTModelTypeGeoKey, TYPE_SHORT, 1, ModelTypeProjected); GTIFKeySet(psGTIF, ProjectedCSTypeGeoKey, TYPE_SHORT, 1, nPCS ); } else if( pszProjection == NULL ) { if( poSRS->IsGeographic() ) GTIFKeySet(psGTIF, GTModelTypeGeoKey, TYPE_SHORT, 1, ModelTypeGeographic); // otherwise, presumably something like LOCAL_CS. } else if( EQUAL(pszProjection,SRS_PT_ALBERS_CONIC_EQUAL_AREA) ) { GTIFKeySet(psGTIF, GTModelTypeGeoKey, TYPE_SHORT, 1, ModelTypeProjected); GTIFKeySet(psGTIF, ProjectedCSTypeGeoKey, TYPE_SHORT, 1, KvUserDefined ); GTIFKeySet(psGTIF, ProjectionGeoKey, TYPE_SHORT, 1, KvUserDefined ); GTIFKeySet(psGTIF, ProjCoordTransGeoKey, TYPE_SHORT, 1, CT_AlbersEqualArea ); GTIFKeySet(psGTIF, ProjStdParallelGeoKey, TYPE_DOUBLE, 1, poSRS->GetNormProjParm( SRS_PP_STANDARD_PARALLEL_1, 0.0 ) ); GTIFKeySet(psGTIF, ProjStdParallel2GeoKey, TYPE_DOUBLE, 1, poSRS->GetNormProjParm( SRS_PP_STANDARD_PARALLEL_2, 0.0 ) ); GTIFKeySet(psGTIF, ProjNatOriginLatGeoKey, TYPE_DOUBLE, 1, poSRS->GetNormProjParm( SRS_PP_LATITUDE_OF_CENTER, 0.0 ) ); GTIFKeySet(psGTIF, ProjNatOriginLongGeoKey, TYPE_DOUBLE, 1, poSRS->GetNormProjParm( SRS_PP_LONGITUDE_OF_CENTER, 0.0 ) ); GTIFKeySet(psGTIF, ProjFalseEastingGeoKey, TYPE_DOUBLE, 1, poSRS->GetNormProjParm( SRS_PP_FALSE_EASTING, 0.0 ) ); GTIFKeySet(psGTIF, ProjFalseNorthingGeoKey, TYPE_DOUBLE, 1, poSRS->GetNormProjParm( SRS_PP_FALSE_NORTHING, 0.0 ) ); } else if( poSRS->GetUTMZone() != 0 ) { int bNorth, nZone, nProjection; GTIFKeySet(psGTIF, GTModelTypeGeoKey, TYPE_SHORT, 1, ModelTypeProjected); nZone = poSRS->GetUTMZone( &bNorth ); if( nDatum == Datum_North_American_Datum_1983 && nZone >= 3 && nZone <= 22 && bNorth && nUOMLengthCode == 9001 ) { nPCS = 26900 + nZone; GTIFKeySet(psGTIF, ProjectedCSTypeGeoKey, TYPE_SHORT, 1, nPCS ); } else if( nDatum == Datum_North_American_Datum_1927 && nZone >= 3 && nZone <= 22 && bNorth && nUOMLengthCode == 9001 ) { nPCS = 26700 + nZone; GTIFKeySet(psGTIF, ProjectedCSTypeGeoKey, TYPE_SHORT, 1, nPCS ); } else if( nDatum == Datum_WGS84 && nUOMLengthCode == 9001 ) { if( bNorth ) nPCS = 32600 + nZone; else nPCS = 32700 + nZone; GTIFKeySet(psGTIF, ProjectedCSTypeGeoKey, TYPE_SHORT, 1, nPCS ); } else { if( bNorth ) nProjection = 16000 + nZone; else nProjection = 16100 + nZone; GTIFKeySet(psGTIF, ProjectedCSTypeGeoKey, TYPE_SHORT, 1, KvUserDefined ); GTIFKeySet(psGTIF, ProjectionGeoKey, TYPE_SHORT, 1, nProjection ); } } else if( EQUAL(pszProjection,SRS_PT_TRANSVERSE_MERCATOR) ) { GTIFKeySet(psGTIF, GTModelTypeGeoKey, TYPE_SHORT, 1, ModelTypeProjected); GTIFKeySet(psGTIF, ProjectedCSTypeGeoKey, TYPE_SHORT, 1, KvUserDefined ); GTIFKeySet(psGTIF, ProjectionGeoKey, TYPE_SHORT, 1, KvUserDefined ); GTIFKeySet(psGTIF, ProjCoordTransGeoKey, TYPE_SHORT, 1, CT_TransverseMercator ); GTIFKeySet(psGTIF, ProjNatOriginLatGeoKey, TYPE_DOUBLE, 1, poSRS->GetNormProjParm( SRS_PP_LATITUDE_OF_ORIGIN, 0.0 ) ); GTIFKeySet(psGTIF, ProjNatOriginLongGeoKey, TYPE_DOUBLE, 1, poSRS->GetNormProjParm( SRS_PP_CENTRAL_MERIDIAN, 0.0 ) ); GTIFKeySet(psGTIF, ProjScaleAtNatOriginGeoKey, TYPE_DOUBLE, 1, poSRS->GetNormProjParm( SRS_PP_SCALE_FACTOR, 1.0 ) ); GTIFKeySet(psGTIF, ProjFalseEastingGeoKey, TYPE_DOUBLE, 1, poSRS->GetNormProjParm( SRS_PP_FALSE_EASTING, 0.0 ) ); GTIFKeySet(psGTIF, ProjFalseNorthingGeoKey, TYPE_DOUBLE, 1, poSRS->GetNormProjParm( SRS_PP_FALSE_NORTHING, 0.0 ) ); } else if( EQUAL(pszProjection,SRS_PT_TRANSVERSE_MERCATOR_SOUTH_ORIENTED) ) { GTIFKeySet(psGTIF, GTModelTypeGeoKey, TYPE_SHORT, 1, ModelTypeProjected); GTIFKeySet(psGTIF, ProjectedCSTypeGeoKey, TYPE_SHORT, 1, KvUserDefined ); GTIFKeySet(psGTIF, ProjectionGeoKey, TYPE_SHORT, 1, KvUserDefined ); GTIFKeySet(psGTIF, ProjCoordTransGeoKey, TYPE_SHORT, 1, CT_TransvMercator_SouthOriented ); GTIFKeySet(psGTIF, ProjNatOriginLatGeoKey, TYPE_DOUBLE, 1, poSRS->GetNormProjParm( SRS_PP_LATITUDE_OF_ORIGIN, 0.0 ) ); GTIFKeySet(psGTIF, ProjNatOriginLongGeoKey, TYPE_DOUBLE, 1, poSRS->GetNormProjParm( SRS_PP_CENTRAL_MERIDIAN, 0.0 ) ); GTIFKeySet(psGTIF, ProjScaleAtNatOriginGeoKey, TYPE_DOUBLE, 1, poSRS->GetNormProjParm( SRS_PP_SCALE_FACTOR, 1.0 ) ); GTIFKeySet(psGTIF, ProjFalseEastingGeoKey, TYPE_DOUBLE, 1, poSRS->GetNormProjParm( SRS_PP_FALSE_EASTING, 0.0 ) ); GTIFKeySet(psGTIF, ProjFalseNorthingGeoKey, TYPE_DOUBLE, 1, poSRS->GetNormProjParm( SRS_PP_FALSE_NORTHING, 0.0 ) ); } else if( EQUAL(pszProjection,SRS_PT_MERCATOR_2SP) || EQUAL(pszProjection,SRS_PT_MERCATOR_1SP) ) { GTIFKeySet(psGTIF, GTModelTypeGeoKey, TYPE_SHORT, 1, ModelTypeProjected); GTIFKeySet(psGTIF, ProjectedCSTypeGeoKey, TYPE_SHORT, 1, KvUserDefined ); GTIFKeySet(psGTIF, ProjectionGeoKey, TYPE_SHORT, 1, KvUserDefined ); GTIFKeySet(psGTIF, ProjCoordTransGeoKey, TYPE_SHORT, 1, CT_Mercator ); GTIFKeySet(psGTIF, ProjNatOriginLatGeoKey, TYPE_DOUBLE, 1, poSRS->GetNormProjParm( SRS_PP_LATITUDE_OF_ORIGIN, 0.0 ) ); GTIFKeySet(psGTIF, ProjNatOriginLongGeoKey, TYPE_DOUBLE, 1, poSRS->GetNormProjParm( SRS_PP_CENTRAL_MERIDIAN, 0.0 ) ); GTIFKeySet(psGTIF, ProjScaleAtNatOriginGeoKey, TYPE_DOUBLE, 1, poSRS->GetNormProjParm( SRS_PP_SCALE_FACTOR, 1.0 ) ); GTIFKeySet(psGTIF, ProjFalseEastingGeoKey, TYPE_DOUBLE, 1, poSRS->GetNormProjParm( SRS_PP_FALSE_EASTING, 0.0 ) ); GTIFKeySet(psGTIF, ProjFalseNorthingGeoKey, TYPE_DOUBLE, 1, poSRS->GetNormProjParm( SRS_PP_FALSE_NORTHING, 0.0 ) ); } else if( EQUAL(pszProjection,SRS_PT_OBLIQUE_STEREOGRAPHIC) ) { GTIFKeySet(psGTIF, GTModelTypeGeoKey, TYPE_SHORT, 1, ModelTypeProjected); GTIFKeySet(psGTIF, ProjectedCSTypeGeoKey, TYPE_SHORT, 1, KvUserDefined ); GTIFKeySet(psGTIF, ProjectionGeoKey, TYPE_SHORT, 1, KvUserDefined ); GTIFKeySet(psGTIF, ProjCoordTransGeoKey, TYPE_SHORT, 1, CT_ObliqueStereographic ); GTIFKeySet(psGTIF, ProjNatOriginLatGeoKey, TYPE_DOUBLE, 1, poSRS->GetNormProjParm( SRS_PP_LATITUDE_OF_ORIGIN, 0.0 ) ); GTIFKeySet(psGTIF, ProjNatOriginLongGeoKey, TYPE_DOUBLE, 1, poSRS->GetNormProjParm( SRS_PP_CENTRAL_MERIDIAN, 0.0 ) ); GTIFKeySet(psGTIF, ProjScaleAtNatOriginGeoKey, TYPE_DOUBLE, 1, poSRS->GetNormProjParm( SRS_PP_SCALE_FACTOR, 1.0 ) ); GTIFKeySet(psGTIF, ProjFalseEastingGeoKey, TYPE_DOUBLE, 1, poSRS->GetNormProjParm( SRS_PP_FALSE_EASTING, 0.0 ) ); GTIFKeySet(psGTIF, ProjFalseNorthingGeoKey, TYPE_DOUBLE, 1, poSRS->GetNormProjParm( SRS_PP_FALSE_NORTHING, 0.0 ) ); } else if( EQUAL(pszProjection,SRS_PT_STEREOGRAPHIC) ) { GTIFKeySet(psGTIF, GTModelTypeGeoKey, TYPE_SHORT, 1, ModelTypeProjected); GTIFKeySet(psGTIF, ProjectedCSTypeGeoKey, TYPE_SHORT, 1, KvUserDefined ); GTIFKeySet(psGTIF, ProjectionGeoKey, TYPE_SHORT, 1, KvUserDefined ); GTIFKeySet(psGTIF, ProjCoordTransGeoKey, TYPE_SHORT, 1, CT_Stereographic ); GTIFKeySet(psGTIF, ProjCenterLatGeoKey, TYPE_DOUBLE, 1, poSRS->GetNormProjParm( SRS_PP_LATITUDE_OF_ORIGIN, 0.0 ) ); GTIFKeySet(psGTIF, ProjCenterLongGeoKey, TYPE_DOUBLE, 1, poSRS->GetNormProjParm( SRS_PP_CENTRAL_MERIDIAN, 0.0 ) ); GTIFKeySet(psGTIF, ProjScaleAtNatOriginGeoKey, TYPE_DOUBLE, 1, poSRS->GetNormProjParm( SRS_PP_SCALE_FACTOR, 1.0 ) ); GTIFKeySet(psGTIF, ProjFalseEastingGeoKey, TYPE_DOUBLE, 1, poSRS->GetNormProjParm( SRS_PP_FALSE_EASTING, 0.0 ) ); GTIFKeySet(psGTIF, ProjFalseNorthingGeoKey, TYPE_DOUBLE, 1, poSRS->GetNormProjParm( SRS_PP_FALSE_NORTHING, 0.0 ) ); } else if( EQUAL(pszProjection,SRS_PT_POLAR_STEREOGRAPHIC) ) { GTIFKeySet(psGTIF, GTModelTypeGeoKey, TYPE_SHORT, 1, ModelTypeProjected); GTIFKeySet(psGTIF, ProjectedCSTypeGeoKey, TYPE_SHORT, 1, KvUserDefined ); GTIFKeySet(psGTIF, ProjectionGeoKey, TYPE_SHORT, 1, KvUserDefined ); GTIFKeySet(psGTIF, ProjCoordTransGeoKey, TYPE_SHORT, 1, CT_PolarStereographic ); GTIFKeySet(psGTIF, ProjNatOriginLatGeoKey, TYPE_DOUBLE, 1, poSRS->GetNormProjParm( SRS_PP_LATITUDE_OF_ORIGIN, 0.0 ) ); GTIFKeySet(psGTIF, ProjStraightVertPoleLongGeoKey, TYPE_DOUBLE, 1, poSRS->GetNormProjParm( SRS_PP_CENTRAL_MERIDIAN, 0.0 ) ); GTIFKeySet(psGTIF, ProjScaleAtNatOriginGeoKey, TYPE_DOUBLE, 1, poSRS->GetNormProjParm( SRS_PP_SCALE_FACTOR, 1.0 ) ); GTIFKeySet(psGTIF, ProjFalseEastingGeoKey, TYPE_DOUBLE, 1, poSRS->GetNormProjParm( SRS_PP_FALSE_EASTING, 0.0 ) ); GTIFKeySet(psGTIF, ProjFalseNorthingGeoKey, TYPE_DOUBLE, 1, poSRS->GetNormProjParm( SRS_PP_FALSE_NORTHING, 0.0 ) ); } else if( EQUAL(pszProjection,SRS_PT_HOTINE_OBLIQUE_MERCATOR) ) { GTIFKeySet(psGTIF, GTModelTypeGeoKey, TYPE_SHORT, 1, ModelTypeProjected); GTIFKeySet(psGTIF, ProjectedCSTypeGeoKey, TYPE_SHORT, 1, KvUserDefined ); GTIFKeySet(psGTIF, ProjectionGeoKey, TYPE_SHORT, 1, KvUserDefined ); GTIFKeySet(psGTIF, ProjCoordTransGeoKey, TYPE_SHORT, 1, CT_ObliqueMercator ); GTIFKeySet(psGTIF, ProjCenterLatGeoKey, TYPE_DOUBLE, 1, poSRS->GetNormProjParm( SRS_PP_LATITUDE_OF_CENTER, 0.0 ) ); GTIFKeySet(psGTIF, ProjCenterLongGeoKey, TYPE_DOUBLE, 1, poSRS->GetNormProjParm( SRS_PP_LONGITUDE_OF_CENTER, 0.0 ) ); GTIFKeySet(psGTIF, ProjAzimuthAngleGeoKey, TYPE_DOUBLE, 1, poSRS->GetNormProjParm( SRS_PP_AZIMUTH, 0.0 ) ); GTIFKeySet(psGTIF, ProjRectifiedGridAngleGeoKey, TYPE_DOUBLE, 1, poSRS->GetNormProjParm( SRS_PP_RECTIFIED_GRID_ANGLE, 0.0 ) ); GTIFKeySet(psGTIF, ProjScaleAtCenterGeoKey, TYPE_DOUBLE, 1, poSRS->GetNormProjParm( SRS_PP_SCALE_FACTOR, 1.0 ) ); GTIFKeySet(psGTIF, ProjFalseEastingGeoKey, TYPE_DOUBLE, 1, poSRS->GetNormProjParm( SRS_PP_FALSE_EASTING, 0.0 ) ); GTIFKeySet(psGTIF, ProjFalseNorthingGeoKey, TYPE_DOUBLE, 1, poSRS->GetNormProjParm( SRS_PP_FALSE_NORTHING, 0.0 ) ); } else if( EQUAL(pszProjection,SRS_PT_CASSINI_SOLDNER) ) { GTIFKeySet(psGTIF, GTModelTypeGeoKey, TYPE_SHORT, 1, ModelTypeProjected); GTIFKeySet(psGTIF, ProjectedCSTypeGeoKey, TYPE_SHORT, 1, KvUserDefined ); GTIFKeySet(psGTIF, ProjectionGeoKey, TYPE_SHORT, 1, KvUserDefined ); GTIFKeySet(psGTIF, ProjCoordTransGeoKey, TYPE_SHORT, 1, CT_CassiniSoldner ); GTIFKeySet(psGTIF, ProjNatOriginLatGeoKey, TYPE_DOUBLE, 1, poSRS->GetNormProjParm( SRS_PP_LATITUDE_OF_ORIGIN, 0.0 ) ); GTIFKeySet(psGTIF, ProjNatOriginLongGeoKey, TYPE_DOUBLE, 1, poSRS->GetNormProjParm( SRS_PP_CENTRAL_MERIDIAN, 0.0 ) ); GTIFKeySet(psGTIF, ProjFalseEastingGeoKey, TYPE_DOUBLE, 1, poSRS->GetNormProjParm( SRS_PP_FALSE_EASTING, 0.0 ) ); GTIFKeySet(psGTIF, ProjFalseNorthingGeoKey, TYPE_DOUBLE, 1, poSRS->GetNormProjParm( SRS_PP_FALSE_NORTHING, 0.0 ) ); } else if( EQUAL(pszProjection,SRS_PT_EQUIDISTANT_CONIC) ) { GTIFKeySet(psGTIF, GTModelTypeGeoKey, TYPE_SHORT, 1, ModelTypeProjected); GTIFKeySet(psGTIF, ProjectedCSTypeGeoKey, TYPE_SHORT, 1, KvUserDefined ); GTIFKeySet(psGTIF, ProjectionGeoKey, TYPE_SHORT, 1, KvUserDefined ); GTIFKeySet(psGTIF, ProjCoordTransGeoKey, TYPE_SHORT, 1, CT_EquidistantConic ); GTIFKeySet(psGTIF, ProjStdParallel1GeoKey, TYPE_DOUBLE, 1, poSRS->GetNormProjParm( SRS_PP_STANDARD_PARALLEL_1, 0.0 ) ); GTIFKeySet(psGTIF, ProjStdParallel2GeoKey, TYPE_DOUBLE, 1, poSRS->GetNormProjParm( SRS_PP_STANDARD_PARALLEL_2, 0.0 ) ); GTIFKeySet(psGTIF, ProjNatOriginLatGeoKey, TYPE_DOUBLE, 1, poSRS->GetNormProjParm( SRS_PP_LATITUDE_OF_CENTER, 0.0 ) ); GTIFKeySet(psGTIF, ProjNatOriginLongGeoKey, TYPE_DOUBLE, 1, poSRS->GetNormProjParm( SRS_PP_LONGITUDE_OF_CENTER, 0.0 ) ); GTIFKeySet(psGTIF, ProjFalseEastingGeoKey, TYPE_DOUBLE, 1, poSRS->GetNormProjParm( SRS_PP_FALSE_EASTING, 0.0 ) ); GTIFKeySet(psGTIF, ProjFalseNorthingGeoKey, TYPE_DOUBLE, 1, poSRS->GetNormProjParm( SRS_PP_FALSE_NORTHING, 0.0 ) ); } else if( EQUAL(pszProjection,SRS_PT_POLYCONIC) ) { GTIFKeySet(psGTIF, GTModelTypeGeoKey, TYPE_SHORT, 1, ModelTypeProjected); GTIFKeySet(psGTIF, ProjectedCSTypeGeoKey, TYPE_SHORT, 1, KvUserDefined ); GTIFKeySet(psGTIF, ProjectionGeoKey, TYPE_SHORT, 1, KvUserDefined ); GTIFKeySet(psGTIF, ProjCoordTransGeoKey, TYPE_SHORT, 1, CT_Polyconic ); GTIFKeySet(psGTIF, ProjNatOriginLatGeoKey, TYPE_DOUBLE, 1, poSRS->GetNormProjParm( SRS_PP_LATITUDE_OF_ORIGIN, 0.0 ) ); GTIFKeySet(psGTIF, ProjNatOriginLongGeoKey, TYPE_DOUBLE, 1, poSRS->GetNormProjParm( SRS_PP_CENTRAL_MERIDIAN, 0.0 ) ); GTIFKeySet(psGTIF, ProjScaleAtNatOriginGeoKey, TYPE_DOUBLE, 1, poSRS->GetNormProjParm( SRS_PP_SCALE_FACTOR, 1.0 ) ); GTIFKeySet(psGTIF, ProjFalseEastingGeoKey, TYPE_DOUBLE, 1, poSRS->GetNormProjParm( SRS_PP_FALSE_EASTING, 0.0 ) ); GTIFKeySet(psGTIF, ProjFalseNorthingGeoKey, TYPE_DOUBLE, 1, poSRS->GetNormProjParm( SRS_PP_FALSE_NORTHING, 0.0 ) ); } else if( EQUAL(pszProjection,SRS_PT_AZIMUTHAL_EQUIDISTANT) ) { GTIFKeySet(psGTIF, GTModelTypeGeoKey, TYPE_SHORT, 1, ModelTypeProjected); GTIFKeySet(psGTIF, ProjectedCSTypeGeoKey, TYPE_SHORT, 1, KvUserDefined ); GTIFKeySet(psGTIF, ProjectionGeoKey, TYPE_SHORT, 1, KvUserDefined ); GTIFKeySet(psGTIF, ProjCoordTransGeoKey, TYPE_SHORT, 1, CT_AzimuthalEquidistant ); GTIFKeySet(psGTIF, ProjCenterLatGeoKey, TYPE_DOUBLE, 1, poSRS->GetNormProjParm( SRS_PP_LATITUDE_OF_CENTER, 0.0 ) ); GTIFKeySet(psGTIF, ProjCenterLongGeoKey, TYPE_DOUBLE, 1, poSRS->GetNormProjParm( SRS_PP_LONGITUDE_OF_CENTER, 0.0 ) ); GTIFKeySet(psGTIF, ProjFalseEastingGeoKey, TYPE_DOUBLE, 1, poSRS->GetNormProjParm( SRS_PP_FALSE_EASTING, 0.0 ) ); GTIFKeySet(psGTIF, ProjFalseNorthingGeoKey, TYPE_DOUBLE, 1, poSRS->GetNormProjParm( SRS_PP_FALSE_NORTHING, 0.0 ) ); } else if( EQUAL(pszProjection,SRS_PT_MILLER_CYLINDRICAL) ) { GTIFKeySet(psGTIF, GTModelTypeGeoKey, TYPE_SHORT, 1, ModelTypeProjected); GTIFKeySet(psGTIF, ProjectedCSTypeGeoKey, TYPE_SHORT, 1, KvUserDefined ); GTIFKeySet(psGTIF, ProjectionGeoKey, TYPE_SHORT, 1, KvUserDefined ); GTIFKeySet(psGTIF, ProjCoordTransGeoKey, TYPE_SHORT, 1, CT_MillerCylindrical ); GTIFKeySet(psGTIF, ProjCenterLatGeoKey, TYPE_DOUBLE, 1, poSRS->GetNormProjParm( SRS_PP_LATITUDE_OF_CENTER, 0.0 ) ); GTIFKeySet(psGTIF, ProjCenterLongGeoKey, TYPE_DOUBLE, 1, poSRS->GetNormProjParm( SRS_PP_LONGITUDE_OF_CENTER, 0.0 ) ); GTIFKeySet(psGTIF, ProjFalseEastingGeoKey, TYPE_DOUBLE, 1, poSRS->GetNormProjParm( SRS_PP_FALSE_EASTING, 0.0 ) ); GTIFKeySet(psGTIF, ProjFalseNorthingGeoKey, TYPE_DOUBLE, 1, poSRS->GetNormProjParm( SRS_PP_FALSE_NORTHING, 0.0 ) ); } else if( EQUAL(pszProjection,SRS_PT_EQUIRECTANGULAR) ) { GTIFKeySet(psGTIF, GTModelTypeGeoKey, TYPE_SHORT, 1, ModelTypeProjected); GTIFKeySet(psGTIF, ProjectedCSTypeGeoKey, TYPE_SHORT, 1, KvUserDefined ); GTIFKeySet(psGTIF, ProjectionGeoKey, TYPE_SHORT, 1, KvUserDefined ); GTIFKeySet(psGTIF, ProjCoordTransGeoKey, TYPE_SHORT, 1, CT_Equirectangular ); GTIFKeySet(psGTIF, ProjCenterLatGeoKey, TYPE_DOUBLE, 1, poSRS->GetNormProjParm( SRS_PP_LATITUDE_OF_ORIGIN, 0.0 ) ); GTIFKeySet(psGTIF, ProjCenterLongGeoKey, TYPE_DOUBLE, 1, poSRS->GetNormProjParm( SRS_PP_CENTRAL_MERIDIAN, 0.0 ) ); GTIFKeySet(psGTIF, ProjStdParallel1GeoKey, TYPE_DOUBLE, 1, poSRS->GetNormProjParm( SRS_PP_STANDARD_PARALLEL_1, 0.0 ) ); GTIFKeySet(psGTIF, ProjFalseEastingGeoKey, TYPE_DOUBLE, 1, poSRS->GetNormProjParm( SRS_PP_FALSE_EASTING, 0.0 ) ); GTIFKeySet(psGTIF, ProjFalseNorthingGeoKey, TYPE_DOUBLE, 1, poSRS->GetNormProjParm( SRS_PP_FALSE_NORTHING, 0.0 ) ); } else if( EQUAL(pszProjection,SRS_PT_GNOMONIC) ) { GTIFKeySet(psGTIF, GTModelTypeGeoKey, TYPE_SHORT, 1, ModelTypeProjected); GTIFKeySet(psGTIF, ProjectedCSTypeGeoKey, TYPE_SHORT, 1, KvUserDefined ); GTIFKeySet(psGTIF, ProjectionGeoKey, TYPE_SHORT, 1, KvUserDefined ); GTIFKeySet(psGTIF, ProjCoordTransGeoKey, TYPE_SHORT, 1, CT_Gnomonic ); GTIFKeySet(psGTIF, ProjCenterLatGeoKey, TYPE_DOUBLE, 1, poSRS->GetNormProjParm( SRS_PP_LATITUDE_OF_ORIGIN, 0.0 ) ); GTIFKeySet(psGTIF, ProjCenterLongGeoKey, TYPE_DOUBLE, 1, poSRS->GetNormProjParm( SRS_PP_CENTRAL_MERIDIAN, 0.0 ) ); GTIFKeySet(psGTIF, ProjFalseEastingGeoKey, TYPE_DOUBLE, 1, poSRS->GetNormProjParm( SRS_PP_FALSE_EASTING, 0.0 ) ); GTIFKeySet(psGTIF, ProjFalseNorthingGeoKey, TYPE_DOUBLE, 1, poSRS->GetNormProjParm( SRS_PP_FALSE_NORTHING, 0.0 ) ); } else if( EQUAL(pszProjection,SRS_PT_LAMBERT_AZIMUTHAL_EQUAL_AREA) ) { GTIFKeySet(psGTIF, GTModelTypeGeoKey, TYPE_SHORT, 1, ModelTypeProjected); GTIFKeySet(psGTIF, ProjectedCSTypeGeoKey, TYPE_SHORT, 1, KvUserDefined ); GTIFKeySet(psGTIF, ProjectionGeoKey, TYPE_SHORT, 1, KvUserDefined ); GTIFKeySet(psGTIF, ProjCoordTransGeoKey, TYPE_SHORT, 1, CT_LambertAzimEqualArea ); GTIFKeySet(psGTIF, ProjCenterLatGeoKey, TYPE_DOUBLE, 1, poSRS->GetNormProjParm( SRS_PP_LATITUDE_OF_CENTER, 0.0 ) ); GTIFKeySet(psGTIF, ProjCenterLongGeoKey, TYPE_DOUBLE, 1, poSRS->GetNormProjParm( SRS_PP_LONGITUDE_OF_CENTER, 0.0 ) ); GTIFKeySet(psGTIF, ProjFalseEastingGeoKey, TYPE_DOUBLE, 1, poSRS->GetNormProjParm( SRS_PP_FALSE_EASTING, 0.0 ) ); GTIFKeySet(psGTIF, ProjFalseNorthingGeoKey, TYPE_DOUBLE, 1, poSRS->GetNormProjParm( SRS_PP_FALSE_NORTHING, 0.0 ) ); } else if( EQUAL(pszProjection,SRS_PT_ORTHOGRAPHIC) ) { GTIFKeySet(psGTIF, GTModelTypeGeoKey, TYPE_SHORT, 1, ModelTypeProjected); GTIFKeySet(psGTIF, ProjectedCSTypeGeoKey, TYPE_SHORT, 1, KvUserDefined ); GTIFKeySet(psGTIF, ProjectionGeoKey, TYPE_SHORT, 1, KvUserDefined ); GTIFKeySet(psGTIF, ProjCoordTransGeoKey, TYPE_SHORT, 1, CT_Orthographic ); GTIFKeySet(psGTIF, ProjCenterLatGeoKey, TYPE_DOUBLE, 1, poSRS->GetNormProjParm( SRS_PP_LATITUDE_OF_ORIGIN, 0.0 ) ); GTIFKeySet(psGTIF, ProjCenterLongGeoKey, TYPE_DOUBLE, 1, poSRS->GetNormProjParm( SRS_PP_CENTRAL_MERIDIAN, 0.0 ) ); GTIFKeySet(psGTIF, ProjFalseEastingGeoKey, TYPE_DOUBLE, 1, poSRS->GetNormProjParm( SRS_PP_FALSE_EASTING, 0.0 ) ); GTIFKeySet(psGTIF, ProjFalseNorthingGeoKey, TYPE_DOUBLE, 1, poSRS->GetNormProjParm( SRS_PP_FALSE_NORTHING, 0.0 ) ); } else if( EQUAL(pszProjection,SRS_PT_NEW_ZEALAND_MAP_GRID) ) { GTIFKeySet(psGTIF, GTModelTypeGeoKey, TYPE_SHORT, 1, ModelTypeProjected); GTIFKeySet(psGTIF, ProjectedCSTypeGeoKey, TYPE_SHORT, 1, KvUserDefined ); GTIFKeySet(psGTIF, ProjectionGeoKey, TYPE_SHORT, 1, KvUserDefined ); GTIFKeySet(psGTIF, ProjCoordTransGeoKey, TYPE_SHORT, 1, CT_NewZealandMapGrid ); GTIFKeySet(psGTIF, ProjNatOriginLatGeoKey, TYPE_DOUBLE, 1, poSRS->GetNormProjParm( SRS_PP_LATITUDE_OF_ORIGIN, 0.0 ) ); GTIFKeySet(psGTIF, ProjNatOriginLongGeoKey, TYPE_DOUBLE, 1, poSRS->GetNormProjParm( SRS_PP_CENTRAL_MERIDIAN, 0.0 ) ); GTIFKeySet(psGTIF, ProjFalseEastingGeoKey, TYPE_DOUBLE, 1, poSRS->GetNormProjParm( SRS_PP_FALSE_EASTING, 0.0 ) ); GTIFKeySet(psGTIF, ProjFalseNorthingGeoKey, TYPE_DOUBLE, 1, poSRS->GetNormProjParm( SRS_PP_FALSE_NORTHING, 0.0 ) ); } else if( EQUAL(pszProjection,SRS_PT_ROBINSON) ) { GTIFKeySet(psGTIF, GTModelTypeGeoKey, TYPE_SHORT, 1, ModelTypeProjected); GTIFKeySet(psGTIF, ProjectedCSTypeGeoKey, TYPE_SHORT, 1, KvUserDefined ); GTIFKeySet(psGTIF, ProjectionGeoKey, TYPE_SHORT, 1, KvUserDefined ); GTIFKeySet(psGTIF, ProjCoordTransGeoKey, TYPE_SHORT, 1, CT_Robinson ); GTIFKeySet(psGTIF, ProjCenterLongGeoKey, TYPE_DOUBLE, 1, poSRS->GetNormProjParm( SRS_PP_LONGITUDE_OF_CENTER, 0.0 ) ); GTIFKeySet(psGTIF, ProjFalseEastingGeoKey, TYPE_DOUBLE, 1, poSRS->GetNormProjParm( SRS_PP_FALSE_EASTING, 0.0 ) ); GTIFKeySet(psGTIF, ProjFalseNorthingGeoKey, TYPE_DOUBLE, 1, poSRS->GetNormProjParm( SRS_PP_FALSE_NORTHING, 0.0 ) ); } else if( EQUAL(pszProjection,SRS_PT_SINUSOIDAL) ) { GTIFKeySet(psGTIF, GTModelTypeGeoKey, TYPE_SHORT, 1, ModelTypeProjected); GTIFKeySet(psGTIF, ProjectedCSTypeGeoKey, TYPE_SHORT, 1, KvUserDefined ); GTIFKeySet(psGTIF, ProjectionGeoKey, TYPE_SHORT, 1, KvUserDefined ); GTIFKeySet(psGTIF, ProjCoordTransGeoKey, TYPE_SHORT, 1, CT_Sinusoidal ); GTIFKeySet(psGTIF, ProjCenterLongGeoKey, TYPE_DOUBLE, 1, poSRS->GetNormProjParm( SRS_PP_LONGITUDE_OF_CENTER, 0.0 ) ); GTIFKeySet(psGTIF, ProjFalseEastingGeoKey, TYPE_DOUBLE, 1, poSRS->GetNormProjParm( SRS_PP_FALSE_EASTING, 0.0 ) ); GTIFKeySet(psGTIF, ProjFalseNorthingGeoKey, TYPE_DOUBLE, 1, poSRS->GetNormProjParm( SRS_PP_FALSE_NORTHING, 0.0 ) ); } else if( EQUAL(pszProjection,SRS_PT_VANDERGRINTEN) ) { GTIFKeySet(psGTIF, GTModelTypeGeoKey, TYPE_SHORT, 1, ModelTypeProjected); GTIFKeySet(psGTIF, ProjectedCSTypeGeoKey, TYPE_SHORT, 1, KvUserDefined ); GTIFKeySet(psGTIF, ProjectionGeoKey, TYPE_SHORT, 1, KvUserDefined ); GTIFKeySet(psGTIF, ProjCoordTransGeoKey, TYPE_SHORT, 1, CT_VanDerGrinten ); GTIFKeySet(psGTIF, ProjCenterLongGeoKey, TYPE_DOUBLE, 1, poSRS->GetNormProjParm( SRS_PP_CENTRAL_MERIDIAN, 0.0 ) ); GTIFKeySet(psGTIF, ProjFalseEastingGeoKey, TYPE_DOUBLE, 1, poSRS->GetNormProjParm( SRS_PP_FALSE_EASTING, 0.0 ) ); GTIFKeySet(psGTIF, ProjFalseNorthingGeoKey, TYPE_DOUBLE, 1, poSRS->GetNormProjParm( SRS_PP_FALSE_NORTHING, 0.0 ) ); } else if( EQUAL(pszProjection,SRS_PT_ALBERS_CONIC_EQUAL_AREA) ) { GTIFKeySet(psGTIF, GTModelTypeGeoKey, TYPE_SHORT, 1, ModelTypeProjected); GTIFKeySet(psGTIF, ProjectedCSTypeGeoKey, TYPE_SHORT, 1, KvUserDefined ); GTIFKeySet(psGTIF, ProjectionGeoKey, TYPE_SHORT, 1, KvUserDefined ); GTIFKeySet(psGTIF, ProjCoordTransGeoKey, TYPE_SHORT, 1, CT_AlbersEqualArea ); GTIFKeySet(psGTIF, ProjNatOriginLatGeoKey, TYPE_DOUBLE, 1, poSRS->GetNormProjParm( SRS_PP_LATITUDE_OF_CENTER, 0.0 ) ); GTIFKeySet(psGTIF, ProjNatOriginLongGeoKey, TYPE_DOUBLE, 1, poSRS->GetNormProjParm( SRS_PP_LONGITUDE_OF_CENTER, 0.0 ) ); GTIFKeySet(psGTIF, ProjStdParallel1GeoKey, TYPE_DOUBLE, 1, poSRS->GetNormProjParm( SRS_PP_STANDARD_PARALLEL_1, 0.0 ) ); GTIFKeySet(psGTIF, ProjStdParallel2GeoKey, TYPE_DOUBLE, 1, poSRS->GetNormProjParm( SRS_PP_STANDARD_PARALLEL_2, 0.0 ) ); GTIFKeySet(psGTIF, ProjFalseEastingGeoKey, TYPE_DOUBLE, 1, poSRS->GetNormProjParm( SRS_PP_FALSE_EASTING, 0.0 ) ); GTIFKeySet(psGTIF, ProjFalseNorthingGeoKey, TYPE_DOUBLE, 1, poSRS->GetNormProjParm( SRS_PP_FALSE_NORTHING, 0.0 ) ); } else if( EQUAL(pszProjection,SRS_PT_LAMBERT_CONFORMAL_CONIC_2SP) ) { GTIFKeySet(psGTIF, GTModelTypeGeoKey, TYPE_SHORT, 1, ModelTypeProjected); GTIFKeySet(psGTIF, ProjectedCSTypeGeoKey, TYPE_SHORT, 1, KvUserDefined ); GTIFKeySet(psGTIF, ProjectionGeoKey, TYPE_SHORT, 1, KvUserDefined ); GTIFKeySet(psGTIF, ProjCoordTransGeoKey, TYPE_SHORT, 1, CT_LambertConfConic_2SP ); GTIFKeySet(psGTIF, ProjFalseOriginLatGeoKey, TYPE_DOUBLE, 1, poSRS->GetNormProjParm( SRS_PP_LATITUDE_OF_ORIGIN, 0.0 ) ); GTIFKeySet(psGTIF, ProjFalseOriginLongGeoKey, TYPE_DOUBLE, 1, poSRS->GetNormProjParm( SRS_PP_CENTRAL_MERIDIAN, 0.0 ) ); GTIFKeySet(psGTIF, ProjStdParallel1GeoKey, TYPE_DOUBLE, 1, poSRS->GetNormProjParm( SRS_PP_STANDARD_PARALLEL_1, 0.0 ) ); GTIFKeySet(psGTIF, ProjStdParallel2GeoKey, TYPE_DOUBLE, 1, poSRS->GetNormProjParm( SRS_PP_STANDARD_PARALLEL_2, 0.0 ) ); GTIFKeySet(psGTIF, ProjFalseOriginEastingGeoKey, TYPE_DOUBLE, 1, poSRS->GetNormProjParm( SRS_PP_FALSE_EASTING, 0.0 ) ); GTIFKeySet(psGTIF, ProjFalseOriginNorthingGeoKey, TYPE_DOUBLE, 1, poSRS->GetNormProjParm( SRS_PP_FALSE_NORTHING, 0.0 ) ); } else if( EQUAL(pszProjection,SRS_PT_LAMBERT_CONFORMAL_CONIC_1SP) ) { GTIFKeySet(psGTIF, GTModelTypeGeoKey, TYPE_SHORT, 1, ModelTypeProjected); GTIFKeySet(psGTIF, ProjectedCSTypeGeoKey, TYPE_SHORT, 1, KvUserDefined ); GTIFKeySet(psGTIF, ProjectionGeoKey, TYPE_SHORT, 1, KvUserDefined ); GTIFKeySet(psGTIF, ProjCoordTransGeoKey, TYPE_SHORT, 1, CT_LambertConfConic_1SP ); GTIFKeySet(psGTIF, ProjNatOriginLatGeoKey, TYPE_DOUBLE, 1, poSRS->GetNormProjParm( SRS_PP_LATITUDE_OF_ORIGIN, 0.0 ) ); GTIFKeySet(psGTIF, ProjNatOriginLongGeoKey, TYPE_DOUBLE, 1, poSRS->GetNormProjParm( SRS_PP_CENTRAL_MERIDIAN, 0.0 ) ); GTIFKeySet(psGTIF, ProjScaleAtNatOriginGeoKey, TYPE_DOUBLE, 1, poSRS->GetNormProjParm( SRS_PP_SCALE_FACTOR, 1.0 ) ); GTIFKeySet(psGTIF, ProjFalseEastingGeoKey, TYPE_DOUBLE, 1, poSRS->GetNormProjParm( SRS_PP_FALSE_EASTING, 0.0 ) ); GTIFKeySet(psGTIF, ProjFalseNorthingGeoKey, TYPE_DOUBLE, 1, poSRS->GetNormProjParm( SRS_PP_FALSE_NORTHING, 0.0 ) ); } else if( EQUAL(pszProjection,SRS_PT_CYLINDRICAL_EQUAL_AREA) ) { GTIFKeySet(psGTIF, GTModelTypeGeoKey, TYPE_SHORT, 1, ModelTypeProjected); GTIFKeySet(psGTIF, ProjectedCSTypeGeoKey, TYPE_SHORT, 1, KvUserDefined ); GTIFKeySet(psGTIF, ProjectionGeoKey, TYPE_SHORT, 1, KvUserDefined ); GTIFKeySet(psGTIF, ProjCoordTransGeoKey, TYPE_SHORT, 1, CT_CylindricalEqualArea ); GTIFKeySet(psGTIF, ProjNatOriginLongGeoKey, TYPE_DOUBLE, 1, poSRS->GetNormProjParm( SRS_PP_CENTRAL_MERIDIAN, 0.0 ) ); GTIFKeySet(psGTIF, ProjStdParallel1GeoKey, TYPE_DOUBLE, 1, poSRS->GetNormProjParm( SRS_PP_STANDARD_PARALLEL_1, 0.0 ) ); GTIFKeySet(psGTIF, ProjFalseEastingGeoKey, TYPE_DOUBLE, 1, poSRS->GetNormProjParm( SRS_PP_FALSE_EASTING, 0.0 ) ); GTIFKeySet(psGTIF, ProjFalseNorthingGeoKey, TYPE_DOUBLE, 1, poSRS->GetNormProjParm( SRS_PP_FALSE_NORTHING, 0.0 ) ); } else { GTIFKeySet(psGTIF, GTModelTypeGeoKey, TYPE_SHORT, 1, KvUserDefined ); } /* -------------------------------------------------------------------- */ /* Write linear units information. */ /* -------------------------------------------------------------------- */ if( !poSRS->IsGeographic() ) { GTIFKeySet(psGTIF, ProjLinearUnitsGeoKey, TYPE_SHORT, 1, nUOMLengthCode ); if( nUOMLengthCode == KvUserDefined ) GTIFKeySet( psGTIF, ProjLinearUnitSizeGeoKey, TYPE_DOUBLE, 1, dfLinearUOM); } /* -------------------------------------------------------------------- */ /* Write angular units. Always Degrees for now. */ /* -------------------------------------------------------------------- */ GTIFKeySet(psGTIF, GeogAngularUnitsGeoKey, TYPE_SHORT, 1, Angular_Degree ); /* -------------------------------------------------------------------- */ /* Try to write a citation from the main coordinate system */ /* name. */ /* -------------------------------------------------------------------- */ if( poSRS->GetRoot() != NULL && poSRS->GetRoot()->GetChild(0) != NULL && (poSRS->IsProjected() || poSRS->IsLocal()) ) { GTIFKeySet( psGTIF, GTCitationGeoKey, TYPE_ASCII, 0, poSRS->GetRoot()->GetChild(0)->GetValue() ); } /* -------------------------------------------------------------------- */ /* Try to write a GCS citation. */ /* -------------------------------------------------------------------- */ OGR_SRSNode *poGCS = poSRS->GetAttrNode( "GEOGCS" ); if( poGCS != NULL && poGCS->GetChild(0) != NULL ) { GTIFKeySet( psGTIF, GeogCitationGeoKey, TYPE_ASCII, 0, poGCS->GetChild(0)->GetValue() ); } /* -------------------------------------------------------------------- */ /* Try to identify the GCS/datum, scanning the EPSG datum file for */ /* a match. */ /* -------------------------------------------------------------------- */ if( nPCS == KvUserDefined ) { if( nGCS == KvUserDefined ) { if( nDatum == Datum_North_American_Datum_1927 ) nGCS = GCS_NAD27; else if( nDatum == Datum_North_American_Datum_1983 ) nGCS = GCS_NAD83; else if( nDatum == Datum_WGS84 || nDatum == DatumE_WGS84 ) nGCS = GCS_WGS_84; } if( nGCS != KvUserDefined ) { GTIFKeySet( psGTIF, GeographicTypeGeoKey, TYPE_SHORT, 1, nGCS ); } else if( nDatum != KvUserDefined ) { GTIFKeySet( psGTIF, GeographicTypeGeoKey, TYPE_SHORT, 1, KvUserDefined ); GTIFKeySet( psGTIF, GeogGeodeticDatumGeoKey, TYPE_SHORT, 1, nDatum ); } else if( nSpheroid != KvUserDefined ) { GTIFKeySet( psGTIF, GeographicTypeGeoKey, TYPE_SHORT, 1, KvUserDefined ); GTIFKeySet( psGTIF, GeogGeodeticDatumGeoKey, TYPE_SHORT, 1, KvUserDefined ); GTIFKeySet( psGTIF, GeogEllipsoidGeoKey, TYPE_SHORT, 1, nSpheroid ); } else if( dfSemiMajor != 0.0 ) { GTIFKeySet( psGTIF, GeographicTypeGeoKey, TYPE_SHORT, 1, KvUserDefined ); GTIFKeySet( psGTIF, GeogGeodeticDatumGeoKey, TYPE_SHORT, 1, KvUserDefined ); GTIFKeySet( psGTIF, GeogEllipsoidGeoKey, TYPE_SHORT, 1, KvUserDefined ); GTIFKeySet( psGTIF, GeogSemiMajorAxisGeoKey, TYPE_DOUBLE, 1, dfSemiMajor ); if( dfInvFlattening == 0.0 ) GTIFKeySet( psGTIF, GeogSemiMinorAxisGeoKey, TYPE_DOUBLE, 1, dfSemiMajor ); else GTIFKeySet( psGTIF, GeogInvFlatteningGeoKey, TYPE_DOUBLE, 1, dfInvFlattening ); } else if( poSRS->GetAttrValue("DATUM") != NULL && strstr(poSRS->GetAttrValue("DATUM"),"unknown") == NULL && strstr(poSRS->GetAttrValue("DATUM"),"unnamed") == NULL ) { CPLError( CE_Warning, CPLE_AppDefined, "Couldn't translate `%s' to a GeoTIFF datum.\n", poSRS->GetAttrValue("DATUM") ); } } /* -------------------------------------------------------------------- */ /* Cleanup */ /* -------------------------------------------------------------------- */ delete poSRS; return TRUE; } /************************************************************************/ /* GTIFWktFromMemBuf() */ /************************************************************************/ CPLErr GTIFWktFromMemBuf( int nSize, unsigned char *pabyBuffer, char **ppszWKT, double *padfGeoTransform, int *pnGCPCount, GDAL_GCP **ppasGCPList ) { TIFF *hTIFF; GTIF *hGTIF; GTIFDefn sGTIFDefn; char szFilename[100]; sprintf( szFilename, "/vsimem/wkt_from_mem_buf_%ld.tif", (long) CPLGetPID() ); /* -------------------------------------------------------------------- */ /* Create a memory file from the buffer. */ /* -------------------------------------------------------------------- */ FILE *fp = VSIFileFromMemBuffer( szFilename, pabyBuffer, nSize, FALSE ); if( fp == NULL ) return CE_Failure; VSIFCloseL( fp ); /* -------------------------------------------------------------------- */ /* Initialize access to the memory geotiff structure. */ /* -------------------------------------------------------------------- */ hTIFF = VSI_TIFFOpen( szFilename, "r" ); if( hTIFF == NULL ) { CPLError( CE_Failure, CPLE_AppDefined, "TIFF/GeoTIFF structure is corrupt." ); return CE_Failure; } /* -------------------------------------------------------------------- */ /* Get the projection definition. */ /* -------------------------------------------------------------------- */ hGTIF = GTIFNew(hTIFF); if( hGTIF != NULL && GTIFGetDefn( hGTIF, &sGTIFDefn ) ) *ppszWKT = GTIFGetOGISDefn( hGTIF, &sGTIFDefn ); else *ppszWKT = NULL; if( hGTIF ) GTIFFree( hGTIF ); /* -------------------------------------------------------------------- */ /* Get geotransform or tiepoints. */ /* -------------------------------------------------------------------- */ double *padfTiePoints, *padfScale, *padfMatrix; int16 nCount; padfGeoTransform[0] = 0.0; padfGeoTransform[1] = 1.0; padfGeoTransform[2] = 0.0; padfGeoTransform[3] = 0.0; padfGeoTransform[4] = 0.0; padfGeoTransform[5] = 1.0; *pnGCPCount = 0; *ppasGCPList = NULL; if( TIFFGetField(hTIFF,TIFFTAG_GEOPIXELSCALE,&nCount,&padfScale ) && nCount >= 2 ) { padfGeoTransform[1] = padfScale[0]; padfGeoTransform[5] = - ABS(padfScale[1]); if( TIFFGetField(hTIFF,TIFFTAG_GEOTIEPOINTS,&nCount,&padfTiePoints ) && nCount >= 6 ) { padfGeoTransform[0] = padfTiePoints[3] - padfTiePoints[0] * padfGeoTransform[1]; padfGeoTransform[3] = padfTiePoints[4] - padfTiePoints[1] * padfGeoTransform[5]; } } else if( TIFFGetField(hTIFF,TIFFTAG_GEOTIEPOINTS,&nCount,&padfTiePoints ) && nCount >= 6 ) { *pnGCPCount = nCount / 6; *ppasGCPList = (GDAL_GCP *) CPLCalloc(sizeof(GDAL_GCP),*pnGCPCount); for( int iGCP = 0; iGCP < *pnGCPCount; iGCP++ ) { char szID[32]; GDAL_GCP *psGCP = *ppasGCPList + iGCP; sprintf( szID, "%d", iGCP+1 ); psGCP->pszId = CPLStrdup( szID ); psGCP->pszInfo = CPLStrdup(""); psGCP->dfGCPPixel = padfTiePoints[iGCP*6+0]; psGCP->dfGCPLine = padfTiePoints[iGCP*6+1]; psGCP->dfGCPX = padfTiePoints[iGCP*6+3]; psGCP->dfGCPY = padfTiePoints[iGCP*6+4]; psGCP->dfGCPZ = padfTiePoints[iGCP*6+5]; } } else if( TIFFGetField(hTIFF,TIFFTAG_GEOTRANSMATRIX,&nCount,&padfMatrix ) && nCount == 16 ) { padfGeoTransform[0] = padfMatrix[3]; padfGeoTransform[1] = padfMatrix[0]; padfGeoTransform[2] = padfMatrix[1]; padfGeoTransform[3] = padfMatrix[7]; padfGeoTransform[4] = padfMatrix[4]; padfGeoTransform[5] = padfMatrix[5]; } /* -------------------------------------------------------------------- */ /* Cleanup. */ /* -------------------------------------------------------------------- */ XTIFFClose( hTIFF ); VSIUnlink( szFilename ); if( *ppszWKT == NULL ) return CE_Failure; else return CE_None; } /************************************************************************/ /* GTIFMemBufFromWkt() */ /************************************************************************/ CPLErr GTIFMemBufFromWkt( const char *pszWKT, const double *padfGeoTransform, int nGCPCount, const GDAL_GCP *pasGCPList, int *pnSize, unsigned char **ppabyBuffer ) { TIFF *hTIFF; GTIF *hGTIF; char szFilename[100]; sprintf( szFilename, "/vsimem/wkt_from_mem_buf_%ld.tif", (long) CPLGetPID() ); /* -------------------------------------------------------------------- */ /* Initialize access to the memory geotiff structure. */ /* -------------------------------------------------------------------- */ hTIFF = VSI_TIFFOpen( szFilename, "w" ); if( hTIFF == NULL ) { CPLError( CE_Failure, CPLE_AppDefined, "TIFF/GeoTIFF structure is corrupt." ); return CE_Failure; } /* -------------------------------------------------------------------- */ /* Write some minimal set of image parameters. */ /* -------------------------------------------------------------------- */ TIFFSetField( hTIFF, TIFFTAG_IMAGEWIDTH, 1 ); TIFFSetField( hTIFF, TIFFTAG_IMAGELENGTH, 1 ); TIFFSetField( hTIFF, TIFFTAG_BITSPERSAMPLE, 8 ); TIFFSetField( hTIFF, TIFFTAG_SAMPLESPERPIXEL, 1 ); TIFFSetField( hTIFF, TIFFTAG_ROWSPERSTRIP, 1 ); TIFFSetField( hTIFF, TIFFTAG_PLANARCONFIG, PLANARCONFIG_CONTIG ); TIFFSetField( hTIFF, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_MINISBLACK ); /* -------------------------------------------------------------------- */ /* Get the projection definition. */ /* -------------------------------------------------------------------- */ if( pszWKT != NULL ) { hGTIF = GTIFNew(hTIFF); GTIFSetFromOGISDefn( hGTIF, pszWKT ); GTIFWriteKeys( hGTIF ); GTIFFree( hGTIF ); } /* -------------------------------------------------------------------- */ /* Set the geotransform, or GCPs. */ /* -------------------------------------------------------------------- */ if( padfGeoTransform[0] != 0.0 || padfGeoTransform[1] != 1.0 || padfGeoTransform[2] != 0.0 || padfGeoTransform[3] != 0.0 || padfGeoTransform[4] != 0.0 || ABS(padfGeoTransform[5]) != 1.0 ) { if( padfGeoTransform[2] == 0.0 && padfGeoTransform[4] == 0.0 ) { double adfPixelScale[3], adfTiePoints[6]; adfPixelScale[0] = padfGeoTransform[1]; adfPixelScale[1] = fabs(padfGeoTransform[5]); adfPixelScale[2] = 0.0; TIFFSetField( hTIFF, TIFFTAG_GEOPIXELSCALE, 3, adfPixelScale ); adfTiePoints[0] = 0.0; adfTiePoints[1] = 0.0; adfTiePoints[2] = 0.0; adfTiePoints[3] = padfGeoTransform[0]; adfTiePoints[4] = padfGeoTransform[3]; adfTiePoints[5] = 0.0; TIFFSetField( hTIFF, TIFFTAG_GEOTIEPOINTS, 6, adfTiePoints ); } else { double adfMatrix[16]; memset(adfMatrix,0,sizeof(double) * 16); adfMatrix[0] = padfGeoTransform[1]; adfMatrix[1] = padfGeoTransform[2]; adfMatrix[3] = padfGeoTransform[0]; adfMatrix[4] = padfGeoTransform[4]; adfMatrix[5] = padfGeoTransform[5]; adfMatrix[7] = padfGeoTransform[3]; adfMatrix[15] = 1.0; TIFFSetField( hTIFF, TIFFTAG_GEOTRANSMATRIX, 16, adfMatrix ); } } /* -------------------------------------------------------------------- */ /* Otherwise write tiepoints if they are available. */ /* -------------------------------------------------------------------- */ else if( nGCPCount > 0 ) { double *padfTiePoints; padfTiePoints = (double *) CPLMalloc(6*sizeof(double)*nGCPCount); for( int iGCP = 0; iGCP < nGCPCount; iGCP++ ) { padfTiePoints[iGCP*6+0] = pasGCPList[iGCP].dfGCPPixel; padfTiePoints[iGCP*6+1] = pasGCPList[iGCP].dfGCPLine; padfTiePoints[iGCP*6+2] = 0; padfTiePoints[iGCP*6+3] = pasGCPList[iGCP].dfGCPX; padfTiePoints[iGCP*6+4] = pasGCPList[iGCP].dfGCPY; padfTiePoints[iGCP*6+5] = pasGCPList[iGCP].dfGCPZ; } TIFFSetField( hTIFF, TIFFTAG_GEOTIEPOINTS, 6*nGCPCount, padfTiePoints); CPLFree( padfTiePoints ); } /* -------------------------------------------------------------------- */ /* Cleanup and return the created memory buffer. */ /* -------------------------------------------------------------------- */ GByte bySmallImage = 0; TIFFWriteEncodedStrip( hTIFF, 0, (char *) &bySmallImage, 1 ); TIFFWriteCheck( hTIFF, TIFFIsTiled(hTIFF), "GTIFMemBufFromWkt"); TIFFWriteDirectory( hTIFF ); XTIFFClose( hTIFF ); /* -------------------------------------------------------------------- */ /* Read back from the memory buffer. It would be preferrable */ /* to be able to "steal" the memory buffer, but there isn't */ /* currently any support for this. */ /* -------------------------------------------------------------------- */ GUIntBig nBigLength; *ppabyBuffer = VSIGetMemFileBuffer( szFilename, &nBigLength, TRUE ); *pnSize = (int) nBigLength; return CE_None; }