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

Deprecate BGR;15, BGR;16 and BGR;24 modes #7978

Merged
merged 7 commits into from
Apr 25, 2024
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.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 6 additions & 1 deletion Tests/helper.py
Original file line number Diff line number Diff line change
Expand Up @@ -300,7 +300,12 @@ def _cached_hopper(mode: str) -> Image.Image:
im = hopper("L")
else:
im = hopper()
return im.convert(mode)
if mode.startswith("BGR;"):
with pytest.warns(DeprecationWarning):
im = im.convert(mode)
else:
im = im.convert(mode)
return im


def djpeg_available() -> bool:
Expand Down
21 changes: 17 additions & 4 deletions Tests/test_image.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,10 +36,19 @@
)


# Deprecation helper
def helper_image_new(mode: str, size: tuple[int, int]) -> Image.Image:
if mode.startswith("BGR;"):
with pytest.warns(DeprecationWarning):
return Image.new(mode, size)
else:
return Image.new(mode, size)


class TestImage:
@pytest.mark.parametrize("mode", modes)
def test_image_modes_success(self, mode: str) -> None:
Image.new(mode, (1, 1))
helper_image_new(mode, (1, 1))

@pytest.mark.parametrize("mode", ("", "bad", "very very long"))
def test_image_modes_fail(self, mode: str) -> None:
Expand Down Expand Up @@ -1023,15 +1032,19 @@ def test_roundtrip_bytes_constructor(self, mode: str) -> None:
im = hopper(mode)
source_bytes = im.tobytes()

reloaded = Image.frombytes(mode, im.size, source_bytes)
if mode.startswith("BGR;"):
with pytest.warns(DeprecationWarning):
reloaded = Image.frombytes(mode, im.size, source_bytes)
else:
reloaded = Image.frombytes(mode, im.size, source_bytes)
assert reloaded.tobytes() == source_bytes

@pytest.mark.parametrize("mode", modes)
def test_roundtrip_bytes_method(self, mode: str) -> None:
im = hopper(mode)
source_bytes = im.tobytes()

reloaded = Image.new(mode, im.size)
reloaded = helper_image_new(mode, im.size)
reloaded.frombytes(source_bytes)
assert reloaded.tobytes() == source_bytes

Expand All @@ -1040,7 +1053,7 @@ def test_getdata_putdata(self, mode: str) -> None:
if is_big_endian and mode == "BGR;15":
pytest.xfail("Known failure of BGR;15 on big-endian")
im = hopper(mode)
reloaded = Image.new(mode, im.size)
reloaded = helper_image_new(mode, im.size)
reloaded.putdata(im.getdata())
assert_image_equal(im, reloaded)

Expand Down
6 changes: 5 additions & 1 deletion Tests/test_image_access.py
Original file line number Diff line number Diff line change
Expand Up @@ -207,7 +207,11 @@ def check(self, mode: str, expected_color_int: int | None = None) -> None:

@pytest.mark.parametrize("mode", modes)
def test_basic(self, mode: str) -> None:
self.check(mode)
if mode.startswith("BGR;"):
with pytest.warns(DeprecationWarning):
self.check(mode)
else:
self.check(mode)

def test_list(self) -> None:
im = hopper()
Expand Down
3 changes: 2 additions & 1 deletion Tests/test_image_putdata.py
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,8 @@ def test_mode_F() -> None:
@pytest.mark.parametrize("mode", ("BGR;15", "BGR;16", "BGR;24"))
def test_mode_BGR(mode: str) -> None:
data = [(16, 32, 49), (32, 32, 98)]
im = Image.new(mode, (1, 2))
with pytest.warns(DeprecationWarning):
im = Image.new(mode, (1, 2))
im.putdata(data)

assert list(im.getdata()) == data
Expand Down
13 changes: 8 additions & 5 deletions Tests/test_lib_pack.py
Original file line number Diff line number Diff line change
Expand Up @@ -362,11 +362,14 @@ def test_RGB(self) -> None:
)

def test_BGR(self) -> None:
self.assert_unpack("BGR;15", "BGR;15", 3, (8, 131, 0), (24, 0, 8), (41, 131, 8))
self.assert_unpack(
"BGR;16", "BGR;16", 3, (8, 64, 0), (24, 129, 0), (41, 194, 0)
)
self.assert_unpack("BGR;24", "BGR;24", 3, (1, 2, 3), (4, 5, 6), (7, 8, 9))
with pytest.warns(DeprecationWarning):
self.assert_unpack(
"BGR;15", "BGR;15", 3, (8, 131, 0), (24, 0, 8), (41, 131, 8)
)
self.assert_unpack(
"BGR;16", "BGR;16", 3, (8, 64, 0), (24, 129, 0), (41, 194, 0)
)
self.assert_unpack("BGR;24", "BGR;24", 3, (1, 2, 3), (4, 5, 6), (7, 8, 9))

def test_RGBA(self) -> None:
self.assert_unpack("RGBA", "LA", 2, (1, 1, 1, 2), (3, 3, 3, 4), (5, 5, 5, 6))
Expand Down
7 changes: 7 additions & 0 deletions docs/deprecations.rst
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,13 @@ ImageMath eval()
``ImageMath.eval()`` has been deprecated. Use :py:meth:`~PIL.ImageMath.lambda_eval` or
:py:meth:`~PIL.ImageMath.unsafe_eval` instead.

BGR;15, BGR 16 and BGR;24
^^^^^^^^^^^^^^^^^^^^^^^^^

.. deprecated:: 10.4.0

The experimental BGR;15, BGR;16 and BGR;24 modes have been deprecated.

Support for LibTIFF earlier than 4
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

Expand Down
3 changes: 0 additions & 3 deletions docs/handbook/concepts.rst
Original file line number Diff line number Diff line change
Expand Up @@ -59,9 +59,6 @@ Pillow also provides limited support for a few additional modes, including:
* ``I;16L`` (16-bit little endian unsigned integer pixels)
* ``I;16B`` (16-bit big endian unsigned integer pixels)
* ``I;16N`` (16-bit native endian unsigned integer pixels)
* ``BGR;15`` (15-bit reversed true colour)
* ``BGR;16`` (16-bit reversed true colour)
* ``BGR;24`` (24-bit reversed true colour)

Premultiplied alpha is where the values for each other channel have been
multiplied by the alpha. For example, an RGBA pixel of ``(10, 20, 30, 127)``
Expand Down
5 changes: 5 additions & 0 deletions docs/releasenotes/10.4.0.rst
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,11 @@ TODO
Deprecations
============

BGR;15, BGR 16 and BGR;24
^^^^^^^^^^^^^^^^^^^^^^^^^

The experimental BGR;15, BGR;16 and BGR;24 modes have been deprecated.

Support for LibTIFF earlier than 4
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

Expand Down
7 changes: 7 additions & 0 deletions src/PIL/Image.py
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@
_plugins,
)
from ._binary import i32le, o32be, o32le
from ._deprecate import deprecate

Check warning on line 58 in src/PIL/Image.py

View check run for this annotation

Codecov / codecov/patch

src/PIL/Image.py#L58

Added line #L58 was not covered by tests
from ._typing import StrOrBytesPath, TypeGuard
from ._util import DeferredError, is_path

Expand Down Expand Up @@ -939,6 +940,9 @@
:returns: An :py:class:`~PIL.Image.Image` object.
"""

if mode in ("BGR;15", "BGR;16", "BGR;24"):
deprecate(mode, 12)

Check warning on line 944 in src/PIL/Image.py

View check run for this annotation

Codecov / codecov/patch

src/PIL/Image.py#L943-L944

Added lines #L943 - L944 were not covered by tests

self.load()

has_transparency = "transparency" in self.info
Expand Down Expand Up @@ -2956,6 +2960,9 @@
:returns: An :py:class:`~PIL.Image.Image` object.
"""

if mode in ("BGR;15", "BGR;16", "BGR;24"):
deprecate(mode, 12)

Check warning on line 2964 in src/PIL/Image.py

View check run for this annotation

Codecov / codecov/patch

src/PIL/Image.py#L2963-L2964

Added lines #L2963 - L2964 were not covered by tests

_check_size(size)

if color is None:
Expand Down
4 changes: 4 additions & 0 deletions src/PIL/ImageMode.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@
from functools import lru_cache
from typing import NamedTuple

from ._deprecate import deprecate

Check warning on line 21 in src/PIL/ImageMode.py

View check run for this annotation

Codecov / codecov/patch

src/PIL/ImageMode.py#L21

Added line #L21 was not covered by tests


class ModeDescriptor(NamedTuple):
"""Wrapper for mode strings."""
Expand Down Expand Up @@ -63,6 +65,8 @@
"PA": ("RGB", "L", ("P", "A"), "|u1"),
}
if mode in modes:
if mode in ("BGR;15", "BGR;16", "BGR;24"):
deprecate(mode, 12)

Check warning on line 69 in src/PIL/ImageMode.py

View check run for this annotation

Codecov / codecov/patch

src/PIL/ImageMode.py#L68-L69

Added lines #L68 - L69 were not covered by tests
base_mode, base_type, bands, type_str = modes[mode]
return ModeDescriptor(mode, bands, base_mode, base_type, type_str)

Expand Down
Loading