Skip to content

Commit

Permalink
Merge pull request #7307 from radarhere/mode
Browse files Browse the repository at this point in the history
  • Loading branch information
hugovk committed Jul 31, 2023
2 parents 1aa0ade + 8eee457 commit c1c474a
Show file tree
Hide file tree
Showing 50 changed files with 180 additions and 115 deletions.
6 changes: 6 additions & 0 deletions Tests/test_image.py
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,12 @@ def test_width_height(self):
with pytest.raises(AttributeError):
im.size = (3, 4)

def test_set_mode(self):
im = Image.new("RGB", (1, 1))

with pytest.raises(AttributeError):
im.mode = "P"

def test_invalid_image(self):
im = io.BytesIO(b"")
with pytest.raises(UnidentifiedImageError):
Expand Down
4 changes: 2 additions & 2 deletions Tests/test_imagefile.py
Original file line number Diff line number Diff line change
Expand Up @@ -136,7 +136,7 @@ def test_no_format(self):

class DummyImageFile(ImageFile.ImageFile):
def _open(self):
self.mode = "RGB"
self._mode = "RGB"
self._size = (1, 1)

im = DummyImageFile(buf)
Expand Down Expand Up @@ -217,7 +217,7 @@ def cleanup(self):
class MockImageFile(ImageFile.ImageFile):
def _open(self):
self.rawmode = "RGBA"
self.mode = "RGBA"
self._mode = "RGBA"
self._size = (200, 200)
self.tile = [("MOCK", (xoff, yoff, xoff + xsize, yoff + ysize), 32, None)]

Expand Down
4 changes: 2 additions & 2 deletions Tests/test_pickle.py
Original file line number Diff line number Diff line change
Expand Up @@ -75,13 +75,13 @@ def test_pickle_la_mode_with_palette(tmp_path):

# Act / Assert
for protocol in range(0, pickle.HIGHEST_PROTOCOL + 1):
im.mode = "LA"
im._mode = "LA"
with open(filename, "wb") as f:
pickle.dump(im, f, protocol)
with open(filename, "rb") as f:
loaded_im = pickle.load(f)

im.mode = "PA"
im._mode = "PA"
assert im == loaded_im


Expand Down
2 changes: 1 addition & 1 deletion docs/example/DdsImagePlugin.py
Original file line number Diff line number Diff line change
Expand Up @@ -225,7 +225,7 @@ def _open(self):

flags, height, width = struct.unpack("<3I", header.read(12))
self._size = (width, height)
self.mode = "RGBA"
self._mode = "RGBA"

pitch, depth, mipmaps = struct.unpack("<3I", header.read(12))
struct.unpack("<11I", header.read(44)) # reserved
Expand Down
6 changes: 3 additions & 3 deletions docs/handbook/writing-your-own-image-plugin.rst
Original file line number Diff line number Diff line change
Expand Up @@ -72,11 +72,11 @@ true color.
# mode setting
bits = int(header[3])
if bits == 1:
self.mode = "1"
self._mode = "1"
elif bits == 8:
self.mode = "L"
self._mode = "L"
elif bits == 24:
self.mode = "RGB"
self._mode = "RGB"
else:
msg = "unknown number of bits"
raise SyntaxError(msg)
Expand Down
54 changes: 54 additions & 0 deletions docs/releasenotes/10.1.0.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
10.1.0
------

Backwards Incompatible Changes
==============================

Setting image mode
^^^^^^^^^^^^^^^^^^

If you attempt to set the mode of an image directly, e.g.
``im.mode = "RGBA"``, you will now receive an ``AttributeError``. This is
not about removing existing functionality, but instead about raising an
explicit error to prevent later consequences. The ``convert`` method is the
correct way to change an image's mode.

Deprecations
============

TODO
^^^^

TODO

API Changes
===========

TODO
^^^^

TODO

API Additions
=============

TODO
^^^^

TODO

Security
========

TODO
^^^^

TODO

Other Changes
=============

TODO
^^^^

TODO
1 change: 1 addition & 0 deletions docs/releasenotes/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ expected to be backported to earlier versions.
.. toctree::
:maxdepth: 2

10.1.0
10.0.0
9.5.0
9.4.0
Expand Down
2 changes: 1 addition & 1 deletion src/PIL/BlpImagePlugin.py
Original file line number Diff line number Diff line change
Expand Up @@ -266,7 +266,7 @@ def _open(self):
msg = f"Bad BLP magic {repr(self.magic)}"
raise BLPFormatError(msg)

self.mode = "RGBA" if self._blp_alpha_depth else "RGB"
self._mode = "RGBA" if self._blp_alpha_depth else "RGB"
self.tile = [(decoder, (0, 0) + self.size, 0, (self.mode, 0, 1))]


Expand Down
10 changes: 5 additions & 5 deletions src/PIL/BmpImagePlugin.py
Original file line number Diff line number Diff line change
Expand Up @@ -163,7 +163,7 @@ def _bitmap(self, header=0, offset=0):
offset += 4 * file_info["colors"]

# ---------------------- Check bit depth for unusual unsupported values
self.mode, raw_mode = BIT2MODE.get(file_info["bits"], (None, None))
self._mode, raw_mode = BIT2MODE.get(file_info["bits"], (None, None))
if self.mode is None:
msg = f"Unsupported BMP pixel depth ({file_info['bits']})"
raise OSError(msg)
Expand Down Expand Up @@ -200,7 +200,7 @@ def _bitmap(self, header=0, offset=0):
and file_info["rgba_mask"] in SUPPORTED[file_info["bits"]]
):
raw_mode = MASK_MODES[(file_info["bits"], file_info["rgba_mask"])]
self.mode = "RGBA" if "A" in raw_mode else self.mode
self._mode = "RGBA" if "A" in raw_mode else self.mode
elif (
file_info["bits"] in (24, 16)
and file_info["rgb_mask"] in SUPPORTED[file_info["bits"]]
Expand All @@ -214,7 +214,7 @@ def _bitmap(self, header=0, offset=0):
raise OSError(msg)
elif file_info["compression"] == self.RAW:
if file_info["bits"] == 32 and header == 22: # 32-bit .cur offset
raw_mode, self.mode = "BGRA", "RGBA"
raw_mode, self._mode = "BGRA", "RGBA"
elif file_info["compression"] in (self.RLE8, self.RLE4):
decoder_name = "bmp_rle"
else:
Expand Down Expand Up @@ -245,10 +245,10 @@ def _bitmap(self, header=0, offset=0):

# ------- If all colors are grey, white or black, ditch palette
if greyscale:
self.mode = "1" if file_info["colors"] == 2 else "L"
self._mode = "1" if file_info["colors"] == 2 else "L"
raw_mode = self.mode
else:
self.mode = "P"
self._mode = "P"
self.palette = ImagePalette.raw(
"BGRX" if padding == 4 else "BGR", palette
)
Expand Down
2 changes: 1 addition & 1 deletion src/PIL/BufrStubImagePlugin.py
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ def _open(self):
self.fp.seek(offset)

# make something up
self.mode = "F"
self._mode = "F"
self._size = 1, 1

loader = self._load()
Expand Down
22 changes: 11 additions & 11 deletions src/PIL/DdsImagePlugin.py
Original file line number Diff line number Diff line change
Expand Up @@ -128,7 +128,7 @@ def _open(self):

flags, height, width = struct.unpack("<3I", header.read(12))
self._size = (width, height)
self.mode = "RGBA"
self._mode = "RGBA"

pitch, depth, mipmaps = struct.unpack("<3I", header.read(12))
struct.unpack("<11I", header.read(44)) # reserved
Expand All @@ -141,9 +141,9 @@ def _open(self):
if pfflags & DDPF_LUMINANCE:
# Texture contains uncompressed L or LA data
if pfflags & DDPF_ALPHAPIXELS:
self.mode = "LA"
self._mode = "LA"
else:
self.mode = "L"
self._mode = "L"

self.tile = [("raw", (0, 0) + self.size, 0, (self.mode, 0, 1))]
elif pfflags & DDPF_RGB:
Expand All @@ -153,7 +153,7 @@ def _open(self):
if pfflags & DDPF_ALPHAPIXELS:
rawmode += masks[0xFF000000]
else:
self.mode = "RGB"
self._mode = "RGB"
rawmode += masks[0xFF0000] + masks[0xFF00] + masks[0xFF]

self.tile = [("raw", (0, 0) + self.size, 0, (rawmode[::-1], 0, 1))]
Expand All @@ -172,15 +172,15 @@ def _open(self):
elif fourcc == b"ATI1":
self.pixel_format = "BC4"
n = 4
self.mode = "L"
self._mode = "L"
elif fourcc == b"ATI2":
self.pixel_format = "BC5"
n = 5
self.mode = "RGB"
self._mode = "RGB"
elif fourcc == b"BC5S":
self.pixel_format = "BC5S"
n = 5
self.mode = "RGB"
self._mode = "RGB"
elif fourcc == b"DX10":
data_start += 20
# ignoring flags which pertain to volume textures and cubemaps
Expand All @@ -189,19 +189,19 @@ def _open(self):
if dxgi_format in (DXGI_FORMAT_BC5_TYPELESS, DXGI_FORMAT_BC5_UNORM):
self.pixel_format = "BC5"
n = 5
self.mode = "RGB"
self._mode = "RGB"
elif dxgi_format == DXGI_FORMAT_BC5_SNORM:
self.pixel_format = "BC5S"
n = 5
self.mode = "RGB"
self._mode = "RGB"
elif dxgi_format == DXGI_FORMAT_BC6H_UF16:
self.pixel_format = "BC6H"
n = 6
self.mode = "RGB"
self._mode = "RGB"
elif dxgi_format == DXGI_FORMAT_BC6H_SF16:
self.pixel_format = "BC6HS"
n = 6
self.mode = "RGB"
self._mode = "RGB"
elif dxgi_format in (DXGI_FORMAT_BC7_TYPELESS, DXGI_FORMAT_BC7_UNORM):
self.pixel_format = "BC7"
n = 7
Expand Down
8 changes: 4 additions & 4 deletions src/PIL/EpsImagePlugin.py
Original file line number Diff line number Diff line change
Expand Up @@ -227,7 +227,7 @@ def _open(self):
# go to offset - start of "%!PS"
self.fp.seek(offset)

self.mode = "RGB"
self._mode = "RGB"
self._size = None

byte_arr = bytearray(255)
Expand Down Expand Up @@ -344,10 +344,10 @@ def check_required_header_comments():
]

if bit_depth == 1:
self.mode = "1"
self._mode = "1"
elif bit_depth == 8:
try:
self.mode = self.mode_map[mode_id]
self._mode = self.mode_map[mode_id]
except ValueError:
break
else:
Expand Down Expand Up @@ -391,7 +391,7 @@ def load(self, scale=1, transparency=False):
# Load EPS via Ghostscript
if self.tile:
self.im = Ghostscript(self.tile, self.size, self.fp, scale, transparency)
self.mode = self.im.mode
self._mode = self.im.mode
self._size = self.im.size
self.tile = []
return Image.Image.load(self)
Expand Down
8 changes: 4 additions & 4 deletions src/PIL/FitsImagePlugin.py
Original file line number Diff line number Diff line change
Expand Up @@ -51,14 +51,14 @@ def _open(self):

number_of_bits = int(headers[b"BITPIX"])
if number_of_bits == 8:
self.mode = "L"
self._mode = "L"
elif number_of_bits == 16:
self.mode = "I"
self._mode = "I"
# rawmode = "I;16S"
elif number_of_bits == 32:
self.mode = "I"
self._mode = "I"
elif number_of_bits in (-32, -64):
self.mode = "F"
self._mode = "F"
# rawmode = "F" if number_of_bits == -32 else "F;64F"

offset = math.ceil(self.fp.tell() / 2880) * 2880
Expand Down
2 changes: 1 addition & 1 deletion src/PIL/FliImagePlugin.py
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ def _open(self):
self.is_animated = self.n_frames > 1

# image characteristics
self.mode = "P"
self._mode = "P"
self._size = i16(s, 8), i16(s, 10)

# animation speed
Expand Down
2 changes: 1 addition & 1 deletion src/PIL/FpxImagePlugin.py
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,7 @@ def _open_index(self, index=1):
# note: for now, we ignore the "uncalibrated" flag
colors.append(i32(s, 8 + i * 4) & 0x7FFFFFFF)

self.mode, self.rawmode = MODES[tuple(colors)]
self._mode, self.rawmode = MODES[tuple(colors)]

# load JPEG tables, if any
self.jpeg = {}
Expand Down
4 changes: 2 additions & 2 deletions src/PIL/FtexImagePlugin.py
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ def _open(self):
self._size = struct.unpack("<2i", self.fp.read(8))
mipmap_count, format_count = struct.unpack("<2i", self.fp.read(8))

self.mode = "RGB"
self._mode = "RGB"

# Only support single-format files.
# I don't know of any multi-format file.
Expand All @@ -90,7 +90,7 @@ def _open(self):
data = self.fp.read(mipmap_size)

if format == Format.DXT1:
self.mode = "RGBA"
self._mode = "RGBA"
self.tile = [("bcn", (0, 0) + self.size, 0, 1)]
elif format == Format.UNCOMPRESSED:
self.tile = [("raw", (0, 0) + self.size, 0, ("RGB", 0, 1))]
Expand Down
4 changes: 2 additions & 2 deletions src/PIL/GbrImagePlugin.py
Original file line number Diff line number Diff line change
Expand Up @@ -73,9 +73,9 @@ def _open(self):
comment = self.fp.read(comment_length)[:-1]

if color_depth == 1:
self.mode = "L"
self._mode = "L"
else:
self.mode = "RGBA"
self._mode = "RGBA"

self._size = width, height

Expand Down
2 changes: 1 addition & 1 deletion src/PIL/GdImageFile.py
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ def _open(self):
msg = "Not a valid GD 2.x .gd file"
raise SyntaxError(msg)

self.mode = "L" # FIXME: "P"
self._mode = "L" # FIXME: "P"
self._size = i16(s, 2), i16(s, 4)

true_color = s[6]
Expand Down

0 comments on commit c1c474a

Please sign in to comment.