Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow converting an image to a numpy array to raise errors #5379

Merged
merged 1 commit into from May 20, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
40 changes: 27 additions & 13 deletions Tests/test_image_array.py
Expand Up @@ -4,26 +4,32 @@

from .helper import hopper

numpy = pytest.importorskip("numpy", reason="NumPy not installed")

im = hopper().resize((128, 100))


def test_toarray():
def test(mode):
ai = im.convert(mode).__array_interface__
return ai["version"], ai["shape"], ai["typestr"], len(ai["data"])
ai = numpy.array(im.convert(mode))
return ai.shape, ai.dtype.str, ai.nbytes

# assert test("1") == (3, (100, 128), '|b1', 1600))
assert test("L") == (3, (100, 128), "|u1", 12800)
# assert test("1") == ((100, 128), '|b1', 1600))
assert test("L") == ((100, 128), "|u1", 12800)

# FIXME: wrong?
assert test("I") == (3, (100, 128), Image._ENDIAN + "i4", 51200)
assert test("I") == ((100, 128), Image._ENDIAN + "i4", 51200)
# FIXME: wrong?
assert test("F") == (3, (100, 128), Image._ENDIAN + "f4", 51200)
assert test("F") == ((100, 128), Image._ENDIAN + "f4", 51200)

assert test("LA") == ((100, 128, 2), "|u1", 25600)
assert test("RGB") == ((100, 128, 3), "|u1", 38400)
assert test("RGBA") == ((100, 128, 4), "|u1", 51200)
assert test("RGBX") == ((100, 128, 4), "|u1", 51200)

assert test("LA") == (3, (100, 128, 2), "|u1", 25600)
assert test("RGB") == (3, (100, 128, 3), "|u1", 38400)
assert test("RGBA") == (3, (100, 128, 4), "|u1", 51200)
assert test("RGBX") == (3, (100, 128, 4), "|u1", 51200)
with Image.open("Tests/images/truncated_jpeg.jpg") as im_truncated:
with pytest.raises(OSError):
numpy.array(im_truncated)


def test_fromarray():
Expand All @@ -39,10 +45,18 @@ def tobytes(self):

def test(mode):
i = im.convert(mode)
a = i.__array_interface__
a["strides"] = 1 # pretend it's non-contiguous
a = numpy.array(i)
# Make wrapper instance for image, new array interface
wrapped = Wrapper(i, a)
wrapped = Wrapper(
i,
{
"shape": a.shape,
"typestr": a.dtype.str,
"version": 3,
"data": a.data,
"strides": 1, # pretend it's non-contiguous
},
)
out = Image.fromarray(wrapped)
return out.mode, out.size, list(i.getdata()) == list(out.getdata())

Expand Down
11 changes: 8 additions & 3 deletions src/PIL/Image.py
Expand Up @@ -676,9 +676,10 @@ def _repr_png_(self):
raise ValueError("Could not save to PNG for display") from e
return b.getvalue()

@property
def __array_interface__(self):
def __array__(self):
# numpy array interface support
import numpy as np

new = {}
shape, typestr = _conv_type_shape(self)
new["shape"] = shape
Expand All @@ -690,7 +691,11 @@ def __array_interface__(self):
new["data"] = self.tobytes("raw", "L")
else:
new["data"] = self.tobytes()
return new

class ArrayData:
__array_interface__ = new

return np.array(ArrayData())

def __getstate__(self):
return [self.info, self.mode, self.size, self.getpalette(), self.tobytes()]
Expand Down