Skip to content

Commit 5832288

Browse files
authored
Merge pull request #7978 from radarhere/bgr
Deprecate BGR;15, BGR;16 and BGR;24 modes
2 parents 1138ea5 + 5736da8 commit 5832288

File tree

10 files changed

+61
-15
lines changed

10 files changed

+61
-15
lines changed

Tests/helper.py

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -300,7 +300,12 @@ def _cached_hopper(mode: str) -> Image.Image:
300300
im = hopper("L")
301301
else:
302302
im = hopper()
303-
return im.convert(mode)
303+
if mode.startswith("BGR;"):
304+
with pytest.warns(DeprecationWarning):
305+
im = im.convert(mode)
306+
else:
307+
im = im.convert(mode)
308+
return im
304309

305310

306311
def djpeg_available() -> bool:

Tests/test_image.py

Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -36,10 +36,19 @@
3636
)
3737

3838

39+
# Deprecation helper
40+
def helper_image_new(mode: str, size: tuple[int, int]) -> Image.Image:
41+
if mode.startswith("BGR;"):
42+
with pytest.warns(DeprecationWarning):
43+
return Image.new(mode, size)
44+
else:
45+
return Image.new(mode, size)
46+
47+
3948
class TestImage:
4049
@pytest.mark.parametrize("mode", modes)
4150
def test_image_modes_success(self, mode: str) -> None:
42-
Image.new(mode, (1, 1))
51+
helper_image_new(mode, (1, 1))
4352

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

1026-
reloaded = Image.frombytes(mode, im.size, source_bytes)
1035+
if mode.startswith("BGR;"):
1036+
with pytest.warns(DeprecationWarning):
1037+
reloaded = Image.frombytes(mode, im.size, source_bytes)
1038+
else:
1039+
reloaded = Image.frombytes(mode, im.size, source_bytes)
10271040
assert reloaded.tobytes() == source_bytes
10281041

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

1034-
reloaded = Image.new(mode, im.size)
1047+
reloaded = helper_image_new(mode, im.size)
10351048
reloaded.frombytes(source_bytes)
10361049
assert reloaded.tobytes() == source_bytes
10371050

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

Tests/test_image_access.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -207,7 +207,11 @@ def check(self, mode: str, expected_color_int: int | None = None) -> None:
207207

208208
@pytest.mark.parametrize("mode", modes)
209209
def test_basic(self, mode: str) -> None:
210-
self.check(mode)
210+
if mode.startswith("BGR;"):
211+
with pytest.warns(DeprecationWarning):
212+
self.check(mode)
213+
else:
214+
self.check(mode)
211215

212216
def test_list(self) -> None:
213217
im = hopper()

Tests/test_image_putdata.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,8 @@ def test_mode_F() -> None:
8181
@pytest.mark.parametrize("mode", ("BGR;15", "BGR;16", "BGR;24"))
8282
def test_mode_BGR(mode: str) -> None:
8383
data = [(16, 32, 49), (32, 32, 98)]
84-
im = Image.new(mode, (1, 2))
84+
with pytest.warns(DeprecationWarning):
85+
im = Image.new(mode, (1, 2))
8586
im.putdata(data)
8687

8788
assert list(im.getdata()) == data

Tests/test_lib_pack.py

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -362,11 +362,14 @@ def test_RGB(self) -> None:
362362
)
363363

364364
def test_BGR(self) -> None:
365-
self.assert_unpack("BGR;15", "BGR;15", 3, (8, 131, 0), (24, 0, 8), (41, 131, 8))
366-
self.assert_unpack(
367-
"BGR;16", "BGR;16", 3, (8, 64, 0), (24, 129, 0), (41, 194, 0)
368-
)
369-
self.assert_unpack("BGR;24", "BGR;24", 3, (1, 2, 3), (4, 5, 6), (7, 8, 9))
365+
with pytest.warns(DeprecationWarning):
366+
self.assert_unpack(
367+
"BGR;15", "BGR;15", 3, (8, 131, 0), (24, 0, 8), (41, 131, 8)
368+
)
369+
self.assert_unpack(
370+
"BGR;16", "BGR;16", 3, (8, 64, 0), (24, 129, 0), (41, 194, 0)
371+
)
372+
self.assert_unpack("BGR;24", "BGR;24", 3, (1, 2, 3), (4, 5, 6), (7, 8, 9))
370373

371374
def test_RGBA(self) -> None:
372375
self.assert_unpack("RGBA", "LA", 2, (1, 1, 1, 2), (3, 3, 3, 4), (5, 5, 5, 6))

docs/deprecations.rst

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,13 @@ ImageMath eval()
100100
``ImageMath.eval()`` has been deprecated. Use :py:meth:`~PIL.ImageMath.lambda_eval` or
101101
:py:meth:`~PIL.ImageMath.unsafe_eval` instead.
102102

103+
BGR;15, BGR 16 and BGR;24
104+
^^^^^^^^^^^^^^^^^^^^^^^^^
105+
106+
.. deprecated:: 10.4.0
107+
108+
The experimental BGR;15, BGR;16 and BGR;24 modes have been deprecated.
109+
103110
Support for LibTIFF earlier than 4
104111
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
105112

docs/handbook/concepts.rst

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -59,9 +59,6 @@ Pillow also provides limited support for a few additional modes, including:
5959
* ``I;16L`` (16-bit little endian unsigned integer pixels)
6060
* ``I;16B`` (16-bit big endian unsigned integer pixels)
6161
* ``I;16N`` (16-bit native endian unsigned integer pixels)
62-
* ``BGR;15`` (15-bit reversed true colour)
63-
* ``BGR;16`` (16-bit reversed true colour)
64-
* ``BGR;24`` (24-bit reversed true colour)
6562

6663
Premultiplied alpha is where the values for each other channel have been
6764
multiplied by the alpha. For example, an RGBA pixel of ``(10, 20, 30, 127)``

docs/releasenotes/10.4.0.rst

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,11 @@ TODO
2323
Deprecations
2424
============
2525

26+
BGR;15, BGR 16 and BGR;24
27+
^^^^^^^^^^^^^^^^^^^^^^^^^
28+
29+
The experimental BGR;15, BGR;16 and BGR;24 modes have been deprecated.
30+
2631
Support for LibTIFF earlier than 4
2732
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
2833

src/PIL/Image.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@
5555
_plugins,
5656
)
5757
from ._binary import i32le, o32be, o32le
58+
from ._deprecate import deprecate
5859
from ._typing import StrOrBytesPath, TypeGuard
5960
from ._util import DeferredError, is_path
6061

@@ -939,6 +940,9 @@ def convert(
939940
:returns: An :py:class:`~PIL.Image.Image` object.
940941
"""
941942

943+
if mode in ("BGR;15", "BGR;16", "BGR;24"):
944+
deprecate(mode, 12)
945+
942946
self.load()
943947

944948
has_transparency = "transparency" in self.info
@@ -2956,6 +2960,9 @@ def new(
29562960
:returns: An :py:class:`~PIL.Image.Image` object.
29572961
"""
29582962

2963+
if mode in ("BGR;15", "BGR;16", "BGR;24"):
2964+
deprecate(mode, 12)
2965+
29592966
_check_size(size)
29602967

29612968
if color is None:

src/PIL/ImageMode.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,8 @@
1818
from functools import lru_cache
1919
from typing import NamedTuple
2020

21+
from ._deprecate import deprecate
22+
2123

2224
class ModeDescriptor(NamedTuple):
2325
"""Wrapper for mode strings."""
@@ -63,6 +65,8 @@ def getmode(mode: str) -> ModeDescriptor:
6365
"PA": ("RGB", "L", ("P", "A"), "|u1"),
6466
}
6567
if mode in modes:
68+
if mode in ("BGR;15", "BGR;16", "BGR;24"):
69+
deprecate(mode, 12)
6670
base_mode, base_type, bands, type_str = modes[mode]
6771
return ModeDescriptor(mode, bands, base_mode, base_type, type_str)
6872

0 commit comments

Comments
 (0)