gdalbuildvrt: Emit warning on invalid value for -vrtnodata

This commit is contained in:
Daniel Baston 2024-12-15 12:52:58 -05:00
parent 5eb90f3e91
commit c004191478
No known key found for this signature in database
GPG Key ID: 0013D0A75214FCFA
3 changed files with 68 additions and 0 deletions

View File

@ -436,6 +436,21 @@ static CPLString GetProjectionName(const char *pszProjection)
/* AnalyseRaster() */
/************************************************************************/
static void checkNoDataValues(const std::vector<BandProperty> &asProperties)
{
for (const auto &oProps : asProperties)
{
if (oProps.bHasNoData && GDALDataTypeIsInteger(oProps.dataType) &&
!GDALIsValueExactAs(oProps.noDataValue, oProps.dataType))
{
CPLError(CE_Warning, CPLE_NotSupported,
"Band data type of %s cannot represent the specified "
"NoData value of %g",
GDALGetDataTypeName(oProps.dataType), oProps.noDataValue);
}
}
}
std::string VRTBuilder::AnalyseRaster(GDALDatasetH hDS,
DatasetProperty *psDatasetProperties)
{
@ -965,6 +980,8 @@ std::string VRTBuilder::AnalyseRaster(GDALDatasetH hDS,
}
}
checkNoDataValues(asBandProperties);
return "";
}

View File

@ -2095,3 +2095,31 @@ def vsi_open(path, mode="r"):
def vrt_has_open_support():
drv = gdal.GetDriverByName("VRT")
return drv is not None and drv.GetMetadataItem(gdal.DMD_OPENOPTIONLIST) is not None
###############################################################################
# Check that an error or warning is raised
@contextlib.contextmanager
def error_raised(type, match=""):
err_levels = {
gdal.CE_Debug: "CE_Debug",
gdal.CE_Failure: "CE_Failure",
gdal.CE_Fatal: "CE_Fatal",
gdal.CE_None: "CE_None",
gdal.CE_Warning: "CE_Warning",
}
errors = []
def handler(lvl, no, msg):
errors.append({"level": lvl, "number": no, "message": msg})
with error_handler(handler):
yield
assert any(
[err["level"] == type and match in err["message"] for err in errors]
), f'Did not receive an error of type {err_levels[type]} matching "{match}"'

View File

@ -900,3 +900,26 @@ def test_gdalbuildvrt_lib_nodataMaxMaskThreshold_rgb_mask(tmp_vsimem):
assert struct.unpack(
"f" * 3, vrt_ds.GetRasterBand(1).ReadRaster(buf_type=gdal.GDT_Float32)
) == pytest.approx((1.0, 1.001, 2.0))
###############################################################################
@pytest.mark.parametrize(
"dtype,nodata",
[
(gdal.GDT_Byte, float("nan")),
(gdal.GDT_UInt16, -1),
],
)
def test_gdalbuildvrt_lib_nodata_invalid(tmp_vsimem, dtype, nodata):
drv = gdal.GetDriverByName("GTiff")
with drv.Create(tmp_vsimem / "in.tif", 1, 1, eType=dtype) as ds:
ds.GetRasterBand(1).Fill(1)
ds.SetGeoTransform((0, 1, 0, 1, 0, -1))
with gdaltest.error_raised(
gdal.CE_Warning, "cannot represent the specified NoData value"
):
gdal.BuildVRT("", [tmp_vsimem / "in.tif"], VRTNodata=nodata)