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

Add new GCI_ constants in particular for InfraRed and SAR, and 'standardize' … #10721

Merged
merged 5 commits into from
Sep 19, 2024
Merged
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
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
Loading