Skip to content

Commit

Permalink
Merge pull request #10721 from rouault/new_gci_values
Browse files Browse the repository at this point in the history
Add new GCI_ constants in particular for InfraRed and SAR, and 'standardize' …
  • Loading branch information
rouault committed Sep 19, 2024
2 parents c814fd3 + 66d2068 commit 9ada0c8
Show file tree
Hide file tree
Showing 27 changed files with 765 additions and 114 deletions.
3 changes: 3 additions & 0 deletions MIGRATION_GUIDE.TXT
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,9 @@ MIGRATION GUIDE FROM GDAL 3.9 to GDAL 3.10
- Python bindings: Band.GetStatistics() and Band.ComputeStatistics() now
return a None value in case of error (when exceptions are not enabled)

- New color interpretation (GCI_xxxx) items have been added to the GDALColorInterp
enumeration. Code testing color interpretation may need to be adapted.

MIGRATION GUIDE FROM GDAL 3.8 to GDAL 3.9
-----------------------------------------

Expand Down
19 changes: 7 additions & 12 deletions apps/gdal_translate_lib.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2737,18 +2737,11 @@ static void CopyBandInfo(GDALRasterBand *poSrcBand, GDALRasterBand *poDstBand,

static int GetColorInterp(const char *pszStr)
{
if (EQUAL(pszStr, "red"))
return GCI_RedBand;
if (EQUAL(pszStr, "green"))
return GCI_GreenBand;
if (EQUAL(pszStr, "blue"))
return GCI_BlueBand;
if (EQUAL(pszStr, "alpha"))
return GCI_AlphaBand;
if (EQUAL(pszStr, "gray") || EQUAL(pszStr, "grey"))
return GCI_GrayIndex;
if (EQUAL(pszStr, "undefined"))
return GCI_Undefined;
const int eInterp = GDALGetColorInterpretationByName(pszStr);
if (eInterp != GCI_Undefined)
return eInterp;
CPLError(CE_Warning, CPLE_NotSupported,
"Unsupported color interpretation: %s", pszStr);
return -1;
Expand Down Expand Up @@ -3078,7 +3071,8 @@ GDALTranslateOptionsGetParser(GDALTranslateOptions *psOptions,
_("Add the indicated ground control point to the output dataset."));

argParser->add_argument("-colorinterp")
.metavar("{red|green|blue|alpha|gray|undefined},...")
.metavar("{red|green|blue|alpha|gray|undefined|pan|coastal|rededge|nir|"
"swir|mwir|lwir|...},...")
.action(
[psOptions](const std::string &s)
{
Expand All @@ -3093,7 +3087,8 @@ GDALTranslateOptionsGetParser(GDALTranslateOptions *psOptions,

argParser->add_argument("-colorinterp_X")
.append()
.metavar("{red|green|blue|alpha|gray|undefined}")
.metavar("{red|green|blue|alpha|gray|undefined|pan|coastal|rededge|nir|"
"swir|mwir|lwir|...}")
.help(_("Override the color interpretation of band X."));

{
Expand Down
28 changes: 19 additions & 9 deletions apps/gdalinfo_lib.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1128,25 +1128,21 @@ char *GDALInfo(GDALDatasetH hDataset, const GDALInfoOptions *psOptions)
json_object_object_add(poStacEOBand, "name", poBandName);
}

if (GDALGetDescription(hBand) != nullptr &&
strlen(GDALGetDescription(hBand)) > 0)
const char *pszBandDesc = GDALGetDescription(hBand);
if (pszBandDesc != nullptr && strlen(pszBandDesc) > 0)
{
if (bJson)
{
json_object *poBandDescription =
json_object_new_string(GDALGetDescription(hBand));
json_object_object_add(poBand, "description",
poBandDescription);
json_object_new_string(pszBandDesc));

json_object *poStacBandDescription =
json_object_new_string(GDALGetDescription(hBand));
json_object_object_add(poStacEOBand, "description",
poStacBandDescription);
json_object_new_string(pszBandDesc));
}
else
{
Concat(osStr, psOptions->bStdoutOutput, " Description = %s\n",
GDALGetDescription(hBand));
pszBandDesc);
}
}
else
Expand All @@ -1161,6 +1157,17 @@ char *GDALInfo(GDALDatasetH hDataset, const GDALInfoOptions *psOptions)
}
}

if (bJson)
{
const char *pszCommonName = GDALGetSTACCommonNameFromColorInterp(
GDALGetRasterColorInterpretation(hBand));
if (pszCommonName)
{
json_object_object_add(poStacEOBand, "common_name",
json_object_new_string(pszCommonName));
}
}

{
int bGotMin = FALSE;
int bGotMax = FALSE;
Expand Down Expand Up @@ -2269,6 +2276,9 @@ static void GDALInfoReportMetadata(const GDALInfoOptions *psOptions,
GDALInfoPrintMetadata(psOptions, hObject, "RPC", "RPC Metadata",
pszIndent, bJson, poMetadata, osStr);
}

GDALInfoPrintMetadata(psOptions, hObject, "IMAGERY", "Imagery", pszIndent,
bJson, poMetadata, osStr);
}

/************************************************************************/
Expand Down
10 changes: 10 additions & 0 deletions autotest/gcore/basic_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -990,3 +990,13 @@ def test_band_getitem():

with pytest.raises(IndexError):
ds[5]


def test_colorinterp():

d = {}
for c in range(gdal.GCI_Max + 1):
name = gdal.GetColorInterpretationName(c)
assert name not in d
d[name] = c
assert gdal.GetColorInterpretationByName(name) == c
Binary file added autotest/gcore/data/gtiff/unknown_colorinterp.tif
Binary file not shown.
12 changes: 12 additions & 0 deletions autotest/gcore/tiff_read.py
Original file line number Diff line number Diff line change
Expand Up @@ -5315,3 +5315,15 @@ def error_handler(type, code, msg):
webserver.server_stop(webserver_process, webserver_port)

gdal.VSICurlClearCache()


###############################################################################
# Test reading a unrecognized value in the special COLORINTERP item in
# GDAL_METADATA


def test_tiff_read_unrecognized_color_interpretation():

ds = gdal.Open("data/gtiff/unknown_colorinterp.tif")
assert ds.GetRasterBand(1).GetColorInterpretation() == gdal.GCI_Undefined
assert ds.GetRasterBand(1).GetMetadataItem("COLOR_INTERPRETATION") == "XXXX"
54 changes: 54 additions & 0 deletions autotest/gcore/tiff_write.py
Original file line number Diff line number Diff line change
Expand Up @@ -11679,3 +11679,57 @@ def test_tiff_write_too_large_webp(
filename = str(tmp_vsimem / "test.tif")
with pytest.raises(Exception, match=expected_error_msg):
gdal.GetDriverByName("GTiff").Create(filename, xsize, ysize, options=options)


###############################################################################
# Test writing/reading band IMAGERY metadata


def test_tiff_write_band_IMAGERY(tmp_vsimem):

filename = str(tmp_vsimem / "test.tif")
with gdal.GetDriverByName("GTiff").Create(filename, 1, 1) as ds:
ds.GetRasterBand(1).SetMetadataItem("foo", "bar", "IMAGERY")
with gdal.Open(filename) as ds:
assert ds.GetRasterBand(1).GetMetadataDomainList() == ["IMAGERY"]
with gdal.Open(filename) as ds:
assert ds.GetRasterBand(1).GetMetadataItem("foo", "IMAGERY") == "bar"
with gdal.Open(filename) as ds:
assert ds.GetRasterBand(1).GetMetadata_Dict("IMAGERY") == {"foo": "bar"}

filename2 = str(tmp_vsimem / "test2.tif")

with gdal.Open(filename) as ds:
gdal.GetDriverByName("GTiff").CreateCopy(filename2, ds)
with gdal.Open(filename2) as ds:
assert ds.GetRasterBand(1).GetMetadata_Dict("IMAGERY") == {"foo": "bar"}

with gdal.Open(filename) as ds:
gdal.GetDriverByName("GTiff").CreateCopy(
filename2, ds, options=["COPY_SRC_MDD=YES"]
)
with gdal.Open(filename2) as ds:
assert ds.GetRasterBand(1).GetMetadata_Dict("IMAGERY") == {"foo": "bar"}

with gdal.Open(filename) as ds:
gdal.GetDriverByName("GTiff").CreateCopy(
filename2, ds, options=["COPY_SRC_MDD=NO"]
)
with gdal.Open(filename2) as ds:
assert ds.GetRasterBand(1).GetMetadataDomainList() is None
assert ds.GetRasterBand(1).GetMetadata_Dict("IMAGERY") == {}

with gdal.Open(filename) as ds:
gdal.GetDriverByName("GTiff").CreateCopy(
filename2, ds, options=["SRC_MDD=not_existing"]
)
with gdal.Open(filename2) as ds:
assert ds.GetRasterBand(1).GetMetadataDomainList() is None
assert ds.GetRasterBand(1).GetMetadata_Dict("IMAGERY") == {}

with gdal.Open(filename) as ds:
gdal.GetDriverByName("GTiff").CreateCopy(
filename2, ds, options=["SRC_MDD=not_existing", "SRC_MDD=IMAGERY"]
)
with gdal.Open(filename2) as ds:
assert ds.GetRasterBand(1).GetMetadata_Dict("IMAGERY") == {"foo": "bar"}
117 changes: 117 additions & 0 deletions autotest/gdrivers/envi.py
Original file line number Diff line number Diff line change
Expand Up @@ -1056,3 +1056,120 @@ def test_envi_read_metadata_with_leading_space():
assert ds.GetRasterBand(1).GetMetadataItem("wavelength") == "3"
ds = None
gdal.GetDriverByName("ENVI").Delete("/vsimem/test.bin")


###############################################################################
# Test wavelength / fwhm


def test_envi_read_wavelength_fwhm_um():

gdal.FileFromMemBuffer(
"/vsimem/test.hdr",
"""ENVI
samples = 1
lines = 1
bands = 3
header offset = 0
file type = ENVI Standard
data type = 1
interleave = bip
sensor type = Unknown
byte order = 0
wavelength units = um
wavelength = {3, 2, 1}
fwhm = {.3, .2, .1}""",
)
gdal.FileFromMemBuffer("/vsimem/test.bin", "xyz")

ds = gdal.Open("/vsimem/test.bin")
assert (
ds.GetRasterBand(1).GetMetadataItem("CENTRAL_WAVELENGTH_UM", "IMAGERY")
== "3.000"
)
assert ds.GetRasterBand(1).GetMetadataItem("FWHM_UM", "IMAGERY") == "0.300"
assert (
ds.GetRasterBand(2).GetMetadataItem("CENTRAL_WAVELENGTH_UM", "IMAGERY")
== "2.000"
)
assert ds.GetRasterBand(2).GetMetadataItem("FWHM_UM", "IMAGERY") == "0.200"
ds = None
gdal.GetDriverByName("ENVI").Delete("/vsimem/test.bin")


###############################################################################
# Test wavelength / fwhm


def test_envi_read_wavelength_fwhm_nm():

gdal.FileFromMemBuffer(
"/vsimem/test.hdr",
"""ENVI
samples = 1
lines = 1
bands = 3
header offset = 0
file type = ENVI Standard
data type = 1
interleave = bip
sensor type = Unknown
byte order = 0
wavelength units = nm
wavelength = {3000, 2000, 1000}
fwhm = {300, 200, 100}""",
)
gdal.FileFromMemBuffer("/vsimem/test.bin", "xyz")

ds = gdal.Open("/vsimem/test.bin")
assert (
ds.GetRasterBand(1).GetMetadataItem("CENTRAL_WAVELENGTH_UM", "IMAGERY")
== "3.000"
)
assert ds.GetRasterBand(1).GetMetadataItem("FWHM_UM", "IMAGERY") == "0.300"
assert (
ds.GetRasterBand(2).GetMetadataItem("CENTRAL_WAVELENGTH_UM", "IMAGERY")
== "2.000"
)
assert ds.GetRasterBand(2).GetMetadataItem("FWHM_UM", "IMAGERY") == "0.200"
ds = None
gdal.GetDriverByName("ENVI").Delete("/vsimem/test.bin")


###############################################################################
# Test wavelength / fwhm


def test_envi_read_wavelength_fwhm_mm():

gdal.FileFromMemBuffer(
"/vsimem/test.hdr",
"""ENVI
samples = 1
lines = 1
bands = 3
header offset = 0
file type = ENVI Standard
data type = 1
interleave = bip
sensor type = Unknown
byte order = 0
wavelength units = mm
wavelength = {0.003, 0.002, 0.001}
fwhm = {0.0003, 0.0002, 0.0001}""",
)
gdal.FileFromMemBuffer("/vsimem/test.bin", "xyz")

ds = gdal.Open("/vsimem/test.bin")
assert (
ds.GetRasterBand(1).GetMetadataItem("CENTRAL_WAVELENGTH_UM", "IMAGERY")
== "3.000"
)
assert ds.GetRasterBand(1).GetMetadataItem("FWHM_UM", "IMAGERY") == "0.300"
assert (
ds.GetRasterBand(2).GetMetadataItem("CENTRAL_WAVELENGTH_UM", "IMAGERY")
== "2.000"
)
assert ds.GetRasterBand(2).GetMetadataItem("FWHM_UM", "IMAGERY") == "0.200"
ds = None
gdal.GetDriverByName("ENVI").Delete("/vsimem/test.bin")
Loading

0 comments on commit 9ada0c8

Please sign in to comment.