diff --git a/CHANGES.md b/CHANGES.md index 1d69117e..b1407607 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -1,3 +1,7 @@ +# 7.2.2 (2024-11-17) + +* Catch and expand error message when GDAL cannot encode data using specified image driver + # 7.2.1 (2024-11-14) * add official support for floating point values in ColorMap diff --git a/rio_tiler/utils.py b/rio_tiler/utils.py index 2c6b0abf..99843535 100644 --- a/rio_tiler/utils.py +++ b/rio_tiler/utils.py @@ -33,7 +33,7 @@ from rio_tiler.colormap import apply_cmap from rio_tiler.constants import WEB_MERCATOR_CRS, WGS84_CRS -from rio_tiler.errors import RioTilerError +from rio_tiler.errors import InvalidFormat, RioTilerError from rio_tiler.types import BBox, ColorMapType, IntervalTuple, RIOResampling @@ -588,24 +588,30 @@ def render( } output_profile.update(creation_options) - with warnings.catch_warnings(): - warnings.filterwarnings( - "ignore", - category=NotGeoreferencedWarning, - module="rasterio", - ) - with MemoryFile() as memfile: - with memfile.open(**output_profile) as dst: - dst.write(data, indexes=list(range(1, count + 1))) + try: + with warnings.catch_warnings(): + warnings.filterwarnings( + "ignore", + category=NotGeoreferencedWarning, + module="rasterio", + ) + with MemoryFile() as memfile: + with memfile.open(**output_profile) as dst: + dst.write(data, indexes=list(range(1, count + 1))) + + # Use Mask as an alpha band + if mask is not None: + if ColorInterp.alpha not in dst.colorinterp: + dst.colorinterp = *dst.colorinterp[:-1], ColorInterp.alpha - # Use Mask as an alpha band - if mask is not None: - if ColorInterp.alpha not in dst.colorinterp: - dst.colorinterp = *dst.colorinterp[:-1], ColorInterp.alpha + dst.write(mask.astype(data.dtype), indexes=count + 1) - dst.write(mask.astype(data.dtype), indexes=count + 1) + return memfile.read() - return memfile.read() + except Exception as e: + raise InvalidFormat( + f"Could not encode array of shape ({count},{height},{width}) and of datatype `{data.dtype}` using {img_format} driver" + ) from e def mapzen_elevation_rgb(data: numpy.ndarray) -> numpy.ndarray: diff --git a/tests/test_models.py b/tests/test_models.py index 6268aed4..988b300a 100644 --- a/tests/test_models.py +++ b/tests/test_models.py @@ -10,7 +10,11 @@ from rasterio.errors import NotGeoreferencedWarning from rasterio.io import MemoryFile -from rio_tiler.errors import InvalidDatatypeWarning, InvalidPointDataError +from rio_tiler.errors import ( + InvalidDatatypeWarning, + InvalidFormat, + InvalidPointDataError, +) from rio_tiler.models import ImageData, PointData @@ -456,3 +460,9 @@ def test_imagedata_coverage(): coverage = im.get_coverage_array(poly, cover_scale=1000) assert numpy.round(numpy.unique(coverage), decimals=3).tolist() == [0, 0.125, 0.25] + + +def test_image_encoding_error(): + """Test ImageData error when using bad data array shape.""" + with pytest.raises(InvalidFormat): + ImageData(numpy.zeros((5, 256, 256), dtype="uint8")).render(img_format="PNG")