From 56780ceaae9cda18a0f0a405fc2ded483c3bb647 Mon Sep 17 00:00:00 2001 From: wiredfool Date: Sun, 25 Aug 2024 15:54:00 +0100 Subject: [PATCH] Tests, lifetime changes --- Tests/test_arrow.py | 65 ++++++++++++++++++++++++++++++++++++++++ pyproject.toml | 1 + src/libImaging/Arrow.c | 2 +- src/libImaging/Storage.c | 12 ++++---- 4 files changed, 74 insertions(+), 6 deletions(-) create mode 100644 Tests/test_arrow.py diff --git a/Tests/test_arrow.py b/Tests/test_arrow.py new file mode 100644 index 000000000..86309b473 --- /dev/null +++ b/Tests/test_arrow.py @@ -0,0 +1,65 @@ +from __future__ import annotations + +import warnings + +import pytest + +from PIL import Image + +from .helper import assert_deep_equal, assert_image, hopper, skip_unless_feature + +from typing import Any # undone + +pyarrow = pytest.importorskip("pyarrow", reason="PyArrow not installed") + +TEST_IMAGE_SIZE = (10, 10) +from numbers import Number + + +def _test_img_equals_pyarray(img: Image.Image, arr: Any, mask) -> None: + assert img.height * img.width == len(arr) + px = img.load() + assert px is not None + for x in range(0, img.size[0], int(img.size[0] / 10)): + for y in range(0, img.size[1], int(img.size[1] / 10)): + if mask: + for ix, elt in enumerate(mask): + assert px[x,y][ix] == arr[y * img.width + x].as_py()[elt] + else: + assert_deep_equal(px[x, y], arr[y * img.width + x].as_py()) + + +# really hard to get a non-nullable list type +fl_uint8_4_type = pyarrow.field("_", + pyarrow.list_( + pyarrow.field("_", + pyarrow.uint8() + ).with_nullable(False) + ,4) + ).type + +@pytest.mark.parametrize( + "mode, dtype, mask", + ( + ("L", pyarrow.uint8(), None), + ("I", pyarrow.int32(), None), + ("F", pyarrow.float32(), None), + ("LA", fl_uint8_4_type, [0,3]), + ("RGB", fl_uint8_4_type, [0,1,2]), + ("RGBA", fl_uint8_4_type, None), + ("RGBX", fl_uint8_4_type, None), + ("CMYK", fl_uint8_4_type, None), + ("YCbCr", fl_uint8_4_type, [0,1,2]), + ("HSV", fl_uint8_4_type, [0,1,2]), + ), +) +def test_to_array(mode: str, dtype: Any, mask: Any ) -> None: + img = hopper(mode) + + # Resize to non-square + img = img.crop((3, 0, 124, 127)) + assert img.size == (121, 127) + + arr = pyarrow.array(img) + _test_img_equals_pyarray(img, arr, mask) + assert arr.type == dtype diff --git a/pyproject.toml b/pyproject.toml index 2c6c7bcd0..2a048f775 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -66,6 +66,7 @@ optional-dependencies.tests = [ "pytest-cov", "pytest-timeout", "trove-classifiers>=2024.10.12", + "pyarrow", ] optional-dependencies.typing = [ "typing-extensions; python_version<'3.10'", diff --git a/src/libImaging/Arrow.c b/src/libImaging/Arrow.c index d3af74c80..2e4d6a474 100644 --- a/src/libImaging/Arrow.c +++ b/src/libImaging/Arrow.c @@ -170,7 +170,7 @@ void export_uint32_array(const uint32_t* data, int64_t nitems, static void release_const_array(struct ArrowArray* array) { Imaging im = (Imaging)array->private_data; - im->arrow_borrow--; + ImagingDelete(im); //assert(array->n_buffers == 2); diff --git a/src/libImaging/Storage.c b/src/libImaging/Storage.c index 49e545367..5505d44d5 100644 --- a/src/libImaging/Storage.c +++ b/src/libImaging/Storage.c @@ -58,7 +58,7 @@ ImagingNewPrologueSubtype(const char *mode, int xsize, int ysize, int size) { /* Setup image descriptor */ im->xsize = xsize; im->ysize = ysize; - + im->arrow_borrow = 1; im->type = IMAGING_TYPE_UINT8; strcpy(im->arrow_band_format, "C"); @@ -298,15 +298,17 @@ ImagingDelete(Imaging im) { return; } + im->arrow_borrow--; + + if (im->arrow_borrow>0) { + return; + } + if (im->palette) { ImagingPaletteDelete(im->palette); im->palette = NULL; } - if (im->arrow_borrow) { - return; - } - if (im->destroy) { im->destroy(im); }