Merge pull request #7936 from adamjstewart/types/fromarray

This commit is contained in:
Hugo van Kemenade 2024-04-17 16:43:57 +03:00 committed by GitHub
commit f8160b858a
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 29 additions and 4 deletions

View File

@ -91,6 +91,16 @@ def test_fromarray() -> None:
Image.fromarray(wrapped) Image.fromarray(wrapped)
def test_fromarray_strides_without_tobytes() -> None:
class Wrapper:
def __init__(self, arr_params: dict[str, Any]) -> None:
self.__array_interface__ = arr_params
with pytest.raises(ValueError):
wrapped = Wrapper({"shape": (1, 1), "strides": (1, 1)})
Image.fromarray(wrapped, "L")
def test_fromarray_palette() -> None: def test_fromarray_palette() -> None:
# Arrange # Arrange
i = im.convert("L") i = im.convert("L")

View File

@ -78,6 +78,8 @@ Constructing images
^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^
.. autofunction:: new .. autofunction:: new
.. autoclass:: SupportsArrayInterface
:show-inheritance:
.. autofunction:: fromarray .. autofunction:: fromarray
.. autofunction:: frombytes .. autofunction:: frombytes
.. autofunction:: frombuffer .. autofunction:: frombuffer

View File

@ -41,7 +41,7 @@ import warnings
from collections.abc import Callable, MutableMapping from collections.abc import Callable, MutableMapping
from enum import IntEnum from enum import IntEnum
from types import ModuleType from types import ModuleType
from typing import IO, TYPE_CHECKING, Any, Literal, cast from typing import IO, TYPE_CHECKING, Any, Literal, Protocol, cast
# VERSION was removed in Pillow 6.0.0. # VERSION was removed in Pillow 6.0.0.
# PILLOW_VERSION was removed in Pillow 9.0.0. # PILLOW_VERSION was removed in Pillow 9.0.0.
@ -3018,7 +3018,7 @@ def frombytes(mode, size, data, decoder_name="raw", *args) -> Image:
return im return im
def frombuffer(mode, size, data, decoder_name="raw", *args): def frombuffer(mode, size, data, decoder_name="raw", *args) -> Image:
""" """
Creates an image memory referencing pixel data in a byte buffer. Creates an image memory referencing pixel data in a byte buffer.
@ -3074,7 +3074,17 @@ def frombuffer(mode, size, data, decoder_name="raw", *args):
return frombytes(mode, size, data, decoder_name, args) return frombytes(mode, size, data, decoder_name, args)
def fromarray(obj, mode=None): class SupportsArrayInterface(Protocol):
"""
An object that has an ``__array_interface__`` dictionary.
"""
@property
def __array_interface__(self) -> dict[str, Any]:
raise NotImplementedError()
def fromarray(obj: SupportsArrayInterface, mode: str | None = None) -> Image:
""" """
Creates an image memory from an object exporting the array interface Creates an image memory from an object exporting the array interface
(using the buffer protocol):: (using the buffer protocol)::
@ -3153,8 +3163,11 @@ def fromarray(obj, mode=None):
if strides is not None: if strides is not None:
if hasattr(obj, "tobytes"): if hasattr(obj, "tobytes"):
obj = obj.tobytes() obj = obj.tobytes()
else: elif hasattr(obj, "tostring"):
obj = obj.tostring() obj = obj.tostring()
else:
msg = "'strides' requires either tobytes() or tostring()"
raise ValueError(msg)
return frombuffer(mode, size, obj, "raw", rawmode, 0, 1) return frombuffer(mode, size, obj, "raw", rawmode, 0, 1)