diff --git a/Tests/test_color_lut.py b/Tests/test_color_lut.py index 26945ae1a69..89a1e675c80 100644 --- a/Tests/test_color_lut.py +++ b/Tests/test_color_lut.py @@ -137,7 +137,7 @@ def test_correct_args( def test_wrong_mode( self, image_mode: str, lut_mode: str, table_channels: int, table_size: int ) -> None: - with pytest.raises(ValueError, match="wrong mode"): + with pytest.raises(ValueError, match="bands"): im = Image.new(image_mode, (10, 10), 0) im.im.color_lut_3d( lut_mode, diff --git a/Tests/test_image_paste.py b/Tests/test_image_paste.py index f9b72e46fc8..e9211dae73e 100644 --- a/Tests/test_image_paste.py +++ b/Tests/test_image_paste.py @@ -368,7 +368,9 @@ def test_overflow(self, box: tuple[int, int, int, int]) -> None: im = Image.new("1", (1, 1)) im.paste(1, box) - with pytest.raises(ValueError, match="images do not match"): + with pytest.raises( + ValueError, match="image dimensions and pixel size must match" + ): im.paste(im.copy(), box) def test_incorrect_abbreviated_form(self) -> None: diff --git a/src/_imaging.c b/src/_imaging.c index 897e718e30a..95176300049 100644 --- a/src/_imaging.c +++ b/src/_imaging.c @@ -328,7 +328,6 @@ _new_arrow(PyObject *self, PyObject *args) { ModeID mode_id; int xsize, ysize; PyObject *schema_capsule, *array_capsule; - PyObject *ret; if (!PyArg_ParseTuple( args, "s(ii)OO", &mode, &xsize, &ysize, &schema_capsule, &array_capsule @@ -371,14 +370,31 @@ ImagingError_MemoryError(void) { } void * -ImagingError_Mismatch(void) { - PyErr_SetString(PyExc_ValueError, "images do not match"); +ImagingError_Mismatch(const char *message) { + PyErr_SetString( + PyExc_ValueError, (message) ? (char *)message : "images do not match" + ); return NULL; } void * -ImagingError_ModeError(void) { - PyErr_SetString(PyExc_ValueError, "image has wrong mode"); +ImagingError_ModeError(const char *message) { + PyErr_SetString( + PyExc_ValueError, (message) ? (char *)message : "image has wrong mode" + ); + return NULL; +} + +// Derives from both NotImplementedError and ValueError +// (as the functions above raise ValueErrors). +static PyObject *ImagingNotSupportedError = NULL; + +void * +ImagingError_NotSupportedError(const char *message) { + PyErr_SetString( + ImagingNotSupportedError ? ImagingNotSupportedError : PyExc_NotImplementedError, + (message) ? (char *)message : "operation not supported" + ); return NULL; } @@ -4326,6 +4342,24 @@ setup_module(PyObject *m) { return -1; } + if (ImagingNotSupportedError == NULL) { + // NotSupportedError derives from both NotImplementedError and ValueError, + // for compatibility with `except ValueError`. + PyObject *bases = PyTuple_Pack(2, PyExc_NotImplementedError, PyExc_ValueError); + if (bases == NULL) { + return -1; + } + ImagingNotSupportedError = + PyErr_NewException("PIL._imaging.NotSupportedError", bases, NULL); + Py_DECREF(bases); + if (ImagingNotSupportedError == NULL) { + return -1; + } + } + if (PyModule_AddObjectRef(m, "NotSupportedError", ImagingNotSupportedError) < 0) { + return -1; + } + #ifdef HAVE_LIBJPEG { extern const char *ImagingJpegVersion(void); diff --git a/src/libImaging/AlphaComposite.c b/src/libImaging/AlphaComposite.c index d1a1e7ad34a..a12f7398e66 100644 --- a/src/libImaging/AlphaComposite.c +++ b/src/libImaging/AlphaComposite.c @@ -24,14 +24,16 @@ ImagingAlphaComposite(Imaging imDst, Imaging imSrc) { Imaging imOut; /* Check arguments */ - if (!imDst || !imSrc || - (imDst->mode != IMAGING_MODE_RGBA && imDst->mode != IMAGING_MODE_LA)) { - return ImagingError_ModeError(); + if (!imDst || !imSrc) { + return ImagingError_ValueError("imDst and imSrc must not be NULL"); + } + if (imDst->mode != IMAGING_MODE_RGBA && imDst->mode != IMAGING_MODE_LA) { + return ImagingError_ModeError("destination image must have alpha channel"); } if (imDst->mode != imSrc->mode || imDst->xsize != imSrc->xsize || imDst->ysize != imSrc->ysize) { - return ImagingError_Mismatch(); + return ImagingError_Mismatch("image modes and dimensions must match"); } imOut = ImagingNewDirty(imDst->mode, imDst->xsize, imDst->ysize); diff --git a/src/libImaging/Bands.c b/src/libImaging/Bands.c index d1fa16addff..29444b5168a 100644 --- a/src/libImaging/Bands.c +++ b/src/libImaging/Bands.c @@ -23,8 +23,12 @@ ImagingGetBand(Imaging imIn, int band) { int x, y; /* Check arguments */ - if (!imIn || imIn->type != IMAGING_TYPE_UINT8) { - return (Imaging)ImagingError_ModeError(); + if (!imIn) { + return (Imaging)ImagingError_ValueError(NULL); + } + + if (imIn->type != IMAGING_TYPE_UINT8) { + return (Imaging)ImagingError_NotSupportedError("only 8-bit images supported"); } if (band < 0 || band >= imIn->bands) { @@ -73,8 +77,13 @@ ImagingSplit(Imaging imIn, Imaging bands[4]) { int i, j, x, y; /* Check arguments */ - if (!imIn || imIn->type != IMAGING_TYPE_UINT8) { - (void)ImagingError_ModeError(); + if (!imIn) { + (void)ImagingError_ValueError(NULL); + return 0; + } + + if (imIn->type != IMAGING_TYPE_UINT8) { + (void)ImagingError_NotSupportedError("only 8-bit images supported"); return 0; } @@ -178,8 +187,11 @@ ImagingPutBand(Imaging imOut, Imaging imIn, int band) { int x, y; /* Check arguments */ - if (!imIn || imIn->bands != 1 || !imOut) { - return (Imaging)ImagingError_ModeError(); + if (!imIn || !imOut) { + return (Imaging)ImagingError_ValueError(NULL); + } + if (imIn->bands != 1) { + return (Imaging)ImagingError_ModeError("source image must have exactly 1 band"); } if (band < 0 || band >= imOut->bands) { @@ -188,7 +200,7 @@ ImagingPutBand(Imaging imOut, Imaging imIn, int band) { if (imIn->type != imOut->type || imIn->xsize != imOut->xsize || imIn->ysize != imOut->ysize) { - return (Imaging)ImagingError_Mismatch(); + return (Imaging)ImagingError_Mismatch("image types and sizes must match"); } /* Shortcuts */ @@ -224,8 +236,16 @@ ImagingFillBand(Imaging imOut, int band, int color) { int x, y; /* Check arguments */ - if (!imOut || imOut->type != IMAGING_TYPE_UINT8) { - return (Imaging)ImagingError_ModeError(); + if (!imOut) { + return (Imaging)ImagingError_ValueError(NULL); + } + + if (!imOut) { + return (Imaging)ImagingError_ValueError("only 8-bit images supported"); + } + + if (imOut->type != IMAGING_TYPE_UINT8) { + return (Imaging)ImagingError_NotSupportedError("only 8-bit images supported"); } if (band < 0 || band >= imOut->bands) { @@ -270,11 +290,13 @@ ImagingMerge(const ModeID mode, Imaging bands[4]) { break; } if (bands[i]->bands != 1) { - return (Imaging)ImagingError_ModeError(); + return (Imaging)ImagingError_ModeError( + "source image must have exactly 1 band" + ); } if (bands[i]->xsize != firstBand->xsize || bands[i]->ysize != firstBand->ysize) { - return (Imaging)ImagingError_Mismatch(); + return (Imaging)ImagingError_Mismatch("image sizes must match"); } } bandsCount = i; diff --git a/src/libImaging/Blend.c b/src/libImaging/Blend.c index 19662abf044..5d849ba6619 100644 --- a/src/libImaging/Blend.c +++ b/src/libImaging/Blend.c @@ -23,15 +23,18 @@ ImagingBlend(Imaging imIn1, Imaging imIn2, float alpha) { int x, y; /* Check arguments */ - if (!imIn1 || !imIn2 || imIn1->type != IMAGING_TYPE_UINT8 || imIn1->palette || + if (!imIn1 || !imIn2) { + return (Imaging)ImagingError_ValueError(NULL); + } + if (imIn1->type != IMAGING_TYPE_UINT8 || imIn1->palette || imIn1->mode == IMAGING_MODE_1 || imIn2->palette || imIn2->mode == IMAGING_MODE_1) { - return ImagingError_ModeError(); + return ImagingError_ModeError(NULL); } if (imIn1->type != imIn2->type || imIn1->bands != imIn2->bands || imIn1->xsize != imIn2->xsize || imIn1->ysize != imIn2->ysize) { - return ImagingError_Mismatch(); + return ImagingError_Mismatch("image types, band count and sizes must match"); } /* Shortcuts */ diff --git a/src/libImaging/BoxBlur.c b/src/libImaging/BoxBlur.c index 4fea4fe44b8..7855085d092 100644 --- a/src/libImaging/BoxBlur.c +++ b/src/libImaging/BoxBlur.c @@ -251,18 +251,20 @@ ImagingBoxBlur(Imaging imOut, Imaging imIn, float xradius, float yradius, int n) if (imIn->mode != imOut->mode || imIn->type != imOut->type || imIn->bands != imOut->bands || imIn->xsize != imOut->xsize || imIn->ysize != imOut->ysize) { - return ImagingError_Mismatch(); + return ImagingError_Mismatch("image mode, type, bands and size must match"); } if (imIn->type != IMAGING_TYPE_UINT8) { - return ImagingError_ModeError(); + return ImagingError_NotSupportedError("non-uint8 images not supported"); } if (imIn->mode != IMAGING_MODE_RGB && imIn->mode != IMAGING_MODE_RGBA && imIn->mode != IMAGING_MODE_RGBa && imIn->mode != IMAGING_MODE_RGBX && imIn->mode != IMAGING_MODE_CMYK && imIn->mode != IMAGING_MODE_L && imIn->mode != IMAGING_MODE_LA && imIn->mode != IMAGING_MODE_La) { - return ImagingError_ModeError(); + return ImagingError_NotSupportedError( + "BoxBlur operation not supported in this mode" + ); } /* Apply blur in one dimension. diff --git a/src/libImaging/Chops.c b/src/libImaging/Chops.c index 557c2f52f10..d8e051fc988 100644 --- a/src/libImaging/Chops.c +++ b/src/libImaging/Chops.c @@ -68,14 +68,17 @@ static Imaging create(Imaging im1, Imaging im2, const ModeID mode) { int xsize, ysize; + if (!im1 || !im2) { + return (Imaging)ImagingError_ValueError(NULL); + } - if (!im1 || !im2 || im1->type != IMAGING_TYPE_UINT8 || + if (im1->type != IMAGING_TYPE_UINT8 || (mode != IMAGING_MODE_UNKNOWN && (im1->mode != IMAGING_MODE_1 || im2->mode != IMAGING_MODE_1))) { - return (Imaging)ImagingError_ModeError(); + return (Imaging)ImagingError_ModeError(NULL); } if (im1->type != im2->type || im1->bands != im2->bands) { - return (Imaging)ImagingError_Mismatch(); + return (Imaging)ImagingError_Mismatch("image types and band count must match"); } xsize = (im1->xsize < im2->xsize) ? im1->xsize : im2->xsize; diff --git a/src/libImaging/ColorLUT.c b/src/libImaging/ColorLUT.c index 5559de689b2..572c5aad8f9 100644 --- a/src/libImaging/ColorLUT.c +++ b/src/libImaging/ColorLUT.c @@ -87,14 +87,23 @@ ImagingColorLUT3D_linear( return NULL; } - if (imIn->type != IMAGING_TYPE_UINT8 || imOut->type != IMAGING_TYPE_UINT8 || - imIn->bands < 3 || imOut->bands < table_channels) { - return (Imaging)ImagingError_ModeError(); + if (imIn->type != IMAGING_TYPE_UINT8 || imOut->type != IMAGING_TYPE_UINT8) { + return (Imaging)ImagingError_NotSupportedError( + "only uint8 images are supported" + ); + } + if (imIn->bands < 3) { + return (Imaging)ImagingError_ModeError("input image needs at least 3 bands"); + } + if (imOut->bands < table_channels) { + return (Imaging)ImagingError_ValueError( + "output image needs at least as many bands as the table" + ); } - - /* In case we have one extra band in imOut and don't have in imIn.*/ if (imOut->bands > table_channels && imOut->bands > imIn->bands) { - return (Imaging)ImagingError_ModeError(); + return (Imaging)ImagingError_ModeError( + "output image has more bands than input image and table" + ); } ImagingSectionEnter(&cookie); diff --git a/src/libImaging/Convert.c b/src/libImaging/Convert.c index 1fd14a944ef..f732dadbc01 100644 --- a/src/libImaging/Convert.c +++ b/src/libImaging/Convert.c @@ -1581,13 +1581,13 @@ convert(Imaging imOut, Imaging imIn, ModeID mode, ImagingPalette palette, int di ImagingShuffler convert; if (!imIn) { - return (Imaging)ImagingError_ModeError(); + return (Imaging)ImagingError_ValueError(NULL); } if (mode == IMAGING_MODE_UNKNOWN) { /* Map palette image to full depth */ if (!imIn->palette) { - return (Imaging)ImagingError_ModeError(); + return (Imaging)ImagingError_ModeError(NULL); } mode = imIn->palette->mode; } else { @@ -1673,7 +1673,7 @@ ImagingConvertTransparent(Imaging imIn, const ModeID mode, int r, int g, int b) int y; if (!imIn) { - return (Imaging)ImagingError_ModeError(); + return (Imaging)ImagingError_ValueError(NULL); } if (imIn->mode == IMAGING_MODE_RGB && @@ -1747,7 +1747,9 @@ ImagingConvertInPlace(Imaging imIn, const ModeID mode) { } else if (imIn->mode == IMAGING_MODE_1 && mode == IMAGING_MODE_L) { convert = bit2l; } else { - return ImagingError_ModeError(); + return ImagingError_NotSupportedError( + "in-place conversion not supported between these formats" + ); } ImagingSectionEnter(&cookie); diff --git a/src/libImaging/Crop.c b/src/libImaging/Crop.c index 2425b4cd589..7379671fe86 100644 --- a/src/libImaging/Crop.c +++ b/src/libImaging/Crop.c @@ -25,7 +25,7 @@ ImagingCrop(Imaging imIn, int sx0, int sy0, int sx1, int sy1) { INT32 zero = 0; if (!imIn) { - return (Imaging)ImagingError_ModeError(); + return (Imaging)ImagingError_ValueError(NULL); } xsize = sx1 - sx0; diff --git a/src/libImaging/Dib.c b/src/libImaging/Dib.c index 2afe71d4ac9..599f886ba30 100644 --- a/src/libImaging/Dib.c +++ b/src/libImaging/Dib.c @@ -59,7 +59,9 @@ ImagingNewDIB(const ModeID mode, int xsize, int ysize) { /* Check mode */ if (mode != IMAGING_MODE_1 && mode != IMAGING_MODE_L && mode != IMAGING_MODE_RGB) { - return (ImagingDIB)ImagingError_ModeError(); + return (ImagingDIB)ImagingError_NotSupportedError( + "only modes I/L/RGB supported" + ); } const int pixelsize = mode == IMAGING_MODE_RGB ? 3 : 1; diff --git a/src/libImaging/Effects.c b/src/libImaging/Effects.c index c05c5764e44..181ad66893b 100644 --- a/src/libImaging/Effects.c +++ b/src/libImaging/Effects.c @@ -33,7 +33,9 @@ ImagingEffectMandelbrot(int xsize, int ysize, double extent[4], int quality) { width = extent[2] - extent[0]; height = extent[3] - extent[1]; if (width < 0.0 || height < 0.0 || quality < 2) { - return (Imaging)ImagingError_ValueError(NULL); + return (Imaging)ImagingError_ValueError( + "width and height must be positive and quality >= 2" + ); } im = ImagingNewDirty(IMAGING_MODE_L, xsize, ysize); diff --git a/src/libImaging/Fill.c b/src/libImaging/Fill.c index 25344cf3a7e..0f63cd9aa67 100644 --- a/src/libImaging/Fill.c +++ b/src/libImaging/Fill.c @@ -78,7 +78,9 @@ ImagingFillLinearGradient(const ModeID mode) { if (mode != IMAGING_MODE_1 && mode != IMAGING_MODE_F && mode != IMAGING_MODE_I && mode != IMAGING_MODE_L && mode != IMAGING_MODE_P) { - return (Imaging)ImagingError_ModeError(); + return (Imaging)ImagingError_NotSupportedError( + "only modes 1/F/I/L/P supported" + ); } im = ImagingNewDirty(mode, 256, 256); @@ -117,7 +119,9 @@ ImagingFillRadialGradient(const ModeID mode) { if (mode != IMAGING_MODE_1 && mode != IMAGING_MODE_F && mode != IMAGING_MODE_I && mode != IMAGING_MODE_L && mode != IMAGING_MODE_P) { - return (Imaging)ImagingError_ModeError(); + return (Imaging)ImagingError_NotSupportedError( + "only modes 1/F/I/L/P supported" + ); } im = ImagingNewDirty(mode, 256, 256); diff --git a/src/libImaging/Filter.c b/src/libImaging/Filter.c index b5f971d40c2..04077f890f2 100644 --- a/src/libImaging/Filter.c +++ b/src/libImaging/Filter.c @@ -472,7 +472,9 @@ ImagingFilter(Imaging im, int xsize, int ysize, const FLOAT32 *kernel, FLOAT32 o if (im->type == IMAGING_TYPE_FLOAT32 || (im->type == IMAGING_TYPE_SPECIAL && im->bands != 1)) { - return (Imaging)ImagingError_ModeError(); + return (Imaging)ImagingError_ModeError( + "32-bpc or special multiband image types not supported" + ); } if (im->xsize < xsize || im->ysize < ysize) { diff --git a/src/libImaging/Geometry.c b/src/libImaging/Geometry.c index 2186f95f8e5..e1ff00840ee 100644 --- a/src/libImaging/Geometry.c +++ b/src/libImaging/Geometry.c @@ -19,11 +19,14 @@ ImagingFlipLeftRight(Imaging imOut, Imaging imIn) { ImagingSectionCookie cookie; int x, y, xr; - if (!imOut || !imIn || imIn->mode != imOut->mode) { - return (Imaging)ImagingError_ModeError(); + if (!imOut || !imIn) { + return (Imaging)ImagingError_ValueError(NULL); + } + if (imIn->mode != imOut->mode) { + return (Imaging)ImagingError_ModeError("images must have the same mode"); } if (imIn->xsize != imOut->xsize || imIn->ysize != imOut->ysize) { - return (Imaging)ImagingError_Mismatch(); + return (Imaging)ImagingError_Mismatch("images must have the same size"); } ImagingCopyPalette(imOut, imIn); @@ -62,11 +65,14 @@ ImagingFlipTopBottom(Imaging imOut, Imaging imIn) { ImagingSectionCookie cookie; int y, yr; - if (!imOut || !imIn || imIn->mode != imOut->mode) { - return (Imaging)ImagingError_ModeError(); + if (!imOut || !imIn) { + return (Imaging)ImagingError_ValueError(NULL); + } + if (imIn->mode != imOut->mode) { + return (Imaging)ImagingError_ModeError("images must have the same mode"); } if (imIn->xsize != imOut->xsize || imIn->ysize != imOut->ysize) { - return (Imaging)ImagingError_Mismatch(); + return (Imaging)ImagingError_Mismatch("images must have the same size"); } ImagingCopyPalette(imOut, imIn); @@ -89,11 +95,16 @@ ImagingRotate90(Imaging imOut, Imaging imIn) { int x, y, xx, yy, xr, xxsize, yysize; int xxx, yyy, xxxsize, yyysize; - if (!imOut || !imIn || imIn->mode != imOut->mode) { - return (Imaging)ImagingError_ModeError(); + if (!imOut || !imIn) { + return (Imaging)ImagingError_ValueError(NULL); + } + if (imIn->mode != imOut->mode) { + return (Imaging)ImagingError_ModeError("images must have the same mode"); } if (imIn->xsize != imOut->ysize || imIn->ysize != imOut->xsize) { - return (Imaging)ImagingError_Mismatch(); + return (Imaging)ImagingError_Mismatch( + "output size must be the transpose of the input size" + ); } ImagingCopyPalette(imOut, imIn); @@ -149,11 +160,16 @@ ImagingTranspose(Imaging imOut, Imaging imIn) { int x, y, xx, yy, xxsize, yysize; int xxx, yyy, xxxsize, yyysize; - if (!imOut || !imIn || imIn->mode != imOut->mode) { - return (Imaging)ImagingError_ModeError(); + if (!imOut || !imIn) { + return (Imaging)ImagingError_ValueError(NULL); + } + if (imIn->mode != imOut->mode) { + return (Imaging)ImagingError_ModeError("images must have the same mode"); } if (imIn->xsize != imOut->ysize || imIn->ysize != imOut->xsize) { - return (Imaging)ImagingError_Mismatch(); + return (Imaging)ImagingError_Mismatch( + "output size must be the transpose of the input size" + ); } ImagingCopyPalette(imOut, imIn); @@ -208,11 +224,16 @@ ImagingTransverse(Imaging imOut, Imaging imIn) { int x, y, xr, yr, xx, yy, xxsize, yysize; int xxx, yyy, xxxsize, yyysize; - if (!imOut || !imIn || imIn->mode != imOut->mode) { - return (Imaging)ImagingError_ModeError(); + if (!imOut || !imIn) { + return (Imaging)ImagingError_ValueError(NULL); + } + if (imIn->mode != imOut->mode) { + return (Imaging)ImagingError_ModeError("images must have the same mode"); } if (imIn->xsize != imOut->ysize || imIn->ysize != imOut->xsize) { - return (Imaging)ImagingError_Mismatch(); + return (Imaging)ImagingError_Mismatch( + "output size must be the transpose of the input size" + ); } ImagingCopyPalette(imOut, imIn); @@ -268,11 +289,14 @@ ImagingRotate180(Imaging imOut, Imaging imIn) { ImagingSectionCookie cookie; int x, y, xr, yr; - if (!imOut || !imIn || imIn->mode != imOut->mode) { - return (Imaging)ImagingError_ModeError(); + if (!imOut || !imIn) { + return (Imaging)ImagingError_ValueError(NULL); + } + if (imIn->mode != imOut->mode) { + return (Imaging)ImagingError_ModeError("images must have the same mode"); } if (imIn->xsize != imOut->xsize || imIn->ysize != imOut->ysize) { - return (Imaging)ImagingError_Mismatch(); + return (Imaging)ImagingError_Mismatch("images must have the same size"); } ImagingCopyPalette(imOut, imIn); @@ -313,11 +337,16 @@ ImagingRotate270(Imaging imOut, Imaging imIn) { int x, y, xx, yy, yr, xxsize, yysize; int xxx, yyy, xxxsize, yyysize; - if (!imOut || !imIn || imIn->mode != imOut->mode) { - return (Imaging)ImagingError_ModeError(); + if (!imOut || !imIn) { + return (Imaging)ImagingError_ValueError(NULL); + } + if (imIn->mode != imOut->mode) { + return (Imaging)ImagingError_ModeError("images must have the same mode"); } if (imIn->xsize != imOut->ysize || imIn->ysize != imOut->xsize) { - return (Imaging)ImagingError_Mismatch(); + return (Imaging)ImagingError_Mismatch( + "output size must be the transpose of the input size" + ); } ImagingCopyPalette(imOut, imIn); @@ -784,8 +813,11 @@ ImagingGenericTransform( char *out; double xx, yy; - if (!imOut || !imIn || imIn->mode != imOut->mode) { - return (Imaging)ImagingError_ModeError(); + if (!imOut || !imIn) { + return (Imaging)ImagingError_ValueError(NULL); + } + if (imIn->mode != imOut->mode) { + return (Imaging)ImagingError_ModeError("images must have the same mode"); } ImagingTransformFilter filter = getfilter(imIn, filterid); @@ -841,8 +873,11 @@ ImagingScaleAffine( int xmin, xmax; int *xintab; - if (!imOut || !imIn || imIn->mode != imOut->mode) { - return (Imaging)ImagingError_ModeError(); + if (!imOut || !imIn) { + return (Imaging)ImagingError_ValueError(NULL); + } + if (imIn->mode != imOut->mode) { + return (Imaging)ImagingError_ModeError("images must have the same mode"); } ImagingCopyPalette(imOut, imIn); @@ -1028,8 +1063,11 @@ ImagingTransformAffine( double xx, yy; double xo, yo; - if (!imOut || !imIn || imIn->mode != imOut->mode) { - return (Imaging)ImagingError_ModeError(); + if (!imOut || !imIn) { + return (Imaging)ImagingError_ValueError(NULL); + } + if (imIn->mode != imOut->mode) { + return (Imaging)ImagingError_ModeError("images must have the same mode"); } if (filterid || imIn->type == IMAGING_TYPE_SPECIAL) { diff --git a/src/libImaging/GetBBox.c b/src/libImaging/GetBBox.c index 7a57f6894a0..f11ba6d1d6b 100644 --- a/src/libImaging/GetBBox.c +++ b/src/libImaging/GetBBox.c @@ -152,7 +152,7 @@ ImagingGetExtrema(Imaging im, void *extrema) { FLOAT32 fmin, fmax; if (im->bands != 1) { - (void)ImagingError_ModeError(); + (void)ImagingError_ModeError("image must have exactly 1 band"); return -1; /* mismatch */ } @@ -242,7 +242,7 @@ ImagingGetExtrema(Imaging im, void *extrema) { } /* FALL THROUGH */ default: - (void)ImagingError_ModeError(); + (void)ImagingError_NotSupportedError("mode not supported"); return -1; } return 1; /* ok */ @@ -304,7 +304,7 @@ getcolors32(Imaging im, int maxcolors, int *size) { } if (!im->image32) { - return ImagingError_ModeError(); + return ImagingError_ModeError("image must have 32-bit data"); } table = calloc(code_size + 1, sizeof(ImagingColorItem)); diff --git a/src/libImaging/Histo.c b/src/libImaging/Histo.c index 7af60003511..83fe4386c6c 100644 --- a/src/libImaging/Histo.c +++ b/src/libImaging/Histo.c @@ -65,13 +65,13 @@ ImagingGetHistogram(Imaging im, Imaging imMask, void *minmax) { FLOAT32 fmin, fmax, scale; if (!im) { - return ImagingError_ModeError(); + return ImagingError_ValueError(NULL); } if (imMask) { /* Validate mask */ if (im->xsize != imMask->xsize || im->ysize != imMask->ysize) { - return ImagingError_Mismatch(); + return ImagingError_Mismatch("mask and image size must match"); } if (imMask->mode != IMAGING_MODE_1 && imMask->mode != IMAGING_MODE_L) { return ImagingError_ValueError("bad transparency mask"); @@ -98,7 +98,7 @@ ImagingGetHistogram(Imaging im, Imaging imMask, void *minmax) { } else { /* yes, we need the braces. C isn't Python! */ if (im->type != IMAGING_TYPE_UINT8) { ImagingHistogramDelete(h); - return ImagingError_ModeError(); + return ImagingError_ModeError(NULL); } ImagingSectionEnter(&cookie); for (y = 0; y < im->ysize; y++) { diff --git a/src/libImaging/Imaging.h b/src/libImaging/Imaging.h index 472bda5d0fd..3a2cafaa39b 100644 --- a/src/libImaging/Imaging.h +++ b/src/libImaging/Imaging.h @@ -268,11 +268,15 @@ ImagingSectionLeave(ImagingSectionCookie *cookie); extern void * ImagingError_MemoryError(void); extern void * -ImagingError_ModeError(void); /* maps to ValueError by default */ +ImagingError_ModeError(const char *message); /* maps to ValueError by default */ extern void * -ImagingError_Mismatch(void); /* maps to ValueError by default */ +ImagingError_Mismatch(const char *message); /* maps to ValueError by default */ extern void * ImagingError_ValueError(const char *message); +extern void * +ImagingError_NotSupportedError( + const char *message +); /* derives from NotImplementedError and ValueError */ /* Transform callbacks */ /* ------------------- */ diff --git a/src/libImaging/Matrix.c b/src/libImaging/Matrix.c index 02676c9e31a..2bcb7c789ae 100644 --- a/src/libImaging/Matrix.c +++ b/src/libImaging/Matrix.c @@ -23,8 +23,11 @@ ImagingConvertMatrix(Imaging im, const ModeID mode, const float m[12]) { ImagingSectionCookie cookie; /* Assume there's enough data in the buffer */ - if (!im || im->bands != 3) { - return (Imaging)ImagingError_ModeError(); + if (!im) { + return (Imaging)ImagingError_ValueError(NULL); + } + if (im->bands != 3) { + return (Imaging)ImagingError_ModeError("image must have exactly 3 bands"); } if (mode == IMAGING_MODE_L) { @@ -77,7 +80,7 @@ ImagingConvertMatrix(Imaging im, const ModeID mode, const float m[12]) { ImagingSectionLeave(&cookie); } } else { - return (Imaging)ImagingError_ModeError(); + return (Imaging)ImagingError_NotSupportedError(NULL); } return imOut; diff --git a/src/libImaging/ModeFilter.c b/src/libImaging/ModeFilter.c index 757cbc3fb86..99fed34c520 100644 --- a/src/libImaging/ModeFilter.c +++ b/src/libImaging/ModeFilter.c @@ -24,8 +24,11 @@ ImagingModeFilter(Imaging im, int size) { UINT8 maxpixel; int histogram[256]; - if (!im || im->bands != 1 || im->type != IMAGING_TYPE_UINT8) { - return (Imaging)ImagingError_ModeError(); + if (!im) { + return (Imaging)ImagingError_ValueError(NULL); + } + if (im->bands != 1 || im->type != IMAGING_TYPE_UINT8) { + return (Imaging)ImagingError_ModeError("image must have 8-bit data in 1 band"); } imOut = ImagingNewDirty(im->mode, im->xsize, im->ysize); diff --git a/src/libImaging/Negative.c b/src/libImaging/Negative.c index 114e8608e87..f8acb7293b9 100644 --- a/src/libImaging/Negative.c +++ b/src/libImaging/Negative.c @@ -24,7 +24,7 @@ ImagingNegative(Imaging im) { int x, y; if (!im) { - return (Imaging)ImagingError_ModeError(); + return (Imaging)ImagingError_ValueError(NULL); } imOut = ImagingNewDirty(im->mode, im->xsize, im->ysize); diff --git a/src/libImaging/Offset.c b/src/libImaging/Offset.c index 91ee91083cc..8802e4a0dc6 100644 --- a/src/libImaging/Offset.c +++ b/src/libImaging/Offset.c @@ -22,7 +22,7 @@ ImagingOffset(Imaging im, int xoffset, int yoffset) { Imaging imOut; if (!im) { - return (Imaging)ImagingError_ModeError(); + return (Imaging)ImagingError_ValueError(NULL); } imOut = ImagingNewDirty(im->mode, im->xsize, im->ysize); diff --git a/src/libImaging/Palette.c b/src/libImaging/Palette.c index b2dacf656b5..4d7791b8aab 100644 --- a/src/libImaging/Palette.c +++ b/src/libImaging/Palette.c @@ -29,7 +29,9 @@ ImagingPaletteNew(const ModeID mode) { if (mode != IMAGING_MODE_RGB && mode != IMAGING_MODE_RGBA && mode != IMAGING_MODE_CMYK) { - return (ImagingPalette)ImagingError_ModeError(); + return (ImagingPalette)ImagingError_ModeError( + "only RGB/RGBA/CMYK images supported" + ); } palette = calloc(1, sizeof(struct ImagingPaletteInstance)); diff --git a/src/libImaging/Paste.c b/src/libImaging/Paste.c index 0396cf58095..4c74b409659 100644 --- a/src/libImaging/Paste.c +++ b/src/libImaging/Paste.c @@ -280,7 +280,7 @@ ImagingPaste( ImagingSectionCookie cookie; if (!imOut || !imIn) { - (void)ImagingError_ModeError(); + (void)ImagingError_ValueError(NULL); return -1; } @@ -290,12 +290,12 @@ ImagingPaste( ysize = (int64_t)dy1 - dy0; if (xsize != imIn->xsize || ysize != imIn->ysize || pixelsize != imIn->pixelsize) { - (void)ImagingError_Mismatch(); + (void)ImagingError_Mismatch("image dimensions and pixel size must match"); return -1; } if (imMask && (xsize != imMask->xsize || ysize != imMask->ysize)) { - (void)ImagingError_Mismatch(); + (void)ImagingError_Mismatch("mask size must match image size"); return -1; } @@ -603,7 +603,7 @@ ImagingFill2( int sx0, sy0; if (!imOut || !ink) { - (void)ImagingError_ModeError(); + (void)ImagingError_ValueError(NULL); return -1; } @@ -613,7 +613,7 @@ ImagingFill2( ysize = (int64_t)dy1 - dy0; if (imMask && (xsize != imMask->xsize || ysize != imMask->ysize)) { - (void)ImagingError_Mismatch(); + (void)ImagingError_Mismatch("mask size must match image size"); return -1; } diff --git a/src/libImaging/Point.c b/src/libImaging/Point.c index 8f6d47c770f..e1abddfc4a1 100644 --- a/src/libImaging/Point.c +++ b/src/libImaging/Point.c @@ -137,7 +137,7 @@ ImagingPoint(Imaging imIn, ModeID mode, const void *table) { void (*point)(Imaging imIn, Imaging imOut, im_point_context *context); if (!imIn) { - return (Imaging)ImagingError_ModeError(); + return (Imaging)ImagingError_ValueError(NULL); } if (mode == IMAGING_MODE_UNKNOWN) { @@ -210,9 +210,12 @@ ImagingPointTransform(Imaging imIn, double scale, double offset) { Imaging imOut; int x, y; - if (!imIn || (imIn->mode != IMAGING_MODE_I && imIn->mode != IMAGING_MODE_I_16 && - imIn->mode != IMAGING_MODE_F)) { - return (Imaging)ImagingError_ModeError(); + if (!imIn) { + return (Imaging)ImagingError_ValueError(NULL); + } + if (imIn->mode != IMAGING_MODE_I && imIn->mode != IMAGING_MODE_I_16 && + imIn->mode != IMAGING_MODE_F) { + return (Imaging)ImagingError_NotSupportedError("only modes I/I;16/F supported"); } imOut = ImagingNew(imIn->mode, imIn->xsize, imIn->ysize); diff --git a/src/libImaging/Quant.c b/src/libImaging/Quant.c index 99c2dbac3af..0713018e208 100644 --- a/src/libImaging/Quant.c +++ b/src/libImaging/Quant.c @@ -1678,7 +1678,7 @@ ImagingQuantize(Imaging im, int colors, int mode, int kmeans) { ImagingSectionCookie cookie; if (!im) { - return ImagingError_ModeError(); + return ImagingError_ValueError(NULL); } if (colors < 1 || colors > 256) { /* FIXME: for colors > 256, consider returning an RGB image @@ -1688,12 +1688,11 @@ ImagingQuantize(Imaging im, int colors, int mode, int kmeans) { if (im->mode != IMAGING_MODE_L && im->mode != IMAGING_MODE_P && im->mode != IMAGING_MODE_RGB && im->mode != IMAGING_MODE_RGBA) { - return ImagingError_ModeError(); + return ImagingError_NotSupportedError("only modes L/P/RGB/RGBA supported"); } - /* only octree and imagequant supports RGBA */ if (im->mode == IMAGING_MODE_RGBA && mode != 2 && mode != 3) { - return ImagingError_ModeError(); + return ImagingError_ModeError("only octree and imagequant support RGBA"); } // Hoisted here as these are invariant over the loops below. diff --git a/src/libImaging/RankFilter.c b/src/libImaging/RankFilter.c index 9b13b103283..5ded6c61bbb 100644 --- a/src/libImaging/RankFilter.c +++ b/src/libImaging/RankFilter.c @@ -64,8 +64,14 @@ MakeRankFunction(UINT8) MakeRankFunction(INT32) MakeRankFunction(FLOAT32) int x, y; int i, margin, size2; - if (!im || im->bands != 1 || im->type == IMAGING_TYPE_SPECIAL) { - return (Imaging)ImagingError_ModeError(); + if (!im) { + return (Imaging)ImagingError_ValueError(NULL); + } + + if (im->bands != 1 || im->type == IMAGING_TYPE_SPECIAL) { + return (Imaging)ImagingError_ModeError( + "image must be 1-band non-special image" + ); } if (!(size & 1)) { @@ -121,7 +127,7 @@ MakeRankFunction(UINT8) MakeRankFunction(INT32) MakeRankFunction(FLOAT32) } else { /* safety net (we shouldn't end up here) */ ImagingDelete(imOut); - return (Imaging)ImagingError_ModeError(); + return (Imaging)ImagingError_ModeError(NULL); } ImagingCopyPalette(imOut, im); diff --git a/src/libImaging/Reduce.c b/src/libImaging/Reduce.c index a4e58ced81b..1cd6e3ef7a6 100644 --- a/src/libImaging/Reduce.c +++ b/src/libImaging/Reduce.c @@ -1453,11 +1453,13 @@ ImagingReduce(Imaging imIn, int xscale, int yscale, int box[4]) { Imaging imOut = NULL; if (imIn->mode == IMAGING_MODE_P || imIn->mode == IMAGING_MODE_1) { - return (Imaging)ImagingError_ModeError(); + return (Imaging)ImagingError_NotSupportedError("only modes P/1 supported"); } if (imIn->type == IMAGING_TYPE_SPECIAL) { - return (Imaging)ImagingError_ModeError(); + return (Imaging)ImagingError_NotSupportedError( + "special image types not supported" + ); } imOut = ImagingNewDirty( diff --git a/src/libImaging/Resample.c b/src/libImaging/Resample.c index c25383a70e4..91c5df6c2a2 100644 --- a/src/libImaging/Resample.c +++ b/src/libImaging/Resample.c @@ -714,7 +714,7 @@ ImagingResample(Imaging imIn, int xsize, int ysize, int filter, float box[4]) { ResampleFunction ResampleVertical; if (imIn->mode == IMAGING_MODE_P || imIn->mode == IMAGING_MODE_1) { - return (Imaging)ImagingError_ModeError(); + return (Imaging)ImagingError_NotSupportedError("only modes P/1 supported"); } if (imIn->type == IMAGING_TYPE_SPECIAL) { @@ -722,7 +722,9 @@ ImagingResample(Imaging imIn, int xsize, int ysize, int filter, float box[4]) { ResampleHorizontal = _ImagingResampleHorizontal_16bpc; ResampleVertical = _ImagingResampleVertical_16bpc; } else { - return (Imaging)ImagingError_ModeError(); + return (Imaging)ImagingError_NotSupportedError( + "special image type not supported" + ); } } else if (imIn->image8) { ResampleHorizontal = _ImagingResampleHorizontal_8bpc; @@ -739,7 +741,7 @@ ImagingResample(Imaging imIn, int xsize, int ysize, int filter, float box[4]) { ResampleVertical = _ImagingResampleVertical_32bpc; break; default: - return (Imaging)ImagingError_ModeError(); + return (Imaging)ImagingError_ModeError(NULL); } } diff --git a/src/libImaging/Storage.c b/src/libImaging/Storage.c index eae4c988f89..ebe59dd8a77 100644 --- a/src/libImaging/Storage.c +++ b/src/libImaging/Storage.c @@ -748,7 +748,7 @@ ImagingNew2Dirty(const ModeID mode, Imaging imOut, Imaging imIn) { /* make sure images match */ if (imOut->mode != mode || imOut->xsize != imIn->xsize || imOut->ysize != imIn->ysize) { - return ImagingError_Mismatch(); + return ImagingError_Mismatch("image modes and dimensions must match"); } } else { /* create new image */