From 41aa6104f37cac205c3230565704be3ba07b552a Mon Sep 17 00:00:00 2001 From: Even Rouault Date: Mon, 19 Feb 2024 18:38:43 +0100 Subject: [PATCH] JP2KAK: do not export GMLJP2 if the SRS isn't compatible (fixes #9223) --- autotest/gdrivers/jp2kak.py | 59 +++++++++++++++++++++++++++++++++- frmts/jp2kak/jp2kakdataset.cpp | 46 +++++++++++++++++++------- 2 files changed, 93 insertions(+), 12 deletions(-) diff --git a/autotest/gdrivers/jp2kak.py b/autotest/gdrivers/jp2kak.py index 209032e4e7c6..9ed83d164f6f 100755 --- a/autotest/gdrivers/jp2kak.py +++ b/autotest/gdrivers/jp2kak.py @@ -33,7 +33,7 @@ import gdaltest import pytest -from osgeo import gdal +from osgeo import gdal, osr pytestmark = pytest.mark.require_driver("JP2KAK") @@ -953,3 +953,60 @@ def find_xml_node(ar, element_name, only_attributes=False): if found is not None: return found return None + + +############################################################################### +# Test unsupported XML SRS + + +def test_jp2kak_unsupported_srs_for_gmljp2(tmp_vsimem): + + filename = str(tmp_vsimem / "out.jp2") + # No EPSG code and Albers Equal Area not supported by OGRSpatialReference::exportToXML() + wkt = """PROJCRS["Africa_Albers_Equal_Area_Conic", + BASEGEOGCRS["WGS 84", + DATUM["World Geodetic System 1984", + ELLIPSOID["WGS 84",6378137,298.257223563, + LENGTHUNIT["metre",1]]], + PRIMEM["Greenwich",0, + ANGLEUNIT["degree",0.0174532925199433]], + ID["EPSG",4326]], + CONVERSION["Albers Equal Area", + METHOD["Albers Equal Area", + ID["EPSG",9822]], + PARAMETER["Latitude of false origin",0, + ANGLEUNIT["degree",0.0174532925199433], + ID["EPSG",8821]], + PARAMETER["Longitude of false origin",25, + ANGLEUNIT["degree",0.0174532925199433], + ID["EPSG",8822]], + PARAMETER["Latitude of 1st standard parallel",20, + ANGLEUNIT["degree",0.0174532925199433], + ID["EPSG",8823]], + PARAMETER["Latitude of 2nd standard parallel",-23, + ANGLEUNIT["degree",0.0174532925199433], + ID["EPSG",8824]], + PARAMETER["Easting at false origin",0, + LENGTHUNIT["metre",1], + ID["EPSG",8826]], + PARAMETER["Northing at false origin",0, + LENGTHUNIT["metre",1], + ID["EPSG",8827]]], + CS[Cartesian,2], + AXIS["easting",east, + ORDER[1], + LENGTHUNIT["metre",1, + ID["EPSG",9001]]], + AXIS["northing",north, + ORDER[2], + LENGTHUNIT["metre",1, + ID["EPSG",9001]]]]""" + gdal.ErrorReset() + assert gdal.Translate(filename, "data/byte.tif", outputSRS=wkt, format="JP2KAK") + assert gdal.GetLastErrorMsg() == "" + ds = gdal.Open(filename) + ref_srs = osr.SpatialReference() + ref_srs.ImportFromWkt(wkt) + assert ds.GetSpatialRef().IsSame(ref_srs) + # Check that we do *not* have a GMLJP2 box + assert "xml:gml.root-instance" not in ds.GetMetadataDomainList() diff --git a/frmts/jp2kak/jp2kakdataset.cpp b/frmts/jp2kak/jp2kakdataset.cpp index 287fea1931b1..b54d8cc7c45b 100644 --- a/frmts/jp2kak/jp2kakdataset.cpp +++ b/frmts/jp2kak/jp2kakdataset.cpp @@ -2701,7 +2701,7 @@ static GDALDataset *JP2KAKCreateCopy(const char *pszFilename, { const char *pszGMLJP2V2Def = CSLFetchNameValue(papszOptions, "GMLJP2V2_DEF"); - GDALJP2Box *poBox; + GDALJP2Box *poBox = nullptr; if (pszGMLJP2V2Def != nullptr) { poBox = oJP2MD.CreateGMLJP2V2(nXSize, nYSize, pszGMLJP2V2Def, @@ -2709,18 +2709,42 @@ static GDALDataset *JP2KAKCreateCopy(const char *pszFilename, } else { - poBox = oJP2MD.CreateGMLJP2(nXSize, nYSize); + const OGRSpatialReference *poSRS = + poSrcDS->GetGCPCount() > 0 ? poSrcDS->GetGCPSpatialRef() + : poSrcDS->GetSpatialRef(); + if (poSRS == nullptr || poSRS->IsEmpty() || + GDALJP2Metadata::IsSRSCompatible(poSRS)) + { + poBox = oJP2MD.CreateGMLJP2(nXSize, nYSize); + } + else if (CSLFetchNameValue(papszOptions, "GMLJP2")) + { + CPLError(CE_Warning, CPLE_AppDefined, + "GMLJP2 box was explicitly required but cannot be " + "written due " + "to lack of georeferencing and/or unsupported " + "georeferencing " + "for GMLJP2"); + } + else + { + CPLDebug("JP2KAK", + "Cannot write GMLJP2 box due to unsupported SRS"); + } } - try + if (poBox) { - JP2KAKWriteBox(&family, poBox); - } - catch (...) - { - CPLDebug("JP2KAK", "JP2KAKWriteBox) - caught exception."); - oCodeStream.destroy(); - delete poBox; - return nullptr; + try + { + JP2KAKWriteBox(&family, poBox); + } + catch (...) + { + CPLDebug("JP2KAK", "JP2KAKWriteBox) - caught exception."); + oCodeStream.destroy(); + delete poBox; + return nullptr; + } } } if (CPLFetchBool(papszOptions, "GeoJP2", true))