Opened 7 years ago

Closed 7 years ago

Last modified 6 years ago

#5791 closed defect (fixed)

Fix handling of Mercator_2SP in GeoTIFF

Reported by: Even Rouault Owned by: Even Rouault
Priority: normal Milestone: 2.0.0
Component: OGR_SF Version: unspecified
Severity: normal Keywords: libgeotiff mercator_2sp


Email threads :

Mercator_[12]SP are both the same projection in GeoTIFF.  Lacking a
definition in the official specification, the intention appears to be that
for Mercator_2SP the latitude of true scale (lat_ts) should be specified in
ProjStdParallel1GeoKey and for Mercator_1SP the scale at origin (k) should
be specified in ProjScaleAtNatOriginGeoKey.  As proposed here,

Current behavior when creating a GTiff with 2SP is to drop lat_ts and create
a default k value of 1.0, which will product an incorrect projection.  When
reading, 1SP is always used and lat_ts is ignored.  It is expected that
libgeotiff will provide a default k of 1.0 if none was specified in the

This patches changes the behavior when writing to supply
ProjScaleAtNatOriginGeoKey for Mercator_1SP or ProjStdParallel1GeoKey for

When reading, 2SP is used if ProjStdParallel1GeoKey is present and 1SP is
used otherwise.  A warning is issued if both keys are present (and scale is
ignored).  It is expected that libgeotiff's normalization will continue to
provide a default scale of 1.0 if neither parameter is present.
Split out libgeotiff part.  This patch does not need the libgeotiff
patch to be applied.  Will write correctly without libgeotiff patch. 
Reading will be unchanged unless libgeotiff is also patched.

 gdal/frmts/gtiff/gt_wkt_srs.cpp |   28 ++++++++++++++++++++++------
 1 file changed, 22 insertions(+), 6 deletions(-)

diff --git a/gdal/frmts/gtiff/gt_wkt_srs.cpp b/gdal/frmts/gtiff/gt_wkt_srs.cpp
index 5934df5..0afb101 100644
--- a/gdal/frmts/gtiff/gt_wkt_srs.cpp
+++ b/gdal/frmts/gtiff/gt_wkt_srs.cpp
@@ -737,9 +737,21 @@ char *GTIFGetOGISDefn( GTIF *hGTIF, GTIFDefn * psDefn )
           case CT_Mercator:
-            oSRS.SetMercator( adfParm[0], adfParm[1],
-                              adfParm[4],
-                              adfParm[5], adfParm[6] );
+            /* If a lat_ts was specified use 2SP, otherwise use 1SP */
+            if (psDefn->ProjParmId[2] == ProjStdParallel1GeoKey)
+            {
+                if (psDefn->ProjParmId[4] == ProjScaleAtNatOriginGeoKey)
+                    CPLError( CE_Warning, CPLE_AppDefined,
+                              "Mercator projection should not define both StdParallel1 and ScaleAtNatOrigin.\n"
+                              "Using StdParallel1 and ignoring ScaleAtNatOrigin.\n" );
+                oSRS.SetMercator2SP( adfParm[2],
+                                     adfParm[0], adfParm[1],
+                                     adfParm[5], adfParm[6]);
+            }
+            else
+                oSRS.SetMercator( adfParm[0], adfParm[1],
+                                  adfParm[4],
+                                  adfParm[5], adfParm[6] );
             if (psDefn->Projection == 1024 || psDefn->Projection == 9841) // override hack for google mercator. 
@@ -1510,14 +1522,18 @@ int GTIFSetFromOGISDefn( GTIF * psGTIF, const char *pszOGCWKT )
         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->GetProjParm( SRS_PP_FALSE_EASTING, 0.0 ) );
         GTIFKeySet(psGTIF, ProjFalseNorthingGeoKey, TYPE_DOUBLE, 1,
                    poSRS->GetProjParm( SRS_PP_FALSE_NORTHING, 0.0 ) );
+        if( EQUAL(pszProjection,SRS_PT_MERCATOR_2SP) )
+            GTIFKeySet(psGTIF, ProjStdParallel1GeoKey, TYPE_DOUBLE, 1,
+                       poSRS->GetNormProjParm( SRS_PP_STANDARD_PARALLEL_1, 0.0 ) );
+        else
+            GTIFKeySet(psGTIF, ProjScaleAtNatOriginGeoKey, TYPE_DOUBLE, 1,
+                       poSRS->GetNormProjParm( SRS_PP_SCALE_FACTOR, 1.0 ) );
     else if( EQUAL(pszProjection,SRS_PT_OBLIQUE_STEREOGRAPHIC) )

Related geotiff tickets :

Change History (3)

comment:1 Changed 7 years ago by Even Rouault

Milestone: 2.0
Resolution: fixed
Status: newclosed

trunk r28237 "GTiff/internal libgeotiff: fix handling of Mercator_2SP when reading/writing it (without associated EPSG code, patch by Trent Piepho); resync with libgeotiff when reading geotiff information with only a PCS corresponding to a Mercator_2SP projection (#5791)"

comment:2 Changed 7 years ago by Even Rouault

trunk r28239 "Add test for reading a GeoTIFF with both StdParallel1 and ScaleAtNatOrigin? defined (#5791)"

comment:3 Changed 6 years ago by Even Rouault


Milestone renamed

Note: See TracTickets for help on using tickets.