Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update ECW Dynamic driver to build with ECW SDK version 6.0 or higher #11593

Draft
wants to merge 5 commits into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
68 changes: 41 additions & 27 deletions autotest/gdrivers/ecw.py
Original file line number Diff line number Diff line change
Expand Up @@ -117,7 +117,7 @@ def test_ecw_2():
if gdaltest.ecw_drv.major_version == 3:
(exp_mean, exp_stddev) = (141.172, 67.3636)
else:
if gdaltest.ecw_drv.major_version == 5:
if gdaltest.ecw_drv.major_version == 5 or gdaltest.ecw_drv.major_version == 6:
(exp_mean, exp_stddev) = (141.606, 67.2919)
else:
(exp_mean, exp_stddev) = (140.332, 67.611)
Expand Down Expand Up @@ -165,7 +165,7 @@ def test_ecw_4(tmp_path):
if gdaltest.ecw_drv.major_version == 3:
(exp_mean, exp_stddev) = (140.290, 66.6303)
else:
if gdaltest.ecw_drv.major_version == 5:
if gdaltest.ecw_drv.major_version == 5 or gdaltest.ecw_drv.major_version == 6:
(exp_mean, exp_stddev) = (141.517, 67.1285)
else:
(exp_mean, exp_stddev) = (138.971, 67.716)
Expand Down Expand Up @@ -635,7 +635,7 @@ def test_ecw_20():
if gdaltest.ecw_drv.major_version == 3:
(exp_mean, exp_stddev) = (141.644, 67.2186)
else:
if gdaltest.ecw_drv.major_version == 5:
if gdaltest.ecw_drv.major_version == 5 or gdaltest.ecw_drv.major_version == 6:
(exp_mean, exp_stddev) = (142.189, 62.4223)
else:
(exp_mean, exp_stddev) = (140.889, 62.742)
Expand Down Expand Up @@ -669,7 +669,7 @@ def test_ecw_21():
if gdaltest.ecw_drv.major_version == 3:
(exp_mean, exp_stddev) = (141.172, 67.3636)
else:
if gdaltest.ecw_drv.major_version == 5:
if gdaltest.ecw_drv.major_version == 5 or gdaltest.ecw_drv.major_version == 6:
(exp_mean, exp_stddev) = (141.606, 67.2919)
else:
(exp_mean, exp_stddev) = (140.332, 67.611)
Expand Down Expand Up @@ -1933,6 +1933,14 @@ def test_ecw_44():
("USE_SOP", "FALSE"),
]

# Modify expected PRECINCT_SIZE_X and PRECINCT_SIZE_Y for ECW SDK 6.x
if gdaltest.ecw_drv.major_version == 6:
for i, (key, value) in enumerate(expected_md):
if key == "PRECINCT_SIZE_X":
expected_md[i] = (key, "64,128,128")
elif key == "PRECINCT_SIZE_Y":
expected_md[i] = (key, "64,128,128")

got_md = ds.GetMetadata("JPEG2000")
for (key, value) in expected_md:
assert key in got_md and got_md[key] == value
Expand All @@ -1949,6 +1957,8 @@ def RemoveDriverMetadata(md):
del md["COLORSPACE"]
if "VERSION" in md:
del md["VERSION"]
if "ALL_COMMENTS" in md:
del md["ALL_COMMENTS"]
return md


Expand All @@ -1973,65 +1983,67 @@ def test_ecw_45():
src_ds = gdal.GetDriverByName("MEM").Create("", 2, 2)
src_ds.SetMetadataItem("FOO", "BAR")
out_ds = gdaltest.jp2ecw_drv.CreateCopy(
"/vsimem/ecw_45.jp2", src_ds, options=options
"/vsimem/ecw_45_1.jp2", src_ds, options=options
)
del out_ds
assert gdal.VSIStatL("/vsimem/ecw_45.jp2.aux.xml") is None
ds = gdal.Open("/vsimem/ecw_45.jp2")
assert gdal.VSIStatL("/vsimem/ecw_45_1.jp2.aux.xml") is None

ds = gdal.Open("/vsimem/ecw_45_1.jp2")

md = RemoveDriverMetadata(ds.GetMetadata())
assert md == {"FOO": "BAR"}
gdal.Unlink("/vsimem/ecw_45.jp2")
gdal.Unlink("/vsimem/ecw_45_1.jp2")

# Simple metadata in auxiliary domain
src_ds = gdal.GetDriverByName("MEM").Create("", 2, 2)
src_ds.SetMetadataItem("FOO", "BAR", "SOME_DOMAIN")
out_ds = gdaltest.jp2ecw_drv.CreateCopy(
"/vsimem/ecw_45.jp2", src_ds, options=["WRITE_METADATA=YES"]
"/vsimem/ecw_45_2.jp2", src_ds, options=["WRITE_METADATA=YES"]
)
del out_ds
assert gdal.VSIStatL("/vsimem/ecw_45.jp2.aux.xml") is None
ds = gdal.Open("/vsimem/ecw_45.jp2")
assert gdal.VSIStatL("/vsimem/ecw_45_2.jp2.aux.xml") is None
ds = gdal.Open("/vsimem/ecw_45_2.jp2")
md = RemoveDriverMetadata(ds.GetMetadata("SOME_DOMAIN"))
assert md == {"FOO": "BAR"}
gdal.Unlink("/vsimem/ecw_45.jp2")
gdal.Unlink("/vsimem/ecw_45_2.jp2")

# Simple metadata in auxiliary XML domain
src_ds = gdal.GetDriverByName("MEM").Create("", 2, 2)
src_ds.SetMetadata(["<some_arbitrary_xml_box/>"], "xml:SOME_DOMAIN")
out_ds = gdaltest.jp2ecw_drv.CreateCopy(
"/vsimem/ecw_45.jp2", src_ds, options=["WRITE_METADATA=YES"]
"/vsimem/ecw_45_3.jp2", src_ds, options=["WRITE_METADATA=YES"]
)
del out_ds
assert gdal.VSIStatL("/vsimem/ecw_45.jp2.aux.xml") is None
ds = gdal.Open("/vsimem/ecw_45.jp2")
assert gdal.VSIStatL("/vsimem/ecw_45_3.jp2.aux.xml") is None
ds = gdal.Open("/vsimem/ecw_45_3.jp2")
assert ds.GetMetadata("xml:SOME_DOMAIN")[0] == "<some_arbitrary_xml_box />\n"
gdal.Unlink("/vsimem/ecw_45.jp2")
gdal.Unlink("/vsimem/ecw_45_3.jp2")

# Special xml:BOX_ metadata domain
for options in [["WRITE_METADATA=YES"]]:
src_ds = gdal.GetDriverByName("MEM").Create("", 2, 2)
src_ds.SetMetadata(["<some_arbitrary_xml_box/>"], "xml:BOX_1")
out_ds = gdaltest.jp2ecw_drv.CreateCopy(
"/vsimem/ecw_45.jp2", src_ds, options=options
"/vsimem/ecw_45_4.jp2", src_ds, options=options
)
del out_ds
assert gdal.VSIStatL("/vsimem/ecw_45.jp2.aux.xml") is None
ds = gdal.Open("/vsimem/ecw_45.jp2")
assert gdal.VSIStatL("/vsimem/ecw_45_4.jp2.aux.xml") is None
ds = gdal.Open("/vsimem/ecw_45_4.jp2")
assert ds.GetMetadata("xml:BOX_0")[0] == "<some_arbitrary_xml_box/>"
gdal.Unlink("/vsimem/ecw_45.jp2")
gdal.Unlink("/vsimem/ecw_45_4.jp2")

# Special xml:XMP metadata domain
for options in [["WRITE_METADATA=YES"]]:
src_ds = gdal.GetDriverByName("MEM").Create("", 2, 2)
src_ds.SetMetadata(["<fake_xmp_box/>"], "xml:XMP")
out_ds = gdaltest.jp2ecw_drv.CreateCopy(
"/vsimem/ecw_45.jp2", src_ds, options=options
"/vsimem/ecw_45_5.jp2", src_ds, options=options
)
del out_ds
assert gdal.VSIStatL("/vsimem/ecw_45.jp2.aux.xml") is None
ds = gdal.Open("/vsimem/ecw_45.jp2")
assert gdal.VSIStatL("/vsimem/ecw_45_5.jp2.aux.xml") is None
ds = gdal.Open("/vsimem/ecw_45_5.jp2")
assert ds.GetMetadata("xml:XMP")[0] == "<fake_xmp_box/>"
gdal.Unlink("/vsimem/ecw_45.jp2")
gdal.Unlink("/vsimem/ecw_45_5.jp2")


###############################################################################
Expand Down Expand Up @@ -2107,7 +2119,7 @@ def test_ecw_47():

mean_tolerance = 0.5

if gdaltest.ecw_drv.major_version == 5:
if gdaltest.ecw_drv.major_version == 5 or gdaltest.ecw_drv.major_version == 6:
(exp_mean, exp_stddev) = (141.606, 67.2919)
elif gdaltest.ecw_drv.major_version == 4:
(exp_mean, exp_stddev) = (140.332, 67.611)
Expand Down Expand Up @@ -2355,7 +2367,9 @@ def test_ecw_online_4():
if gdaltest.jp2ecw_drv is None:
pytest.skip()

if gdaltest.ecw_drv.major_version == 5 and gdaltest.ecw_drv.minor_version == 2:
if (
gdaltest.ecw_drv.major_version == 5 and gdaltest.ecw_drv.minor_version == 2
) or gdaltest.ecw_drv.major_version >= 6:
pytest.skip("This test hangs on Linux in a mutex in the SDK 5.2.1")

gdaltest.download_or_skip(
Expand Down Expand Up @@ -2403,7 +2417,7 @@ def test_ecw_online_5():
mean_tolerance = 1
else:
mean_tolerance = 0.5
if gdaltest.ecw_drv.major_version == 5:
if gdaltest.ecw_drv.major_version == 5 or gdaltest.ecw_drv.major_version == 6:
(exp_mean, exp_stddev) = (113.345, 52.1259)
else:
(exp_mean, exp_stddev) = (114.337, 52.1751)
Expand Down
95 changes: 95 additions & 0 deletions frmts/ecw/ecwcreatecopy.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -814,6 +814,86 @@ CPLErr GDALECWCompressor::Initialize(

if (bIsJPEG2000)
{
#if ECWSDK_VERSION >= 60

pszOption = CSLFetchNameValue(papszOptions, "PROFILE");
if (pszOption != nullptr && EQUAL(pszOption, "BASELINE_0"))
parameters->jp2.compress.SetProfile(
NCS::JPC::CJPC::Profile::BASELINE_0);
else if (pszOption != nullptr && EQUAL(pszOption, "BASELINE_1"))
parameters->jp2.compress.SetProfile(
NCS::JPC::CJPC::Profile::BASELINE_1);
else if (pszOption != nullptr && EQUAL(pszOption, "BASELINE_2"))
parameters->jp2.compress.SetProfile(
NCS::JPC::CJPC::Profile::BASELINE_2);
else if (pszOption != nullptr && EQUAL(pszOption, "NPJE"))
parameters->jp2.compress.SetProfile(
NCS::JPC::CJPC::Profile::NITF_BIIF_NPJE);
else if (pszOption != nullptr && EQUAL(pszOption, "EPJE"))
parameters->jp2.compress.SetProfile(
NCS::JPC::CJPC::Profile::NITF_BIIF_EPJE);

pszOption = CSLFetchNameValue(papszOptions, "CODESTREAM_ONLY");
if (pszOption == nullptr && EQUAL(CPLGetExtension(pszFilename), "j2k"))
pszOption = "YES";
if (pszOption != nullptr)
parameters->jp2.compress.SetWriteCodestreamOnly(
CPLTestBool(pszOption));

pszOption = CSLFetchNameValue(papszOptions, "LEVELS");
if (pszOption != nullptr)
parameters->jp2.compress.SetLevels((UINT32)atoi(pszOption));

pszOption = CSLFetchNameValue(papszOptions, "LAYERS");
if (pszOption != nullptr)
parameters->jp2.compress.SetLayers((UINT32)atoi(pszOption));

pszOption = CSLFetchNameValue(papszOptions, "PRECINCT_WIDTH");
UINT32 width = 0;
UINT32 height = 0;
if (pszOption != nullptr)
{
width = (UINT32)atoi(pszOption);

pszOption = CSLFetchNameValue(papszOptions, "PRECINCT_HEIGHT");
if (pszOption != nullptr)
{
height = (UINT32)atoi(pszOption);
parameters->jp2.compress.SetPrecinctDimensions(width, height);
}
}
pszOption = CSLFetchNameValue(papszOptions, "TILE_WIDTH");
if (pszOption != nullptr)
{
width = (UINT32)atoi(pszOption);

pszOption = CSLFetchNameValue(papszOptions, "TILE_HEIGHT");
if (pszOption != nullptr)
{
height = (UINT32)atoi(pszOption);
parameters->jp2.compress.SetTileDimensions(width, height);
}
}

pszOption = CSLFetchNameValue(papszOptions, "INCLUDE_SOP");
if (pszOption != nullptr)
parameters->jp2.compress.SetIncludeSOP(CPLTestBool(pszOption));

pszOption = CSLFetchNameValue(papszOptions, "INCLUDE_EPH");
if (pszOption != nullptr)
parameters->jp2.compress.SetIncludeEPH(CPLTestBool(pszOption));

pszOption = CSLFetchNameValue(papszOptions, "PROGRESSION");
if (pszOption != nullptr && EQUAL(pszOption, "LRCP"))
parameters->jp2.compress.SetPrecinctProgressionOrder(
NCS::JPC::CProgressionOrderType::Type::LRCP);
else if (pszOption != nullptr && EQUAL(pszOption, "RLCP"))
parameters->jp2.compress.SetPrecinctProgressionOrder(
NCS::JPC::CProgressionOrderType::Type::RLCP);
else if (pszOption != nullptr && EQUAL(pszOption, "RPCL"))
parameters->jp2.compress.SetPrecinctProgressionOrder(
NCS::JPC::CProgressionOrderType::Type::RPCL);
#else
pszOption = CSLFetchNameValue(papszOptions, "PROFILE");
if (pszOption != nullptr && EQUAL(pszOption, "BASELINE_0"))
SetParameter(CNCSJP2FileView::JP2_COMPRESS_PROFILE_BASELINE_0);
Expand Down Expand Up @@ -882,6 +962,7 @@ CPLErr GDALECWCompressor::Initialize(

else if (pszOption != nullptr && EQUAL(pszOption, "RPCL"))
SetParameter(CNCSJP2FileView::JP2_COMPRESS_PROGRESSION_RPCL);
#endif

pszOption = CSLFetchNameValue(papszOptions, "GEODATA_USAGE");
if (pszOption == nullptr)
Expand All @@ -900,6 +981,19 @@ CPLErr GDALECWCompressor::Initialize(
else if (EQUAL(pszOption, "ALL"))
SetGeodataUsage(JP2_GEODATA_USE_GML_PCS_WLD);

#if ECWSDK_VERSION >= 60
pszOption = CSLFetchNameValue(papszOptions, "DECOMPRESS_LAYERS");
if (pszOption != nullptr)
parameters->jp2.decompress.SetLayersToDecode(
(UINT32)atoi(pszOption));

pszOption = CSLFetchNameValue(papszOptions,
"DECOMPRESS_RECONSTRUCTION_PARAMETER");
if (pszOption != nullptr)
parameters->jp2.decompress.SetReconstructionParameter(
(IEEE4)CPLAtof(pszOption));

#else
pszOption = CSLFetchNameValue(papszOptions, "DECOMPRESS_LAYERS");
if (pszOption != nullptr)
SetParameter(CNCSJP2FileView::JP2_DECOMPRESS_LAYERS,
Expand All @@ -911,6 +1005,7 @@ CPLErr GDALECWCompressor::Initialize(
SetParameter(
CNCSJP2FileView::JPC_DECOMPRESS_RECONSTRUCTION_PARAMETER,
(IEEE4)CPLAtof(pszOption));
#endif
}

/* -------------------------------------------------------------------- */
Expand Down
Loading
Loading