Skip to content

Commit acdb4bd

Browse files
authored
Merge pull request OSGeo#11496 from dbaston/buildvrt-warn-invalid-nodata
gdalbuildvrt: Emit warning on invalid value for -vrtnodata
2 parents 03bd036 + c004191 commit acdb4bd

File tree

3 files changed

+68
-0
lines changed

3 files changed

+68
-0
lines changed

apps/gdalbuildvrt_lib.cpp

+17
Original file line numberDiff line numberDiff line change
@@ -436,6 +436,21 @@ static CPLString GetProjectionName(const char *pszProjection)
436436
/* AnalyseRaster() */
437437
/************************************************************************/
438438

439+
static void checkNoDataValues(const std::vector<BandProperty> &asProperties)
440+
{
441+
for (const auto &oProps : asProperties)
442+
{
443+
if (oProps.bHasNoData && GDALDataTypeIsInteger(oProps.dataType) &&
444+
!GDALIsValueExactAs(oProps.noDataValue, oProps.dataType))
445+
{
446+
CPLError(CE_Warning, CPLE_NotSupported,
447+
"Band data type of %s cannot represent the specified "
448+
"NoData value of %g",
449+
GDALGetDataTypeName(oProps.dataType), oProps.noDataValue);
450+
}
451+
}
452+
}
453+
439454
std::string VRTBuilder::AnalyseRaster(GDALDatasetH hDS,
440455
DatasetProperty *psDatasetProperties)
441456
{
@@ -965,6 +980,8 @@ std::string VRTBuilder::AnalyseRaster(GDALDatasetH hDS,
965980
}
966981
}
967982

983+
checkNoDataValues(asBandProperties);
984+
968985
return "";
969986
}
970987

autotest/pymod/gdaltest.py

+28
Original file line numberDiff line numberDiff line change
@@ -2095,3 +2095,31 @@ def vsi_open(path, mode="r"):
20952095
def vrt_has_open_support():
20962096
drv = gdal.GetDriverByName("VRT")
20972097
return drv is not None and drv.GetMetadataItem(gdal.DMD_OPENOPTIONLIST) is not None
2098+
2099+
2100+
###############################################################################
2101+
# Check that an error or warning is raised
2102+
2103+
2104+
@contextlib.contextmanager
2105+
def error_raised(type, match=""):
2106+
2107+
err_levels = {
2108+
gdal.CE_Debug: "CE_Debug",
2109+
gdal.CE_Failure: "CE_Failure",
2110+
gdal.CE_Fatal: "CE_Fatal",
2111+
gdal.CE_None: "CE_None",
2112+
gdal.CE_Warning: "CE_Warning",
2113+
}
2114+
2115+
errors = []
2116+
2117+
def handler(lvl, no, msg):
2118+
errors.append({"level": lvl, "number": no, "message": msg})
2119+
2120+
with error_handler(handler):
2121+
yield
2122+
2123+
assert any(
2124+
[err["level"] == type and match in err["message"] for err in errors]
2125+
), f'Did not receive an error of type {err_levels[type]} matching "{match}"'

autotest/utilities/test_gdalbuildvrt_lib.py

+23
Original file line numberDiff line numberDiff line change
@@ -900,3 +900,26 @@ def test_gdalbuildvrt_lib_nodataMaxMaskThreshold_rgb_mask(tmp_vsimem):
900900
assert struct.unpack(
901901
"f" * 3, vrt_ds.GetRasterBand(1).ReadRaster(buf_type=gdal.GDT_Float32)
902902
) == pytest.approx((1.0, 1.001, 2.0))
903+
904+
905+
###############################################################################
906+
907+
908+
@pytest.mark.parametrize(
909+
"dtype,nodata",
910+
[
911+
(gdal.GDT_Byte, float("nan")),
912+
(gdal.GDT_UInt16, -1),
913+
],
914+
)
915+
def test_gdalbuildvrt_lib_nodata_invalid(tmp_vsimem, dtype, nodata):
916+
917+
drv = gdal.GetDriverByName("GTiff")
918+
with drv.Create(tmp_vsimem / "in.tif", 1, 1, eType=dtype) as ds:
919+
ds.GetRasterBand(1).Fill(1)
920+
ds.SetGeoTransform((0, 1, 0, 1, 0, -1))
921+
922+
with gdaltest.error_raised(
923+
gdal.CE_Warning, "cannot represent the specified NoData value"
924+
):
925+
gdal.BuildVRT("", [tmp_vsimem / "in.tif"], VRTNodata=nodata)

0 commit comments

Comments
 (0)