diff --git a/autotest/gcore/data/gtiff/epsg_27563_allgeokeys.tif b/autotest/gcore/data/gtiff/epsg_27563_allgeokeys.tif new file mode 100644 index 000000000000..da79734dd378 Binary files /dev/null and b/autotest/gcore/data/gtiff/epsg_27563_allgeokeys.tif differ diff --git a/autotest/gcore/tiff_srs.py b/autotest/gcore/tiff_srs.py index 1596a5427842..71a922ad89f6 100755 --- a/autotest/gcore/tiff_srs.py +++ b/autotest/gcore/tiff_srs.py @@ -1424,3 +1424,106 @@ def test_tiff_srs_build_compd_crs_name_without_citation(): ds = gdal.Open("data/gtiff/compdcrs_no_citation.tif") assert ds.GetSpatialRef().GetName() == "WGS 84 / UTM zone 17N + EGM2008 height" + + +def test_tiff_srs_read_epsg_27563_allgeokeys(): + + ds = gdal.Open("data/gtiff/epsg_27563_allgeokeys.tif") + srs = ds.GetSpatialRef() + wkt = srs.ExportToWkt(["FORMAT=WKT2_2019"]) + # deal with differences of precision according to PROJ version + wkt = wkt.replace("49.0000000000001", "49") + wkt = wkt.replace("49.0000000000002", "49") + assert 'PARAMETER["Latitude of natural origin",49,ANGLEUNIT["grad"' in wkt + assert ( + srs.ExportToProj4() + == "+proj=lcc +lat_1=44.1 +lat_0=44.1 +lon_0=0 +k_0=0.999877499 +x_0=600000 +y_0=200000 +ellps=clrk80ign +pm=paris +towgs84=-168,-60,320,0,0,0,0 +units=m +no_defs" + ) + + +def test_tiff_srs_write_read_epsg_27563_only_code(tmp_vsimem): + + filename = str(tmp_vsimem / "test.tif") + srs = osr.SpatialReference() + srs.ImportFromEPSG(27563) + ds = gdal.GetDriverByName("GTiff").Create(filename, 1, 1) + ds.SetSpatialRef(srs) + ds = None + + ds = gdal.Open(filename) + srs = ds.GetSpatialRef() + assert ( + 'PARAMETER["Latitude of natural origin",49,ANGLEUNIT["grad"' + in srs.ExportToWkt(["FORMAT=WKT2_2019"]) + ) + assert ( + srs.ExportToProj4() + == "+proj=lcc +lat_1=44.1 +lat_0=44.1 +lon_0=0 +k_0=0.999877499 +x_0=600000 +y_0=200000 +ellps=clrk80ign +pm=paris +towgs84=-168,-60,320,0,0,0,0 +units=m +no_defs" + ) + + +@pytest.mark.parametrize( + "config_options", + [ + {}, + { + "GTIFF_WRITE_ANGULAR_PARAMS_IN_DEGREE": "YES", + "GTIFF_READ_ANGULAR_PARAMS_IN_DEGREE": "YES", + }, + ], +) +def test_tiff_srs_write_read_epsg_27563_full_def(tmp_vsimem, config_options): + + with gdal.config_options(config_options): + filename = str(tmp_vsimem / "test.tif") + srs = osr.SpatialReference() + srs.SetFromUserInput( + """PROJCRS["NTF (Paris) / Lambert Sud France", + BASEGEOGCRS["NTF (Paris)", + DATUM["Nouvelle Triangulation Francaise (Paris)", + ELLIPSOID["Clarke 1880 (IGN)",6378249.2,293.466021293627, + LENGTHUNIT["metre",1]]], + PRIMEM["Paris",2.5969213, + ANGLEUNIT["grad",0.0157079632679489]], + ID["EPSG",4807]], + CONVERSION["Lambert Sud France", + METHOD["Lambert Conic Conformal (1SP)", + ID["EPSG",9801]], + PARAMETER["Latitude of natural origin",49, + ANGLEUNIT["grad",0.0157079632679489], + ID["EPSG",8801]], + PARAMETER["Longitude of natural origin",0, + ANGLEUNIT["grad",0.0157079632679489], + ID["EPSG",8802]], + PARAMETER["Scale factor at natural origin",0.999877499, + SCALEUNIT["unity",1], + ID["EPSG",8805]], + PARAMETER["False easting",600000, + LENGTHUNIT["metre",1], + ID["EPSG",8806]], + PARAMETER["False northing",200000, + LENGTHUNIT["metre",1], + ID["EPSG",8807]]], + CS[Cartesian,2], + AXIS["easting (X)",east, + ORDER[1], + LENGTHUNIT["metre",1]], + AXIS["northing (Y)",north, + ORDER[2], + LENGTHUNIT["metre",1]]]""" + ) + ds = gdal.GetDriverByName("GTiff").Create(filename, 1, 1) + ds.SetSpatialRef(srs) + ds = None + + ds = gdal.Open(filename) + srs = ds.GetSpatialRef() + wkt = srs.ExportToWkt(["FORMAT=WKT2_2019"]) + # deal with differences of precision according to PROJ version + wkt = wkt.replace("49.0000000000001", "49") + wkt = wkt.replace("49.0000000000002", "49") + assert 'PARAMETER["Latitude of natural origin",49,ANGLEUNIT["grad"' in wkt + assert ( + srs.ExportToProj4() + == "+proj=lcc +lat_1=44.1 +lat_0=44.1 +lon_0=0 +k_0=0.999877499 +x_0=600000 +y_0=200000 +ellps=clrk80ign +pm=paris +units=m +no_defs" + ) diff --git a/doc/source/drivers/raster/gtiff.rst b/doc/source/drivers/raster/gtiff.rst index 148d0647fcf4..1f62e2f17eab 100644 --- a/doc/source/drivers/raster/gtiff.rst +++ b/doc/source/drivers/raster/gtiff.rst @@ -1124,6 +1124,34 @@ the default behavior of the GTiff driver. expected to be necessary, unless GDAL is incorrectly determining the disk space available on the destination file system. +- .. config:: GTIFF_READ_ANGULAR_PARAMS_IN_DEGREE + :choices: YES, NO + :default: NO + :since: 3.9.1 + + Conformant GeoTIFF files should have the values of angular projection + parameters written in the unit of the GeogAngularUnitsGeoKey. But some + non-conformant implementations, such as GDAL <= 3.9.0, always wrote them + in degrees. + This option can be set to YES when reading such non-conformant GeoTIFF + files (typically using grads), to instruct GDAL (>= 3.9.1) that the projection + parameters are in degrees, instead of being expressed in the unit of the + GeogAngularUnitsGeoKey. + +- .. config:: GTIFF_WRITE_ANGULAR_PARAMS_IN_DEGREE + :choices: YES, NO + :default: NO + :since: 3.9.1 + + Conformant GeoTIFF files should have the values of angular projection + parameters written in the unit of the GeogAngularUnitsGeoKey. But some + non-conformant implementations, such as GDAL >= 3.0 and <= 3.9.0, assumed + those values to be in degree. + This option can be set to YES to force writing such non-conformant GeoTIFF + files. It should *not* be nominally used, except to workaround interoperability + issues. + + Codec Recommendations --------------------- diff --git a/frmts/gtiff/gt_wkt_srs.cpp b/frmts/gtiff/gt_wkt_srs.cpp index 75662539444a..919829f2d511 100644 --- a/frmts/gtiff/gt_wkt_srs.cpp +++ b/frmts/gtiff/gt_wkt_srs.cpp @@ -1397,6 +1397,43 @@ OGRSpatialReferenceH GTIFGetOGISDefnAsOSR(GTIF *hGTIF, GTIFDefn *psDefn) for (; i < 10; i++) adfParam[i] = 0.0; +#if LIBGEOTIFF_VERSION <= 1730 + // libgeotiff <= 1.7.3 is unfortunately inconsistent. When it synthetizes the + // projection parameters from the EPSG ProjectedCRS code, it returns + // them normalized in degrees. But when it gets them from + // ProjCoordTransGeoKey and other Proj....GeoKey's it return them in + // a raw way, that is in the units of GeogAngularUnitSizeGeoKey + // The below oSRS.SetXXXXX() methods assume the angular projection + // parameters to be in degrees, so convert them to degrees in that later case. + // From GDAL 3.0 to 3.9.0, we didn't do that conversion... + // And all versions of GDAL <= 3.9.0 when writing those geokeys, wrote + // them as degrees, hence this GTIFF_READ_ANGULAR_PARAMS_IN_DEGREE + // config option that can be set to YES to avoid that conversion and + // assume that the angular parameters have been written as degree. + if (GDALGTIFKeyGetSHORT(hGTIF, ProjCoordTransGeoKey, &tmp, 0, 1) && + !CPLTestBool(CPLGetConfigOption( + "GTIFF_READ_ANGULAR_PARAMS_IN_DEGREE", "NO"))) + { + adfParam[0] *= psDefn->UOMAngleInDegrees; + adfParam[1] *= psDefn->UOMAngleInDegrees; + adfParam[2] *= psDefn->UOMAngleInDegrees; + adfParam[3] *= psDefn->UOMAngleInDegrees; + } +#else + // If GTIFF_READ_ANGULAR_PARAMS_IN_DEGREE=YES (non-nominal case), undo + // the conversion to degrees, that has been done by libgeotiff > 1.7.3 + if (GDALGTIFKeyGetSHORT(hGTIF, ProjCoordTransGeoKey, &tmp, 0, 1) && + psDefn->UOMAngleInDegrees != 0 && psDefn->UOMAngleInDegrees != 1 && + CPLTestBool(CPLGetConfigOption( + "GTIFF_READ_ANGULAR_PARAMS_IN_DEGREE", "NO"))) + { + adfParam[0] /= psDefn->UOMAngleInDegrees; + adfParam[1] /= psDefn->UOMAngleInDegrees; + adfParam[2] /= psDefn->UOMAngleInDegrees; + adfParam[3] /= psDefn->UOMAngleInDegrees; + } +#endif + /* -------------------------------------------------------------------- */ /* Translation the fundamental projection. */ @@ -2150,6 +2187,31 @@ int GTIFSetFromOGISDefnEx(GTIF *psGTIF, OGRSpatialReferenceH hSRS, } #endif + double dfAngUnitValue = 0; + std::string osAngUnitName; + if (bHasEllipsoid) + { + const char *angUnitNameTmp = ""; + dfAngUnitValue = poSRS->GetAngularUnits(&angUnitNameTmp); + osAngUnitName = angUnitNameTmp; + } + + // Convert angular projection parameters from its normalized value in degree + // to the units of GeogAngularUnitsGeoKey. + // Note: for GDAL <= 3.9.0, we always have written them in degrees ! + // We can set GTIFF_WRITE_ANGULAR_PARAMS_IN_DEGREE=YES to get that + // non-conformant behavior... + const auto ConvertAngularParam = [dfAngUnitValue](double dfValInDeg) + { + constexpr double DEG_TO_RAD = M_PI / 180.0; + return dfAngUnitValue != 0 && + std::fabs(dfAngUnitValue - DEG_TO_RAD) > 1e-10 && + !CPLTestBool(CPLGetConfigOption( + "GTIFF_WRITE_ANGULAR_PARAMS_IN_DEGREE", "NO")) + ? dfValInDeg * DEG_TO_RAD / dfAngUnitValue + : dfValInDeg; + }; + const char *pszProjection = poSRSCompatibleOfWKT1->GetAttrValue("PROJECTION"); if (nPCS != KvUserDefined) @@ -2191,20 +2253,20 @@ int GTIFSetFromOGISDefnEx(GTIF *psGTIF, OGRSpatialReferenceH hSRS, CT_AlbersEqualArea); GTIFKeySet(psGTIF, ProjStdParallelGeoKey, TYPE_DOUBLE, 1, - poSRSCompatibleOfWKT1->GetNormProjParm( - SRS_PP_STANDARD_PARALLEL_1, 0.0)); + ConvertAngularParam(poSRSCompatibleOfWKT1->GetNormProjParm( + SRS_PP_STANDARD_PARALLEL_1, 0.0))); GTIFKeySet(psGTIF, ProjStdParallel2GeoKey, TYPE_DOUBLE, 1, - poSRSCompatibleOfWKT1->GetNormProjParm( - SRS_PP_STANDARD_PARALLEL_2, 0.0)); + ConvertAngularParam(poSRSCompatibleOfWKT1->GetNormProjParm( + SRS_PP_STANDARD_PARALLEL_2, 0.0))); GTIFKeySet(psGTIF, ProjNatOriginLatGeoKey, TYPE_DOUBLE, 1, - poSRSCompatibleOfWKT1->GetNormProjParm( - SRS_PP_LATITUDE_OF_CENTER, 0.0)); + ConvertAngularParam(poSRSCompatibleOfWKT1->GetNormProjParm( + SRS_PP_LATITUDE_OF_CENTER, 0.0))); GTIFKeySet(psGTIF, ProjNatOriginLongGeoKey, TYPE_DOUBLE, 1, - poSRSCompatibleOfWKT1->GetNormProjParm( - SRS_PP_LONGITUDE_OF_CENTER, 0.0)); + ConvertAngularParam(poSRSCompatibleOfWKT1->GetNormProjParm( + SRS_PP_LONGITUDE_OF_CENTER, 0.0))); GTIFKeySet( psGTIF, ProjFalseEastingGeoKey, TYPE_DOUBLE, 1, @@ -2267,12 +2329,12 @@ int GTIFSetFromOGISDefnEx(GTIF *psGTIF, OGRSpatialReferenceH hSRS, CT_TransverseMercator); GTIFKeySet(psGTIF, ProjNatOriginLatGeoKey, TYPE_DOUBLE, 1, - poSRSCompatibleOfWKT1->GetNormProjParm( - SRS_PP_LATITUDE_OF_ORIGIN, 0.0)); + ConvertAngularParam(poSRSCompatibleOfWKT1->GetNormProjParm( + SRS_PP_LATITUDE_OF_ORIGIN, 0.0))); GTIFKeySet(psGTIF, ProjNatOriginLongGeoKey, TYPE_DOUBLE, 1, - poSRSCompatibleOfWKT1->GetNormProjParm( - SRS_PP_CENTRAL_MERIDIAN, 0.0)); + ConvertAngularParam(poSRSCompatibleOfWKT1->GetNormProjParm( + SRS_PP_CENTRAL_MERIDIAN, 0.0))); GTIFKeySet( psGTIF, ProjScaleAtNatOriginGeoKey, TYPE_DOUBLE, 1, @@ -2298,12 +2360,12 @@ int GTIFSetFromOGISDefnEx(GTIF *psGTIF, OGRSpatialReferenceH hSRS, CT_TransvMercator_SouthOriented); GTIFKeySet(psGTIF, ProjNatOriginLatGeoKey, TYPE_DOUBLE, 1, - poSRSCompatibleOfWKT1->GetNormProjParm( - SRS_PP_LATITUDE_OF_ORIGIN, 0.0)); + ConvertAngularParam(poSRSCompatibleOfWKT1->GetNormProjParm( + SRS_PP_LATITUDE_OF_ORIGIN, 0.0))); GTIFKeySet(psGTIF, ProjNatOriginLongGeoKey, TYPE_DOUBLE, 1, - poSRSCompatibleOfWKT1->GetNormProjParm( - SRS_PP_CENTRAL_MERIDIAN, 0.0)); + ConvertAngularParam(poSRSCompatibleOfWKT1->GetNormProjParm( + SRS_PP_CENTRAL_MERIDIAN, 0.0))); GTIFKeySet( psGTIF, ProjScaleAtNatOriginGeoKey, TYPE_DOUBLE, 1, @@ -2330,17 +2392,18 @@ int GTIFSetFromOGISDefnEx(GTIF *psGTIF, OGRSpatialReferenceH hSRS, GTIFKeySet(psGTIF, ProjCoordTransGeoKey, TYPE_SHORT, 1, CT_Mercator); GTIFKeySet(psGTIF, ProjNatOriginLatGeoKey, TYPE_DOUBLE, 1, - poSRSCompatibleOfWKT1->GetNormProjParm( - SRS_PP_LATITUDE_OF_ORIGIN, 0.0)); + ConvertAngularParam(poSRSCompatibleOfWKT1->GetNormProjParm( + SRS_PP_LATITUDE_OF_ORIGIN, 0.0))); GTIFKeySet(psGTIF, ProjNatOriginLongGeoKey, TYPE_DOUBLE, 1, - poSRSCompatibleOfWKT1->GetNormProjParm( - SRS_PP_CENTRAL_MERIDIAN, 0.0)); + ConvertAngularParam(poSRSCompatibleOfWKT1->GetNormProjParm( + SRS_PP_CENTRAL_MERIDIAN, 0.0))); if (EQUAL(pszProjection, SRS_PT_MERCATOR_2SP)) - GTIFKeySet(psGTIF, ProjStdParallel1GeoKey, TYPE_DOUBLE, 1, - poSRSCompatibleOfWKT1->GetNormProjParm( - SRS_PP_STANDARD_PARALLEL_1, 0.0)); + GTIFKeySet( + psGTIF, ProjStdParallel1GeoKey, TYPE_DOUBLE, 1, + ConvertAngularParam(poSRSCompatibleOfWKT1->GetNormProjParm( + SRS_PP_STANDARD_PARALLEL_1, 0.0))); else GTIFKeySet(psGTIF, ProjScaleAtNatOriginGeoKey, TYPE_DOUBLE, 1, poSRSCompatibleOfWKT1->GetNormProjParm( @@ -2366,12 +2429,12 @@ int GTIFSetFromOGISDefnEx(GTIF *psGTIF, OGRSpatialReferenceH hSRS, CT_ObliqueStereographic); GTIFKeySet(psGTIF, ProjNatOriginLatGeoKey, TYPE_DOUBLE, 1, - poSRSCompatibleOfWKT1->GetNormProjParm( - SRS_PP_LATITUDE_OF_ORIGIN, 0.0)); + ConvertAngularParam(poSRSCompatibleOfWKT1->GetNormProjParm( + SRS_PP_LATITUDE_OF_ORIGIN, 0.0))); GTIFKeySet(psGTIF, ProjNatOriginLongGeoKey, TYPE_DOUBLE, 1, - poSRSCompatibleOfWKT1->GetNormProjParm( - SRS_PP_CENTRAL_MERIDIAN, 0.0)); + ConvertAngularParam(poSRSCompatibleOfWKT1->GetNormProjParm( + SRS_PP_CENTRAL_MERIDIAN, 0.0))); GTIFKeySet( psGTIF, ProjScaleAtNatOriginGeoKey, TYPE_DOUBLE, 1, @@ -2397,12 +2460,12 @@ int GTIFSetFromOGISDefnEx(GTIF *psGTIF, OGRSpatialReferenceH hSRS, CT_Stereographic); GTIFKeySet(psGTIF, ProjCenterLatGeoKey, TYPE_DOUBLE, 1, - poSRSCompatibleOfWKT1->GetNormProjParm( - SRS_PP_LATITUDE_OF_ORIGIN, 0.0)); + ConvertAngularParam(poSRSCompatibleOfWKT1->GetNormProjParm( + SRS_PP_LATITUDE_OF_ORIGIN, 0.0))); GTIFKeySet(psGTIF, ProjCenterLongGeoKey, TYPE_DOUBLE, 1, - poSRSCompatibleOfWKT1->GetNormProjParm( - SRS_PP_CENTRAL_MERIDIAN, 0.0)); + ConvertAngularParam(poSRSCompatibleOfWKT1->GetNormProjParm( + SRS_PP_CENTRAL_MERIDIAN, 0.0))); GTIFKeySet( psGTIF, ProjScaleAtNatOriginGeoKey, TYPE_DOUBLE, 1, @@ -2428,12 +2491,12 @@ int GTIFSetFromOGISDefnEx(GTIF *psGTIF, OGRSpatialReferenceH hSRS, CT_PolarStereographic); GTIFKeySet(psGTIF, ProjNatOriginLatGeoKey, TYPE_DOUBLE, 1, - poSRSCompatibleOfWKT1->GetNormProjParm( - SRS_PP_LATITUDE_OF_ORIGIN, 0.0)); + ConvertAngularParam(poSRSCompatibleOfWKT1->GetNormProjParm( + SRS_PP_LATITUDE_OF_ORIGIN, 0.0))); GTIFKeySet(psGTIF, ProjStraightVertPoleLongGeoKey, TYPE_DOUBLE, 1, - poSRSCompatibleOfWKT1->GetNormProjParm( - SRS_PP_CENTRAL_MERIDIAN, 0.0)); + ConvertAngularParam(poSRSCompatibleOfWKT1->GetNormProjParm( + SRS_PP_CENTRAL_MERIDIAN, 0.0))); GTIFKeySet( psGTIF, ProjScaleAtNatOriginGeoKey, TYPE_DOUBLE, 1, @@ -2459,19 +2522,19 @@ int GTIFSetFromOGISDefnEx(GTIF *psGTIF, OGRSpatialReferenceH hSRS, CT_ObliqueMercator); GTIFKeySet(psGTIF, ProjCenterLatGeoKey, TYPE_DOUBLE, 1, - poSRSCompatibleOfWKT1->GetNormProjParm( - SRS_PP_LATITUDE_OF_CENTER, 0.0)); + ConvertAngularParam(poSRSCompatibleOfWKT1->GetNormProjParm( + SRS_PP_LATITUDE_OF_CENTER, 0.0))); GTIFKeySet(psGTIF, ProjCenterLongGeoKey, TYPE_DOUBLE, 1, - poSRSCompatibleOfWKT1->GetNormProjParm( - SRS_PP_LONGITUDE_OF_CENTER, 0.0)); + ConvertAngularParam(poSRSCompatibleOfWKT1->GetNormProjParm( + SRS_PP_LONGITUDE_OF_CENTER, 0.0))); GTIFKeySet(psGTIF, ProjAzimuthAngleGeoKey, TYPE_DOUBLE, 1, poSRSCompatibleOfWKT1->GetNormProjParm(SRS_PP_AZIMUTH, 0.0)); GTIFKeySet(psGTIF, ProjRectifiedGridAngleGeoKey, TYPE_DOUBLE, 1, - poSRSCompatibleOfWKT1->GetNormProjParm( - SRS_PP_RECTIFIED_GRID_ANGLE, 0.0)); + ConvertAngularParam(poSRSCompatibleOfWKT1->GetNormProjParm( + SRS_PP_RECTIFIED_GRID_ANGLE, 0.0))); GTIFKeySet( psGTIF, ProjScaleAtCenterGeoKey, TYPE_DOUBLE, 1, @@ -2498,19 +2561,19 @@ int GTIFSetFromOGISDefnEx(GTIF *psGTIF, OGRSpatialReferenceH hSRS, CT_HotineObliqueMercatorAzimuthCenter); GTIFKeySet(psGTIF, ProjCenterLatGeoKey, TYPE_DOUBLE, 1, - poSRSCompatibleOfWKT1->GetNormProjParm( - SRS_PP_LATITUDE_OF_CENTER, 0.0)); + ConvertAngularParam(poSRSCompatibleOfWKT1->GetNormProjParm( + SRS_PP_LATITUDE_OF_CENTER, 0.0))); GTIFKeySet(psGTIF, ProjCenterLongGeoKey, TYPE_DOUBLE, 1, - poSRSCompatibleOfWKT1->GetNormProjParm( - SRS_PP_LONGITUDE_OF_CENTER, 0.0)); + ConvertAngularParam(poSRSCompatibleOfWKT1->GetNormProjParm( + SRS_PP_LONGITUDE_OF_CENTER, 0.0))); GTIFKeySet(psGTIF, ProjAzimuthAngleGeoKey, TYPE_DOUBLE, 1, poSRSCompatibleOfWKT1->GetNormProjParm(SRS_PP_AZIMUTH, 0.0)); GTIFKeySet(psGTIF, ProjRectifiedGridAngleGeoKey, TYPE_DOUBLE, 1, - poSRSCompatibleOfWKT1->GetNormProjParm( - SRS_PP_RECTIFIED_GRID_ANGLE, 0.0)); + ConvertAngularParam(poSRSCompatibleOfWKT1->GetNormProjParm( + SRS_PP_RECTIFIED_GRID_ANGLE, 0.0))); GTIFKeySet( psGTIF, ProjScaleAtCenterGeoKey, TYPE_DOUBLE, 1, @@ -2536,12 +2599,12 @@ int GTIFSetFromOGISDefnEx(GTIF *psGTIF, OGRSpatialReferenceH hSRS, CT_ObliqueMercator_Laborde); GTIFKeySet(psGTIF, ProjCenterLatGeoKey, TYPE_DOUBLE, 1, - poSRSCompatibleOfWKT1->GetNormProjParm( - SRS_PP_LATITUDE_OF_CENTER, 0.0)); + ConvertAngularParam(poSRSCompatibleOfWKT1->GetNormProjParm( + SRS_PP_LATITUDE_OF_CENTER, 0.0))); GTIFKeySet(psGTIF, ProjCenterLongGeoKey, TYPE_DOUBLE, 1, - poSRSCompatibleOfWKT1->GetNormProjParm( - SRS_PP_LONGITUDE_OF_CENTER, 0.0)); + ConvertAngularParam(poSRSCompatibleOfWKT1->GetNormProjParm( + SRS_PP_LONGITUDE_OF_CENTER, 0.0))); GTIFKeySet(psGTIF, ProjAzimuthAngleGeoKey, TYPE_DOUBLE, 1, poSRSCompatibleOfWKT1->GetNormProjParm(SRS_PP_AZIMUTH, 0.0)); @@ -2570,12 +2633,12 @@ int GTIFSetFromOGISDefnEx(GTIF *psGTIF, OGRSpatialReferenceH hSRS, CT_CassiniSoldner); GTIFKeySet(psGTIF, ProjNatOriginLatGeoKey, TYPE_DOUBLE, 1, - poSRSCompatibleOfWKT1->GetNormProjParm( - SRS_PP_LATITUDE_OF_ORIGIN, 0.0)); + ConvertAngularParam(poSRSCompatibleOfWKT1->GetNormProjParm( + SRS_PP_LATITUDE_OF_ORIGIN, 0.0))); GTIFKeySet(psGTIF, ProjNatOriginLongGeoKey, TYPE_DOUBLE, 1, - poSRSCompatibleOfWKT1->GetNormProjParm( - SRS_PP_CENTRAL_MERIDIAN, 0.0)); + ConvertAngularParam(poSRSCompatibleOfWKT1->GetNormProjParm( + SRS_PP_CENTRAL_MERIDIAN, 0.0))); GTIFKeySet( psGTIF, ProjFalseEastingGeoKey, TYPE_DOUBLE, 1, @@ -2597,20 +2660,20 @@ int GTIFSetFromOGISDefnEx(GTIF *psGTIF, OGRSpatialReferenceH hSRS, CT_EquidistantConic); GTIFKeySet(psGTIF, ProjStdParallel1GeoKey, TYPE_DOUBLE, 1, - poSRSCompatibleOfWKT1->GetNormProjParm( - SRS_PP_STANDARD_PARALLEL_1, 0.0)); + ConvertAngularParam(poSRSCompatibleOfWKT1->GetNormProjParm( + SRS_PP_STANDARD_PARALLEL_1, 0.0))); GTIFKeySet(psGTIF, ProjStdParallel2GeoKey, TYPE_DOUBLE, 1, - poSRSCompatibleOfWKT1->GetNormProjParm( - SRS_PP_STANDARD_PARALLEL_2, 0.0)); + ConvertAngularParam(poSRSCompatibleOfWKT1->GetNormProjParm( + SRS_PP_STANDARD_PARALLEL_2, 0.0))); GTIFKeySet(psGTIF, ProjNatOriginLatGeoKey, TYPE_DOUBLE, 1, - poSRSCompatibleOfWKT1->GetNormProjParm( - SRS_PP_LATITUDE_OF_CENTER, 0.0)); + ConvertAngularParam(poSRSCompatibleOfWKT1->GetNormProjParm( + SRS_PP_LATITUDE_OF_CENTER, 0.0))); GTIFKeySet(psGTIF, ProjNatOriginLongGeoKey, TYPE_DOUBLE, 1, - poSRSCompatibleOfWKT1->GetNormProjParm( - SRS_PP_LONGITUDE_OF_CENTER, 0.0)); + ConvertAngularParam(poSRSCompatibleOfWKT1->GetNormProjParm( + SRS_PP_LONGITUDE_OF_CENTER, 0.0))); GTIFKeySet( psGTIF, ProjFalseEastingGeoKey, TYPE_DOUBLE, 1, @@ -2662,12 +2725,12 @@ int GTIFSetFromOGISDefnEx(GTIF *psGTIF, OGRSpatialReferenceH hSRS, CT_AzimuthalEquidistant); GTIFKeySet(psGTIF, ProjCenterLatGeoKey, TYPE_DOUBLE, 1, - poSRSCompatibleOfWKT1->GetNormProjParm( - SRS_PP_LATITUDE_OF_CENTER, 0.0)); + ConvertAngularParam(poSRSCompatibleOfWKT1->GetNormProjParm( + SRS_PP_LATITUDE_OF_CENTER, 0.0))); GTIFKeySet(psGTIF, ProjCenterLongGeoKey, TYPE_DOUBLE, 1, - poSRSCompatibleOfWKT1->GetNormProjParm( - SRS_PP_LONGITUDE_OF_CENTER, 0.0)); + ConvertAngularParam(poSRSCompatibleOfWKT1->GetNormProjParm( + SRS_PP_LONGITUDE_OF_CENTER, 0.0))); GTIFKeySet( psGTIF, ProjFalseEastingGeoKey, TYPE_DOUBLE, 1, @@ -2689,12 +2752,12 @@ int GTIFSetFromOGISDefnEx(GTIF *psGTIF, OGRSpatialReferenceH hSRS, CT_MillerCylindrical); GTIFKeySet(psGTIF, ProjCenterLatGeoKey, TYPE_DOUBLE, 1, - poSRSCompatibleOfWKT1->GetNormProjParm( - SRS_PP_LATITUDE_OF_CENTER, 0.0)); + ConvertAngularParam(poSRSCompatibleOfWKT1->GetNormProjParm( + SRS_PP_LATITUDE_OF_CENTER, 0.0))); GTIFKeySet(psGTIF, ProjCenterLongGeoKey, TYPE_DOUBLE, 1, - poSRSCompatibleOfWKT1->GetNormProjParm( - SRS_PP_LONGITUDE_OF_CENTER, 0.0)); + ConvertAngularParam(poSRSCompatibleOfWKT1->GetNormProjParm( + SRS_PP_LONGITUDE_OF_CENTER, 0.0))); GTIFKeySet( psGTIF, ProjFalseEastingGeoKey, TYPE_DOUBLE, 1, @@ -2716,16 +2779,16 @@ int GTIFSetFromOGISDefnEx(GTIF *psGTIF, OGRSpatialReferenceH hSRS, CT_Equirectangular); GTIFKeySet(psGTIF, ProjCenterLatGeoKey, TYPE_DOUBLE, 1, - poSRSCompatibleOfWKT1->GetNormProjParm( - SRS_PP_LATITUDE_OF_ORIGIN, 0.0)); + ConvertAngularParam(poSRSCompatibleOfWKT1->GetNormProjParm( + SRS_PP_LATITUDE_OF_ORIGIN, 0.0))); GTIFKeySet(psGTIF, ProjCenterLongGeoKey, TYPE_DOUBLE, 1, - poSRSCompatibleOfWKT1->GetNormProjParm( - SRS_PP_CENTRAL_MERIDIAN, 0.0)); + ConvertAngularParam(poSRSCompatibleOfWKT1->GetNormProjParm( + SRS_PP_CENTRAL_MERIDIAN, 0.0))); GTIFKeySet(psGTIF, ProjStdParallel1GeoKey, TYPE_DOUBLE, 1, - poSRSCompatibleOfWKT1->GetNormProjParm( - SRS_PP_STANDARD_PARALLEL_1, 0.0)); + ConvertAngularParam(poSRSCompatibleOfWKT1->GetNormProjParm( + SRS_PP_STANDARD_PARALLEL_1, 0.0))); GTIFKeySet( psGTIF, ProjFalseEastingGeoKey, TYPE_DOUBLE, 1, @@ -2746,12 +2809,12 @@ int GTIFSetFromOGISDefnEx(GTIF *psGTIF, OGRSpatialReferenceH hSRS, GTIFKeySet(psGTIF, ProjCoordTransGeoKey, TYPE_SHORT, 1, CT_Gnomonic); GTIFKeySet(psGTIF, ProjCenterLatGeoKey, TYPE_DOUBLE, 1, - poSRSCompatibleOfWKT1->GetNormProjParm( - SRS_PP_LATITUDE_OF_ORIGIN, 0.0)); + ConvertAngularParam(poSRSCompatibleOfWKT1->GetNormProjParm( + SRS_PP_LATITUDE_OF_ORIGIN, 0.0))); GTIFKeySet(psGTIF, ProjCenterLongGeoKey, TYPE_DOUBLE, 1, - poSRSCompatibleOfWKT1->GetNormProjParm( - SRS_PP_CENTRAL_MERIDIAN, 0.0)); + ConvertAngularParam(poSRSCompatibleOfWKT1->GetNormProjParm( + SRS_PP_CENTRAL_MERIDIAN, 0.0))); GTIFKeySet( psGTIF, ProjFalseEastingGeoKey, TYPE_DOUBLE, 1, @@ -2773,12 +2836,12 @@ int GTIFSetFromOGISDefnEx(GTIF *psGTIF, OGRSpatialReferenceH hSRS, CT_LambertAzimEqualArea); GTIFKeySet(psGTIF, ProjCenterLatGeoKey, TYPE_DOUBLE, 1, - poSRSCompatibleOfWKT1->GetNormProjParm( - SRS_PP_LATITUDE_OF_CENTER, 0.0)); + ConvertAngularParam(poSRSCompatibleOfWKT1->GetNormProjParm( + SRS_PP_LATITUDE_OF_CENTER, 0.0))); GTIFKeySet(psGTIF, ProjCenterLongGeoKey, TYPE_DOUBLE, 1, - poSRSCompatibleOfWKT1->GetNormProjParm( - SRS_PP_LONGITUDE_OF_CENTER, 0.0)); + ConvertAngularParam(poSRSCompatibleOfWKT1->GetNormProjParm( + SRS_PP_LONGITUDE_OF_CENTER, 0.0))); GTIFKeySet( psGTIF, ProjFalseEastingGeoKey, TYPE_DOUBLE, 1, @@ -2800,12 +2863,12 @@ int GTIFSetFromOGISDefnEx(GTIF *psGTIF, OGRSpatialReferenceH hSRS, CT_Orthographic); GTIFKeySet(psGTIF, ProjCenterLatGeoKey, TYPE_DOUBLE, 1, - poSRSCompatibleOfWKT1->GetNormProjParm( - SRS_PP_LATITUDE_OF_ORIGIN, 0.0)); + ConvertAngularParam(poSRSCompatibleOfWKT1->GetNormProjParm( + SRS_PP_LATITUDE_OF_ORIGIN, 0.0))); GTIFKeySet(psGTIF, ProjCenterLongGeoKey, TYPE_DOUBLE, 1, - poSRSCompatibleOfWKT1->GetNormProjParm( - SRS_PP_CENTRAL_MERIDIAN, 0.0)); + ConvertAngularParam(poSRSCompatibleOfWKT1->GetNormProjParm( + SRS_PP_CENTRAL_MERIDIAN, 0.0))); GTIFKeySet( psGTIF, ProjFalseEastingGeoKey, TYPE_DOUBLE, 1, @@ -2827,12 +2890,12 @@ int GTIFSetFromOGISDefnEx(GTIF *psGTIF, OGRSpatialReferenceH hSRS, CT_NewZealandMapGrid); GTIFKeySet(psGTIF, ProjNatOriginLatGeoKey, TYPE_DOUBLE, 1, - poSRSCompatibleOfWKT1->GetNormProjParm( - SRS_PP_LATITUDE_OF_ORIGIN, 0.0)); + ConvertAngularParam(poSRSCompatibleOfWKT1->GetNormProjParm( + SRS_PP_LATITUDE_OF_ORIGIN, 0.0))); GTIFKeySet(psGTIF, ProjNatOriginLongGeoKey, TYPE_DOUBLE, 1, - poSRSCompatibleOfWKT1->GetNormProjParm( - SRS_PP_CENTRAL_MERIDIAN, 0.0)); + ConvertAngularParam(poSRSCompatibleOfWKT1->GetNormProjParm( + SRS_PP_CENTRAL_MERIDIAN, 0.0))); GTIFKeySet( psGTIF, ProjFalseEastingGeoKey, TYPE_DOUBLE, 1, @@ -2853,8 +2916,8 @@ int GTIFSetFromOGISDefnEx(GTIF *psGTIF, OGRSpatialReferenceH hSRS, GTIFKeySet(psGTIF, ProjCoordTransGeoKey, TYPE_SHORT, 1, CT_Robinson); GTIFKeySet(psGTIF, ProjCenterLongGeoKey, TYPE_DOUBLE, 1, - poSRSCompatibleOfWKT1->GetNormProjParm( - SRS_PP_LONGITUDE_OF_CENTER, 0.0)); + ConvertAngularParam(poSRSCompatibleOfWKT1->GetNormProjParm( + SRS_PP_LONGITUDE_OF_CENTER, 0.0))); GTIFKeySet( psGTIF, ProjFalseEastingGeoKey, TYPE_DOUBLE, 1, @@ -2875,8 +2938,8 @@ int GTIFSetFromOGISDefnEx(GTIF *psGTIF, OGRSpatialReferenceH hSRS, GTIFKeySet(psGTIF, ProjCoordTransGeoKey, TYPE_SHORT, 1, CT_Sinusoidal); GTIFKeySet(psGTIF, ProjCenterLongGeoKey, TYPE_DOUBLE, 1, - poSRSCompatibleOfWKT1->GetNormProjParm( - SRS_PP_LONGITUDE_OF_CENTER, 0.0)); + ConvertAngularParam(poSRSCompatibleOfWKT1->GetNormProjParm( + SRS_PP_LONGITUDE_OF_CENTER, 0.0))); GTIFKeySet( psGTIF, ProjFalseEastingGeoKey, TYPE_DOUBLE, 1, @@ -2898,8 +2961,8 @@ int GTIFSetFromOGISDefnEx(GTIF *psGTIF, OGRSpatialReferenceH hSRS, CT_VanDerGrinten); GTIFKeySet(psGTIF, ProjCenterLongGeoKey, TYPE_DOUBLE, 1, - poSRSCompatibleOfWKT1->GetNormProjParm( - SRS_PP_CENTRAL_MERIDIAN, 0.0)); + ConvertAngularParam(poSRSCompatibleOfWKT1->GetNormProjParm( + SRS_PP_CENTRAL_MERIDIAN, 0.0))); GTIFKeySet( psGTIF, ProjFalseEastingGeoKey, TYPE_DOUBLE, 1, @@ -2921,20 +2984,20 @@ int GTIFSetFromOGISDefnEx(GTIF *psGTIF, OGRSpatialReferenceH hSRS, CT_LambertConfConic_2SP); GTIFKeySet(psGTIF, ProjFalseOriginLatGeoKey, TYPE_DOUBLE, 1, - poSRSCompatibleOfWKT1->GetNormProjParm( - SRS_PP_LATITUDE_OF_ORIGIN, 0.0)); + ConvertAngularParam(poSRSCompatibleOfWKT1->GetNormProjParm( + SRS_PP_LATITUDE_OF_ORIGIN, 0.0))); GTIFKeySet(psGTIF, ProjFalseOriginLongGeoKey, TYPE_DOUBLE, 1, - poSRSCompatibleOfWKT1->GetNormProjParm( - SRS_PP_CENTRAL_MERIDIAN, 0.0)); + ConvertAngularParam(poSRSCompatibleOfWKT1->GetNormProjParm( + SRS_PP_CENTRAL_MERIDIAN, 0.0))); GTIFKeySet(psGTIF, ProjStdParallel1GeoKey, TYPE_DOUBLE, 1, - poSRSCompatibleOfWKT1->GetNormProjParm( - SRS_PP_STANDARD_PARALLEL_1, 0.0)); + ConvertAngularParam(poSRSCompatibleOfWKT1->GetNormProjParm( + SRS_PP_STANDARD_PARALLEL_1, 0.0))); GTIFKeySet(psGTIF, ProjStdParallel2GeoKey, TYPE_DOUBLE, 1, - poSRSCompatibleOfWKT1->GetNormProjParm( - SRS_PP_STANDARD_PARALLEL_2, 0.0)); + ConvertAngularParam(poSRSCompatibleOfWKT1->GetNormProjParm( + SRS_PP_STANDARD_PARALLEL_2, 0.0))); GTIFKeySet( psGTIF, ProjFalseOriginEastingGeoKey, TYPE_DOUBLE, 1, @@ -2956,12 +3019,12 @@ int GTIFSetFromOGISDefnEx(GTIF *psGTIF, OGRSpatialReferenceH hSRS, CT_LambertConfConic_1SP); GTIFKeySet(psGTIF, ProjNatOriginLatGeoKey, TYPE_DOUBLE, 1, - poSRSCompatibleOfWKT1->GetNormProjParm( - SRS_PP_LATITUDE_OF_ORIGIN, 0.0)); + ConvertAngularParam(poSRSCompatibleOfWKT1->GetNormProjParm( + SRS_PP_LATITUDE_OF_ORIGIN, 0.0))); GTIFKeySet(psGTIF, ProjNatOriginLongGeoKey, TYPE_DOUBLE, 1, - poSRSCompatibleOfWKT1->GetNormProjParm( - SRS_PP_CENTRAL_MERIDIAN, 0.0)); + ConvertAngularParam(poSRSCompatibleOfWKT1->GetNormProjParm( + SRS_PP_CENTRAL_MERIDIAN, 0.0))); GTIFKeySet( psGTIF, ProjScaleAtNatOriginGeoKey, TYPE_DOUBLE, 1, @@ -2987,12 +3050,12 @@ int GTIFSetFromOGISDefnEx(GTIF *psGTIF, OGRSpatialReferenceH hSRS, CT_CylindricalEqualArea); GTIFKeySet(psGTIF, ProjNatOriginLongGeoKey, TYPE_DOUBLE, 1, - poSRSCompatibleOfWKT1->GetNormProjParm( - SRS_PP_CENTRAL_MERIDIAN, 0.0)); + ConvertAngularParam(poSRSCompatibleOfWKT1->GetNormProjParm( + SRS_PP_CENTRAL_MERIDIAN, 0.0))); GTIFKeySet(psGTIF, ProjStdParallel1GeoKey, TYPE_DOUBLE, 1, - poSRSCompatibleOfWKT1->GetNormProjParm( - SRS_PP_STANDARD_PARALLEL_1, 0.0)); + ConvertAngularParam(poSRSCompatibleOfWKT1->GetNormProjParm( + SRS_PP_STANDARD_PARALLEL_1, 0.0))); GTIFKeySet( psGTIF, ProjFalseEastingGeoKey, TYPE_DOUBLE, 1, @@ -3133,38 +3196,36 @@ int GTIFSetFromOGISDefnEx(GTIF *psGTIF, OGRSpatialReferenceH hSRS, /* Write angular units. */ /* -------------------------------------------------------------------- */ - const char *angUnitName = ""; if (bHasEllipsoid && (nGCS == KvUserDefined || eVersion == GEOTIFF_VERSION_1_0)) { - double angUnitValue = poSRS->GetAngularUnits(&angUnitName); - if (EQUAL(angUnitName, "Degree")) + if (EQUAL(osAngUnitName.c_str(), "Degree")) GTIFKeySet(psGTIF, GeogAngularUnitsGeoKey, TYPE_SHORT, 1, Angular_Degree); - else if (EQUAL(angUnitName, "arc-second")) + else if (EQUAL(osAngUnitName.c_str(), "arc-second")) GTIFKeySet(psGTIF, GeogAngularUnitsGeoKey, TYPE_SHORT, 1, Angular_Arc_Second); - else if (EQUAL(angUnitName, "arc-minute")) + else if (EQUAL(osAngUnitName.c_str(), "arc-minute")) GTIFKeySet(psGTIF, GeogAngularUnitsGeoKey, TYPE_SHORT, 1, Angular_Arc_Minute); - else if (EQUAL(angUnitName, "grad")) + else if (EQUAL(osAngUnitName.c_str(), "grad")) GTIFKeySet(psGTIF, GeogAngularUnitsGeoKey, TYPE_SHORT, 1, Angular_Grad); - else if (EQUAL(angUnitName, "gon")) + else if (EQUAL(osAngUnitName.c_str(), "gon")) GTIFKeySet(psGTIF, GeogAngularUnitsGeoKey, TYPE_SHORT, 1, Angular_Gon); - else if (EQUAL(angUnitName, "radian")) + else if (EQUAL(osAngUnitName.c_str(), "radian")) GTIFKeySet(psGTIF, GeogAngularUnitsGeoKey, TYPE_SHORT, 1, Angular_Radian); - // else if (EQUAL(angUnitName, "microradian")) + // else if (EQUAL(osAngUnitName.c_str(), "microradian")) // GTIFKeySet(psGTIF, GeogAngularUnitsGeoKey, TYPE_SHORT, 1, // 9109); else { // GeogCitationGeoKey may be rewritten if the gcs is user defined. - oMapAsciiKeys[GeogCitationGeoKey] = angUnitName; + oMapAsciiKeys[GeogCitationGeoKey] = osAngUnitName; GTIFKeySet(psGTIF, GeogAngularUnitSizeGeoKey, TYPE_DOUBLE, 1, - angUnitValue); + dfAngUnitValue); } } @@ -3275,8 +3336,8 @@ int GTIFSetFromOGISDefnEx(GTIF *psGTIF, OGRSpatialReferenceH hSRS, if (nGCS == KvUserDefined && CPLTestBool(CPLGetConfigOption("GTIFF_ESRI_CITATION", "YES"))) { - SetGeogCSCitation(psGTIF, oMapAsciiKeys, poSRS, angUnitName, - nDatum, nSpheroid); + SetGeogCSCitation(psGTIF, oMapAsciiKeys, poSRS, + osAngUnitName.c_str(), nDatum, nSpheroid); } } } diff --git a/frmts/gtiff/libgeotiff/geo_normalize.c b/frmts/gtiff/libgeotiff/geo_normalize.c index 11517462c761..f16b67be4d9d 100644 --- a/frmts/gtiff/libgeotiff/geo_normalize.c +++ b/frmts/gtiff/libgeotiff/geo_normalize.c @@ -2241,15 +2241,16 @@ static void GTIFFetchProjParms( GTIF * psGTIF, GTIFDefn * psDefn ) break; } + for( int iParam = 0; iParam < psDefn->nParms; iParam++ ) + { + switch( psDefn->ProjParmId[iParam] ) + { + /* -------------------------------------------------------------------- */ /* Normalize any linear parameters into meters. In GeoTIFF */ /* the linear projection parameter tags are normally in the */ /* units of the coordinate system described. */ /* -------------------------------------------------------------------- */ - for( int iParam = 0; iParam < psDefn->nParms; iParam++ ) - { - switch( psDefn->ProjParmId[iParam] ) - { case ProjFalseEastingGeoKey: case ProjFalseNorthingGeoKey: case ProjFalseOriginEastingGeoKey: @@ -2263,6 +2264,30 @@ static void GTIFFetchProjParms( GTIF * psGTIF, GTIFDefn * psDefn ) } break; +/* -------------------------------------------------------------------- */ +/* Normalize any angular parameters into degrees. In GeoTIFF */ +/* the angular projection parameter tags are normally in the */ +/* units of GeogAngularUnit. Note: this conversion is only done */ +/* since libgeotiff 1.7.4 */ +/* -------------------------------------------------------------------- */ + + case ProjStdParallel1GeoKey: + case ProjStdParallel2GeoKey: + case ProjNatOriginLongGeoKey: + case ProjNatOriginLatGeoKey: + case ProjFalseOriginLongGeoKey: + case ProjFalseOriginLatGeoKey: + case ProjCenterLongGeoKey: + case ProjCenterLatGeoKey: + case ProjStraightVertPoleLongGeoKey: + case ProjRectifiedGridAngleGeoKey: + if( psDefn->UOMAngleInDegrees != 0 + && psDefn->UOMAngleInDegrees != 1.0 ) + { + psDefn->ProjParm[iParam] *= psDefn->UOMAngleInDegrees; + } + break; + default: break; } diff --git a/frmts/gtiff/libgeotiff/geo_normalize.h b/frmts/gtiff/libgeotiff/geo_normalize.h index 87dd22c7e7df..79f588c813b9 100644 --- a/frmts/gtiff/libgeotiff/geo_normalize.h +++ b/frmts/gtiff/libgeotiff/geo_normalize.h @@ -121,9 +121,15 @@ typedef struct { int nParms; /** Projection parameter value. The identify of this parameter - is established from the corresponding entry in ProjParmId. The - value will be measured in meters, or decimal degrees if it is a - linear or angular measure. */ + is established from the corresponding entry in ProjParmId. + In GeoTIFF keys, the values of the projection parameters are expressed + in the units of ProjLinearUnitsGeoKey (for linear measures) or + GeogAngularUnitsGeoKey (for angular measures). + However, the value returned in ProjParam[] will be normalized to meters + or decimal degrees. + Note: until libgeotiff 1.7.3, the conversion to degrees for angular + measures was *not* done when ProjCoordTransGeoKey is present. + */ double ProjParm[MAX_GTIF_PROJPARMS]; /** Projection parameter identifier. For example ProjFalseEastingGeoKey. diff --git a/frmts/gtiff/libgeotiff/geotiff.h b/frmts/gtiff/libgeotiff/geotiff.h index 29f22917f4c4..75de593c8a0e 100644 --- a/frmts/gtiff/libgeotiff/geotiff.h +++ b/frmts/gtiff/libgeotiff/geotiff.h @@ -47,7 +47,7 @@ #define GEOTIFF_SPEC_1_1_MINOR_REVISION 1 /* Library version */ -#define LIBGEOTIFF_VERSION 1710 +#define LIBGEOTIFF_VERSION 1740 #include "geo_config.h" #include "geokeys.h"