Skip to content

Commit

Permalink
Merge pull request OSGeo#11496 from dbaston/buildvrt-warn-invalid-nodata
Browse files Browse the repository at this point in the history
gdalbuildvrt: Emit warning on invalid value for -vrtnodata
  • Loading branch information
rouault authored Dec 16, 2024
2 parents 03bd036 + c004191 commit acdb4bd
Show file tree
Hide file tree
Showing 3 changed files with 68 additions and 0 deletions.
17 changes: 17 additions & 0 deletions apps/gdalbuildvrt_lib.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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)
{
Expand Down Expand Up @@ -965,6 +980,8 @@ std::string VRTBuilder::AnalyseRaster(GDALDatasetH hDS,
}
}

checkNoDataValues(asBandProperties);

return "";
}

Expand Down
28 changes: 28 additions & 0 deletions autotest/pymod/gdaltest.py
Original file line number Diff line number Diff line change
Expand Up @@ -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}"'
23 changes: 23 additions & 0 deletions autotest/utilities/test_gdalbuildvrt_lib.py
Original file line number Diff line number Diff line change
Expand Up @@ -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)

0 comments on commit acdb4bd

Please sign in to comment.