mirror of
https://github.com/python-pillow/Pillow.git
synced 2024-12-26 01:46:18 +03:00
Merge branch 'main' into enum
This commit is contained in:
commit
b4347daa3c
|
@ -35,7 +35,8 @@ repos:
|
|||
rev: 6.0.0
|
||||
hooks:
|
||||
- id: flake8
|
||||
additional_dependencies: [flake8-2020, flake8-implicit-str-concat]
|
||||
additional_dependencies:
|
||||
[flake8-2020, flake8-errmsg, flake8-implicit-str-concat]
|
||||
|
||||
- repo: https://github.com/pre-commit/pygrep-hooks
|
||||
rev: v1.9.0
|
||||
|
|
24
CHANGES.rst
24
CHANGES.rst
|
@ -5,6 +5,30 @@ Changelog (Pillow)
|
|||
9.4.0 (unreleased)
|
||||
------------------
|
||||
|
||||
- Improve exception traceback readability #6836
|
||||
[hugovk, radarhere]
|
||||
|
||||
- Do not attempt to read IFD1 if absent #6840
|
||||
[radarhere]
|
||||
|
||||
- Fixed writing int as ASCII tag #6800
|
||||
[radarhere]
|
||||
|
||||
- If available, use wl-paste or xclip for grabclipboard() on Linux #6783
|
||||
[radarhere]
|
||||
|
||||
- Added signed option when saving JPEG2000 images #6709
|
||||
[radarhere]
|
||||
|
||||
- Patch OpenJPEG to include ARM64 fix #6718
|
||||
[radarhere]
|
||||
|
||||
- Added support for I;16 modes in putdata() #6825
|
||||
[radarhere]
|
||||
|
||||
- Added conversion from RGBa to RGB #6708
|
||||
[radarhere]
|
||||
|
||||
- Added DDS support for uncompressed L and LA images #6820
|
||||
[radarhere, REDxEYE]
|
||||
|
||||
|
|
|
@ -252,6 +252,20 @@ def test_mct():
|
|||
assert_image_similar(im, jp2, 1.0e-3)
|
||||
|
||||
|
||||
def test_sgnd(tmp_path):
|
||||
outfile = str(tmp_path / "temp.jp2")
|
||||
|
||||
im = Image.new("L", (1, 1))
|
||||
im.save(outfile)
|
||||
with Image.open(outfile) as reloaded:
|
||||
assert reloaded.getpixel((0, 0)) == 0
|
||||
|
||||
im = Image.new("L", (1, 1))
|
||||
im.save(outfile, signed=True)
|
||||
with Image.open(outfile) as reloaded_signed:
|
||||
assert reloaded_signed.getpixel((0, 0)) == 128
|
||||
|
||||
|
||||
def test_rgba():
|
||||
# Arrange
|
||||
with Image.open("Tests/images/rgb_trns_ycbc.j2k") as j2k:
|
||||
|
|
|
@ -185,20 +185,21 @@ def test_iptc(tmp_path):
|
|||
im.save(out)
|
||||
|
||||
|
||||
def test_writing_bytes_to_ascii(tmp_path):
|
||||
im = hopper()
|
||||
@pytest.mark.parametrize("value, expected", ((b"test", "test"), (1, "1")))
|
||||
def test_writing_other_types_to_ascii(value, expected, tmp_path):
|
||||
info = TiffImagePlugin.ImageFileDirectory_v2()
|
||||
|
||||
tag = TiffTags.TAGS_V2[271]
|
||||
assert tag.type == TiffTags.ASCII
|
||||
|
||||
info[271] = b"test"
|
||||
info[271] = value
|
||||
|
||||
im = hopper()
|
||||
out = str(tmp_path / "temp.tiff")
|
||||
im.save(out, tiffinfo=info)
|
||||
|
||||
with Image.open(out) as reloaded:
|
||||
assert reloaded.tag_v2[271] == "test"
|
||||
assert reloaded.tag_v2[271] == expected
|
||||
|
||||
|
||||
def test_writing_int_to_bytes(tmp_path):
|
||||
|
|
|
@ -104,6 +104,13 @@ def test_rgba_p():
|
|||
assert_image_similar(im, comparable, 20)
|
||||
|
||||
|
||||
def test_rgba():
|
||||
with Image.open("Tests/images/transparent.png") as im:
|
||||
assert im.mode == "RGBA"
|
||||
|
||||
assert_image_similar(im.convert("RGBa").convert("RGB"), im.convert("RGB"), 1.5)
|
||||
|
||||
|
||||
def test_trns_p(tmp_path):
|
||||
im = hopper("P")
|
||||
im.info["transparency"] = 0
|
||||
|
|
|
@ -55,10 +55,11 @@ def test_mode_with_L_with_float():
|
|||
assert im.getpixel((0, 0)) == 2
|
||||
|
||||
|
||||
def test_mode_i():
|
||||
@pytest.mark.parametrize("mode", ("I", "I;16", "I;16L", "I;16B"))
|
||||
def test_mode_i(mode):
|
||||
src = hopper("L")
|
||||
data = list(src.getdata())
|
||||
im = Image.new("I", src.size, 0)
|
||||
im = Image.new(mode, src.size, 0)
|
||||
im.putdata(data, 2, 256)
|
||||
|
||||
target = [2 * elt + 256 for elt in data]
|
||||
|
|
|
@ -64,9 +64,13 @@ $bmp = New-Object Drawing.Bitmap 200, 200
|
|||
)
|
||||
p.communicate()
|
||||
else:
|
||||
with pytest.raises(NotImplementedError) as e:
|
||||
ImageGrab.grabclipboard()
|
||||
assert str(e.value) == "ImageGrab.grabclipboard() is macOS and Windows only"
|
||||
if not shutil.which("wl-paste"):
|
||||
with pytest.raises(
|
||||
NotImplementedError,
|
||||
match="wl-paste or xclip is required for"
|
||||
r" ImageGrab.grabclipboard\(\) on Linux",
|
||||
):
|
||||
ImageGrab.grabclipboard()
|
||||
return
|
||||
|
||||
ImageGrab.grabclipboard()
|
||||
|
|
|
@ -211,13 +211,16 @@ class DdsImageFile(ImageFile.ImageFile):
|
|||
|
||||
def _open(self):
|
||||
if not _accept(self.fp.read(4)):
|
||||
raise SyntaxError("not a DDS file")
|
||||
msg = "not a DDS file"
|
||||
raise SyntaxError(msg)
|
||||
(header_size,) = struct.unpack("<I", self.fp.read(4))
|
||||
if header_size != 124:
|
||||
raise OSError(f"Unsupported header size {repr(header_size)}")
|
||||
msg = f"Unsupported header size {repr(header_size)}"
|
||||
raise OSError(msg)
|
||||
header_bytes = self.fp.read(header_size - 4)
|
||||
if len(header_bytes) != 120:
|
||||
raise OSError(f"Incomplete header: {len(header_bytes)} bytes")
|
||||
msg = f"Incomplete header: {len(header_bytes)} bytes"
|
||||
raise OSError(msg)
|
||||
header = BytesIO(header_bytes)
|
||||
|
||||
flags, height, width = struct.unpack("<3I", header.read(12))
|
||||
|
@ -237,7 +240,8 @@ class DdsImageFile(ImageFile.ImageFile):
|
|||
elif fourcc == b"DXT5":
|
||||
self.decoder = "DXT5"
|
||||
else:
|
||||
raise NotImplementedError(f"Unimplemented pixel format {fourcc}")
|
||||
msg = f"Unimplemented pixel format {fourcc}"
|
||||
raise NotImplementedError(msg)
|
||||
|
||||
self.tile = [(self.decoder, (0, 0) + self.size, 0, (self.mode, 0, 1))]
|
||||
|
||||
|
@ -252,7 +256,8 @@ class DXT1Decoder(ImageFile.PyDecoder):
|
|||
try:
|
||||
self.set_as_raw(_dxt1(self.fd, self.state.xsize, self.state.ysize))
|
||||
except struct.error as e:
|
||||
raise OSError("Truncated DDS file") from e
|
||||
msg = "Truncated DDS file"
|
||||
raise OSError(msg) from e
|
||||
return -1, 0
|
||||
|
||||
|
||||
|
@ -263,7 +268,8 @@ class DXT5Decoder(ImageFile.PyDecoder):
|
|||
try:
|
||||
self.set_as_raw(_dxt5(self.fd, self.state.xsize, self.state.ysize))
|
||||
except struct.error as e:
|
||||
raise OSError("Truncated DDS file") from e
|
||||
msg = "Truncated DDS file"
|
||||
raise OSError(msg) from e
|
||||
return -1, 0
|
||||
|
||||
|
||||
|
|
|
@ -64,6 +64,12 @@ Pillow also provides limited support for a few additional modes, including:
|
|||
* ``BGR;24`` (24-bit reversed true colour)
|
||||
* ``BGR;32`` (32-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)``
|
||||
would convert to an RGBa pixel of ``(5, 10, 15, 127)``. The values of the R,
|
||||
G and B channels are halved as a result of the half transparency in the alpha
|
||||
channel.
|
||||
|
||||
Apart from these additional modes, Pillow doesn't yet support multichannel
|
||||
images with a depth of more than 8 bits per channel.
|
||||
|
||||
|
@ -111,6 +117,18 @@ the file format handler (see the chapter on :ref:`image-file-formats`). Most
|
|||
handlers add properties to the :py:attr:`~PIL.Image.Image.info` attribute when
|
||||
loading an image, but ignore it when saving images.
|
||||
|
||||
Transparency
|
||||
------------
|
||||
|
||||
If an image does not have an alpha band, transparency may be specified in the
|
||||
:py:attr:`~PIL.Image.Image.info` attribute with a "transparency" key.
|
||||
|
||||
Most of the time, the "transparency" value is a single integer, describing
|
||||
which pixel value is transparent in a "1", "L", "I" or "P" mode image.
|
||||
However, PNG images may have three values, one for each channel in an "RGB"
|
||||
mode image, or can have a byte string for a "P" mode image, to specify the
|
||||
alpha value for each palette entry.
|
||||
|
||||
Orientation
|
||||
-----------
|
||||
|
||||
|
|
|
@ -568,6 +568,11 @@ The :py:meth:`~PIL.Image.Image.save` method supports the following options:
|
|||
encoded using RLCP mode will have increasing resolutions decoded as they
|
||||
arrive, and so on.
|
||||
|
||||
**signed**
|
||||
If true, then tell the encoder to save the image as signed.
|
||||
|
||||
.. versionadded:: 9.4.0
|
||||
|
||||
**cinema_mode**
|
||||
Set the encoder to produce output compliant with the digital cinema
|
||||
specifications. The options here are ``"no"`` (the default),
|
||||
|
|
|
@ -78,7 +78,8 @@ true color.
|
|||
elif bits == 24:
|
||||
self.mode = "RGB"
|
||||
else:
|
||||
raise SyntaxError("unknown number of bits")
|
||||
msg = "unknown number of bits"
|
||||
raise SyntaxError(msg)
|
||||
|
||||
# data descriptor
|
||||
self.tile = [("raw", (0, 0) + self.size, 128, (self.mode, 0, 1))]
|
||||
|
|
|
@ -45,6 +45,12 @@ removes the hidden RGB values for better compression by default in libwebp 0.5
|
|||
or later. By setting this option to ``True``, the encoder will keep the hidden
|
||||
RGB values.
|
||||
|
||||
Added ``signed`` option when saving JPEG2000
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
If the ``signed`` keyword argument is present and true when saving JPEG2000
|
||||
images, then tell the encoder to save the image as signed.
|
||||
|
||||
Added IFD, Interop and LightSource ExifTags enums
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
|
|
18
setup.py
18
setup.py
|
@ -362,15 +362,15 @@ class pil_build_ext(build_ext):
|
|||
self.feature.required.discard(x)
|
||||
_dbg("Disabling %s", x)
|
||||
if getattr(self, f"enable_{x}"):
|
||||
raise ValueError(
|
||||
f"Conflicting options: --enable-{x} and --disable-{x}"
|
||||
)
|
||||
msg = f"Conflicting options: --enable-{x} and --disable-{x}"
|
||||
raise ValueError(msg)
|
||||
if x == "freetype":
|
||||
_dbg("--disable-freetype implies --disable-raqm")
|
||||
if getattr(self, "enable_raqm"):
|
||||
raise ValueError(
|
||||
msg = (
|
||||
"Conflicting options: --enable-raqm and --disable-freetype"
|
||||
)
|
||||
raise ValueError(msg)
|
||||
setattr(self, "disable_raqm", True)
|
||||
if getattr(self, f"enable_{x}"):
|
||||
_dbg("Requiring %s", x)
|
||||
|
@ -381,13 +381,11 @@ class pil_build_ext(build_ext):
|
|||
for x in ("raqm", "fribidi"):
|
||||
if getattr(self, f"vendor_{x}"):
|
||||
if getattr(self, "disable_raqm"):
|
||||
raise ValueError(
|
||||
f"Conflicting options: --vendor-{x} and --disable-raqm"
|
||||
)
|
||||
msg = f"Conflicting options: --vendor-{x} and --disable-raqm"
|
||||
raise ValueError(msg)
|
||||
if x == "fribidi" and not getattr(self, "vendor_raqm"):
|
||||
raise ValueError(
|
||||
f"Conflicting options: --vendor-{x} and not --vendor-raqm"
|
||||
)
|
||||
msg = f"Conflicting options: --vendor-{x} and not --vendor-raqm"
|
||||
raise ValueError(msg)
|
||||
_dbg("Using vendored version of %s", x)
|
||||
self.feature.vendor.add(x)
|
||||
|
||||
|
|
|
@ -86,7 +86,8 @@ class BdfFontFile(FontFile.FontFile):
|
|||
|
||||
s = fp.readline()
|
||||
if s[:13] != b"STARTFONT 2.1":
|
||||
raise SyntaxError("not a valid BDF file")
|
||||
msg = "not a valid BDF file"
|
||||
raise SyntaxError(msg)
|
||||
|
||||
props = {}
|
||||
comments = []
|
||||
|
|
|
@ -65,7 +65,8 @@ def __getattr__(name):
|
|||
if name in enum.__members__:
|
||||
deprecate(f"{prefix}{name}", 10, f"{enum.__name__}.{name}")
|
||||
return enum[name]
|
||||
raise AttributeError(f"module '{__name__}' has no attribute '{name}'")
|
||||
msg = f"module '{__name__}' has no attribute '{name}'"
|
||||
raise AttributeError(msg)
|
||||
|
||||
|
||||
def unpack_565(i):
|
||||
|
@ -278,7 +279,8 @@ class BlpImageFile(ImageFile.ImageFile):
|
|||
if self.magic in (b"BLP1", b"BLP2"):
|
||||
decoder = self.magic.decode()
|
||||
else:
|
||||
raise BLPFormatError(f"Bad BLP magic {repr(self.magic)}")
|
||||
msg = f"Bad BLP magic {repr(self.magic)}"
|
||||
raise BLPFormatError(msg)
|
||||
|
||||
self.mode = "RGBA" if self._blp_alpha_depth else "RGB"
|
||||
self.tile = [(decoder, (0, 0) + self.size, 0, (self.mode, 0, 1))]
|
||||
|
@ -292,7 +294,8 @@ class _BLPBaseDecoder(ImageFile.PyDecoder):
|
|||
self._read_blp_header()
|
||||
self._load()
|
||||
except struct.error as e:
|
||||
raise OSError("Truncated BLP file") from e
|
||||
msg = "Truncated BLP file"
|
||||
raise OSError(msg) from e
|
||||
return -1, 0
|
||||
|
||||
def _read_blp_header(self):
|
||||
|
@ -354,13 +357,11 @@ class BLP1Decoder(_BLPBaseDecoder):
|
|||
data = self._read_bgra(palette)
|
||||
self.set_as_raw(bytes(data))
|
||||
else:
|
||||
raise BLPFormatError(
|
||||
f"Unsupported BLP encoding {repr(self._blp_encoding)}"
|
||||
)
|
||||
msg = f"Unsupported BLP encoding {repr(self._blp_encoding)}"
|
||||
raise BLPFormatError(msg)
|
||||
else:
|
||||
raise BLPFormatError(
|
||||
f"Unsupported BLP compression {repr(self._blp_encoding)}"
|
||||
)
|
||||
msg = f"Unsupported BLP compression {repr(self._blp_encoding)}"
|
||||
raise BLPFormatError(msg)
|
||||
|
||||
def _decode_jpeg_stream(self):
|
||||
from .JpegImagePlugin import JpegImageFile
|
||||
|
@ -415,16 +416,15 @@ class BLP2Decoder(_BLPBaseDecoder):
|
|||
for d in decode_dxt5(self._safe_read(linesize)):
|
||||
data += d
|
||||
else:
|
||||
raise BLPFormatError(
|
||||
f"Unsupported alpha encoding {repr(self._blp_alpha_encoding)}"
|
||||
)
|
||||
msg = f"Unsupported alpha encoding {repr(self._blp_alpha_encoding)}"
|
||||
raise BLPFormatError(msg)
|
||||
else:
|
||||
raise BLPFormatError(f"Unknown BLP encoding {repr(self._blp_encoding)}")
|
||||
msg = f"Unknown BLP encoding {repr(self._blp_encoding)}"
|
||||
raise BLPFormatError(msg)
|
||||
|
||||
else:
|
||||
raise BLPFormatError(
|
||||
f"Unknown BLP compression {repr(self._blp_compression)}"
|
||||
)
|
||||
msg = f"Unknown BLP compression {repr(self._blp_compression)}"
|
||||
raise BLPFormatError(msg)
|
||||
|
||||
self.set_as_raw(bytes(data))
|
||||
|
||||
|
@ -460,7 +460,8 @@ class BLPEncoder(ImageFile.PyEncoder):
|
|||
|
||||
def _save(im, fp, filename, save_all=False):
|
||||
if im.mode != "P":
|
||||
raise ValueError("Unsupported BLP image mode")
|
||||
msg = "Unsupported BLP image mode"
|
||||
raise ValueError(msg)
|
||||
|
||||
magic = b"BLP1" if im.encoderinfo.get("blp_version") == "BLP1" else b"BLP2"
|
||||
fp.write(magic)
|
||||
|
|
|
@ -146,7 +146,8 @@ class BmpImageFile(ImageFile.ImageFile):
|
|||
file_info["a_mask"],
|
||||
)
|
||||
else:
|
||||
raise OSError(f"Unsupported BMP header type ({file_info['header_size']})")
|
||||
msg = f"Unsupported BMP header type ({file_info['header_size']})"
|
||||
raise OSError(msg)
|
||||
|
||||
# ------------------ Special case : header is reported 40, which
|
||||
# ---------------------- is shorter than real size for bpp >= 16
|
||||
|
@ -164,7 +165,8 @@ class BmpImageFile(ImageFile.ImageFile):
|
|||
# ---------------------- Check bit depth for unusual unsupported values
|
||||
self.mode, raw_mode = BIT2MODE.get(file_info["bits"], (None, None))
|
||||
if self.mode is None:
|
||||
raise OSError(f"Unsupported BMP pixel depth ({file_info['bits']})")
|
||||
msg = f"Unsupported BMP pixel depth ({file_info['bits']})"
|
||||
raise OSError(msg)
|
||||
|
||||
# ---------------- Process BMP with Bitfields compression (not palette)
|
||||
decoder_name = "raw"
|
||||
|
@ -205,23 +207,27 @@ class BmpImageFile(ImageFile.ImageFile):
|
|||
):
|
||||
raw_mode = MASK_MODES[(file_info["bits"], file_info["rgb_mask"])]
|
||||
else:
|
||||
raise OSError("Unsupported BMP bitfields layout")
|
||||
msg = "Unsupported BMP bitfields layout"
|
||||
raise OSError(msg)
|
||||
else:
|
||||
raise OSError("Unsupported BMP bitfields layout")
|
||||
msg = "Unsupported BMP bitfields layout"
|
||||
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"
|
||||
elif file_info["compression"] in (self.RLE8, self.RLE4):
|
||||
decoder_name = "bmp_rle"
|
||||
else:
|
||||
raise OSError(f"Unsupported BMP compression ({file_info['compression']})")
|
||||
msg = f"Unsupported BMP compression ({file_info['compression']})"
|
||||
raise OSError(msg)
|
||||
|
||||
# --------------- Once the header is processed, process the palette/LUT
|
||||
if self.mode == "P": # Paletted for 1, 4 and 8 bit images
|
||||
|
||||
# ---------------------------------------------------- 1-bit images
|
||||
if not (0 < file_info["colors"] <= 65536):
|
||||
raise OSError(f"Unsupported BMP Palette size ({file_info['colors']})")
|
||||
msg = f"Unsupported BMP Palette size ({file_info['colors']})"
|
||||
raise OSError(msg)
|
||||
else:
|
||||
padding = file_info["palette_padding"]
|
||||
palette = read(padding * file_info["colors"])
|
||||
|
@ -271,7 +277,8 @@ class BmpImageFile(ImageFile.ImageFile):
|
|||
head_data = self.fp.read(14)
|
||||
# choke if the file does not have the required magic bytes
|
||||
if not _accept(head_data):
|
||||
raise SyntaxError("Not a BMP file")
|
||||
msg = "Not a BMP file"
|
||||
raise SyntaxError(msg)
|
||||
# read the start position of the BMP image data (u32)
|
||||
offset = i32(head_data, 10)
|
||||
# load bitmap information (offset=raster info)
|
||||
|
@ -383,7 +390,8 @@ def _save(im, fp, filename, bitmap_header=True):
|
|||
try:
|
||||
rawmode, bits, colors = SAVE[im.mode]
|
||||
except KeyError as e:
|
||||
raise OSError(f"cannot write mode {im.mode} as BMP") from e
|
||||
msg = f"cannot write mode {im.mode} as BMP"
|
||||
raise OSError(msg) from e
|
||||
|
||||
info = im.encoderinfo
|
||||
|
||||
|
@ -411,7 +419,8 @@ def _save(im, fp, filename, bitmap_header=True):
|
|||
offset = 14 + header + colors * 4
|
||||
file_size = offset + image
|
||||
if file_size > 2**32 - 1:
|
||||
raise ValueError("File size is too large for the BMP format")
|
||||
msg = "File size is too large for the BMP format"
|
||||
raise ValueError(msg)
|
||||
fp.write(
|
||||
b"BM" # file type (magic)
|
||||
+ o32(file_size) # file size
|
||||
|
|
|
@ -42,7 +42,8 @@ class BufrStubImageFile(ImageFile.StubImageFile):
|
|||
offset = self.fp.tell()
|
||||
|
||||
if not _accept(self.fp.read(4)):
|
||||
raise SyntaxError("Not a BUFR file")
|
||||
msg = "Not a BUFR file"
|
||||
raise SyntaxError(msg)
|
||||
|
||||
self.fp.seek(offset)
|
||||
|
||||
|
@ -60,7 +61,8 @@ class BufrStubImageFile(ImageFile.StubImageFile):
|
|||
|
||||
def _save(im, fp, filename):
|
||||
if _handler is None or not hasattr(_handler, "save"):
|
||||
raise OSError("BUFR save handler not installed")
|
||||
msg = "BUFR save handler not installed"
|
||||
raise OSError(msg)
|
||||
_handler.save(im, fp, filename)
|
||||
|
||||
|
||||
|
|
|
@ -43,7 +43,8 @@ class CurImageFile(BmpImagePlugin.BmpImageFile):
|
|||
# check magic
|
||||
s = self.fp.read(6)
|
||||
if not _accept(s):
|
||||
raise SyntaxError("not a CUR file")
|
||||
msg = "not a CUR file"
|
||||
raise SyntaxError(msg)
|
||||
|
||||
# pick the largest cursor in the file
|
||||
m = b""
|
||||
|
@ -54,7 +55,8 @@ class CurImageFile(BmpImagePlugin.BmpImageFile):
|
|||
elif s[0] > m[0] and s[1] > m[1]:
|
||||
m = s
|
||||
if not m:
|
||||
raise TypeError("No cursors were found")
|
||||
msg = "No cursors were found"
|
||||
raise TypeError(msg)
|
||||
|
||||
# load as bitmap
|
||||
self._bitmap(i32(m, 12) + offset)
|
||||
|
|
|
@ -47,7 +47,8 @@ class DcxImageFile(PcxImageFile):
|
|||
# Header
|
||||
s = self.fp.read(4)
|
||||
if not _accept(s):
|
||||
raise SyntaxError("not a DCX file")
|
||||
msg = "not a DCX file"
|
||||
raise SyntaxError(msg)
|
||||
|
||||
# Component directory
|
||||
self._offset = []
|
||||
|
|
|
@ -114,13 +114,16 @@ class DdsImageFile(ImageFile.ImageFile):
|
|||
|
||||
def _open(self):
|
||||
if not _accept(self.fp.read(4)):
|
||||
raise SyntaxError("not a DDS file")
|
||||
msg = "not a DDS file"
|
||||
raise SyntaxError(msg)
|
||||
(header_size,) = struct.unpack("<I", self.fp.read(4))
|
||||
if header_size != 124:
|
||||
raise OSError(f"Unsupported header size {repr(header_size)}")
|
||||
msg = f"Unsupported header size {repr(header_size)}"
|
||||
raise OSError(msg)
|
||||
header_bytes = self.fp.read(header_size - 4)
|
||||
if len(header_bytes) != 120:
|
||||
raise OSError(f"Incomplete header: {len(header_bytes)} bytes")
|
||||
msg = f"Incomplete header: {len(header_bytes)} bytes"
|
||||
raise OSError(msg)
|
||||
header = BytesIO(header_bytes)
|
||||
|
||||
flags, height, width = struct.unpack("<3I", header.read(12))
|
||||
|
@ -216,11 +219,11 @@ class DdsImageFile(ImageFile.ImageFile):
|
|||
self.info["gamma"] = 1 / 2.2
|
||||
return
|
||||
else:
|
||||
raise NotImplementedError(
|
||||
f"Unimplemented DXGI format {dxgi_format}"
|
||||
)
|
||||
msg = f"Unimplemented DXGI format {dxgi_format}"
|
||||
raise NotImplementedError(msg)
|
||||
else:
|
||||
raise NotImplementedError(f"Unimplemented pixel format {repr(fourcc)}")
|
||||
msg = f"Unimplemented pixel format {repr(fourcc)}"
|
||||
raise NotImplementedError(msg)
|
||||
|
||||
self.tile = [
|
||||
("bcn", (0, 0) + self.size, data_start, (n, self.pixel_format))
|
||||
|
@ -232,7 +235,8 @@ class DdsImageFile(ImageFile.ImageFile):
|
|||
|
||||
def _save(im, fp, filename):
|
||||
if im.mode not in ("RGB", "RGBA", "L", "LA"):
|
||||
raise OSError(f"cannot write mode {im.mode} as DDS")
|
||||
msg = f"cannot write mode {im.mode} as DDS"
|
||||
raise OSError(msg)
|
||||
|
||||
rawmode = im.mode
|
||||
masks = [0xFF0000, 0xFF00, 0xFF]
|
||||
|
|
|
@ -133,7 +133,8 @@ def Ghostscript(tile, size, fp, scale=1, transparency=False):
|
|||
|
||||
if gs_windows_binary is not None:
|
||||
if not gs_windows_binary:
|
||||
raise OSError("Unable to locate Ghostscript on paths")
|
||||
msg = "Unable to locate Ghostscript on paths"
|
||||
raise OSError(msg)
|
||||
command[0] = gs_windows_binary
|
||||
|
||||
# push data through Ghostscript
|
||||
|
@ -229,12 +230,14 @@ class EpsImageFile(ImageFile.ImageFile):
|
|||
while s_raw:
|
||||
if s:
|
||||
if len(s) > 255:
|
||||
raise SyntaxError("not an EPS file")
|
||||
msg = "not an EPS file"
|
||||
raise SyntaxError(msg)
|
||||
|
||||
try:
|
||||
m = split.match(s)
|
||||
except re.error as e:
|
||||
raise SyntaxError("not an EPS file") from e
|
||||
msg = "not an EPS file"
|
||||
raise SyntaxError(msg) from e
|
||||
|
||||
if m:
|
||||
k, v = m.group(1, 2)
|
||||
|
@ -268,7 +271,8 @@ class EpsImageFile(ImageFile.ImageFile):
|
|||
# tools mistakenly put in the Comments section
|
||||
pass
|
||||
else:
|
||||
raise OSError("bad EPS header")
|
||||
msg = "bad EPS header"
|
||||
raise OSError(msg)
|
||||
|
||||
s_raw = fp.readline()
|
||||
s = s_raw.strip("\r\n")
|
||||
|
@ -282,7 +286,8 @@ class EpsImageFile(ImageFile.ImageFile):
|
|||
while s[:1] == "%":
|
||||
|
||||
if len(s) > 255:
|
||||
raise SyntaxError("not an EPS file")
|
||||
msg = "not an EPS file"
|
||||
raise SyntaxError(msg)
|
||||
|
||||
if s[:11] == "%ImageData:":
|
||||
# Encoded bitmapped image.
|
||||
|
@ -306,7 +311,8 @@ class EpsImageFile(ImageFile.ImageFile):
|
|||
break
|
||||
|
||||
if not box:
|
||||
raise OSError("cannot determine EPS bounding box")
|
||||
msg = "cannot determine EPS bounding box"
|
||||
raise OSError(msg)
|
||||
|
||||
def _find_offset(self, fp):
|
||||
|
||||
|
@ -326,7 +332,8 @@ class EpsImageFile(ImageFile.ImageFile):
|
|||
offset = i32(s, 4)
|
||||
length = i32(s, 8)
|
||||
else:
|
||||
raise SyntaxError("not an EPS file")
|
||||
msg = "not an EPS file"
|
||||
raise SyntaxError(msg)
|
||||
|
||||
return length, offset
|
||||
|
||||
|
@ -365,7 +372,8 @@ def _save(im, fp, filename, eps=1):
|
|||
elif im.mode == "CMYK":
|
||||
operator = (8, 4, b"false 4 colorimage")
|
||||
else:
|
||||
raise ValueError("image mode is not supported")
|
||||
msg = "image mode is not supported"
|
||||
raise ValueError(msg)
|
||||
|
||||
if eps:
|
||||
#
|
||||
|
|
|
@ -28,7 +28,8 @@ class FitsImageFile(ImageFile.ImageFile):
|
|||
while True:
|
||||
header = self.fp.read(80)
|
||||
if not header:
|
||||
raise OSError("Truncated FITS file")
|
||||
msg = "Truncated FITS file"
|
||||
raise OSError(msg)
|
||||
keyword = header[:8].strip()
|
||||
if keyword == b"END":
|
||||
break
|
||||
|
@ -36,12 +37,14 @@ class FitsImageFile(ImageFile.ImageFile):
|
|||
if value.startswith(b"="):
|
||||
value = value[1:].strip()
|
||||
if not headers and (not _accept(keyword) or value != b"T"):
|
||||
raise SyntaxError("Not a FITS file")
|
||||
msg = "Not a FITS file"
|
||||
raise SyntaxError(msg)
|
||||
headers[keyword] = value
|
||||
|
||||
naxis = int(headers[b"NAXIS"])
|
||||
if naxis == 0:
|
||||
raise ValueError("No image data")
|
||||
msg = "No image data"
|
||||
raise ValueError(msg)
|
||||
elif naxis == 1:
|
||||
self._size = 1, int(headers[b"NAXIS1"])
|
||||
else:
|
||||
|
|
|
@ -67,7 +67,8 @@ class FITSStubImageFile(ImageFile.StubImageFile):
|
|||
|
||||
|
||||
def _save(im, fp, filename):
|
||||
raise OSError("FITS save handler not installed")
|
||||
msg = "FITS save handler not installed"
|
||||
raise OSError(msg)
|
||||
|
||||
|
||||
# --------------------------------------------------------------------
|
||||
|
|
|
@ -50,7 +50,8 @@ class FliImageFile(ImageFile.ImageFile):
|
|||
# HEAD
|
||||
s = self.fp.read(128)
|
||||
if not (_accept(s) and s[20:22] == b"\x00\x00"):
|
||||
raise SyntaxError("not an FLI/FLC file")
|
||||
msg = "not an FLI/FLC file"
|
||||
raise SyntaxError(msg)
|
||||
|
||||
# frames
|
||||
self.n_frames = i16(s, 6)
|
||||
|
@ -141,7 +142,8 @@ class FliImageFile(ImageFile.ImageFile):
|
|||
self.load()
|
||||
|
||||
if frame != self.__frame + 1:
|
||||
raise ValueError(f"cannot seek to frame {frame}")
|
||||
msg = f"cannot seek to frame {frame}"
|
||||
raise ValueError(msg)
|
||||
self.__frame = frame
|
||||
|
||||
# move to next frame
|
||||
|
|
|
@ -60,10 +60,12 @@ class FpxImageFile(ImageFile.ImageFile):
|
|||
try:
|
||||
self.ole = olefile.OleFileIO(self.fp)
|
||||
except OSError as e:
|
||||
raise SyntaxError("not an FPX file; invalid OLE file") from e
|
||||
msg = "not an FPX file; invalid OLE file"
|
||||
raise SyntaxError(msg) from e
|
||||
|
||||
if self.ole.root.clsid != "56616700-C154-11CE-8553-00AA00A1F95B":
|
||||
raise SyntaxError("not an FPX file; bad root CLSID")
|
||||
msg = "not an FPX file; bad root CLSID"
|
||||
raise SyntaxError(msg)
|
||||
|
||||
self._open_index(1)
|
||||
|
||||
|
@ -99,7 +101,8 @@ class FpxImageFile(ImageFile.ImageFile):
|
|||
colors = []
|
||||
bands = i32(s, 4)
|
||||
if bands > 4:
|
||||
raise OSError("Invalid number of bands")
|
||||
msg = "Invalid number of bands"
|
||||
raise OSError(msg)
|
||||
for i in range(bands):
|
||||
# note: for now, we ignore the "uncalibrated" flag
|
||||
colors.append(i32(s, 8 + i * 4) & 0x7FFFFFFF)
|
||||
|
@ -141,7 +144,8 @@ class FpxImageFile(ImageFile.ImageFile):
|
|||
length = i32(s, 32)
|
||||
|
||||
if size != self.size:
|
||||
raise OSError("subimage mismatch")
|
||||
msg = "subimage mismatch"
|
||||
raise OSError(msg)
|
||||
|
||||
# get tile descriptors
|
||||
fp.seek(28 + offset)
|
||||
|
@ -217,7 +221,8 @@ class FpxImageFile(ImageFile.ImageFile):
|
|||
self.tile_prefix = self.jpeg[jpeg_tables]
|
||||
|
||||
else:
|
||||
raise OSError("unknown/invalid compression")
|
||||
msg = "unknown/invalid compression"
|
||||
raise OSError(msg)
|
||||
|
||||
x = x + xtile
|
||||
if x >= xsize:
|
||||
|
|
|
@ -73,7 +73,8 @@ def __getattr__(name):
|
|||
if name in enum.__members__:
|
||||
deprecate(f"{prefix}{name}", 10, f"{enum.__name__}.{name}")
|
||||
return enum[name]
|
||||
raise AttributeError(f"module '{__name__}' has no attribute '{name}'")
|
||||
msg = f"module '{__name__}' has no attribute '{name}'"
|
||||
raise AttributeError(msg)
|
||||
|
||||
|
||||
class FtexImageFile(ImageFile.ImageFile):
|
||||
|
@ -82,7 +83,8 @@ class FtexImageFile(ImageFile.ImageFile):
|
|||
|
||||
def _open(self):
|
||||
if not _accept(self.fp.read(4)):
|
||||
raise SyntaxError("not an FTEX file")
|
||||
msg = "not an FTEX file"
|
||||
raise SyntaxError(msg)
|
||||
struct.unpack("<i", self.fp.read(4)) # version
|
||||
self._size = struct.unpack("<2i", self.fp.read(8))
|
||||
mipmap_count, format_count = struct.unpack("<2i", self.fp.read(8))
|
||||
|
@ -105,7 +107,8 @@ class FtexImageFile(ImageFile.ImageFile):
|
|||
elif format == Format.UNCOMPRESSED:
|
||||
self.tile = [("raw", (0, 0) + self.size, 0, ("RGB", 0, 1))]
|
||||
else:
|
||||
raise ValueError(f"Invalid texture compression format: {repr(format)}")
|
||||
msg = f"Invalid texture compression format: {repr(format)}"
|
||||
raise ValueError(msg)
|
||||
|
||||
self.fp.close()
|
||||
self.fp = BytesIO(data)
|
||||
|
|
|
@ -44,18 +44,22 @@ class GbrImageFile(ImageFile.ImageFile):
|
|||
def _open(self):
|
||||
header_size = i32(self.fp.read(4))
|
||||
if header_size < 20:
|
||||
raise SyntaxError("not a GIMP brush")
|
||||
msg = "not a GIMP brush"
|
||||
raise SyntaxError(msg)
|
||||
version = i32(self.fp.read(4))
|
||||
if version not in (1, 2):
|
||||
raise SyntaxError(f"Unsupported GIMP brush version: {version}")
|
||||
msg = f"Unsupported GIMP brush version: {version}"
|
||||
raise SyntaxError(msg)
|
||||
|
||||
width = i32(self.fp.read(4))
|
||||
height = i32(self.fp.read(4))
|
||||
color_depth = i32(self.fp.read(4))
|
||||
if width <= 0 or height <= 0:
|
||||
raise SyntaxError("not a GIMP brush")
|
||||
msg = "not a GIMP brush"
|
||||
raise SyntaxError(msg)
|
||||
if color_depth not in (1, 4):
|
||||
raise SyntaxError(f"Unsupported GIMP brush color depth: {color_depth}")
|
||||
msg = f"Unsupported GIMP brush color depth: {color_depth}"
|
||||
raise SyntaxError(msg)
|
||||
|
||||
if version == 1:
|
||||
comment_length = header_size - 20
|
||||
|
@ -63,7 +67,8 @@ class GbrImageFile(ImageFile.ImageFile):
|
|||
comment_length = header_size - 28
|
||||
magic_number = self.fp.read(4)
|
||||
if magic_number != b"GIMP":
|
||||
raise SyntaxError("not a GIMP brush, bad magic number")
|
||||
msg = "not a GIMP brush, bad magic number"
|
||||
raise SyntaxError(msg)
|
||||
self.info["spacing"] = i32(self.fp.read(4))
|
||||
|
||||
comment = self.fp.read(comment_length)[:-1]
|
||||
|
|
|
@ -49,7 +49,8 @@ class GdImageFile(ImageFile.ImageFile):
|
|||
s = self.fp.read(1037)
|
||||
|
||||
if not i16(s) in [65534, 65535]:
|
||||
raise SyntaxError("Not a valid GD 2.x .gd file")
|
||||
msg = "Not a valid GD 2.x .gd file"
|
||||
raise SyntaxError(msg)
|
||||
|
||||
self.mode = "L" # FIXME: "P"
|
||||
self._size = i16(s, 2), i16(s, 4)
|
||||
|
@ -87,9 +88,11 @@ def open(fp, mode="r"):
|
|||
:raises OSError: If the image could not be read.
|
||||
"""
|
||||
if mode != "r":
|
||||
raise ValueError("bad mode")
|
||||
msg = "bad mode"
|
||||
raise ValueError(msg)
|
||||
|
||||
try:
|
||||
return GdImageFile(fp)
|
||||
except SyntaxError as e:
|
||||
raise UnidentifiedImageError("cannot identify this image file") from e
|
||||
msg = "cannot identify this image file"
|
||||
raise UnidentifiedImageError(msg) from e
|
||||
|
|
|
@ -85,7 +85,8 @@ class GifImageFile(ImageFile.ImageFile):
|
|||
# Screen
|
||||
s = self.fp.read(13)
|
||||
if not _accept(s):
|
||||
raise SyntaxError("not a GIF file")
|
||||
msg = "not a GIF file"
|
||||
raise SyntaxError(msg)
|
||||
|
||||
self.info["version"] = s[:6]
|
||||
self._size = i16(s, 6), i16(s, 8)
|
||||
|
@ -152,7 +153,8 @@ class GifImageFile(ImageFile.ImageFile):
|
|||
self._seek(f)
|
||||
except EOFError as e:
|
||||
self.seek(last_frame)
|
||||
raise EOFError("no more images in GIF file") from e
|
||||
msg = "no more images in GIF file"
|
||||
raise EOFError(msg) from e
|
||||
|
||||
def _seek(self, frame, update_image=True):
|
||||
|
||||
|
@ -171,7 +173,8 @@ class GifImageFile(ImageFile.ImageFile):
|
|||
self.load()
|
||||
|
||||
if frame != self.__frame + 1:
|
||||
raise ValueError(f"cannot seek to frame {frame}")
|
||||
msg = f"cannot seek to frame {frame}"
|
||||
raise ValueError(msg)
|
||||
|
||||
self.fp = self._fp
|
||||
if self.__offset:
|
||||
|
|
|
@ -107,7 +107,8 @@ class GimpGradientFile(GradientFile):
|
|||
def __init__(self, fp):
|
||||
|
||||
if fp.readline()[:13] != b"GIMP Gradient":
|
||||
raise SyntaxError("not a GIMP gradient file")
|
||||
msg = "not a GIMP gradient file"
|
||||
raise SyntaxError(msg)
|
||||
|
||||
line = fp.readline()
|
||||
|
||||
|
@ -133,7 +134,8 @@ class GimpGradientFile(GradientFile):
|
|||
cspace = int(s[12])
|
||||
|
||||
if cspace != 0:
|
||||
raise OSError("cannot handle HSV colour space")
|
||||
msg = "cannot handle HSV colour space"
|
||||
raise OSError(msg)
|
||||
|
||||
gradient.append((x0, x1, xm, rgb0, rgb1, segment))
|
||||
|
||||
|
|
|
@ -29,7 +29,8 @@ class GimpPaletteFile:
|
|||
self.palette = [o8(i) * 3 for i in range(256)]
|
||||
|
||||
if fp.readline()[:12] != b"GIMP Palette":
|
||||
raise SyntaxError("not a GIMP palette file")
|
||||
msg = "not a GIMP palette file"
|
||||
raise SyntaxError(msg)
|
||||
|
||||
for i in range(256):
|
||||
|
||||
|
@ -41,11 +42,13 @@ class GimpPaletteFile:
|
|||
if re.match(rb"\w+:|#", s):
|
||||
continue
|
||||
if len(s) > 100:
|
||||
raise SyntaxError("bad palette file")
|
||||
msg = "bad palette file"
|
||||
raise SyntaxError(msg)
|
||||
|
||||
v = tuple(map(int, s.split()[:3]))
|
||||
if len(v) != 3:
|
||||
raise ValueError("bad palette entry")
|
||||
msg = "bad palette entry"
|
||||
raise ValueError(msg)
|
||||
|
||||
self.palette[i] = o8(v[0]) + o8(v[1]) + o8(v[2])
|
||||
|
||||
|
|
|
@ -42,7 +42,8 @@ class GribStubImageFile(ImageFile.StubImageFile):
|
|||
offset = self.fp.tell()
|
||||
|
||||
if not _accept(self.fp.read(8)):
|
||||
raise SyntaxError("Not a GRIB file")
|
||||
msg = "Not a GRIB file"
|
||||
raise SyntaxError(msg)
|
||||
|
||||
self.fp.seek(offset)
|
||||
|
||||
|
@ -60,7 +61,8 @@ class GribStubImageFile(ImageFile.StubImageFile):
|
|||
|
||||
def _save(im, fp, filename):
|
||||
if _handler is None or not hasattr(_handler, "save"):
|
||||
raise OSError("GRIB save handler not installed")
|
||||
msg = "GRIB save handler not installed"
|
||||
raise OSError(msg)
|
||||
_handler.save(im, fp, filename)
|
||||
|
||||
|
||||
|
|
|
@ -42,7 +42,8 @@ class HDF5StubImageFile(ImageFile.StubImageFile):
|
|||
offset = self.fp.tell()
|
||||
|
||||
if not _accept(self.fp.read(8)):
|
||||
raise SyntaxError("Not an HDF file")
|
||||
msg = "Not an HDF file"
|
||||
raise SyntaxError(msg)
|
||||
|
||||
self.fp.seek(offset)
|
||||
|
||||
|
@ -60,7 +61,8 @@ class HDF5StubImageFile(ImageFile.StubImageFile):
|
|||
|
||||
def _save(im, fp, filename):
|
||||
if _handler is None or not hasattr(_handler, "save"):
|
||||
raise OSError("HDF5 save handler not installed")
|
||||
msg = "HDF5 save handler not installed"
|
||||
raise OSError(msg)
|
||||
_handler.save(im, fp, filename)
|
||||
|
||||
|
||||
|
|
|
@ -42,7 +42,8 @@ def read_32t(fobj, start_length, size):
|
|||
fobj.seek(start)
|
||||
sig = fobj.read(4)
|
||||
if sig != b"\x00\x00\x00\x00":
|
||||
raise SyntaxError("Unknown signature, expecting 0x00000000")
|
||||
msg = "Unknown signature, expecting 0x00000000"
|
||||
raise SyntaxError(msg)
|
||||
return read_32(fobj, (start + 4, length - 4), size)
|
||||
|
||||
|
||||
|
@ -82,7 +83,8 @@ def read_32(fobj, start_length, size):
|
|||
if bytesleft <= 0:
|
||||
break
|
||||
if bytesleft != 0:
|
||||
raise SyntaxError(f"Error reading channel [{repr(bytesleft)} left]")
|
||||
msg = f"Error reading channel [{repr(bytesleft)} left]"
|
||||
raise SyntaxError(msg)
|
||||
band = Image.frombuffer("L", pixel_size, b"".join(data), "raw", "L", 0, 1)
|
||||
im.im.putband(band.im, band_ix)
|
||||
return {"RGB": im}
|
||||
|
@ -113,10 +115,11 @@ def read_png_or_jpeg2000(fobj, start_length, size):
|
|||
or sig == b"\x00\x00\x00\x0cjP \x0d\x0a\x87\x0a"
|
||||
):
|
||||
if not enable_jpeg2k:
|
||||
raise ValueError(
|
||||
msg = (
|
||||
"Unsupported icon subimage format (rebuild PIL "
|
||||
"with JPEG 2000 support to fix this)"
|
||||
)
|
||||
raise ValueError(msg)
|
||||
# j2k, jpc or j2c
|
||||
fobj.seek(start)
|
||||
jp2kstream = fobj.read(length)
|
||||
|
@ -127,7 +130,8 @@ def read_png_or_jpeg2000(fobj, start_length, size):
|
|||
im = im.convert("RGBA")
|
||||
return {"RGBA": im}
|
||||
else:
|
||||
raise ValueError("Unsupported icon subimage format")
|
||||
msg = "Unsupported icon subimage format"
|
||||
raise ValueError(msg)
|
||||
|
||||
|
||||
class IcnsFile:
|
||||
|
@ -168,12 +172,14 @@ class IcnsFile:
|
|||
self.fobj = fobj
|
||||
sig, filesize = nextheader(fobj)
|
||||
if not _accept(sig):
|
||||
raise SyntaxError("not an icns file")
|
||||
msg = "not an icns file"
|
||||
raise SyntaxError(msg)
|
||||
i = HEADERSIZE
|
||||
while i < filesize:
|
||||
sig, blocksize = nextheader(fobj)
|
||||
if blocksize <= 0:
|
||||
raise SyntaxError("invalid block header")
|
||||
msg = "invalid block header"
|
||||
raise SyntaxError(msg)
|
||||
i += HEADERSIZE
|
||||
blocksize -= HEADERSIZE
|
||||
dct[sig] = (i, blocksize)
|
||||
|
@ -192,7 +198,8 @@ class IcnsFile:
|
|||
def bestsize(self):
|
||||
sizes = self.itersizes()
|
||||
if not sizes:
|
||||
raise SyntaxError("No 32bit icon resources found")
|
||||
msg = "No 32bit icon resources found"
|
||||
raise SyntaxError(msg)
|
||||
return max(sizes)
|
||||
|
||||
def dataforsize(self, size):
|
||||
|
@ -275,7 +282,8 @@ class IcnsImageFile(ImageFile.ImageFile):
|
|||
if value in simple_sizes:
|
||||
info_size = self.info["sizes"][simple_sizes.index(value)]
|
||||
if info_size not in self.info["sizes"]:
|
||||
raise ValueError("This is not one of the allowed sizes of this image")
|
||||
msg = "This is not one of the allowed sizes of this image"
|
||||
raise ValueError(msg)
|
||||
self._size = value
|
||||
|
||||
def load(self):
|
||||
|
|
|
@ -127,7 +127,8 @@ class IcoFile:
|
|||
# check magic
|
||||
s = buf.read(6)
|
||||
if not _accept(s):
|
||||
raise SyntaxError("not an ICO file")
|
||||
msg = "not an ICO file"
|
||||
raise SyntaxError(msg)
|
||||
|
||||
self.buf = buf
|
||||
self.entry = []
|
||||
|
@ -316,7 +317,8 @@ class IcoImageFile(ImageFile.ImageFile):
|
|||
@size.setter
|
||||
def size(self, value):
|
||||
if value not in self.info["sizes"]:
|
||||
raise ValueError("This is not one of the allowed sizes of this image")
|
||||
msg = "This is not one of the allowed sizes of this image"
|
||||
raise ValueError(msg)
|
||||
self._size = value
|
||||
|
||||
def load(self):
|
||||
|
|
|
@ -126,7 +126,8 @@ class ImImageFile(ImageFile.ImageFile):
|
|||
# 100 bytes, this is (probably) not a text header.
|
||||
|
||||
if b"\n" not in self.fp.read(100):
|
||||
raise SyntaxError("not an IM file")
|
||||
msg = "not an IM file"
|
||||
raise SyntaxError(msg)
|
||||
self.fp.seek(0)
|
||||
|
||||
n = 0
|
||||
|
@ -153,7 +154,8 @@ class ImImageFile(ImageFile.ImageFile):
|
|||
s = s + self.fp.readline()
|
||||
|
||||
if len(s) > 100:
|
||||
raise SyntaxError("not an IM file")
|
||||
msg = "not an IM file"
|
||||
raise SyntaxError(msg)
|
||||
|
||||
if s[-2:] == b"\r\n":
|
||||
s = s[:-2]
|
||||
|
@ -163,7 +165,8 @@ class ImImageFile(ImageFile.ImageFile):
|
|||
try:
|
||||
m = split.match(s)
|
||||
except re.error as e:
|
||||
raise SyntaxError("not an IM file") from e
|
||||
msg = "not an IM file"
|
||||
raise SyntaxError(msg) from e
|
||||
|
||||
if m:
|
||||
|
||||
|
@ -198,12 +201,12 @@ class ImImageFile(ImageFile.ImageFile):
|
|||
|
||||
else:
|
||||
|
||||
raise SyntaxError(
|
||||
"Syntax error in IM header: " + s.decode("ascii", "replace")
|
||||
)
|
||||
msg = "Syntax error in IM header: " + s.decode("ascii", "replace")
|
||||
raise SyntaxError(msg)
|
||||
|
||||
if not n:
|
||||
raise SyntaxError("Not an IM file")
|
||||
msg = "Not an IM file"
|
||||
raise SyntaxError(msg)
|
||||
|
||||
# Basic attributes
|
||||
self._size = self.info[SIZE]
|
||||
|
@ -213,7 +216,8 @@ class ImImageFile(ImageFile.ImageFile):
|
|||
while s and s[:1] != b"\x1A":
|
||||
s = self.fp.read(1)
|
||||
if not s:
|
||||
raise SyntaxError("File truncated")
|
||||
msg = "File truncated"
|
||||
raise SyntaxError(msg)
|
||||
|
||||
if LUT in self.info:
|
||||
# convert lookup table to palette or lut attribute
|
||||
|
@ -332,7 +336,8 @@ def _save(im, fp, filename):
|
|||
try:
|
||||
image_type, rawmode = SAVE[im.mode]
|
||||
except KeyError as e:
|
||||
raise ValueError(f"Cannot save {im.mode} images as IM") from e
|
||||
msg = f"Cannot save {im.mode} images as IM"
|
||||
raise ValueError(msg) from e
|
||||
|
||||
frames = im.encoderinfo.get("frames", 1)
|
||||
|
||||
|
|
183
src/PIL/Image.py
183
src/PIL/Image.py
|
@ -75,7 +75,8 @@ def __getattr__(name):
|
|||
name, 10, f"{old_resampling[name]} or Resampling.{old_resampling[name]}"
|
||||
)
|
||||
return Resampling[old_resampling[name]]
|
||||
raise AttributeError(f"module '{__name__}' has no attribute '{name}'")
|
||||
msg = f"module '{__name__}' has no attribute '{name}'"
|
||||
raise AttributeError(msg)
|
||||
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
@ -102,11 +103,12 @@ try:
|
|||
from . import _imaging as core
|
||||
|
||||
if __version__ != getattr(core, "PILLOW_VERSION", None):
|
||||
raise ImportError(
|
||||
msg = (
|
||||
"The _imaging extension was built for another version of Pillow or PIL:\n"
|
||||
f"Core version: {getattr(core, 'PILLOW_VERSION', None)}\n"
|
||||
f"Pillow version: {__version__}"
|
||||
)
|
||||
raise ImportError(msg)
|
||||
|
||||
except ImportError as v:
|
||||
core = DeferredError(ImportError("The _imaging C module is not installed."))
|
||||
|
@ -407,7 +409,8 @@ def _getdecoder(mode, decoder_name, args, extra=()):
|
|||
# get decoder
|
||||
decoder = getattr(core, decoder_name + "_decoder")
|
||||
except AttributeError as e:
|
||||
raise OSError(f"decoder {decoder_name} not available") from e
|
||||
msg = f"decoder {decoder_name} not available"
|
||||
raise OSError(msg) from e
|
||||
return decoder(mode, *args + extra)
|
||||
|
||||
|
||||
|
@ -430,7 +433,8 @@ def _getencoder(mode, encoder_name, args, extra=()):
|
|||
# get encoder
|
||||
encoder = getattr(core, encoder_name + "_encoder")
|
||||
except AttributeError as e:
|
||||
raise OSError(f"encoder {encoder_name} not available") from e
|
||||
msg = f"encoder {encoder_name} not available"
|
||||
raise OSError(msg) from e
|
||||
return encoder(mode, *args + extra)
|
||||
|
||||
|
||||
|
@ -676,7 +680,8 @@ class Image:
|
|||
try:
|
||||
self.save(b, "PNG")
|
||||
except Exception as e:
|
||||
raise ValueError("Could not save to PNG for display") from e
|
||||
msg = "Could not save to PNG for display"
|
||||
raise ValueError(msg) from e
|
||||
return b.getvalue()
|
||||
|
||||
@property
|
||||
|
@ -768,7 +773,8 @@ class Image:
|
|||
if s:
|
||||
break
|
||||
if s < 0:
|
||||
raise RuntimeError(f"encoder error {s} in tobytes")
|
||||
msg = f"encoder error {s} in tobytes"
|
||||
raise RuntimeError(msg)
|
||||
|
||||
return b"".join(data)
|
||||
|
||||
|
@ -785,7 +791,8 @@ class Image:
|
|||
|
||||
self.load()
|
||||
if self.mode != "1":
|
||||
raise ValueError("not a bitmap")
|
||||
msg = "not a bitmap"
|
||||
raise ValueError(msg)
|
||||
data = self.tobytes("xbm")
|
||||
return b"".join(
|
||||
[
|
||||
|
@ -819,9 +826,11 @@ class Image:
|
|||
s = d.decode(data)
|
||||
|
||||
if s[0] >= 0:
|
||||
raise ValueError("not enough image data")
|
||||
msg = "not enough image data"
|
||||
raise ValueError(msg)
|
||||
if s[1] != 0:
|
||||
raise ValueError("cannot decode image data")
|
||||
msg = "cannot decode image data"
|
||||
raise ValueError(msg)
|
||||
|
||||
def load(self):
|
||||
"""
|
||||
|
@ -942,7 +951,8 @@ class Image:
|
|||
if matrix:
|
||||
# matrix conversion
|
||||
if mode not in ("L", "RGB"):
|
||||
raise ValueError("illegal conversion")
|
||||
msg = "illegal conversion"
|
||||
raise ValueError(msg)
|
||||
im = self.im.convert_matrix(mode, matrix)
|
||||
new = self._new(im)
|
||||
if has_transparency and self.im.bands == 3:
|
||||
|
@ -1027,7 +1037,8 @@ class Image:
|
|||
elif isinstance(t, int):
|
||||
self.im.putpalettealpha(t, 0)
|
||||
else:
|
||||
raise ValueError("Transparency for P mode should be bytes or int")
|
||||
msg = "Transparency for P mode should be bytes or int"
|
||||
raise ValueError(msg)
|
||||
|
||||
if mode == "P" and palette == Palette.ADAPTIVE:
|
||||
im = self.im.quantize(colors)
|
||||
|
@ -1077,7 +1088,8 @@ class Image:
|
|||
im = self.im.convert(modebase)
|
||||
im = im.convert(mode, dither)
|
||||
except KeyError as e:
|
||||
raise ValueError("illegal conversion") from e
|
||||
msg = "illegal conversion"
|
||||
raise ValueError(msg) from e
|
||||
|
||||
new_im = self._new(im)
|
||||
if mode == "P" and palette != Palette.ADAPTIVE:
|
||||
|
@ -1152,20 +1164,21 @@ class Image:
|
|||
Quantize.LIBIMAGEQUANT,
|
||||
):
|
||||
# Caller specified an invalid mode.
|
||||
raise ValueError(
|
||||
msg = (
|
||||
"Fast Octree (method == 2) and libimagequant (method == 3) "
|
||||
"are the only valid methods for quantizing RGBA images"
|
||||
)
|
||||
raise ValueError(msg)
|
||||
|
||||
if palette:
|
||||
# use palette from reference image
|
||||
palette.load()
|
||||
if palette.mode != "P":
|
||||
raise ValueError("bad mode for palette image")
|
||||
msg = "bad mode for palette image"
|
||||
raise ValueError(msg)
|
||||
if self.mode != "RGB" and self.mode != "L":
|
||||
raise ValueError(
|
||||
"only RGB or L mode images can be quantized to a palette"
|
||||
)
|
||||
msg = "only RGB or L mode images can be quantized to a palette"
|
||||
raise ValueError(msg)
|
||||
im = self.im.convert("P", dither, palette.im)
|
||||
new_im = self._new(im)
|
||||
new_im.palette = palette.palette.copy()
|
||||
|
@ -1211,9 +1224,11 @@ class Image:
|
|||
return self.copy()
|
||||
|
||||
if box[2] < box[0]:
|
||||
raise ValueError("Coordinate 'right' is less than 'left'")
|
||||
msg = "Coordinate 'right' is less than 'left'"
|
||||
raise ValueError(msg)
|
||||
elif box[3] < box[1]:
|
||||
raise ValueError("Coordinate 'lower' is less than 'upper'")
|
||||
msg = "Coordinate 'lower' is less than 'upper'"
|
||||
raise ValueError(msg)
|
||||
|
||||
self.load()
|
||||
return self._new(self._crop(self.im, box))
|
||||
|
@ -1281,9 +1296,8 @@ class Image:
|
|||
if isinstance(filter, Callable):
|
||||
filter = filter()
|
||||
if not hasattr(filter, "filter"):
|
||||
raise TypeError(
|
||||
"filter argument should be ImageFilter.Filter instance or class"
|
||||
)
|
||||
msg = "filter argument should be ImageFilter.Filter instance or class"
|
||||
raise TypeError(msg)
|
||||
|
||||
multiband = isinstance(filter, ImageFilter.MultibandFilter)
|
||||
if self.im.bands == 1 or multiband:
|
||||
|
@ -1532,7 +1546,8 @@ class Image:
|
|||
def apply_transparency(self):
|
||||
"""
|
||||
If a P mode image has a "transparency" key in the info dictionary,
|
||||
remove the key and apply the transparency to the palette instead.
|
||||
remove the key and instead apply the transparency to the palette.
|
||||
Otherwise, the image is unchanged.
|
||||
"""
|
||||
if self.mode != "P" or "transparency" not in self.info:
|
||||
return
|
||||
|
@ -1691,7 +1706,8 @@ class Image:
|
|||
size = mask.size
|
||||
else:
|
||||
# FIXME: use self.size here?
|
||||
raise ValueError("cannot determine region size; use 4-item box")
|
||||
msg = "cannot determine region size; use 4-item box"
|
||||
raise ValueError(msg)
|
||||
box += (box[0] + size[0], box[1] + size[1])
|
||||
|
||||
if isinstance(im, str):
|
||||
|
@ -1730,15 +1746,20 @@ class Image:
|
|||
"""
|
||||
|
||||
if not isinstance(source, (list, tuple)):
|
||||
raise ValueError("Source must be a tuple")
|
||||
msg = "Source must be a tuple"
|
||||
raise ValueError(msg)
|
||||
if not isinstance(dest, (list, tuple)):
|
||||
raise ValueError("Destination must be a tuple")
|
||||
msg = "Destination must be a tuple"
|
||||
raise ValueError(msg)
|
||||
if not len(source) in (2, 4):
|
||||
raise ValueError("Source must be a 2 or 4-tuple")
|
||||
msg = "Source must be a 2 or 4-tuple"
|
||||
raise ValueError(msg)
|
||||
if not len(dest) == 2:
|
||||
raise ValueError("Destination must be a 2-tuple")
|
||||
msg = "Destination must be a 2-tuple"
|
||||
raise ValueError(msg)
|
||||
if min(source) < 0:
|
||||
raise ValueError("Source must be non-negative")
|
||||
msg = "Source must be non-negative"
|
||||
raise ValueError(msg)
|
||||
|
||||
if len(source) == 2:
|
||||
source = source + im.size
|
||||
|
@ -1803,7 +1824,8 @@ class Image:
|
|||
|
||||
if self.mode == "F":
|
||||
# FIXME: _imaging returns a confusing error message for this case
|
||||
raise ValueError("point operation not supported for this mode")
|
||||
msg = "point operation not supported for this mode"
|
||||
raise ValueError(msg)
|
||||
|
||||
if mode != "F":
|
||||
lut = [round(i) for i in lut]
|
||||
|
@ -1837,7 +1859,8 @@ class Image:
|
|||
self.pyaccess = None
|
||||
self.mode = self.im.mode
|
||||
except KeyError as e:
|
||||
raise ValueError("illegal image mode") from e
|
||||
msg = "illegal image mode"
|
||||
raise ValueError(msg) from e
|
||||
|
||||
if self.mode in ("LA", "PA"):
|
||||
band = 1
|
||||
|
@ -1847,7 +1870,8 @@ class Image:
|
|||
if isImageType(alpha):
|
||||
# alpha layer
|
||||
if alpha.mode not in ("1", "L"):
|
||||
raise ValueError("illegal image mode")
|
||||
msg = "illegal image mode"
|
||||
raise ValueError(msg)
|
||||
alpha.load()
|
||||
if alpha.mode == "1":
|
||||
alpha = alpha.convert("L")
|
||||
|
@ -1903,7 +1927,8 @@ class Image:
|
|||
from . import ImagePalette
|
||||
|
||||
if self.mode not in ("L", "LA", "P", "PA"):
|
||||
raise ValueError("illegal image mode")
|
||||
msg = "illegal image mode"
|
||||
raise ValueError(msg)
|
||||
if isinstance(data, ImagePalette.ImagePalette):
|
||||
palette = ImagePalette.raw(data.rawmode, data.palette)
|
||||
else:
|
||||
|
@ -1972,7 +1997,8 @@ class Image:
|
|||
from . import ImagePalette
|
||||
|
||||
if self.mode not in ("L", "P"):
|
||||
raise ValueError("illegal image mode")
|
||||
msg = "illegal image mode"
|
||||
raise ValueError(msg)
|
||||
|
||||
bands = 3
|
||||
palette_mode = "RGB"
|
||||
|
@ -2104,7 +2130,7 @@ class Image:
|
|||
Resampling.BOX,
|
||||
Resampling.HAMMING,
|
||||
):
|
||||
message = f"Unknown resampling filter ({resample})."
|
||||
msg = f"Unknown resampling filter ({resample})."
|
||||
|
||||
filters = [
|
||||
f"{filter[1]} ({filter[0]})"
|
||||
|
@ -2117,12 +2143,12 @@ class Image:
|
|||
(Resampling.HAMMING, "Image.Resampling.HAMMING"),
|
||||
)
|
||||
]
|
||||
raise ValueError(
|
||||
message + " Use " + ", ".join(filters[:-1]) + " or " + filters[-1]
|
||||
)
|
||||
msg += " Use " + ", ".join(filters[:-1]) + " or " + filters[-1]
|
||||
raise ValueError(msg)
|
||||
|
||||
if reducing_gap is not None and reducing_gap < 1.0:
|
||||
raise ValueError("reducing_gap must be 1.0 or greater")
|
||||
msg = "reducing_gap must be 1.0 or greater"
|
||||
raise ValueError(msg)
|
||||
|
||||
size = tuple(size)
|
||||
|
||||
|
@ -2380,7 +2406,8 @@ class Image:
|
|||
try:
|
||||
format = EXTENSION[ext]
|
||||
except KeyError as e:
|
||||
raise ValueError(f"unknown file extension: {ext}") from e
|
||||
msg = f"unknown file extension: {ext}"
|
||||
raise ValueError(msg) from e
|
||||
|
||||
if format.upper() not in SAVE:
|
||||
init()
|
||||
|
@ -2494,7 +2521,8 @@ class Image:
|
|||
try:
|
||||
channel = self.getbands().index(channel)
|
||||
except ValueError as e:
|
||||
raise ValueError(f'The image has no channel "{channel}"') from e
|
||||
msg = f'The image has no channel "{channel}"'
|
||||
raise ValueError(msg) from e
|
||||
|
||||
return self._new(self.im.getband(channel))
|
||||
|
||||
|
@ -2665,7 +2693,8 @@ class Image:
|
|||
method, data = method.getdata()
|
||||
|
||||
if data is None:
|
||||
raise ValueError("missing method data")
|
||||
msg = "missing method data"
|
||||
raise ValueError(msg)
|
||||
|
||||
im = new(self.mode, size, fillcolor)
|
||||
if self.mode == "P" and self.palette:
|
||||
|
@ -2726,7 +2755,8 @@ class Image:
|
|||
)
|
||||
|
||||
else:
|
||||
raise ValueError("unknown transformation method")
|
||||
msg = "unknown transformation method"
|
||||
raise ValueError(msg)
|
||||
|
||||
if resample not in (
|
||||
Resampling.NEAREST,
|
||||
|
@ -2734,13 +2764,13 @@ class Image:
|
|||
Resampling.BICUBIC,
|
||||
):
|
||||
if resample in (Resampling.BOX, Resampling.HAMMING, Resampling.LANCZOS):
|
||||
message = {
|
||||
msg = {
|
||||
Resampling.BOX: "Image.Resampling.BOX",
|
||||
Resampling.HAMMING: "Image.Resampling.HAMMING",
|
||||
Resampling.LANCZOS: "Image.Resampling.LANCZOS",
|
||||
}[resample] + f" ({resample}) cannot be used."
|
||||
else:
|
||||
message = f"Unknown resampling filter ({resample})."
|
||||
msg = f"Unknown resampling filter ({resample})."
|
||||
|
||||
filters = [
|
||||
f"{filter[1]} ({filter[0]})"
|
||||
|
@ -2750,9 +2780,8 @@ class Image:
|
|||
(Resampling.BICUBIC, "Image.Resampling.BICUBIC"),
|
||||
)
|
||||
]
|
||||
raise ValueError(
|
||||
message + " Use " + ", ".join(filters[:-1]) + " or " + filters[-1]
|
||||
)
|
||||
msg += " Use " + ", ".join(filters[:-1]) + " or " + filters[-1]
|
||||
raise ValueError(msg)
|
||||
|
||||
image.load()
|
||||
|
||||
|
@ -2791,7 +2820,8 @@ class Image:
|
|||
from . import ImageQt
|
||||
|
||||
if not ImageQt.qt_is_installed:
|
||||
raise ImportError("Qt bindings are not installed")
|
||||
msg = "Qt bindings are not installed"
|
||||
raise ImportError(msg)
|
||||
return ImageQt.toqimage(self)
|
||||
|
||||
def toqpixmap(self):
|
||||
|
@ -2799,7 +2829,8 @@ class Image:
|
|||
from . import ImageQt
|
||||
|
||||
if not ImageQt.qt_is_installed:
|
||||
raise ImportError("Qt bindings are not installed")
|
||||
msg = "Qt bindings are not installed"
|
||||
raise ImportError(msg)
|
||||
return ImageQt.toqpixmap(self)
|
||||
|
||||
|
||||
|
@ -2847,11 +2878,14 @@ def _check_size(size):
|
|||
"""
|
||||
|
||||
if not isinstance(size, (list, tuple)):
|
||||
raise ValueError("Size must be a tuple")
|
||||
msg = "Size must be a tuple"
|
||||
raise ValueError(msg)
|
||||
if len(size) != 2:
|
||||
raise ValueError("Size must be a tuple of length 2")
|
||||
msg = "Size must be a tuple of length 2"
|
||||
raise ValueError(msg)
|
||||
if size[0] < 0 or size[1] < 0:
|
||||
raise ValueError("Width and height must be >= 0")
|
||||
msg = "Width and height must be >= 0"
|
||||
raise ValueError(msg)
|
||||
|
||||
return True
|
||||
|
||||
|
@ -3037,11 +3071,13 @@ def fromarray(obj, mode=None):
|
|||
try:
|
||||
typekey = (1, 1) + shape[2:], arr["typestr"]
|
||||
except KeyError as e:
|
||||
raise TypeError("Cannot handle this data type") from e
|
||||
msg = "Cannot handle this data type"
|
||||
raise TypeError(msg) from e
|
||||
try:
|
||||
mode, rawmode = _fromarray_typemap[typekey]
|
||||
except KeyError as e:
|
||||
raise TypeError("Cannot handle this data type: %s, %s" % typekey) from e
|
||||
msg = "Cannot handle this data type: %s, %s" % typekey
|
||||
raise TypeError(msg) from e
|
||||
else:
|
||||
rawmode = mode
|
||||
if mode in ["1", "L", "I", "P", "F"]:
|
||||
|
@ -3051,7 +3087,8 @@ def fromarray(obj, mode=None):
|
|||
else:
|
||||
ndmax = 4
|
||||
if ndim > ndmax:
|
||||
raise ValueError(f"Too many dimensions: {ndim} > {ndmax}.")
|
||||
msg = f"Too many dimensions: {ndim} > {ndmax}."
|
||||
raise ValueError(msg)
|
||||
|
||||
size = 1 if ndim == 1 else shape[1], shape[0]
|
||||
if strides is not None:
|
||||
|
@ -3068,7 +3105,8 @@ def fromqimage(im):
|
|||
from . import ImageQt
|
||||
|
||||
if not ImageQt.qt_is_installed:
|
||||
raise ImportError("Qt bindings are not installed")
|
||||
msg = "Qt bindings are not installed"
|
||||
raise ImportError(msg)
|
||||
return ImageQt.fromqimage(im)
|
||||
|
||||
|
||||
|
@ -3077,7 +3115,8 @@ def fromqpixmap(im):
|
|||
from . import ImageQt
|
||||
|
||||
if not ImageQt.qt_is_installed:
|
||||
raise ImportError("Qt bindings are not installed")
|
||||
msg = "Qt bindings are not installed"
|
||||
raise ImportError(msg)
|
||||
return ImageQt.fromqpixmap(im)
|
||||
|
||||
|
||||
|
@ -3115,10 +3154,11 @@ def _decompression_bomb_check(size):
|
|||
pixels = size[0] * size[1]
|
||||
|
||||
if pixels > 2 * MAX_IMAGE_PIXELS:
|
||||
raise DecompressionBombError(
|
||||
msg = (
|
||||
f"Image size ({pixels} pixels) exceeds limit of {2 * MAX_IMAGE_PIXELS} "
|
||||
"pixels, could be decompression bomb DOS attack."
|
||||
)
|
||||
raise DecompressionBombError(msg)
|
||||
|
||||
if pixels > MAX_IMAGE_PIXELS:
|
||||
warnings.warn(
|
||||
|
@ -3158,17 +3198,20 @@ def open(fp, mode="r", formats=None):
|
|||
"""
|
||||
|
||||
if mode != "r":
|
||||
raise ValueError(f"bad mode {repr(mode)}")
|
||||
msg = f"bad mode {repr(mode)}"
|
||||
raise ValueError(msg)
|
||||
elif isinstance(fp, io.StringIO):
|
||||
raise ValueError(
|
||||
msg = (
|
||||
"StringIO cannot be used to open an image. "
|
||||
"Binary data must be used instead."
|
||||
)
|
||||
raise ValueError(msg)
|
||||
|
||||
if formats is None:
|
||||
formats = ID
|
||||
elif not isinstance(formats, (list, tuple)):
|
||||
raise TypeError("formats must be a list or tuple")
|
||||
msg = "formats must be a list or tuple"
|
||||
raise TypeError(msg)
|
||||
|
||||
exclusive_fp = False
|
||||
filename = ""
|
||||
|
@ -3233,9 +3276,8 @@ def open(fp, mode="r", formats=None):
|
|||
fp.close()
|
||||
for message in accept_warnings:
|
||||
warnings.warn(message)
|
||||
raise UnidentifiedImageError(
|
||||
"cannot identify image file %r" % (filename if filename else fp)
|
||||
)
|
||||
msg = "cannot identify image file %r" % (filename if filename else fp)
|
||||
raise UnidentifiedImageError(msg)
|
||||
|
||||
|
||||
#
|
||||
|
@ -3326,12 +3368,15 @@ def merge(mode, bands):
|
|||
"""
|
||||
|
||||
if getmodebands(mode) != len(bands) or "*" in mode:
|
||||
raise ValueError("wrong number of bands")
|
||||
msg = "wrong number of bands"
|
||||
raise ValueError(msg)
|
||||
for band in bands[1:]:
|
||||
if band.mode != getmodetype(mode):
|
||||
raise ValueError("mode mismatch")
|
||||
msg = "mode mismatch"
|
||||
raise ValueError(msg)
|
||||
if band.size != bands[0].size:
|
||||
raise ValueError("size mismatch")
|
||||
msg = "size mismatch"
|
||||
raise ValueError(msg)
|
||||
for band in bands:
|
||||
band.load()
|
||||
return bands[0]._new(core.merge(mode, *[b.im for b in bands]))
|
||||
|
@ -3687,7 +3732,7 @@ class Exif(MutableMapping):
|
|||
def get_ifd(self, tag):
|
||||
if tag not in self._ifds:
|
||||
if tag == ExifTags.IFD.IFD1:
|
||||
if self._info is not None:
|
||||
if self._info is not None and self._info.next != 0:
|
||||
self._ifds[tag] = self._get_ifd_dict(self._info.next)
|
||||
elif tag in [ExifTags.IFD.Exif, ExifTags.IFD.GPSInfo]:
|
||||
offset = self._hidden_data.get(tag, self.get(tag))
|
||||
|
|
|
@ -124,7 +124,8 @@ def __getattr__(name):
|
|||
if name in enum.__members__:
|
||||
deprecate(f"{prefix}{name}", 10, f"{enum.__name__}.{name}")
|
||||
return enum[name]
|
||||
raise AttributeError(f"module '{__name__}' has no attribute '{name}'")
|
||||
msg = f"module '{__name__}' has no attribute '{name}'"
|
||||
raise AttributeError(msg)
|
||||
|
||||
|
||||
#
|
||||
|
@ -191,7 +192,8 @@ class ImageCmsProfile:
|
|||
elif isinstance(profile, _imagingcms.CmsProfile):
|
||||
self._set(profile)
|
||||
else:
|
||||
raise TypeError("Invalid type for Profile")
|
||||
msg = "Invalid type for Profile"
|
||||
raise TypeError(msg)
|
||||
|
||||
def _set(self, profile, filename=None):
|
||||
self.profile = profile
|
||||
|
@ -269,7 +271,8 @@ class ImageCmsTransform(Image.ImagePointHandler):
|
|||
def apply_in_place(self, im):
|
||||
im.load()
|
||||
if im.mode != self.output_mode:
|
||||
raise ValueError("mode mismatch") # wrong output mode
|
||||
msg = "mode mismatch"
|
||||
raise ValueError(msg) # wrong output mode
|
||||
self.transform.apply(im.im.id, im.im.id)
|
||||
im.info["icc_profile"] = self.output_profile.tobytes()
|
||||
return im
|
||||
|
@ -374,10 +377,12 @@ def profileToProfile(
|
|||
outputMode = im.mode
|
||||
|
||||
if not isinstance(renderingIntent, int) or not (0 <= renderingIntent <= 3):
|
||||
raise PyCMSError("renderingIntent must be an integer between 0 and 3")
|
||||
msg = "renderingIntent must be an integer between 0 and 3"
|
||||
raise PyCMSError(msg)
|
||||
|
||||
if not isinstance(flags, int) or not (0 <= flags <= _MAX_FLAG):
|
||||
raise PyCMSError(f"flags must be an integer between 0 and {_MAX_FLAG}")
|
||||
msg = f"flags must be an integer between 0 and {_MAX_FLAG}"
|
||||
raise PyCMSError(msg)
|
||||
|
||||
try:
|
||||
if not isinstance(inputProfile, ImageCmsProfile):
|
||||
|
@ -489,10 +494,12 @@ def buildTransform(
|
|||
"""
|
||||
|
||||
if not isinstance(renderingIntent, int) or not (0 <= renderingIntent <= 3):
|
||||
raise PyCMSError("renderingIntent must be an integer between 0 and 3")
|
||||
msg = "renderingIntent must be an integer between 0 and 3"
|
||||
raise PyCMSError(msg)
|
||||
|
||||
if not isinstance(flags, int) or not (0 <= flags <= _MAX_FLAG):
|
||||
raise PyCMSError("flags must be an integer between 0 and %s" + _MAX_FLAG)
|
||||
msg = "flags must be an integer between 0 and %s" + _MAX_FLAG
|
||||
raise PyCMSError(msg)
|
||||
|
||||
try:
|
||||
if not isinstance(inputProfile, ImageCmsProfile):
|
||||
|
@ -591,10 +598,12 @@ def buildProofTransform(
|
|||
"""
|
||||
|
||||
if not isinstance(renderingIntent, int) or not (0 <= renderingIntent <= 3):
|
||||
raise PyCMSError("renderingIntent must be an integer between 0 and 3")
|
||||
msg = "renderingIntent must be an integer between 0 and 3"
|
||||
raise PyCMSError(msg)
|
||||
|
||||
if not isinstance(flags, int) or not (0 <= flags <= _MAX_FLAG):
|
||||
raise PyCMSError("flags must be an integer between 0 and %s" + _MAX_FLAG)
|
||||
msg = "flags must be an integer between 0 and %s" + _MAX_FLAG
|
||||
raise PyCMSError(msg)
|
||||
|
||||
try:
|
||||
if not isinstance(inputProfile, ImageCmsProfile):
|
||||
|
@ -705,17 +714,17 @@ def createProfile(colorSpace, colorTemp=-1):
|
|||
"""
|
||||
|
||||
if colorSpace not in ["LAB", "XYZ", "sRGB"]:
|
||||
raise PyCMSError(
|
||||
msg = (
|
||||
f"Color space not supported for on-the-fly profile creation ({colorSpace})"
|
||||
)
|
||||
raise PyCMSError(msg)
|
||||
|
||||
if colorSpace == "LAB":
|
||||
try:
|
||||
colorTemp = float(colorTemp)
|
||||
except (TypeError, ValueError) as e:
|
||||
raise PyCMSError(
|
||||
f'Color temperature must be numeric, "{colorTemp}" not valid'
|
||||
) from e
|
||||
msg = f'Color temperature must be numeric, "{colorTemp}" not valid'
|
||||
raise PyCMSError(msg) from e
|
||||
|
||||
try:
|
||||
return core.createProfile(colorSpace, colorTemp)
|
||||
|
|
|
@ -33,7 +33,8 @@ def getrgb(color):
|
|||
:return: ``(red, green, blue[, alpha])``
|
||||
"""
|
||||
if len(color) > 100:
|
||||
raise ValueError("color specifier is too long")
|
||||
msg = "color specifier is too long"
|
||||
raise ValueError(msg)
|
||||
color = color.lower()
|
||||
|
||||
rgb = colormap.get(color, None)
|
||||
|
@ -115,7 +116,8 @@ def getrgb(color):
|
|||
m = re.match(r"rgba\(\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*\)$", color)
|
||||
if m:
|
||||
return int(m.group(1)), int(m.group(2)), int(m.group(3)), int(m.group(4))
|
||||
raise ValueError(f"unknown color specifier: {repr(color)}")
|
||||
msg = f"unknown color specifier: {repr(color)}"
|
||||
raise ValueError(msg)
|
||||
|
||||
|
||||
def getcolor(color, mode):
|
||||
|
|
|
@ -69,7 +69,8 @@ class ImageDraw:
|
|||
if mode == "RGBA" and im.mode == "RGB":
|
||||
blend = 1
|
||||
else:
|
||||
raise ValueError("mode mismatch")
|
||||
msg = "mode mismatch"
|
||||
raise ValueError(msg)
|
||||
if mode == "P":
|
||||
self.palette = im.palette
|
||||
else:
|
||||
|
@ -437,7 +438,8 @@ class ImageDraw:
|
|||
)
|
||||
|
||||
if embedded_color and self.mode not in ("RGB", "RGBA"):
|
||||
raise ValueError("Embedded color supported only in RGB and RGBA modes")
|
||||
msg = "Embedded color supported only in RGB and RGBA modes"
|
||||
raise ValueError(msg)
|
||||
|
||||
if font is None:
|
||||
font = self.getfont()
|
||||
|
@ -534,14 +536,17 @@ class ImageDraw:
|
|||
embedded_color=False,
|
||||
):
|
||||
if direction == "ttb":
|
||||
raise ValueError("ttb direction is unsupported for multiline text")
|
||||
msg = "ttb direction is unsupported for multiline text"
|
||||
raise ValueError(msg)
|
||||
|
||||
if anchor is None:
|
||||
anchor = "la"
|
||||
elif len(anchor) != 2:
|
||||
raise ValueError("anchor must be a 2 character string")
|
||||
msg = "anchor must be a 2 character string"
|
||||
raise ValueError(msg)
|
||||
elif anchor[1] in "tb":
|
||||
raise ValueError("anchor not supported for multiline text")
|
||||
msg = "anchor not supported for multiline text"
|
||||
raise ValueError(msg)
|
||||
|
||||
widths = []
|
||||
max_width = 0
|
||||
|
@ -578,7 +583,8 @@ class ImageDraw:
|
|||
elif align == "right":
|
||||
left += width_difference
|
||||
else:
|
||||
raise ValueError('align must be "left", "center" or "right"')
|
||||
msg = 'align must be "left", "center" or "right"'
|
||||
raise ValueError(msg)
|
||||
|
||||
self.text(
|
||||
(left, top),
|
||||
|
@ -672,9 +678,11 @@ class ImageDraw:
|
|||
):
|
||||
"""Get the length of a given string, in pixels with 1/64 precision."""
|
||||
if self._multiline_check(text):
|
||||
raise ValueError("can't measure length of multiline text")
|
||||
msg = "can't measure length of multiline text"
|
||||
raise ValueError(msg)
|
||||
if embedded_color and self.mode not in ("RGB", "RGBA"):
|
||||
raise ValueError("Embedded color supported only in RGB and RGBA modes")
|
||||
msg = "Embedded color supported only in RGB and RGBA modes"
|
||||
raise ValueError(msg)
|
||||
|
||||
if font is None:
|
||||
font = self.getfont()
|
||||
|
@ -712,7 +720,8 @@ class ImageDraw:
|
|||
):
|
||||
"""Get the bounding box of a given string, in pixels."""
|
||||
if embedded_color and self.mode not in ("RGB", "RGBA"):
|
||||
raise ValueError("Embedded color supported only in RGB and RGBA modes")
|
||||
msg = "Embedded color supported only in RGB and RGBA modes"
|
||||
raise ValueError(msg)
|
||||
|
||||
if self._multiline_check(text):
|
||||
return self.multiline_textbbox(
|
||||
|
@ -752,14 +761,17 @@ class ImageDraw:
|
|||
embedded_color=False,
|
||||
):
|
||||
if direction == "ttb":
|
||||
raise ValueError("ttb direction is unsupported for multiline text")
|
||||
msg = "ttb direction is unsupported for multiline text"
|
||||
raise ValueError(msg)
|
||||
|
||||
if anchor is None:
|
||||
anchor = "la"
|
||||
elif len(anchor) != 2:
|
||||
raise ValueError("anchor must be a 2 character string")
|
||||
msg = "anchor must be a 2 character string"
|
||||
raise ValueError(msg)
|
||||
elif anchor[1] in "tb":
|
||||
raise ValueError("anchor not supported for multiline text")
|
||||
msg = "anchor not supported for multiline text"
|
||||
raise ValueError(msg)
|
||||
|
||||
widths = []
|
||||
max_width = 0
|
||||
|
@ -803,7 +815,8 @@ class ImageDraw:
|
|||
elif align == "right":
|
||||
left += width_difference
|
||||
else:
|
||||
raise ValueError('align must be "left", "center" or "right"')
|
||||
msg = 'align must be "left", "center" or "right"'
|
||||
raise ValueError(msg)
|
||||
|
||||
bbox_line = self.textbbox(
|
||||
(left, top),
|
||||
|
@ -979,38 +992,44 @@ def _compute_regular_polygon_vertices(bounding_circle, n_sides, rotation):
|
|||
# 1. Error Handling
|
||||
# 1.1 Check `n_sides` has an appropriate value
|
||||
if not isinstance(n_sides, int):
|
||||
raise TypeError("n_sides should be an int")
|
||||
msg = "n_sides should be an int"
|
||||
raise TypeError(msg)
|
||||
if n_sides < 3:
|
||||
raise ValueError("n_sides should be an int > 2")
|
||||
msg = "n_sides should be an int > 2"
|
||||
raise ValueError(msg)
|
||||
|
||||
# 1.2 Check `bounding_circle` has an appropriate value
|
||||
if not isinstance(bounding_circle, (list, tuple)):
|
||||
raise TypeError("bounding_circle should be a tuple")
|
||||
msg = "bounding_circle should be a tuple"
|
||||
raise TypeError(msg)
|
||||
|
||||
if len(bounding_circle) == 3:
|
||||
*centroid, polygon_radius = bounding_circle
|
||||
elif len(bounding_circle) == 2:
|
||||
centroid, polygon_radius = bounding_circle
|
||||
else:
|
||||
raise ValueError(
|
||||
msg = (
|
||||
"bounding_circle should contain 2D coordinates "
|
||||
"and a radius (e.g. (x, y, r) or ((x, y), r) )"
|
||||
)
|
||||
raise ValueError(msg)
|
||||
|
||||
if not all(isinstance(i, (int, float)) for i in (*centroid, polygon_radius)):
|
||||
raise ValueError("bounding_circle should only contain numeric data")
|
||||
msg = "bounding_circle should only contain numeric data"
|
||||
raise ValueError(msg)
|
||||
|
||||
if not len(centroid) == 2:
|
||||
raise ValueError(
|
||||
"bounding_circle centre should contain 2D coordinates (e.g. (x, y))"
|
||||
)
|
||||
msg = "bounding_circle centre should contain 2D coordinates (e.g. (x, y))"
|
||||
raise ValueError(msg)
|
||||
|
||||
if polygon_radius <= 0:
|
||||
raise ValueError("bounding_circle radius should be > 0")
|
||||
msg = "bounding_circle radius should be > 0"
|
||||
raise ValueError(msg)
|
||||
|
||||
# 1.3 Check `rotation` has an appropriate value
|
||||
if not isinstance(rotation, (int, float)):
|
||||
raise ValueError("rotation should be an int or float")
|
||||
msg = "rotation should be an int or float"
|
||||
raise ValueError(msg)
|
||||
|
||||
# 2. Define Helper Functions
|
||||
def _apply_rotation(point, degrees, centroid):
|
||||
|
|
|
@ -63,12 +63,13 @@ Dict of known error codes returned from :meth:`.PyDecoder.decode`,
|
|||
|
||||
def raise_oserror(error):
|
||||
try:
|
||||
message = Image.core.getcodecstatus(error)
|
||||
msg = Image.core.getcodecstatus(error)
|
||||
except AttributeError:
|
||||
message = ERRORS.get(error)
|
||||
if not message:
|
||||
message = f"decoder error {error}"
|
||||
raise OSError(message + " when reading image file")
|
||||
msg = ERRORS.get(error)
|
||||
if not msg:
|
||||
msg = f"decoder error {error}"
|
||||
msg += " when reading image file"
|
||||
raise OSError(msg)
|
||||
|
||||
|
||||
def _tilesort(t):
|
||||
|
@ -124,7 +125,8 @@ class ImageFile(Image.Image):
|
|||
raise SyntaxError(v) from v
|
||||
|
||||
if not self.mode or self.size[0] <= 0 or self.size[1] <= 0:
|
||||
raise SyntaxError("not identified by this driver")
|
||||
msg = "not identified by this driver"
|
||||
raise SyntaxError(msg)
|
||||
except BaseException:
|
||||
# close the file only if we have opened it this constructor
|
||||
if self._exclusive_fp:
|
||||
|
@ -154,7 +156,8 @@ class ImageFile(Image.Image):
|
|||
"""Load image data based on tile list"""
|
||||
|
||||
if self.tile is None:
|
||||
raise OSError("cannot load this image")
|
||||
msg = "cannot load this image"
|
||||
raise OSError(msg)
|
||||
|
||||
pixel = Image.Image.load(self)
|
||||
if not self.tile:
|
||||
|
@ -249,16 +252,18 @@ class ImageFile(Image.Image):
|
|||
if LOAD_TRUNCATED_IMAGES:
|
||||
break
|
||||
else:
|
||||
raise OSError("image file is truncated") from e
|
||||
msg = "image file is truncated"
|
||||
raise OSError(msg) from e
|
||||
|
||||
if not s: # truncated jpeg
|
||||
if LOAD_TRUNCATED_IMAGES:
|
||||
break
|
||||
else:
|
||||
raise OSError(
|
||||
msg = (
|
||||
"image file is truncated "
|
||||
f"({len(b)} bytes not processed)"
|
||||
)
|
||||
raise OSError(msg)
|
||||
|
||||
b = b + s
|
||||
n, err_code = decoder.decode(b)
|
||||
|
@ -314,7 +319,8 @@ class ImageFile(Image.Image):
|
|||
and frame >= self.n_frames + self._min_frame
|
||||
)
|
||||
):
|
||||
raise EOFError("attempt to seek outside sequence")
|
||||
msg = "attempt to seek outside sequence"
|
||||
raise EOFError(msg)
|
||||
|
||||
return self.tell() != frame
|
||||
|
||||
|
@ -328,12 +334,14 @@ class StubImageFile(ImageFile):
|
|||
"""
|
||||
|
||||
def _open(self):
|
||||
raise NotImplementedError("StubImageFile subclass must implement _open")
|
||||
msg = "StubImageFile subclass must implement _open"
|
||||
raise NotImplementedError(msg)
|
||||
|
||||
def load(self):
|
||||
loader = self._load()
|
||||
if loader is None:
|
||||
raise OSError(f"cannot find loader for this {self.format} file")
|
||||
msg = f"cannot find loader for this {self.format} file"
|
||||
raise OSError(msg)
|
||||
image = loader.load(self)
|
||||
assert image is not None
|
||||
# become the other object (!)
|
||||
|
@ -343,7 +351,8 @@ class StubImageFile(ImageFile):
|
|||
|
||||
def _load(self):
|
||||
"""(Hook) Find actual image loader."""
|
||||
raise NotImplementedError("StubImageFile subclass must implement _load")
|
||||
msg = "StubImageFile subclass must implement _load"
|
||||
raise NotImplementedError(msg)
|
||||
|
||||
|
||||
class Parser:
|
||||
|
@ -468,9 +477,11 @@ class Parser:
|
|||
self.feed(b"")
|
||||
self.data = self.decoder = None
|
||||
if not self.finished:
|
||||
raise OSError("image was incomplete")
|
||||
msg = "image was incomplete"
|
||||
raise OSError(msg)
|
||||
if not self.image:
|
||||
raise OSError("cannot parse this image")
|
||||
msg = "cannot parse this image"
|
||||
raise OSError(msg)
|
||||
if self.data:
|
||||
# incremental parsing not possible; reopen the file
|
||||
# not that we have all data
|
||||
|
@ -535,7 +546,8 @@ def _encode_tile(im, fp, tile, bufsize, fh, exc=None):
|
|||
# slight speedup: compress to real file object
|
||||
s = encoder.encode_to_file(fh, bufsize)
|
||||
if s < 0:
|
||||
raise OSError(f"encoder error {s} when writing image file") from exc
|
||||
msg = f"encoder error {s} when writing image file"
|
||||
raise OSError(msg) from exc
|
||||
finally:
|
||||
encoder.cleanup()
|
||||
|
||||
|
@ -558,7 +570,8 @@ def _safe_read(fp, size):
|
|||
if size <= SAFEBLOCK:
|
||||
data = fp.read(size)
|
||||
if len(data) < size:
|
||||
raise OSError("Truncated File Read")
|
||||
msg = "Truncated File Read"
|
||||
raise OSError(msg)
|
||||
return data
|
||||
data = []
|
||||
remaining_size = size
|
||||
|
@ -569,7 +582,8 @@ def _safe_read(fp, size):
|
|||
data.append(block)
|
||||
remaining_size -= len(block)
|
||||
if sum(len(d) for d in data) < size:
|
||||
raise OSError("Truncated File Read")
|
||||
msg = "Truncated File Read"
|
||||
raise OSError(msg)
|
||||
return b"".join(data)
|
||||
|
||||
|
||||
|
@ -645,13 +659,15 @@ class PyCodec:
|
|||
self.state.ysize = y1 - y0
|
||||
|
||||
if self.state.xsize <= 0 or self.state.ysize <= 0:
|
||||
raise ValueError("Size cannot be negative")
|
||||
msg = "Size cannot be negative"
|
||||
raise ValueError(msg)
|
||||
|
||||
if (
|
||||
self.state.xsize + self.state.xoff > self.im.size[0]
|
||||
or self.state.ysize + self.state.yoff > self.im.size[1]
|
||||
):
|
||||
raise ValueError("Tile cannot extend outside image")
|
||||
msg = "Tile cannot extend outside image"
|
||||
raise ValueError(msg)
|
||||
|
||||
|
||||
class PyDecoder(PyCodec):
|
||||
|
@ -696,9 +712,11 @@ class PyDecoder(PyCodec):
|
|||
s = d.decode(data)
|
||||
|
||||
if s[0] >= 0:
|
||||
raise ValueError("not enough image data")
|
||||
msg = "not enough image data"
|
||||
raise ValueError(msg)
|
||||
if s[1] != 0:
|
||||
raise ValueError("cannot decode image data")
|
||||
msg = "cannot decode image data"
|
||||
raise ValueError(msg)
|
||||
|
||||
|
||||
class PyEncoder(PyCodec):
|
||||
|
|
|
@ -28,7 +28,8 @@ class MultibandFilter(Filter):
|
|||
class BuiltinFilter(MultibandFilter):
|
||||
def filter(self, image):
|
||||
if image.mode == "P":
|
||||
raise ValueError("cannot filter palette images")
|
||||
msg = "cannot filter palette images"
|
||||
raise ValueError(msg)
|
||||
return image.filter(*self.filterargs)
|
||||
|
||||
|
||||
|
@ -57,7 +58,8 @@ class Kernel(BuiltinFilter):
|
|||
# default scale is sum of kernel
|
||||
scale = functools.reduce(lambda a, b: a + b, kernel)
|
||||
if size[0] * size[1] != len(kernel):
|
||||
raise ValueError("not enough coefficients in kernel")
|
||||
msg = "not enough coefficients in kernel"
|
||||
raise ValueError(msg)
|
||||
self.filterargs = size, scale, offset, kernel
|
||||
|
||||
|
||||
|
@ -80,7 +82,8 @@ class RankFilter(Filter):
|
|||
|
||||
def filter(self, image):
|
||||
if image.mode == "P":
|
||||
raise ValueError("cannot filter palette images")
|
||||
msg = "cannot filter palette images"
|
||||
raise ValueError(msg)
|
||||
image = image.expand(self.size // 2, self.size // 2)
|
||||
return image.rankfilter(self.size, self.rank)
|
||||
|
||||
|
@ -355,7 +358,8 @@ class Color3DLUT(MultibandFilter):
|
|||
|
||||
def __init__(self, size, table, channels=3, target_mode=None, **kwargs):
|
||||
if channels not in (3, 4):
|
||||
raise ValueError("Only 3 or 4 output channels are supported")
|
||||
msg = "Only 3 or 4 output channels are supported"
|
||||
raise ValueError(msg)
|
||||
self.size = size = self._check_size(size)
|
||||
self.channels = channels
|
||||
self.mode = target_mode
|
||||
|
@ -395,19 +399,21 @@ class Color3DLUT(MultibandFilter):
|
|||
table, raw_table = [], table
|
||||
for pixel in raw_table:
|
||||
if len(pixel) != channels:
|
||||
raise ValueError(
|
||||
msg = (
|
||||
"The elements of the table should "
|
||||
"have a length of {}.".format(channels)
|
||||
f"have a length of {channels}."
|
||||
)
|
||||
raise ValueError(msg)
|
||||
table.extend(pixel)
|
||||
|
||||
if wrong_size or len(table) != items * channels:
|
||||
raise ValueError(
|
||||
msg = (
|
||||
"The table should have either channels * size**3 float items "
|
||||
"or size**3 items of channels-sized tuples with floats. "
|
||||
f"Table should be: {channels}x{size[0]}x{size[1]}x{size[2]}. "
|
||||
f"Actual length: {len(table)}"
|
||||
)
|
||||
raise ValueError(msg)
|
||||
self.table = table
|
||||
|
||||
@staticmethod
|
||||
|
@ -415,15 +421,15 @@ class Color3DLUT(MultibandFilter):
|
|||
try:
|
||||
_, _, _ = size
|
||||
except ValueError as e:
|
||||
raise ValueError(
|
||||
"Size should be either an integer or a tuple of three integers."
|
||||
) from e
|
||||
msg = "Size should be either an integer or a tuple of three integers."
|
||||
raise ValueError(msg) from e
|
||||
except TypeError:
|
||||
size = (size, size, size)
|
||||
size = [int(x) for x in size]
|
||||
for size_1d in size:
|
||||
if not 2 <= size_1d <= 65:
|
||||
raise ValueError("Size should be in [2, 65] range.")
|
||||
msg = "Size should be in [2, 65] range."
|
||||
raise ValueError(msg)
|
||||
return size
|
||||
|
||||
@classmethod
|
||||
|
@ -441,7 +447,8 @@ class Color3DLUT(MultibandFilter):
|
|||
"""
|
||||
size_1d, size_2d, size_3d = cls._check_size(size)
|
||||
if channels not in (3, 4):
|
||||
raise ValueError("Only 3 or 4 output channels are supported")
|
||||
msg = "Only 3 or 4 output channels are supported"
|
||||
raise ValueError(msg)
|
||||
|
||||
table = [0] * (size_1d * size_2d * size_3d * channels)
|
||||
idx_out = 0
|
||||
|
@ -481,7 +488,8 @@ class Color3DLUT(MultibandFilter):
|
|||
lookup table.
|
||||
"""
|
||||
if channels not in (None, 3, 4):
|
||||
raise ValueError("Only 3 or 4 output channels are supported")
|
||||
msg = "Only 3 or 4 output channels are supported"
|
||||
raise ValueError(msg)
|
||||
ch_in = self.channels
|
||||
ch_out = channels or ch_in
|
||||
size_1d, size_2d, size_3d = self.size
|
||||
|
|
|
@ -50,13 +50,15 @@ def __getattr__(name):
|
|||
if name in enum.__members__:
|
||||
deprecate(f"{prefix}{name}", 10, f"{enum.__name__}.{name}")
|
||||
return enum[name]
|
||||
raise AttributeError(f"module '{__name__}' has no attribute '{name}'")
|
||||
msg = f"module '{__name__}' has no attribute '{name}'"
|
||||
raise AttributeError(msg)
|
||||
|
||||
|
||||
class _ImagingFtNotInstalled:
|
||||
# module placeholder
|
||||
def __getattr__(self, id):
|
||||
raise ImportError("The _imagingft C module is not installed")
|
||||
msg = "The _imagingft C module is not installed"
|
||||
raise ImportError(msg)
|
||||
|
||||
|
||||
try:
|
||||
|
@ -105,7 +107,8 @@ class ImageFont:
|
|||
else:
|
||||
if image:
|
||||
image.close()
|
||||
raise OSError("cannot find glyph data file")
|
||||
msg = "cannot find glyph data file"
|
||||
raise OSError(msg)
|
||||
|
||||
self.file = fullname
|
||||
|
||||
|
@ -116,7 +119,8 @@ class ImageFont:
|
|||
|
||||
# read PILfont header
|
||||
if file.readline() != b"PILfont\n":
|
||||
raise SyntaxError("Not a PILfont file")
|
||||
msg = "Not a PILfont file"
|
||||
raise SyntaxError(msg)
|
||||
file.readline().split(b";")
|
||||
self.info = [] # FIXME: should be a dictionary
|
||||
while True:
|
||||
|
@ -130,7 +134,8 @@ class ImageFont:
|
|||
|
||||
# check image
|
||||
if image.mode not in ("1", "L"):
|
||||
raise TypeError("invalid font image mode")
|
||||
msg = "invalid font image mode"
|
||||
raise TypeError(msg)
|
||||
|
||||
image.load()
|
||||
|
||||
|
@ -817,7 +822,8 @@ class FreeTypeFont:
|
|||
try:
|
||||
names = self.font.getvarnames()
|
||||
except AttributeError as e:
|
||||
raise NotImplementedError("FreeType 2.9.1 or greater is required") from e
|
||||
msg = "FreeType 2.9.1 or greater is required"
|
||||
raise NotImplementedError(msg) from e
|
||||
return [name.replace(b"\x00", b"") for name in names]
|
||||
|
||||
def set_variation_by_name(self, name):
|
||||
|
@ -847,7 +853,8 @@ class FreeTypeFont:
|
|||
try:
|
||||
axes = self.font.getvaraxes()
|
||||
except AttributeError as e:
|
||||
raise NotImplementedError("FreeType 2.9.1 or greater is required") from e
|
||||
msg = "FreeType 2.9.1 or greater is required"
|
||||
raise NotImplementedError(msg) from e
|
||||
for axis in axes:
|
||||
axis["name"] = axis["name"].replace(b"\x00", b"")
|
||||
return axes
|
||||
|
@ -860,7 +867,8 @@ class FreeTypeFont:
|
|||
try:
|
||||
self.font.setvaraxes(axes)
|
||||
except AttributeError as e:
|
||||
raise NotImplementedError("FreeType 2.9.1 or greater is required") from e
|
||||
msg = "FreeType 2.9.1 or greater is required"
|
||||
raise NotImplementedError(msg) from e
|
||||
|
||||
|
||||
class TransposedFont:
|
||||
|
@ -914,9 +922,8 @@ class TransposedFont:
|
|||
|
||||
def getlength(self, text, *args, **kwargs):
|
||||
if self.orientation in (Image.Transpose.ROTATE_90, Image.Transpose.ROTATE_270):
|
||||
raise ValueError(
|
||||
"text length is undefined for text rotated by 90 or 270 degrees"
|
||||
)
|
||||
msg = "text length is undefined for text rotated by 90 or 270 degrees"
|
||||
raise ValueError(msg)
|
||||
return self.font.getlength(text, *args, **kwargs)
|
||||
|
||||
|
||||
|
@ -1061,7 +1068,8 @@ def load_path(filename):
|
|||
return load(os.path.join(directory, filename))
|
||||
except OSError:
|
||||
pass
|
||||
raise OSError("cannot find font file")
|
||||
msg = "cannot find font file"
|
||||
raise OSError(msg)
|
||||
|
||||
|
||||
def load_default():
|
||||
|
|
|
@ -75,7 +75,8 @@ def grab(bbox=None, include_layered_windows=False, all_screens=False, xdisplay=N
|
|||
return im
|
||||
# use xdisplay=None for default display on non-win32/macOS systems
|
||||
if not Image.core.HAVE_XCB:
|
||||
raise OSError("Pillow was built without XCB support")
|
||||
msg = "Pillow was built without XCB support"
|
||||
raise OSError(msg)
|
||||
size, data = Image.core.grabscreen_x11(xdisplay)
|
||||
im = Image.frombytes("RGB", size, data, "raw", "BGRX", size[0] * 4, 1)
|
||||
if bbox:
|
||||
|
@ -132,4 +133,17 @@ def grabclipboard():
|
|||
return BmpImagePlugin.DibImageFile(data)
|
||||
return None
|
||||
else:
|
||||
raise NotImplementedError("ImageGrab.grabclipboard() is macOS and Windows only")
|
||||
if shutil.which("wl-paste"):
|
||||
args = ["wl-paste"]
|
||||
elif shutil.which("xclip"):
|
||||
args = ["xclip", "-selection", "clipboard", "-t", "image/png", "-o"]
|
||||
else:
|
||||
msg = "wl-paste or xclip is required for ImageGrab.grabclipboard() on Linux"
|
||||
raise NotImplementedError(msg)
|
||||
fh, filepath = tempfile.mkstemp()
|
||||
subprocess.call(args, stdout=fh)
|
||||
os.close(fh)
|
||||
im = Image.open(filepath)
|
||||
im.load()
|
||||
os.unlink(filepath)
|
||||
return im
|
||||
|
|
|
@ -39,7 +39,8 @@ class _Operand:
|
|||
elif im1.im.mode in ("I", "F"):
|
||||
return im1.im
|
||||
else:
|
||||
raise ValueError(f"unsupported mode: {im1.im.mode}")
|
||||
msg = f"unsupported mode: {im1.im.mode}"
|
||||
raise ValueError(msg)
|
||||
else:
|
||||
# argument was a constant
|
||||
if _isconstant(im1) and self.im.mode in ("1", "L", "I"):
|
||||
|
@ -56,7 +57,8 @@ class _Operand:
|
|||
try:
|
||||
op = getattr(_imagingmath, op + "_" + im1.mode)
|
||||
except AttributeError as e:
|
||||
raise TypeError(f"bad operand type for '{op}'") from e
|
||||
msg = f"bad operand type for '{op}'"
|
||||
raise TypeError(msg) from e
|
||||
_imagingmath.unop(op, out.im.id, im1.im.id)
|
||||
else:
|
||||
# binary operation
|
||||
|
@ -80,7 +82,8 @@ class _Operand:
|
|||
try:
|
||||
op = getattr(_imagingmath, op + "_" + im1.mode)
|
||||
except AttributeError as e:
|
||||
raise TypeError(f"bad operand type for '{op}'") from e
|
||||
msg = f"bad operand type for '{op}'"
|
||||
raise TypeError(msg) from e
|
||||
_imagingmath.binop(op, out.im.id, im1.im.id, im2.im.id)
|
||||
return _Operand(out)
|
||||
|
||||
|
@ -249,7 +252,8 @@ def eval(expression, _dict={}, **kw):
|
|||
|
||||
for name in code.co_names:
|
||||
if name not in args and name != "abs":
|
||||
raise ValueError(f"'{name}' not allowed")
|
||||
msg = f"'{name}' not allowed"
|
||||
raise ValueError(msg)
|
||||
|
||||
scan(compiled_code)
|
||||
out = builtins.eval(expression, {"__builtins": {"abs": abs}}, args)
|
||||
|
|
|
@ -81,7 +81,8 @@ class LutBuilder:
|
|||
],
|
||||
}
|
||||
if op_name not in known_patterns:
|
||||
raise Exception("Unknown pattern " + op_name + "!")
|
||||
msg = "Unknown pattern " + op_name + "!"
|
||||
raise Exception(msg)
|
||||
|
||||
self.patterns = known_patterns[op_name]
|
||||
|
||||
|
@ -145,7 +146,8 @@ class LutBuilder:
|
|||
for p in self.patterns:
|
||||
m = re.search(r"(\w*):?\s*\((.+?)\)\s*->\s*(\d)", p.replace("\n", ""))
|
||||
if not m:
|
||||
raise Exception('Syntax error in pattern "' + p + '"')
|
||||
msg = 'Syntax error in pattern "' + p + '"'
|
||||
raise Exception(msg)
|
||||
options = m.group(1)
|
||||
pattern = m.group(2)
|
||||
result = int(m.group(3))
|
||||
|
@ -193,10 +195,12 @@ class MorphOp:
|
|||
Returns a tuple of the number of changed pixels and the
|
||||
morphed image"""
|
||||
if self.lut is None:
|
||||
raise Exception("No operator loaded")
|
||||
msg = "No operator loaded"
|
||||
raise Exception(msg)
|
||||
|
||||
if image.mode != "L":
|
||||
raise ValueError("Image mode must be L")
|
||||
msg = "Image mode must be L"
|
||||
raise ValueError(msg)
|
||||
outimage = Image.new(image.mode, image.size, None)
|
||||
count = _imagingmorph.apply(bytes(self.lut), image.im.id, outimage.im.id)
|
||||
return count, outimage
|
||||
|
@ -208,10 +212,12 @@ class MorphOp:
|
|||
Returns a list of tuples of (x,y) coordinates
|
||||
of all matching pixels. See :ref:`coordinate-system`."""
|
||||
if self.lut is None:
|
||||
raise Exception("No operator loaded")
|
||||
msg = "No operator loaded"
|
||||
raise Exception(msg)
|
||||
|
||||
if image.mode != "L":
|
||||
raise ValueError("Image mode must be L")
|
||||
msg = "Image mode must be L"
|
||||
raise ValueError(msg)
|
||||
return _imagingmorph.match(bytes(self.lut), image.im.id)
|
||||
|
||||
def get_on_pixels(self, image):
|
||||
|
@ -221,7 +227,8 @@ class MorphOp:
|
|||
of all matching pixels. See :ref:`coordinate-system`."""
|
||||
|
||||
if image.mode != "L":
|
||||
raise ValueError("Image mode must be L")
|
||||
msg = "Image mode must be L"
|
||||
raise ValueError(msg)
|
||||
return _imagingmorph.get_on_pixels(image.im.id)
|
||||
|
||||
def load_lut(self, filename):
|
||||
|
@ -231,12 +238,14 @@ class MorphOp:
|
|||
|
||||
if len(self.lut) != LUT_SIZE:
|
||||
self.lut = None
|
||||
raise Exception("Wrong size operator file!")
|
||||
msg = "Wrong size operator file!"
|
||||
raise Exception(msg)
|
||||
|
||||
def save_lut(self, filename):
|
||||
"""Save an operator to an mrl file"""
|
||||
if self.lut is None:
|
||||
raise Exception("No operator loaded")
|
||||
msg = "No operator loaded"
|
||||
raise Exception(msg)
|
||||
with open(filename, "wb") as f:
|
||||
f.write(self.lut)
|
||||
|
||||
|
|
|
@ -49,13 +49,15 @@ def _color(color, mode):
|
|||
def _lut(image, lut):
|
||||
if image.mode == "P":
|
||||
# FIXME: apply to lookup table, not image data
|
||||
raise NotImplementedError("mode P support coming soon")
|
||||
msg = "mode P support coming soon"
|
||||
raise NotImplementedError(msg)
|
||||
elif image.mode in ("L", "RGB"):
|
||||
if image.mode == "RGB" and len(lut) == 256:
|
||||
lut = lut + lut + lut
|
||||
return image.point(lut)
|
||||
else:
|
||||
raise OSError("not supported for this image mode")
|
||||
msg = "not supported for this image mode"
|
||||
raise OSError(msg)
|
||||
|
||||
|
||||
#
|
||||
|
@ -332,7 +334,8 @@ def scale(image, factor, resample=Image.Resampling.BICUBIC):
|
|||
if factor == 1:
|
||||
return image.copy()
|
||||
elif factor <= 0:
|
||||
raise ValueError("the factor must be greater than 0")
|
||||
msg = "the factor must be greater than 0"
|
||||
raise ValueError(msg)
|
||||
else:
|
||||
size = (round(factor * image.width), round(factor * image.height))
|
||||
return image.resize(size, resample)
|
||||
|
|
|
@ -42,7 +42,8 @@ class ImagePalette:
|
|||
if size != 0:
|
||||
deprecate("The size parameter", 10, None)
|
||||
if size != len(self.palette):
|
||||
raise ValueError("wrong palette size")
|
||||
msg = "wrong palette size"
|
||||
raise ValueError(msg)
|
||||
|
||||
@property
|
||||
def palette(self):
|
||||
|
@ -97,7 +98,8 @@ class ImagePalette:
|
|||
.. warning:: This method is experimental.
|
||||
"""
|
||||
if self.rawmode:
|
||||
raise ValueError("palette contains raw palette data")
|
||||
msg = "palette contains raw palette data"
|
||||
raise ValueError(msg)
|
||||
if isinstance(self.palette, bytes):
|
||||
return self.palette
|
||||
arr = array.array("B", self.palette)
|
||||
|
@ -112,14 +114,14 @@ class ImagePalette:
|
|||
.. warning:: This method is experimental.
|
||||
"""
|
||||
if self.rawmode:
|
||||
raise ValueError("palette contains raw palette data")
|
||||
msg = "palette contains raw palette data"
|
||||
raise ValueError(msg)
|
||||
if isinstance(color, tuple):
|
||||
if self.mode == "RGB":
|
||||
if len(color) == 4:
|
||||
if color[3] != 255:
|
||||
raise ValueError(
|
||||
"cannot add non-opaque RGBA color to RGB palette"
|
||||
)
|
||||
msg = "cannot add non-opaque RGBA color to RGB palette"
|
||||
raise ValueError(msg)
|
||||
color = color[:3]
|
||||
elif self.mode == "RGBA":
|
||||
if len(color) == 3:
|
||||
|
@ -147,7 +149,8 @@ class ImagePalette:
|
|||
index = i
|
||||
break
|
||||
if index >= 256:
|
||||
raise ValueError("cannot allocate more than 256 colors") from e
|
||||
msg = "cannot allocate more than 256 colors"
|
||||
raise ValueError(msg) from e
|
||||
self.colors[color] = index
|
||||
if index * 3 < len(self.palette):
|
||||
self._palette = (
|
||||
|
@ -160,7 +163,8 @@ class ImagePalette:
|
|||
self.dirty = 1
|
||||
return index
|
||||
else:
|
||||
raise ValueError(f"unknown color specifier: {repr(color)}")
|
||||
msg = f"unknown color specifier: {repr(color)}"
|
||||
raise ValueError(msg)
|
||||
|
||||
def save(self, fp):
|
||||
"""Save palette to text file.
|
||||
|
@ -168,7 +172,8 @@ class ImagePalette:
|
|||
.. warning:: This method is experimental.
|
||||
"""
|
||||
if self.rawmode:
|
||||
raise ValueError("palette contains raw palette data")
|
||||
msg = "palette contains raw palette data"
|
||||
raise ValueError(msg)
|
||||
if isinstance(fp, str):
|
||||
fp = open(fp, "w")
|
||||
fp.write("# Palette\n")
|
||||
|
@ -263,6 +268,7 @@ def load(filename):
|
|||
# traceback.print_exc()
|
||||
pass
|
||||
else:
|
||||
raise OSError("cannot load palette")
|
||||
msg = "cannot load palette"
|
||||
raise OSError(msg)
|
||||
|
||||
return lut # data, rawmode
|
||||
|
|
|
@ -179,7 +179,8 @@ def _toqclass_helper(im):
|
|||
else:
|
||||
if exclusive_fp:
|
||||
im.close()
|
||||
raise ValueError(f"unsupported image mode {repr(im.mode)}")
|
||||
msg = f"unsupported image mode {repr(im.mode)}"
|
||||
raise ValueError(msg)
|
||||
|
||||
size = im.size
|
||||
__data = data or align8to32(im.tobytes(), size[0], im.mode)
|
||||
|
|
|
@ -30,7 +30,8 @@ class Iterator:
|
|||
|
||||
def __init__(self, im):
|
||||
if not hasattr(im, "seek"):
|
||||
raise AttributeError("im must have seek method")
|
||||
msg = "im must have seek method"
|
||||
raise AttributeError(msg)
|
||||
self.im = im
|
||||
self.position = getattr(self.im, "_min_frame", 0)
|
||||
|
||||
|
|
|
@ -124,7 +124,8 @@ class Viewer:
|
|||
deprecate("The 'file' argument", 10, "'path'")
|
||||
path = options.pop("file")
|
||||
else:
|
||||
raise TypeError("Missing required argument: 'path'")
|
||||
msg = "Missing required argument: 'path'"
|
||||
raise TypeError(msg)
|
||||
os.system(self.get_command(path, **options)) # nosec
|
||||
return 1
|
||||
|
||||
|
@ -176,7 +177,8 @@ class MacViewer(Viewer):
|
|||
deprecate("The 'file' argument", 10, "'path'")
|
||||
path = options.pop("file")
|
||||
else:
|
||||
raise TypeError("Missing required argument: 'path'")
|
||||
msg = "Missing required argument: 'path'"
|
||||
raise TypeError(msg)
|
||||
subprocess.call(["open", "-a", "Preview.app", path])
|
||||
executable = sys.executable or shutil.which("python3")
|
||||
if executable:
|
||||
|
@ -226,7 +228,8 @@ class XDGViewer(UnixViewer):
|
|||
deprecate("The 'file' argument", 10, "'path'")
|
||||
path = options.pop("file")
|
||||
else:
|
||||
raise TypeError("Missing required argument: 'path'")
|
||||
msg = "Missing required argument: 'path'"
|
||||
raise TypeError(msg)
|
||||
subprocess.Popen(["xdg-open", path])
|
||||
return 1
|
||||
|
||||
|
@ -255,7 +258,8 @@ class DisplayViewer(UnixViewer):
|
|||
deprecate("The 'file' argument", 10, "'path'")
|
||||
path = options.pop("file")
|
||||
else:
|
||||
raise TypeError("Missing required argument: 'path'")
|
||||
msg = "Missing required argument: 'path'"
|
||||
raise TypeError(msg)
|
||||
args = ["display"]
|
||||
title = options.get("title")
|
||||
if title:
|
||||
|
@ -286,7 +290,8 @@ class GmDisplayViewer(UnixViewer):
|
|||
deprecate("The 'file' argument", 10, "'path'")
|
||||
path = options.pop("file")
|
||||
else:
|
||||
raise TypeError("Missing required argument: 'path'")
|
||||
msg = "Missing required argument: 'path'"
|
||||
raise TypeError(msg)
|
||||
subprocess.Popen(["gm", "display", path])
|
||||
return 1
|
||||
|
||||
|
@ -311,7 +316,8 @@ class EogViewer(UnixViewer):
|
|||
deprecate("The 'file' argument", 10, "'path'")
|
||||
path = options.pop("file")
|
||||
else:
|
||||
raise TypeError("Missing required argument: 'path'")
|
||||
msg = "Missing required argument: 'path'"
|
||||
raise TypeError(msg)
|
||||
subprocess.Popen(["eog", "-n", path])
|
||||
return 1
|
||||
|
||||
|
@ -342,7 +348,8 @@ class XVViewer(UnixViewer):
|
|||
deprecate("The 'file' argument", 10, "'path'")
|
||||
path = options.pop("file")
|
||||
else:
|
||||
raise TypeError("Missing required argument: 'path'")
|
||||
msg = "Missing required argument: 'path'"
|
||||
raise TypeError(msg)
|
||||
args = ["xv"]
|
||||
title = options.get("title")
|
||||
if title:
|
||||
|
|
|
@ -36,7 +36,8 @@ class Stat:
|
|||
except AttributeError:
|
||||
self.h = image_or_list # assume it to be a histogram list
|
||||
if not isinstance(self.h, list):
|
||||
raise TypeError("first argument must be image or list")
|
||||
msg = "first argument must be image or list"
|
||||
raise TypeError(msg)
|
||||
self.bands = list(range(len(self.h) // 256))
|
||||
|
||||
def __getattr__(self, id):
|
||||
|
|
|
@ -284,7 +284,8 @@ def _show(image, title):
|
|||
super().__init__(master, image=self.image, bg="black", bd=0)
|
||||
|
||||
if not tkinter._default_root:
|
||||
raise OSError("tkinter not initialized")
|
||||
msg = "tkinter not initialized"
|
||||
raise OSError(msg)
|
||||
top = tkinter.Toplevel()
|
||||
if title:
|
||||
top.title(title)
|
||||
|
|
|
@ -41,7 +41,8 @@ class ImtImageFile(ImageFile.ImageFile):
|
|||
|
||||
buffer = self.fp.read(100)
|
||||
if b"\n" not in buffer:
|
||||
raise SyntaxError("not an IM file")
|
||||
msg = "not an IM file"
|
||||
raise SyntaxError(msg)
|
||||
|
||||
xsize = ysize = 0
|
||||
|
||||
|
|
|
@ -66,12 +66,14 @@ class IptcImageFile(ImageFile.ImageFile):
|
|||
|
||||
# syntax
|
||||
if s[0] != 0x1C or tag[0] < 1 or tag[0] > 9:
|
||||
raise SyntaxError("invalid IPTC/NAA file")
|
||||
msg = "invalid IPTC/NAA file"
|
||||
raise SyntaxError(msg)
|
||||
|
||||
# field size
|
||||
size = s[3]
|
||||
if size > 132:
|
||||
raise OSError("illegal field length in IPTC/NAA file")
|
||||
msg = "illegal field length in IPTC/NAA file"
|
||||
raise OSError(msg)
|
||||
elif size == 128:
|
||||
size = 0
|
||||
elif size > 128:
|
||||
|
@ -122,7 +124,8 @@ class IptcImageFile(ImageFile.ImageFile):
|
|||
try:
|
||||
compression = COMPRESSION[self.getint((3, 120))]
|
||||
except KeyError as e:
|
||||
raise OSError("Unknown IPTC image compression") from e
|
||||
msg = "Unknown IPTC image compression"
|
||||
raise OSError(msg) from e
|
||||
|
||||
# tile
|
||||
if tag == (8, 10):
|
||||
|
|
|
@ -44,13 +44,13 @@ class BoxReader:
|
|||
|
||||
def _read_bytes(self, num_bytes):
|
||||
if not self._can_read(num_bytes):
|
||||
raise SyntaxError("Not enough data in header")
|
||||
msg = "Not enough data in header"
|
||||
raise SyntaxError(msg)
|
||||
|
||||
data = self.fp.read(num_bytes)
|
||||
if len(data) < num_bytes:
|
||||
raise OSError(
|
||||
f"Expected to read {num_bytes} bytes but only got {len(data)}."
|
||||
)
|
||||
msg = f"Expected to read {num_bytes} bytes but only got {len(data)}."
|
||||
raise OSError(msg)
|
||||
|
||||
if self.remaining_in_box > 0:
|
||||
self.remaining_in_box -= num_bytes
|
||||
|
@ -87,7 +87,8 @@ class BoxReader:
|
|||
hlen = 8
|
||||
|
||||
if lbox < hlen or not self._can_read(lbox - hlen):
|
||||
raise SyntaxError("Invalid header length")
|
||||
msg = "Invalid header length"
|
||||
raise SyntaxError(msg)
|
||||
|
||||
self.remaining_in_box = lbox - hlen
|
||||
return tbox
|
||||
|
@ -189,7 +190,8 @@ def _parse_jp2_header(fp):
|
|||
break
|
||||
|
||||
if size is None or mode is None:
|
||||
raise SyntaxError("Malformed JP2 header")
|
||||
msg = "Malformed JP2 header"
|
||||
raise SyntaxError(msg)
|
||||
|
||||
return size, mode, mimetype, dpi
|
||||
|
||||
|
@ -217,10 +219,12 @@ class Jpeg2KImageFile(ImageFile.ImageFile):
|
|||
if dpi is not None:
|
||||
self.info["dpi"] = dpi
|
||||
else:
|
||||
raise SyntaxError("not a JPEG 2000 file")
|
||||
msg = "not a JPEG 2000 file"
|
||||
raise SyntaxError(msg)
|
||||
|
||||
if self.size is None or self.mode is None:
|
||||
raise SyntaxError("unable to determine size/mode")
|
||||
msg = "unable to determine size/mode"
|
||||
raise SyntaxError(msg)
|
||||
|
||||
self._reduce = 0
|
||||
self.layers = 0
|
||||
|
@ -312,7 +316,8 @@ def _save(im, fp, filename):
|
|||
]
|
||||
)
|
||||
):
|
||||
raise ValueError("quality_layers must be a sequence of numbers")
|
||||
msg = "quality_layers must be a sequence of numbers"
|
||||
raise ValueError(msg)
|
||||
|
||||
num_resolutions = info.get("num_resolutions", 0)
|
||||
cblk_size = info.get("codeblock_size", None)
|
||||
|
@ -321,6 +326,7 @@ def _save(im, fp, filename):
|
|||
progression = info.get("progression", "LRCP")
|
||||
cinema_mode = info.get("cinema_mode", "no")
|
||||
mct = info.get("mct", 0)
|
||||
signed = info.get("signed", False)
|
||||
fd = -1
|
||||
|
||||
if hasattr(fp, "fileno"):
|
||||
|
@ -342,6 +348,7 @@ def _save(im, fp, filename):
|
|||
progression,
|
||||
cinema_mode,
|
||||
mct,
|
||||
signed,
|
||||
fd,
|
||||
)
|
||||
|
||||
|
|
|
@ -204,7 +204,8 @@ def SOF(self, marker):
|
|||
|
||||
self.bits = s[0]
|
||||
if self.bits != 8:
|
||||
raise SyntaxError(f"cannot handle {self.bits}-bit layers")
|
||||
msg = f"cannot handle {self.bits}-bit layers"
|
||||
raise SyntaxError(msg)
|
||||
|
||||
self.layers = s[5]
|
||||
if self.layers == 1:
|
||||
|
@ -214,7 +215,8 @@ def SOF(self, marker):
|
|||
elif self.layers == 4:
|
||||
self.mode = "CMYK"
|
||||
else:
|
||||
raise SyntaxError(f"cannot handle {self.layers}-layer images")
|
||||
msg = f"cannot handle {self.layers}-layer images"
|
||||
raise SyntaxError(msg)
|
||||
|
||||
if marker in [0xFFC2, 0xFFC6, 0xFFCA, 0xFFCE]:
|
||||
self.info["progressive"] = self.info["progression"] = 1
|
||||
|
@ -253,7 +255,8 @@ def DQT(self, marker):
|
|||
precision = 1 if (v // 16 == 0) else 2 # in bytes
|
||||
qt_length = 1 + precision * 64
|
||||
if len(s) < qt_length:
|
||||
raise SyntaxError("bad quantization table marker")
|
||||
msg = "bad quantization table marker"
|
||||
raise SyntaxError(msg)
|
||||
data = array.array("B" if precision == 1 else "H", s[1:qt_length])
|
||||
if sys.byteorder == "little" and precision > 1:
|
||||
data.byteswap() # the values are always big-endian
|
||||
|
@ -350,7 +353,8 @@ class JpegImageFile(ImageFile.ImageFile):
|
|||
s = self.fp.read(3)
|
||||
|
||||
if not _accept(s):
|
||||
raise SyntaxError("not a JPEG file")
|
||||
msg = "not a JPEG file"
|
||||
raise SyntaxError(msg)
|
||||
s = b"\xFF"
|
||||
|
||||
# Create attributes
|
||||
|
@ -394,7 +398,8 @@ class JpegImageFile(ImageFile.ImageFile):
|
|||
elif i == 0xFF00: # Skip extraneous data (escaped 0xFF)
|
||||
s = self.fp.read(1)
|
||||
else:
|
||||
raise SyntaxError("no marker found")
|
||||
msg = "no marker found"
|
||||
raise SyntaxError(msg)
|
||||
|
||||
def load_read(self, read_bytes):
|
||||
"""
|
||||
|
@ -458,7 +463,8 @@ class JpegImageFile(ImageFile.ImageFile):
|
|||
if os.path.exists(self.filename):
|
||||
subprocess.check_call(["djpeg", "-outfile", path, self.filename])
|
||||
else:
|
||||
raise ValueError("Invalid Filename")
|
||||
msg = "Invalid Filename"
|
||||
raise ValueError(msg)
|
||||
|
||||
try:
|
||||
with Image.open(path) as _im:
|
||||
|
@ -524,12 +530,14 @@ def _getmp(self):
|
|||
info.load(file_contents)
|
||||
mp = dict(info)
|
||||
except Exception as e:
|
||||
raise SyntaxError("malformed MP Index (unreadable directory)") from e
|
||||
msg = "malformed MP Index (unreadable directory)"
|
||||
raise SyntaxError(msg) from e
|
||||
# it's an error not to have a number of images
|
||||
try:
|
||||
quant = mp[0xB001]
|
||||
except KeyError as e:
|
||||
raise SyntaxError("malformed MP Index (no number of images)") from e
|
||||
msg = "malformed MP Index (no number of images)"
|
||||
raise SyntaxError(msg) from e
|
||||
# get MP entries
|
||||
mpentries = []
|
||||
try:
|
||||
|
@ -551,7 +559,8 @@ def _getmp(self):
|
|||
if mpentryattr["ImageDataFormat"] == 0:
|
||||
mpentryattr["ImageDataFormat"] = "JPEG"
|
||||
else:
|
||||
raise SyntaxError("unsupported picture format in MPO")
|
||||
msg = "unsupported picture format in MPO"
|
||||
raise SyntaxError(msg)
|
||||
mptypemap = {
|
||||
0x000000: "Undefined",
|
||||
0x010001: "Large Thumbnail (VGA Equivalent)",
|
||||
|
@ -566,7 +575,8 @@ def _getmp(self):
|
|||
mpentries.append(mpentry)
|
||||
mp[0xB002] = mpentries
|
||||
except KeyError as e:
|
||||
raise SyntaxError("malformed MP Index (bad MP Entry)") from e
|
||||
msg = "malformed MP Index (bad MP Entry)"
|
||||
raise SyntaxError(msg) from e
|
||||
# Next we should try and parse the individual image unique ID list;
|
||||
# we don't because I've never seen this actually used in a real MPO
|
||||
# file and so can't test it.
|
||||
|
@ -626,12 +636,14 @@ def get_sampling(im):
|
|||
|
||||
def _save(im, fp, filename):
|
||||
if im.width == 0 or im.height == 0:
|
||||
raise ValueError("cannot write empty image as JPEG")
|
||||
msg = "cannot write empty image as JPEG"
|
||||
raise ValueError(msg)
|
||||
|
||||
try:
|
||||
rawmode = RAWMODE[im.mode]
|
||||
except KeyError as e:
|
||||
raise OSError(f"cannot write mode {im.mode} as JPEG") from e
|
||||
msg = f"cannot write mode {im.mode} as JPEG"
|
||||
raise OSError(msg) from e
|
||||
|
||||
info = im.encoderinfo
|
||||
|
||||
|
@ -651,7 +663,8 @@ def _save(im, fp, filename):
|
|||
subsampling = preset.get("subsampling", -1)
|
||||
qtables = preset.get("quantization")
|
||||
elif not isinstance(quality, int):
|
||||
raise ValueError("Invalid quality setting")
|
||||
msg = "Invalid quality setting"
|
||||
raise ValueError(msg)
|
||||
else:
|
||||
if subsampling in presets:
|
||||
subsampling = presets[subsampling].get("subsampling", -1)
|
||||
|
@ -670,7 +683,8 @@ def _save(im, fp, filename):
|
|||
subsampling = 2
|
||||
elif subsampling == "keep":
|
||||
if im.format != "JPEG":
|
||||
raise ValueError("Cannot use 'keep' when original image is not a JPEG")
|
||||
msg = "Cannot use 'keep' when original image is not a JPEG"
|
||||
raise ValueError(msg)
|
||||
subsampling = get_sampling(im)
|
||||
|
||||
def validate_qtables(qtables):
|
||||
|
@ -684,7 +698,8 @@ def _save(im, fp, filename):
|
|||
for num in line.split("#", 1)[0].split()
|
||||
]
|
||||
except ValueError as e:
|
||||
raise ValueError("Invalid quantization table") from e
|
||||
msg = "Invalid quantization table"
|
||||
raise ValueError(msg) from e
|
||||
else:
|
||||
qtables = [lines[s : s + 64] for s in range(0, len(lines), 64)]
|
||||
if isinstance(qtables, (tuple, list, dict)):
|
||||
|
@ -695,21 +710,24 @@ def _save(im, fp, filename):
|
|||
elif isinstance(qtables, tuple):
|
||||
qtables = list(qtables)
|
||||
if not (0 < len(qtables) < 5):
|
||||
raise ValueError("None or too many quantization tables")
|
||||
msg = "None or too many quantization tables"
|
||||
raise ValueError(msg)
|
||||
for idx, table in enumerate(qtables):
|
||||
try:
|
||||
if len(table) != 64:
|
||||
raise TypeError
|
||||
table = array.array("H", table)
|
||||
except TypeError as e:
|
||||
raise ValueError("Invalid quantization table") from e
|
||||
msg = "Invalid quantization table"
|
||||
raise ValueError(msg) from e
|
||||
else:
|
||||
qtables[idx] = list(table)
|
||||
return qtables
|
||||
|
||||
if qtables == "keep":
|
||||
if im.format != "JPEG":
|
||||
raise ValueError("Cannot use 'keep' when original image is not a JPEG")
|
||||
msg = "Cannot use 'keep' when original image is not a JPEG"
|
||||
raise ValueError(msg)
|
||||
qtables = getattr(im, "quantization", None)
|
||||
qtables = validate_qtables(qtables)
|
||||
|
||||
|
|
|
@ -39,7 +39,8 @@ class McIdasImageFile(ImageFile.ImageFile):
|
|||
# parse area file directory
|
||||
s = self.fp.read(256)
|
||||
if not _accept(s) or len(s) != 256:
|
||||
raise SyntaxError("not an McIdas area file")
|
||||
msg = "not an McIdas area file"
|
||||
raise SyntaxError(msg)
|
||||
|
||||
self.area_descriptor_raw = s
|
||||
self.area_descriptor = w = [0] + list(struct.unpack("!64i", s))
|
||||
|
@ -56,7 +57,8 @@ class McIdasImageFile(ImageFile.ImageFile):
|
|||
mode = "I"
|
||||
rawmode = "I;32B"
|
||||
else:
|
||||
raise SyntaxError("unsupported McIdas format")
|
||||
msg = "unsupported McIdas format"
|
||||
raise SyntaxError(msg)
|
||||
|
||||
self.mode = mode
|
||||
self._size = w[10], w[9]
|
||||
|
|
|
@ -47,7 +47,8 @@ class MicImageFile(TiffImagePlugin.TiffImageFile):
|
|||
try:
|
||||
self.ole = olefile.OleFileIO(self.fp)
|
||||
except OSError as e:
|
||||
raise SyntaxError("not an MIC file; invalid OLE file") from e
|
||||
msg = "not an MIC file; invalid OLE file"
|
||||
raise SyntaxError(msg) from e
|
||||
|
||||
# find ACI subfiles with Image members (maybe not the
|
||||
# best way to identify MIC files, but what the... ;-)
|
||||
|
@ -60,7 +61,8 @@ class MicImageFile(TiffImagePlugin.TiffImageFile):
|
|||
# if we didn't find any images, this is probably not
|
||||
# an MIC file.
|
||||
if not self.images:
|
||||
raise SyntaxError("not an MIC file; no image entries")
|
||||
msg = "not an MIC file; no image entries"
|
||||
raise SyntaxError(msg)
|
||||
|
||||
self.frame = None
|
||||
self._n_frames = len(self.images)
|
||||
|
@ -77,7 +79,8 @@ class MicImageFile(TiffImagePlugin.TiffImageFile):
|
|||
try:
|
||||
filename = self.images[frame]
|
||||
except IndexError as e:
|
||||
raise EOFError("no such frame") from e
|
||||
msg = "no such frame"
|
||||
raise EOFError(msg) from e
|
||||
|
||||
self.fp = self.ole.openstream(filename)
|
||||
|
||||
|
|
|
@ -67,7 +67,8 @@ class MpegImageFile(ImageFile.ImageFile):
|
|||
s = BitStream(self.fp)
|
||||
|
||||
if s.read(32) != 0x1B3:
|
||||
raise SyntaxError("not an MPEG file")
|
||||
msg = "not an MPEG file"
|
||||
raise SyntaxError(msg)
|
||||
|
||||
self.mode = "RGB"
|
||||
self._size = s.read(12), s.read(12)
|
||||
|
|
|
@ -143,7 +143,8 @@ class MpoImageFile(JpegImagePlugin.JpegImageFile):
|
|||
self.fp.seek(self.offset + 2) # skip SOI marker
|
||||
segment = self.fp.read(2)
|
||||
if not segment:
|
||||
raise ValueError("No data found for frame")
|
||||
msg = "No data found for frame"
|
||||
raise ValueError(msg)
|
||||
self._size = self._initial_size
|
||||
if i16(segment) == 0xFFE1: # APP1
|
||||
n = i16(self.fp.read(2)) - 2
|
||||
|
|
|
@ -53,14 +53,16 @@ class MspImageFile(ImageFile.ImageFile):
|
|||
# Header
|
||||
s = self.fp.read(32)
|
||||
if not _accept(s):
|
||||
raise SyntaxError("not an MSP file")
|
||||
msg = "not an MSP file"
|
||||
raise SyntaxError(msg)
|
||||
|
||||
# Header checksum
|
||||
checksum = 0
|
||||
for i in range(0, 32, 2):
|
||||
checksum = checksum ^ i16(s, i)
|
||||
if checksum != 0:
|
||||
raise SyntaxError("bad MSP checksum")
|
||||
msg = "bad MSP checksum"
|
||||
raise SyntaxError(msg)
|
||||
|
||||
self.mode = "1"
|
||||
self._size = i16(s, 4), i16(s, 6)
|
||||
|
@ -118,7 +120,8 @@ class MspDecoder(ImageFile.PyDecoder):
|
|||
f"<{self.state.ysize}H", self.fd.read(self.state.ysize * 2)
|
||||
)
|
||||
except struct.error as e:
|
||||
raise OSError("Truncated MSP file in row map") from e
|
||||
msg = "Truncated MSP file in row map"
|
||||
raise OSError(msg) from e
|
||||
|
||||
for x, rowlen in enumerate(rowmap):
|
||||
try:
|
||||
|
@ -127,9 +130,8 @@ class MspDecoder(ImageFile.PyDecoder):
|
|||
continue
|
||||
row = self.fd.read(rowlen)
|
||||
if len(row) != rowlen:
|
||||
raise OSError(
|
||||
"Truncated MSP file, expected %d bytes on row %s", (rowlen, x)
|
||||
)
|
||||
msg = f"Truncated MSP file, expected {rowlen} bytes on row {x}"
|
||||
raise OSError(msg)
|
||||
idx = 0
|
||||
while idx < rowlen:
|
||||
runtype = row[idx]
|
||||
|
@ -144,7 +146,8 @@ class MspDecoder(ImageFile.PyDecoder):
|
|||
idx += runcount
|
||||
|
||||
except struct.error as e:
|
||||
raise OSError(f"Corrupted MSP file in row {x}") from e
|
||||
msg = f"Corrupted MSP file in row {x}"
|
||||
raise OSError(msg) from e
|
||||
|
||||
self.set_as_raw(img.getvalue(), ("1", 0, 1))
|
||||
|
||||
|
@ -161,7 +164,8 @@ Image.register_decoder("MSP", MspDecoder)
|
|||
def _save(im, fp, filename):
|
||||
|
||||
if im.mode != "1":
|
||||
raise OSError(f"cannot write mode {im.mode} as MSP")
|
||||
msg = f"cannot write mode {im.mode} as MSP"
|
||||
raise OSError(msg)
|
||||
|
||||
# create MSP header
|
||||
header = [0] * 16
|
||||
|
|
|
@ -34,7 +34,8 @@ class PaletteFile:
|
|||
if s[:1] == b"#":
|
||||
continue
|
||||
if len(s) > 100:
|
||||
raise SyntaxError("bad palette file")
|
||||
msg = "bad palette file"
|
||||
raise SyntaxError(msg)
|
||||
|
||||
v = [int(x) for x in s.split()]
|
||||
try:
|
||||
|
|
|
@ -138,7 +138,8 @@ def _save(im, fp, filename):
|
|||
bpp = im.info["bpp"]
|
||||
im = im.point(lambda x, maxval=(1 << bpp) - 1: maxval - (x & maxval))
|
||||
else:
|
||||
raise OSError(f"cannot write mode {im.mode} as Palm")
|
||||
msg = f"cannot write mode {im.mode} as Palm"
|
||||
raise OSError(msg)
|
||||
|
||||
# we ignore the palette here
|
||||
im.mode = "P"
|
||||
|
@ -154,7 +155,8 @@ def _save(im, fp, filename):
|
|||
|
||||
else:
|
||||
|
||||
raise OSError(f"cannot write mode {im.mode} as Palm")
|
||||
msg = f"cannot write mode {im.mode} as Palm"
|
||||
raise OSError(msg)
|
||||
|
||||
#
|
||||
# make sure image data is available
|
||||
|
|
|
@ -35,7 +35,8 @@ class PcdImageFile(ImageFile.ImageFile):
|
|||
s = self.fp.read(2048)
|
||||
|
||||
if s[:4] != b"PCD_":
|
||||
raise SyntaxError("not a PCD file")
|
||||
msg = "not a PCD file"
|
||||
raise SyntaxError(msg)
|
||||
|
||||
orientation = s[1538] & 3
|
||||
self.tile_post_rotate = None
|
||||
|
|
|
@ -63,7 +63,8 @@ class PcfFontFile(FontFile.FontFile):
|
|||
|
||||
magic = l32(fp.read(4))
|
||||
if magic != PCF_MAGIC:
|
||||
raise SyntaxError("not a PCF file")
|
||||
msg = "not a PCF file"
|
||||
raise SyntaxError(msg)
|
||||
|
||||
super().__init__()
|
||||
|
||||
|
@ -186,7 +187,8 @@ class PcfFontFile(FontFile.FontFile):
|
|||
nbitmaps = i32(fp.read(4))
|
||||
|
||||
if nbitmaps != len(metrics):
|
||||
raise OSError("Wrong number of bitmaps")
|
||||
msg = "Wrong number of bitmaps"
|
||||
raise OSError(msg)
|
||||
|
||||
offsets = []
|
||||
for i in range(nbitmaps):
|
||||
|
|
|
@ -54,12 +54,14 @@ class PcxImageFile(ImageFile.ImageFile):
|
|||
# header
|
||||
s = self.fp.read(128)
|
||||
if not _accept(s):
|
||||
raise SyntaxError("not a PCX file")
|
||||
msg = "not a PCX file"
|
||||
raise SyntaxError(msg)
|
||||
|
||||
# image
|
||||
bbox = i16(s, 4), i16(s, 6), i16(s, 8) + 1, i16(s, 10) + 1
|
||||
if bbox[2] <= bbox[0] or bbox[3] <= bbox[1]:
|
||||
raise SyntaxError("bad PCX image size")
|
||||
msg = "bad PCX image size"
|
||||
raise SyntaxError(msg)
|
||||
logger.debug("BBox: %s %s %s %s", *bbox)
|
||||
|
||||
# format
|
||||
|
@ -105,7 +107,8 @@ class PcxImageFile(ImageFile.ImageFile):
|
|||
rawmode = "RGB;L"
|
||||
|
||||
else:
|
||||
raise OSError("unknown PCX mode")
|
||||
msg = "unknown PCX mode"
|
||||
raise OSError(msg)
|
||||
|
||||
self.mode = mode
|
||||
self._size = bbox[2] - bbox[0], bbox[3] - bbox[1]
|
||||
|
@ -144,7 +147,8 @@ def _save(im, fp, filename):
|
|||
try:
|
||||
version, bits, planes, rawmode = SAVE[im.mode]
|
||||
except KeyError as e:
|
||||
raise ValueError(f"Cannot save {im.mode} images as PCX") from e
|
||||
msg = f"Cannot save {im.mode} images as PCX"
|
||||
raise ValueError(msg) from e
|
||||
|
||||
# bytes per plane
|
||||
stride = (im.size[0] * bits + 7) // 8
|
||||
|
|
|
@ -174,7 +174,8 @@ def _save(im, fp, filename, save_all=False):
|
|||
procset = "ImageC" # color images
|
||||
decode = [1, 0, 1, 0, 1, 0, 1, 0]
|
||||
else:
|
||||
raise ValueError(f"cannot save mode {im.mode}")
|
||||
msg = f"cannot save mode {im.mode}"
|
||||
raise ValueError(msg)
|
||||
|
||||
#
|
||||
# image
|
||||
|
@ -198,7 +199,8 @@ def _save(im, fp, filename, save_all=False):
|
|||
elif filter == "RunLengthDecode":
|
||||
ImageFile._save(im, op, [("packbits", (0, 0) + im.size, 0, im.mode)])
|
||||
else:
|
||||
raise ValueError(f"unsupported PDF filter ({filter})")
|
||||
msg = f"unsupported PDF filter ({filter})"
|
||||
raise ValueError(msg)
|
||||
|
||||
stream = op.getvalue()
|
||||
if filter == "CCITTFaxDecode":
|
||||
|
|
|
@ -138,9 +138,10 @@ class XrefTable:
|
|||
elif key in self.deleted_entries:
|
||||
generation = self.deleted_entries[key]
|
||||
else:
|
||||
raise IndexError(
|
||||
msg = (
|
||||
"object ID " + str(key) + " cannot be deleted because it doesn't exist"
|
||||
)
|
||||
raise IndexError(msg)
|
||||
|
||||
def __contains__(self, key):
|
||||
return key in self.existing_entries or key in self.new_entries
|
||||
|
@ -314,9 +315,8 @@ class PdfStream:
|
|||
expected_length = self.dictionary.Length
|
||||
return zlib.decompress(self.buf, bufsize=int(expected_length))
|
||||
else:
|
||||
raise NotImplementedError(
|
||||
f"stream filter {repr(self.dictionary.Filter)} unknown/unsupported"
|
||||
)
|
||||
msg = f"stream filter {repr(self.dictionary.Filter)} unknown/unsupported"
|
||||
raise NotImplementedError(msg)
|
||||
|
||||
|
||||
def pdf_repr(x):
|
||||
|
@ -358,7 +358,8 @@ class PdfParser:
|
|||
|
||||
def __init__(self, filename=None, f=None, buf=None, start_offset=0, mode="rb"):
|
||||
if buf and f:
|
||||
raise RuntimeError("specify buf or f or filename, but not both buf and f")
|
||||
msg = "specify buf or f or filename, but not both buf and f"
|
||||
raise RuntimeError(msg)
|
||||
self.filename = filename
|
||||
self.buf = buf
|
||||
self.f = f
|
||||
|
@ -816,10 +817,10 @@ class PdfParser:
|
|||
try:
|
||||
stream_len = int(result[b"Length"])
|
||||
except (TypeError, KeyError, ValueError) as e:
|
||||
raise PdfFormatError(
|
||||
"bad or missing Length in stream dict (%r)"
|
||||
% result.get(b"Length", None)
|
||||
) from e
|
||||
msg = "bad or missing Length in stream dict (%r)" % result.get(
|
||||
b"Length", None
|
||||
)
|
||||
raise PdfFormatError(msg) from e
|
||||
stream_data = data[m.end() : m.end() + stream_len]
|
||||
m = cls.re_stream_end.match(data, m.end() + stream_len)
|
||||
check_format_condition(m, "stream end not found")
|
||||
|
@ -873,7 +874,8 @@ class PdfParser:
|
|||
if m:
|
||||
return cls.get_literal_string(data, m.end())
|
||||
# return None, offset # fallback (only for debugging)
|
||||
raise PdfFormatError("unrecognized object: " + repr(data[offset : offset + 32]))
|
||||
msg = "unrecognized object: " + repr(data[offset : offset + 32])
|
||||
raise PdfFormatError(msg)
|
||||
|
||||
re_lit_str_token = re.compile(
|
||||
rb"(\\[nrtbf()\\])|(\\[0-9]{1,3})|(\\(\r\n|\r|\n))|(\r\n|\r|\n)|(\()|(\))"
|
||||
|
@ -920,7 +922,8 @@ class PdfParser:
|
|||
result.extend(b")")
|
||||
nesting_depth -= 1
|
||||
offset = m.end()
|
||||
raise PdfFormatError("unfinished literal string")
|
||||
msg = "unfinished literal string"
|
||||
raise PdfFormatError(msg)
|
||||
|
||||
re_xref_section_start = re.compile(whitespace_optional + rb"xref" + newline)
|
||||
re_xref_subsection_start = re.compile(
|
||||
|
|
|
@ -44,7 +44,8 @@ class PixarImageFile(ImageFile.ImageFile):
|
|||
# assuming a 4-byte magic label
|
||||
s = self.fp.read(4)
|
||||
if not _accept(s):
|
||||
raise SyntaxError("not a PIXAR file")
|
||||
msg = "not a PIXAR file"
|
||||
raise SyntaxError(msg)
|
||||
|
||||
# read rest of header
|
||||
s = s + self.fp.read(508)
|
||||
|
|
|
@ -138,14 +138,16 @@ def __getattr__(name):
|
|||
if name in enum.__members__:
|
||||
deprecate(f"{prefix}{name}", 10, f"{enum.__name__}.{name}")
|
||||
return enum[name]
|
||||
raise AttributeError(f"module '{__name__}' has no attribute '{name}'")
|
||||
msg = f"module '{__name__}' has no attribute '{name}'"
|
||||
raise AttributeError(msg)
|
||||
|
||||
|
||||
def _safe_zlib_decompress(s):
|
||||
dobj = zlib.decompressobj()
|
||||
plaintext = dobj.decompress(s, MAX_TEXT_CHUNK)
|
||||
if dobj.unconsumed_tail:
|
||||
raise ValueError("Decompressed Data Too Large")
|
||||
msg = "Decompressed Data Too Large"
|
||||
raise ValueError(msg)
|
||||
return plaintext
|
||||
|
||||
|
||||
|
@ -178,7 +180,8 @@ class ChunkStream:
|
|||
|
||||
if not is_cid(cid):
|
||||
if not ImageFile.LOAD_TRUNCATED_IMAGES:
|
||||
raise SyntaxError(f"broken PNG file (chunk {repr(cid)})")
|
||||
msg = f"broken PNG file (chunk {repr(cid)})"
|
||||
raise SyntaxError(msg)
|
||||
|
||||
return cid, pos, length
|
||||
|
||||
|
@ -215,13 +218,11 @@ class ChunkStream:
|
|||
crc1 = _crc32(data, _crc32(cid))
|
||||
crc2 = i32(self.fp.read(4))
|
||||
if crc1 != crc2:
|
||||
raise SyntaxError(
|
||||
f"broken PNG file (bad header checksum in {repr(cid)})"
|
||||
)
|
||||
msg = f"broken PNG file (bad header checksum in {repr(cid)})"
|
||||
raise SyntaxError(msg)
|
||||
except struct.error as e:
|
||||
raise SyntaxError(
|
||||
f"broken PNG file (incomplete checksum in {repr(cid)})"
|
||||
) from e
|
||||
msg = f"broken PNG file (incomplete checksum in {repr(cid)})"
|
||||
raise SyntaxError(msg) from e
|
||||
|
||||
def crc_skip(self, cid, data):
|
||||
"""Read checksum"""
|
||||
|
@ -239,7 +240,8 @@ class ChunkStream:
|
|||
try:
|
||||
cid, pos, length = self.read()
|
||||
except struct.error as e:
|
||||
raise OSError("truncated PNG file") from e
|
||||
msg = "truncated PNG file"
|
||||
raise OSError(msg) from e
|
||||
|
||||
if cid == endchunk:
|
||||
break
|
||||
|
@ -376,10 +378,11 @@ class PngStream(ChunkStream):
|
|||
def check_text_memory(self, chunklen):
|
||||
self.text_memory += chunklen
|
||||
if self.text_memory > MAX_TEXT_MEMORY:
|
||||
raise ValueError(
|
||||
msg = (
|
||||
"Too much memory used in text chunks: "
|
||||
f"{self.text_memory}>MAX_TEXT_MEMORY"
|
||||
)
|
||||
raise ValueError(msg)
|
||||
|
||||
def save_rewind(self):
|
||||
self.rewind_state = {
|
||||
|
@ -407,7 +410,8 @@ class PngStream(ChunkStream):
|
|||
logger.debug("Compression method %s", s[i])
|
||||
comp_method = s[i]
|
||||
if comp_method != 0:
|
||||
raise SyntaxError(f"Unknown compression method {comp_method} in iCCP chunk")
|
||||
msg = f"Unknown compression method {comp_method} in iCCP chunk"
|
||||
raise SyntaxError(msg)
|
||||
try:
|
||||
icc_profile = _safe_zlib_decompress(s[i + 2 :])
|
||||
except ValueError:
|
||||
|
@ -427,7 +431,8 @@ class PngStream(ChunkStream):
|
|||
if length < 13:
|
||||
if ImageFile.LOAD_TRUNCATED_IMAGES:
|
||||
return s
|
||||
raise ValueError("Truncated IHDR chunk")
|
||||
msg = "Truncated IHDR chunk"
|
||||
raise ValueError(msg)
|
||||
self.im_size = i32(s, 0), i32(s, 4)
|
||||
try:
|
||||
self.im_mode, self.im_rawmode = _MODES[(s[8], s[9])]
|
||||
|
@ -436,7 +441,8 @@ class PngStream(ChunkStream):
|
|||
if s[12]:
|
||||
self.im_info["interlace"] = 1
|
||||
if s[11]:
|
||||
raise SyntaxError("unknown filter category")
|
||||
msg = "unknown filter category"
|
||||
raise SyntaxError(msg)
|
||||
return s
|
||||
|
||||
def chunk_IDAT(self, pos, length):
|
||||
|
@ -512,7 +518,8 @@ class PngStream(ChunkStream):
|
|||
if length < 1:
|
||||
if ImageFile.LOAD_TRUNCATED_IMAGES:
|
||||
return s
|
||||
raise ValueError("Truncated sRGB chunk")
|
||||
msg = "Truncated sRGB chunk"
|
||||
raise ValueError(msg)
|
||||
self.im_info["srgb"] = s[0]
|
||||
return s
|
||||
|
||||
|
@ -523,7 +530,8 @@ class PngStream(ChunkStream):
|
|||
if length < 9:
|
||||
if ImageFile.LOAD_TRUNCATED_IMAGES:
|
||||
return s
|
||||
raise ValueError("Truncated pHYs chunk")
|
||||
msg = "Truncated pHYs chunk"
|
||||
raise ValueError(msg)
|
||||
px, py = i32(s, 0), i32(s, 4)
|
||||
unit = s[8]
|
||||
if unit == 1: # meter
|
||||
|
@ -567,7 +575,8 @@ class PngStream(ChunkStream):
|
|||
else:
|
||||
comp_method = 0
|
||||
if comp_method != 0:
|
||||
raise SyntaxError(f"Unknown compression method {comp_method} in zTXt chunk")
|
||||
msg = f"Unknown compression method {comp_method} in zTXt chunk"
|
||||
raise SyntaxError(msg)
|
||||
try:
|
||||
v = _safe_zlib_decompress(v[1:])
|
||||
except ValueError:
|
||||
|
@ -639,7 +648,8 @@ class PngStream(ChunkStream):
|
|||
if length < 8:
|
||||
if ImageFile.LOAD_TRUNCATED_IMAGES:
|
||||
return s
|
||||
raise ValueError("APNG contains truncated acTL chunk")
|
||||
msg = "APNG contains truncated acTL chunk"
|
||||
raise ValueError(msg)
|
||||
if self.im_n_frames is not None:
|
||||
self.im_n_frames = None
|
||||
warnings.warn("Invalid APNG, will use default PNG image if possible")
|
||||
|
@ -658,18 +668,21 @@ class PngStream(ChunkStream):
|
|||
if length < 26:
|
||||
if ImageFile.LOAD_TRUNCATED_IMAGES:
|
||||
return s
|
||||
raise ValueError("APNG contains truncated fcTL chunk")
|
||||
msg = "APNG contains truncated fcTL chunk"
|
||||
raise ValueError(msg)
|
||||
seq = i32(s)
|
||||
if (self._seq_num is None and seq != 0) or (
|
||||
self._seq_num is not None and self._seq_num != seq - 1
|
||||
):
|
||||
raise SyntaxError("APNG contains frame sequence errors")
|
||||
msg = "APNG contains frame sequence errors"
|
||||
raise SyntaxError(msg)
|
||||
self._seq_num = seq
|
||||
width, height = i32(s, 4), i32(s, 8)
|
||||
px, py = i32(s, 12), i32(s, 16)
|
||||
im_w, im_h = self.im_size
|
||||
if px + width > im_w or py + height > im_h:
|
||||
raise SyntaxError("APNG contains invalid frames")
|
||||
msg = "APNG contains invalid frames"
|
||||
raise SyntaxError(msg)
|
||||
self.im_info["bbox"] = (px, py, px + width, py + height)
|
||||
delay_num, delay_den = i16(s, 20), i16(s, 22)
|
||||
if delay_den == 0:
|
||||
|
@ -684,11 +697,13 @@ class PngStream(ChunkStream):
|
|||
if ImageFile.LOAD_TRUNCATED_IMAGES:
|
||||
s = ImageFile._safe_read(self.fp, length)
|
||||
return s
|
||||
raise ValueError("APNG contains truncated fDAT chunk")
|
||||
msg = "APNG contains truncated fDAT chunk"
|
||||
raise ValueError(msg)
|
||||
s = ImageFile._safe_read(self.fp, 4)
|
||||
seq = i32(s)
|
||||
if self._seq_num != seq - 1:
|
||||
raise SyntaxError("APNG contains frame sequence errors")
|
||||
msg = "APNG contains frame sequence errors"
|
||||
raise SyntaxError(msg)
|
||||
self._seq_num = seq
|
||||
return self.chunk_IDAT(pos + 4, length - 4)
|
||||
|
||||
|
@ -713,7 +728,8 @@ class PngImageFile(ImageFile.ImageFile):
|
|||
def _open(self):
|
||||
|
||||
if not _accept(self.fp.read(8)):
|
||||
raise SyntaxError("not a PNG file")
|
||||
msg = "not a PNG file"
|
||||
raise SyntaxError(msg)
|
||||
self._fp = self.fp
|
||||
self.__frame = 0
|
||||
|
||||
|
@ -797,7 +813,8 @@ class PngImageFile(ImageFile.ImageFile):
|
|||
"""Verify PNG file"""
|
||||
|
||||
if self.fp is None:
|
||||
raise RuntimeError("verify must be called directly after open")
|
||||
msg = "verify must be called directly after open"
|
||||
raise RuntimeError(msg)
|
||||
|
||||
# back up to beginning of IDAT block
|
||||
self.fp.seek(self.tile[0][2] - 8)
|
||||
|
@ -821,7 +838,8 @@ class PngImageFile(ImageFile.ImageFile):
|
|||
self._seek(f)
|
||||
except EOFError as e:
|
||||
self.seek(last_frame)
|
||||
raise EOFError("no more images in APNG file") from e
|
||||
msg = "no more images in APNG file"
|
||||
raise EOFError(msg) from e
|
||||
|
||||
def _seek(self, frame, rewind=False):
|
||||
if frame == 0:
|
||||
|
@ -844,7 +862,8 @@ class PngImageFile(ImageFile.ImageFile):
|
|||
self.__frame = 0
|
||||
else:
|
||||
if frame != self.__frame + 1:
|
||||
raise ValueError(f"cannot seek to frame {frame}")
|
||||
msg = f"cannot seek to frame {frame}"
|
||||
raise ValueError(msg)
|
||||
|
||||
# ensure previous frame was loaded
|
||||
self.load()
|
||||
|
@ -869,11 +888,13 @@ class PngImageFile(ImageFile.ImageFile):
|
|||
break
|
||||
|
||||
if cid == b"IEND":
|
||||
raise EOFError("No more images in APNG file")
|
||||
msg = "No more images in APNG file"
|
||||
raise EOFError(msg)
|
||||
if cid == b"fcTL":
|
||||
if frame_start:
|
||||
# there must be at least one fdAT chunk between fcTL chunks
|
||||
raise SyntaxError("APNG missing frame data")
|
||||
msg = "APNG missing frame data"
|
||||
raise SyntaxError(msg)
|
||||
frame_start = True
|
||||
|
||||
try:
|
||||
|
@ -1277,7 +1298,8 @@ def _save(im, fp, filename, chunk=putchunk, save_all=False):
|
|||
try:
|
||||
rawmode, mode = _OUTMODES[mode]
|
||||
except KeyError as e:
|
||||
raise OSError(f"cannot write mode {mode} as PNG") from e
|
||||
msg = f"cannot write mode {mode} as PNG"
|
||||
raise OSError(msg) from e
|
||||
|
||||
#
|
||||
# write minimal PNG file
|
||||
|
@ -1358,7 +1380,8 @@ def _save(im, fp, filename, chunk=putchunk, save_all=False):
|
|||
if "transparency" in im.encoderinfo:
|
||||
# don't bother with transparency if it's an RGBA
|
||||
# and it's in the info dict. It's probably just stale.
|
||||
raise OSError("cannot use transparency for this mode")
|
||||
msg = "cannot use transparency for this mode"
|
||||
raise OSError(msg)
|
||||
else:
|
||||
if im.mode == "P" and im.im.getpalettemode() == "RGBA":
|
||||
alpha = im.im.getpalette("RGBA", "A")
|
||||
|
|
|
@ -84,9 +84,11 @@ class PpmImageFile(ImageFile.ImageFile):
|
|||
token += c
|
||||
if not token:
|
||||
# Token was not even 1 byte
|
||||
raise ValueError("Reached EOF while reading header")
|
||||
msg = "Reached EOF while reading header"
|
||||
raise ValueError(msg)
|
||||
elif len(token) > 10:
|
||||
raise ValueError(f"Token too long in file header: {token.decode()}")
|
||||
msg = f"Token too long in file header: {token.decode()}"
|
||||
raise ValueError(msg)
|
||||
return token
|
||||
|
||||
def _open(self):
|
||||
|
@ -94,7 +96,8 @@ class PpmImageFile(ImageFile.ImageFile):
|
|||
try:
|
||||
mode = MODES[magic_number]
|
||||
except KeyError:
|
||||
raise SyntaxError("not a PPM file")
|
||||
msg = "not a PPM file"
|
||||
raise SyntaxError(msg)
|
||||
|
||||
if magic_number in (b"P1", b"P4"):
|
||||
self.custom_mimetype = "image/x-portable-bitmap"
|
||||
|
@ -122,9 +125,8 @@ class PpmImageFile(ImageFile.ImageFile):
|
|||
elif ix == 2: # token is maxval
|
||||
maxval = token
|
||||
if not 0 < maxval < 65536:
|
||||
raise ValueError(
|
||||
"maxval must be greater than 0 and less than 65536"
|
||||
)
|
||||
msg = "maxval must be greater than 0 and less than 65536"
|
||||
raise ValueError(msg)
|
||||
if maxval > 255 and mode == "L":
|
||||
self.mode = "I"
|
||||
|
||||
|
@ -208,9 +210,8 @@ class PpmPlainDecoder(ImageFile.PyDecoder):
|
|||
tokens = b"".join(block.split())
|
||||
for token in tokens:
|
||||
if token not in (48, 49):
|
||||
raise ValueError(
|
||||
b"Invalid token for this mode: %s" % bytes([token])
|
||||
)
|
||||
msg = b"Invalid token for this mode: %s" % bytes([token])
|
||||
raise ValueError(msg)
|
||||
data = (data + tokens)[:total_bytes]
|
||||
invert = bytes.maketrans(b"01", b"\xFF\x00")
|
||||
return data.translate(invert)
|
||||
|
@ -243,18 +244,19 @@ class PpmPlainDecoder(ImageFile.PyDecoder):
|
|||
if block and not block[-1:].isspace(): # block might split token
|
||||
half_token = tokens.pop() # save half token for later
|
||||
if len(half_token) > max_len: # prevent buildup of half_token
|
||||
raise ValueError(
|
||||
msg = (
|
||||
b"Token too long found in data: %s" % half_token[: max_len + 1]
|
||||
)
|
||||
raise ValueError(msg)
|
||||
|
||||
for token in tokens:
|
||||
if len(token) > max_len:
|
||||
raise ValueError(
|
||||
b"Token too long found in data: %s" % token[: max_len + 1]
|
||||
)
|
||||
msg = b"Token too long found in data: %s" % token[: max_len + 1]
|
||||
raise ValueError(msg)
|
||||
value = int(token)
|
||||
if value > maxval:
|
||||
raise ValueError(f"Channel value too large for this mode: {value}")
|
||||
msg = f"Channel value too large for this mode: {value}"
|
||||
raise ValueError(msg)
|
||||
value = round(value / maxval * out_max)
|
||||
data += o32(value) if self.mode == "I" else o8(value)
|
||||
if len(data) == total_bytes: # finished!
|
||||
|
@ -314,7 +316,8 @@ def _save(im, fp, filename):
|
|||
elif im.mode in ("RGB", "RGBA"):
|
||||
rawmode, head = "RGB", b"P6"
|
||||
else:
|
||||
raise OSError(f"cannot write mode {im.mode} as PPM")
|
||||
msg = f"cannot write mode {im.mode} as PPM"
|
||||
raise OSError(msg)
|
||||
fp.write(head + b"\n%d %d\n" % im.size)
|
||||
if head == b"P6":
|
||||
fp.write(b"255\n")
|
||||
|
|
|
@ -65,7 +65,8 @@ class PsdImageFile(ImageFile.ImageFile):
|
|||
|
||||
s = read(26)
|
||||
if not _accept(s) or i16(s, 4) != 1:
|
||||
raise SyntaxError("not a PSD file")
|
||||
msg = "not a PSD file"
|
||||
raise SyntaxError(msg)
|
||||
|
||||
psd_bits = i16(s, 22)
|
||||
psd_channels = i16(s, 12)
|
||||
|
@ -74,7 +75,8 @@ class PsdImageFile(ImageFile.ImageFile):
|
|||
mode, channels = MODES[(psd_mode, psd_bits)]
|
||||
|
||||
if channels > psd_channels:
|
||||
raise OSError("not enough channels")
|
||||
msg = "not enough channels"
|
||||
raise OSError(msg)
|
||||
if mode == "RGB" and psd_channels == 4:
|
||||
mode = "RGBA"
|
||||
channels = 4
|
||||
|
@ -152,7 +154,8 @@ class PsdImageFile(ImageFile.ImageFile):
|
|||
self.fp = self._fp
|
||||
return name, bbox
|
||||
except IndexError as e:
|
||||
raise EOFError("no such layer") from e
|
||||
msg = "no such layer"
|
||||
raise EOFError(msg) from e
|
||||
|
||||
def tell(self):
|
||||
# return layer number (0=image, 1..max=layers)
|
||||
|
@ -170,7 +173,8 @@ def _layerinfo(fp, ct_bytes):
|
|||
|
||||
# sanity check
|
||||
if ct_bytes < (abs(ct) * 20):
|
||||
raise SyntaxError("Layer block too short for number of layers requested")
|
||||
msg = "Layer block too short for number of layers requested"
|
||||
raise SyntaxError(msg)
|
||||
|
||||
for _ in range(abs(ct)):
|
||||
|
||||
|
|
|
@ -79,7 +79,8 @@ class PyAccess:
|
|||
:param color: The pixel value.
|
||||
"""
|
||||
if self.readonly:
|
||||
raise ValueError("Attempt to putpixel a read only image")
|
||||
msg = "Attempt to putpixel a read only image"
|
||||
raise ValueError(msg)
|
||||
(x, y) = xy
|
||||
if x < 0:
|
||||
x = self.xsize + x
|
||||
|
@ -127,7 +128,8 @@ class PyAccess:
|
|||
def check_xy(self, xy):
|
||||
(x, y) = xy
|
||||
if not (0 <= x < self.xsize and 0 <= y < self.ysize):
|
||||
raise ValueError("pixel location out of range")
|
||||
msg = "pixel location out of range"
|
||||
raise ValueError(msg)
|
||||
return xy
|
||||
|
||||
|
||||
|
|
|
@ -60,7 +60,8 @@ class SgiImageFile(ImageFile.ImageFile):
|
|||
s = self.fp.read(headlen)
|
||||
|
||||
if not _accept(s):
|
||||
raise ValueError("Not an SGI image file")
|
||||
msg = "Not an SGI image file"
|
||||
raise ValueError(msg)
|
||||
|
||||
# compression : verbatim or RLE
|
||||
compression = s[2]
|
||||
|
@ -91,7 +92,8 @@ class SgiImageFile(ImageFile.ImageFile):
|
|||
pass
|
||||
|
||||
if rawmode == "":
|
||||
raise ValueError("Unsupported SGI image mode")
|
||||
msg = "Unsupported SGI image mode"
|
||||
raise ValueError(msg)
|
||||
|
||||
self._size = xsize, ysize
|
||||
self.mode = rawmode.split(";")[0]
|
||||
|
@ -124,7 +126,8 @@ class SgiImageFile(ImageFile.ImageFile):
|
|||
|
||||
def _save(im, fp, filename):
|
||||
if im.mode != "RGB" and im.mode != "RGBA" and im.mode != "L":
|
||||
raise ValueError("Unsupported SGI image mode")
|
||||
msg = "Unsupported SGI image mode"
|
||||
raise ValueError(msg)
|
||||
|
||||
# Get the keyword arguments
|
||||
info = im.encoderinfo
|
||||
|
@ -133,7 +136,8 @@ def _save(im, fp, filename):
|
|||
bpc = info.get("bpc", 1)
|
||||
|
||||
if bpc not in (1, 2):
|
||||
raise ValueError("Unsupported number of bytes per pixel")
|
||||
msg = "Unsupported number of bytes per pixel"
|
||||
raise ValueError(msg)
|
||||
|
||||
# Flip the image, since the origin of SGI file is the bottom-left corner
|
||||
orientation = -1
|
||||
|
@ -158,9 +162,8 @@ def _save(im, fp, filename):
|
|||
|
||||
# assert we've got the right number of bands.
|
||||
if len(im.getbands()) != z:
|
||||
raise ValueError(
|
||||
f"incorrect number of bands in SGI write: {z} vs {len(im.getbands())}"
|
||||
)
|
||||
msg = f"incorrect number of bands in SGI write: {z} vs {len(im.getbands())}"
|
||||
raise ValueError(msg)
|
||||
|
||||
# Minimum Byte value
|
||||
pinmin = 0
|
||||
|
|
|
@ -110,14 +110,17 @@ class SpiderImageFile(ImageFile.ImageFile):
|
|||
t = struct.unpack("<27f", f) # little-endian
|
||||
hdrlen = isSpiderHeader(t)
|
||||
if hdrlen == 0:
|
||||
raise SyntaxError("not a valid Spider file")
|
||||
msg = "not a valid Spider file"
|
||||
raise SyntaxError(msg)
|
||||
except struct.error as e:
|
||||
raise SyntaxError("not a valid Spider file") from e
|
||||
msg = "not a valid Spider file"
|
||||
raise SyntaxError(msg) from e
|
||||
|
||||
h = (99,) + t # add 1 value : spider header index starts at 1
|
||||
iform = int(h[5])
|
||||
if iform != 1:
|
||||
raise SyntaxError("not a Spider 2D image")
|
||||
msg = "not a Spider 2D image"
|
||||
raise SyntaxError(msg)
|
||||
|
||||
self._size = int(h[12]), int(h[2]) # size in pixels (width, height)
|
||||
self.istack = int(h[24])
|
||||
|
@ -140,7 +143,8 @@ class SpiderImageFile(ImageFile.ImageFile):
|
|||
offset = hdrlen + self.stkoffset
|
||||
self.istack = 2 # So Image knows it's still a stack
|
||||
else:
|
||||
raise SyntaxError("inconsistent stack header values")
|
||||
msg = "inconsistent stack header values"
|
||||
raise SyntaxError(msg)
|
||||
|
||||
if self.bigendian:
|
||||
self.rawmode = "F;32BF"
|
||||
|
@ -168,7 +172,8 @@ class SpiderImageFile(ImageFile.ImageFile):
|
|||
|
||||
def seek(self, frame):
|
||||
if self.istack == 0:
|
||||
raise EOFError("attempt to seek in a non-stack file")
|
||||
msg = "attempt to seek in a non-stack file"
|
||||
raise EOFError(msg)
|
||||
if not self._seek_check(frame):
|
||||
return
|
||||
self.stkoffset = self.hdrlen + frame * (self.hdrlen + self.imgbytes)
|
||||
|
@ -260,7 +265,8 @@ def _save(im, fp, filename):
|
|||
|
||||
hdr = makeSpiderHeader(im)
|
||||
if len(hdr) < 256:
|
||||
raise OSError("Error creating Spider header")
|
||||
msg = "Error creating Spider header"
|
||||
raise OSError(msg)
|
||||
|
||||
# write the SPIDER header
|
||||
fp.writelines(hdr)
|
||||
|
|
|
@ -54,7 +54,8 @@ class SunImageFile(ImageFile.ImageFile):
|
|||
# HEAD
|
||||
s = self.fp.read(32)
|
||||
if not _accept(s):
|
||||
raise SyntaxError("not an SUN raster file")
|
||||
msg = "not an SUN raster file"
|
||||
raise SyntaxError(msg)
|
||||
|
||||
offset = 32
|
||||
|
||||
|
@ -83,14 +84,17 @@ class SunImageFile(ImageFile.ImageFile):
|
|||
else:
|
||||
self.mode, rawmode = "RGB", "BGRX"
|
||||
else:
|
||||
raise SyntaxError("Unsupported Mode/Bit Depth")
|
||||
msg = "Unsupported Mode/Bit Depth"
|
||||
raise SyntaxError(msg)
|
||||
|
||||
if palette_length:
|
||||
if palette_length > 1024:
|
||||
raise SyntaxError("Unsupported Color Palette Length")
|
||||
msg = "Unsupported Color Palette Length"
|
||||
raise SyntaxError(msg)
|
||||
|
||||
if palette_type != 1:
|
||||
raise SyntaxError("Unsupported Palette Type")
|
||||
msg = "Unsupported Palette Type"
|
||||
raise SyntaxError(msg)
|
||||
|
||||
offset = offset + palette_length
|
||||
self.palette = ImagePalette.raw("RGB;L", self.fp.read(palette_length))
|
||||
|
@ -124,7 +128,8 @@ class SunImageFile(ImageFile.ImageFile):
|
|||
elif file_type == 2:
|
||||
self.tile = [("sun_rle", (0, 0) + self.size, offset, rawmode)]
|
||||
else:
|
||||
raise SyntaxError("Unsupported Sun Raster file type")
|
||||
msg = "Unsupported Sun Raster file type"
|
||||
raise SyntaxError(msg)
|
||||
|
||||
|
||||
#
|
||||
|
|
|
@ -35,12 +35,14 @@ class TarIO(ContainerIO.ContainerIO):
|
|||
|
||||
s = self.fh.read(512)
|
||||
if len(s) != 512:
|
||||
raise OSError("unexpected end of tar file")
|
||||
msg = "unexpected end of tar file"
|
||||
raise OSError(msg)
|
||||
|
||||
name = s[:100].decode("utf-8")
|
||||
i = name.find("\0")
|
||||
if i == 0:
|
||||
raise OSError("cannot find subfile")
|
||||
msg = "cannot find subfile"
|
||||
raise OSError(msg)
|
||||
if i > 0:
|
||||
name = name[:i]
|
||||
|
||||
|
|
|
@ -73,7 +73,8 @@ class TgaImageFile(ImageFile.ImageFile):
|
|||
or self.size[1] <= 0
|
||||
or depth not in (1, 8, 16, 24, 32)
|
||||
):
|
||||
raise SyntaxError("not a TGA file")
|
||||
msg = "not a TGA file"
|
||||
raise SyntaxError(msg)
|
||||
|
||||
# image mode
|
||||
if imagetype in (3, 11):
|
||||
|
@ -89,7 +90,8 @@ class TgaImageFile(ImageFile.ImageFile):
|
|||
if depth == 32:
|
||||
self.mode = "RGBA"
|
||||
else:
|
||||
raise SyntaxError("unknown TGA mode")
|
||||
msg = "unknown TGA mode"
|
||||
raise SyntaxError(msg)
|
||||
|
||||
# orientation
|
||||
orientation = flags & 0x30
|
||||
|
@ -99,7 +101,8 @@ class TgaImageFile(ImageFile.ImageFile):
|
|||
elif orientation in [0, 0x10]:
|
||||
orientation = -1
|
||||
else:
|
||||
raise SyntaxError("unknown TGA orientation")
|
||||
msg = "unknown TGA orientation"
|
||||
raise SyntaxError(msg)
|
||||
|
||||
self.info["orientation"] = orientation
|
||||
|
||||
|
@ -175,7 +178,8 @@ def _save(im, fp, filename):
|
|||
try:
|
||||
rawmode, bits, colormaptype, imagetype = SAVE[im.mode]
|
||||
except KeyError as e:
|
||||
raise OSError(f"cannot write mode {im.mode} as TGA") from e
|
||||
msg = f"cannot write mode {im.mode} as TGA"
|
||||
raise OSError(msg) from e
|
||||
|
||||
if "rle" in im.encoderinfo:
|
||||
rle = im.encoderinfo["rle"]
|
||||
|
|
|
@ -500,14 +500,16 @@ class ImageFileDirectory_v2(MutableMapping):
|
|||
:param prefix: Override the endianness of the file.
|
||||
"""
|
||||
if not _accept(ifh):
|
||||
raise SyntaxError(f"not a TIFF file (header {repr(ifh)} not valid)")
|
||||
msg = f"not a TIFF file (header {repr(ifh)} not valid)"
|
||||
raise SyntaxError(msg)
|
||||
self._prefix = prefix if prefix is not None else ifh[:2]
|
||||
if self._prefix == MM:
|
||||
self._endian = ">"
|
||||
elif self._prefix == II:
|
||||
self._endian = "<"
|
||||
else:
|
||||
raise SyntaxError("not a TIFF IFD")
|
||||
msg = "not a TIFF IFD"
|
||||
raise SyntaxError(msg)
|
||||
self._bigtiff = ifh[2] == 43
|
||||
self.group = group
|
||||
self.tagtype = {}
|
||||
|
@ -524,7 +526,8 @@ class ImageFileDirectory_v2(MutableMapping):
|
|||
|
||||
@legacy_api.setter
|
||||
def legacy_api(self, value):
|
||||
raise Exception("Not allowing setting of legacy api")
|
||||
msg = "Not allowing setting of legacy api"
|
||||
raise Exception(msg)
|
||||
|
||||
def reset(self):
|
||||
self._tags_v1 = {} # will remain empty if legacy_api is false
|
||||
|
@ -732,6 +735,8 @@ class ImageFileDirectory_v2(MutableMapping):
|
|||
@_register_writer(2)
|
||||
def write_string(self, value):
|
||||
# remerge of https://github.com/python-pillow/Pillow/pull/1416
|
||||
if isinstance(value, int):
|
||||
value = str(value)
|
||||
if not isinstance(value, bytes):
|
||||
value = value.encode("ascii", "replace")
|
||||
return value + b"\0"
|
||||
|
@ -778,10 +783,11 @@ class ImageFileDirectory_v2(MutableMapping):
|
|||
def _ensure_read(self, fp, size):
|
||||
ret = fp.read(size)
|
||||
if len(ret) != size:
|
||||
raise OSError(
|
||||
msg = (
|
||||
"Corrupt EXIF data. "
|
||||
f"Expecting to read {size} bytes but only got {len(ret)}. "
|
||||
)
|
||||
raise OSError(msg)
|
||||
return ret
|
||||
|
||||
def load(self, fp):
|
||||
|
@ -908,7 +914,8 @@ class ImageFileDirectory_v2(MutableMapping):
|
|||
if stripoffsets is not None:
|
||||
tag, typ, count, value, data = entries[stripoffsets]
|
||||
if data:
|
||||
raise NotImplementedError("multistrip support not yet implemented")
|
||||
msg = "multistrip support not yet implemented"
|
||||
raise NotImplementedError(msg)
|
||||
value = self._pack("L", self._unpack("L", value)[0] + offset)
|
||||
entries[stripoffsets] = tag, typ, count, value, data
|
||||
|
||||
|
@ -1121,7 +1128,8 @@ class TiffImageFile(ImageFile.ImageFile):
|
|||
|
||||
while len(self._frame_pos) <= frame:
|
||||
if not self.__next:
|
||||
raise EOFError("no more images in TIFF file")
|
||||
msg = "no more images in TIFF file"
|
||||
raise EOFError(msg)
|
||||
logger.debug(
|
||||
f"Seeking to frame {frame}, on frame {self.__frame}, "
|
||||
f"__next {self.__next}, location: {self.fp.tell()}"
|
||||
|
@ -1228,7 +1236,8 @@ class TiffImageFile(ImageFile.ImageFile):
|
|||
self.load_prepare()
|
||||
|
||||
if not len(self.tile) == 1:
|
||||
raise OSError("Not exactly one tile")
|
||||
msg = "Not exactly one tile"
|
||||
raise OSError(msg)
|
||||
|
||||
# (self._compression, (extents tuple),
|
||||
# 0, (rawmode, self._compression, fp))
|
||||
|
@ -1260,7 +1269,8 @@ class TiffImageFile(ImageFile.ImageFile):
|
|||
try:
|
||||
decoder.setimage(self.im, extents)
|
||||
except ValueError as e:
|
||||
raise OSError("Couldn't set the image") from e
|
||||
msg = "Couldn't set the image"
|
||||
raise OSError(msg) from e
|
||||
|
||||
close_self_fp = self._exclusive_fp and not self.is_animated
|
||||
if hasattr(self.fp, "getvalue"):
|
||||
|
@ -1314,7 +1324,8 @@ class TiffImageFile(ImageFile.ImageFile):
|
|||
"""Setup this image object based on current tags"""
|
||||
|
||||
if 0xBC01 in self.tag_v2:
|
||||
raise OSError("Windows Media Photo files not yet supported")
|
||||
msg = "Windows Media Photo files not yet supported"
|
||||
raise OSError(msg)
|
||||
|
||||
# extract relevant tags
|
||||
self._compression = COMPRESSION_INFO[self.tag_v2.get(COMPRESSION, 1)]
|
||||
|
@ -1373,7 +1384,8 @@ class TiffImageFile(ImageFile.ImageFile):
|
|||
logger.error(
|
||||
"More samples per pixel than can be decoded: %s", samples_per_pixel
|
||||
)
|
||||
raise SyntaxError("Invalid value for samples per pixel")
|
||||
msg = "Invalid value for samples per pixel"
|
||||
raise SyntaxError(msg)
|
||||
|
||||
if samples_per_pixel < bps_actual_count:
|
||||
# If a file has more values in bps_tuple than expected,
|
||||
|
@ -1385,7 +1397,8 @@ class TiffImageFile(ImageFile.ImageFile):
|
|||
bps_tuple = bps_tuple * samples_per_pixel
|
||||
|
||||
if len(bps_tuple) != samples_per_pixel:
|
||||
raise SyntaxError("unknown data organization")
|
||||
msg = "unknown data organization"
|
||||
raise SyntaxError(msg)
|
||||
|
||||
# mode: check photometric interpretation and bits per pixel
|
||||
key = (
|
||||
|
@ -1401,7 +1414,8 @@ class TiffImageFile(ImageFile.ImageFile):
|
|||
self.mode, rawmode = OPEN_INFO[key]
|
||||
except KeyError as e:
|
||||
logger.debug("- unsupported format")
|
||||
raise SyntaxError("unknown pixel mode") from e
|
||||
msg = "unknown pixel mode"
|
||||
raise SyntaxError(msg) from e
|
||||
|
||||
logger.debug(f"- raw mode: {rawmode}")
|
||||
logger.debug(f"- pil mode: {self.mode}")
|
||||
|
@ -1517,7 +1531,8 @@ class TiffImageFile(ImageFile.ImageFile):
|
|||
layer += 1
|
||||
else:
|
||||
logger.debug("- unsupported data organization")
|
||||
raise SyntaxError("unknown data organization")
|
||||
msg = "unknown data organization"
|
||||
raise SyntaxError(msg)
|
||||
|
||||
# Fix up info.
|
||||
if ICCPROFILE in self.tag_v2:
|
||||
|
@ -1569,7 +1584,8 @@ def _save(im, fp, filename):
|
|||
try:
|
||||
rawmode, prefix, photo, format, bits, extra = SAVE_INFO[im.mode]
|
||||
except KeyError as e:
|
||||
raise OSError(f"cannot write mode {im.mode} as TIFF") from e
|
||||
msg = f"cannot write mode {im.mode} as TIFF"
|
||||
raise OSError(msg) from e
|
||||
|
||||
ifd = ImageFileDirectory_v2(prefix=prefix)
|
||||
|
||||
|
@ -1734,11 +1750,11 @@ def _save(im, fp, filename):
|
|||
if "quality" in encoderinfo:
|
||||
quality = encoderinfo["quality"]
|
||||
if not isinstance(quality, int) or quality < 0 or quality > 100:
|
||||
raise ValueError("Invalid quality setting")
|
||||
msg = "Invalid quality setting"
|
||||
raise ValueError(msg)
|
||||
if compression != "jpeg":
|
||||
raise ValueError(
|
||||
"quality setting only supported for 'jpeg' compression"
|
||||
)
|
||||
msg = "quality setting only supported for 'jpeg' compression"
|
||||
raise ValueError(msg)
|
||||
ifd[JPEGQUALITY] = quality
|
||||
|
||||
logger.debug("Saving using libtiff encoder")
|
||||
|
@ -1835,7 +1851,8 @@ def _save(im, fp, filename):
|
|||
if s:
|
||||
break
|
||||
if s < 0:
|
||||
raise OSError(f"encoder error {s} when writing image file")
|
||||
msg = f"encoder error {s} when writing image file"
|
||||
raise OSError(msg)
|
||||
|
||||
else:
|
||||
for tag in blocklist:
|
||||
|
@ -1910,7 +1927,8 @@ class AppendingTiffWriter:
|
|||
elif iimm == b"MM\x00\x2a":
|
||||
self.setEndian(">")
|
||||
else:
|
||||
raise RuntimeError("Invalid TIFF file header")
|
||||
msg = "Invalid TIFF file header"
|
||||
raise RuntimeError(msg)
|
||||
|
||||
self.skipIFDs()
|
||||
self.goToEnd()
|
||||
|
@ -1924,12 +1942,14 @@ class AppendingTiffWriter:
|
|||
|
||||
iimm = self.f.read(4)
|
||||
if not iimm:
|
||||
# raise RuntimeError("nothing written into new page")
|
||||
# msg = "nothing written into new page"
|
||||
# raise RuntimeError(msg)
|
||||
# Make it easy to finish a frame without committing to a new one.
|
||||
return
|
||||
|
||||
if iimm != self.IIMM:
|
||||
raise RuntimeError("IIMM of new page doesn't match IIMM of first page")
|
||||
msg = "IIMM of new page doesn't match IIMM of first page"
|
||||
raise RuntimeError(msg)
|
||||
|
||||
ifd_offset = self.readLong()
|
||||
ifd_offset += self.offsetOfNewPage
|
||||
|
@ -2003,29 +2023,34 @@ class AppendingTiffWriter:
|
|||
self.f.seek(-2, os.SEEK_CUR)
|
||||
bytes_written = self.f.write(struct.pack(self.longFmt, value))
|
||||
if bytes_written is not None and bytes_written != 4:
|
||||
raise RuntimeError(f"wrote only {bytes_written} bytes but wanted 4")
|
||||
msg = f"wrote only {bytes_written} bytes but wanted 4"
|
||||
raise RuntimeError(msg)
|
||||
|
||||
def rewriteLastShort(self, value):
|
||||
self.f.seek(-2, os.SEEK_CUR)
|
||||
bytes_written = self.f.write(struct.pack(self.shortFmt, value))
|
||||
if bytes_written is not None and bytes_written != 2:
|
||||
raise RuntimeError(f"wrote only {bytes_written} bytes but wanted 2")
|
||||
msg = f"wrote only {bytes_written} bytes but wanted 2"
|
||||
raise RuntimeError(msg)
|
||||
|
||||
def rewriteLastLong(self, value):
|
||||
self.f.seek(-4, os.SEEK_CUR)
|
||||
bytes_written = self.f.write(struct.pack(self.longFmt, value))
|
||||
if bytes_written is not None and bytes_written != 4:
|
||||
raise RuntimeError(f"wrote only {bytes_written} bytes but wanted 4")
|
||||
msg = f"wrote only {bytes_written} bytes but wanted 4"
|
||||
raise RuntimeError(msg)
|
||||
|
||||
def writeShort(self, value):
|
||||
bytes_written = self.f.write(struct.pack(self.shortFmt, value))
|
||||
if bytes_written is not None and bytes_written != 2:
|
||||
raise RuntimeError(f"wrote only {bytes_written} bytes but wanted 2")
|
||||
msg = f"wrote only {bytes_written} bytes but wanted 2"
|
||||
raise RuntimeError(msg)
|
||||
|
||||
def writeLong(self, value):
|
||||
bytes_written = self.f.write(struct.pack(self.longFmt, value))
|
||||
if bytes_written is not None and bytes_written != 4:
|
||||
raise RuntimeError(f"wrote only {bytes_written} bytes but wanted 4")
|
||||
msg = f"wrote only {bytes_written} bytes but wanted 4"
|
||||
raise RuntimeError(msg)
|
||||
|
||||
def close(self):
|
||||
self.finalize()
|
||||
|
@ -2068,7 +2093,8 @@ class AppendingTiffWriter:
|
|||
|
||||
def fixOffsets(self, count, isShort=False, isLong=False):
|
||||
if not isShort and not isLong:
|
||||
raise RuntimeError("offset is neither short nor long")
|
||||
msg = "offset is neither short nor long"
|
||||
raise RuntimeError(msg)
|
||||
|
||||
for i in range(count):
|
||||
offset = self.readShort() if isShort else self.readLong()
|
||||
|
@ -2076,7 +2102,8 @@ class AppendingTiffWriter:
|
|||
if isShort and offset >= 65536:
|
||||
# offset is now too large - we must convert shorts to longs
|
||||
if count != 1:
|
||||
raise RuntimeError("not implemented") # XXX TODO
|
||||
msg = "not implemented"
|
||||
raise RuntimeError(msg) # XXX TODO
|
||||
|
||||
# simple case - the offset is just one and therefore it is
|
||||
# local (not referenced with another offset)
|
||||
|
|
|
@ -130,7 +130,8 @@ class WebPImageFile(ImageFile.ImageFile):
|
|||
if ret is None:
|
||||
self._reset() # Reset just to be safe
|
||||
self.seek(0)
|
||||
raise EOFError("failed to decode next frame in WebP file")
|
||||
msg = "failed to decode next frame in WebP file"
|
||||
raise EOFError(msg)
|
||||
|
||||
# Compute duration
|
||||
data, timestamp = ret
|
||||
|
@ -233,9 +234,8 @@ def _save_all(im, fp, filename):
|
|||
or len(background) != 4
|
||||
or not all(0 <= v < 256 for v in background)
|
||||
):
|
||||
raise OSError(
|
||||
f"Background color is not an RGBA tuple clamped to (0-255): {background}"
|
||||
)
|
||||
msg = f"Background color is not an RGBA tuple clamped to (0-255): {background}"
|
||||
raise OSError(msg)
|
||||
|
||||
# Convert to packed uint
|
||||
bg_r, bg_g, bg_b, bg_a = background
|
||||
|
@ -311,7 +311,8 @@ def _save_all(im, fp, filename):
|
|||
# Get the final output from the encoder
|
||||
data = enc.assemble(icc_profile, exif, xmp)
|
||||
if data is None:
|
||||
raise OSError("cannot write file as WebP (encoder returned None)")
|
||||
msg = "cannot write file as WebP (encoder returned None)"
|
||||
raise OSError(msg)
|
||||
|
||||
fp.write(data)
|
||||
|
||||
|
@ -351,7 +352,8 @@ def _save(im, fp, filename):
|
|||
xmp,
|
||||
)
|
||||
if data is None:
|
||||
raise OSError("cannot write file as WebP (encoder returned None)")
|
||||
msg = "cannot write file as WebP (encoder returned None)"
|
||||
raise OSError(msg)
|
||||
|
||||
fp.write(data)
|
||||
|
||||
|
|
|
@ -109,7 +109,8 @@ class WmfStubImageFile(ImageFile.StubImageFile):
|
|||
|
||||
# sanity check (standard metafile header)
|
||||
if s[22:26] != b"\x01\x00\t\x00":
|
||||
raise SyntaxError("Unsupported WMF file format")
|
||||
msg = "Unsupported WMF file format"
|
||||
raise SyntaxError(msg)
|
||||
|
||||
elif s[:4] == b"\x01\x00\x00\x00" and s[40:44] == b" EMF":
|
||||
# enhanced metafile
|
||||
|
@ -137,7 +138,8 @@ class WmfStubImageFile(ImageFile.StubImageFile):
|
|||
self.info["dpi"] = xdpi, ydpi
|
||||
|
||||
else:
|
||||
raise SyntaxError("Unsupported file format")
|
||||
msg = "Unsupported file format"
|
||||
raise SyntaxError(msg)
|
||||
|
||||
self.mode = "RGB"
|
||||
self._size = size
|
||||
|
@ -162,7 +164,8 @@ class WmfStubImageFile(ImageFile.StubImageFile):
|
|||
|
||||
def _save(im, fp, filename):
|
||||
if _handler is None or not hasattr(_handler, "save"):
|
||||
raise OSError("WMF save handler not installed")
|
||||
msg = "WMF save handler not installed"
|
||||
raise OSError(msg)
|
||||
_handler.save(im, fp, filename)
|
||||
|
||||
|
||||
|
|
|
@ -49,7 +49,8 @@ class XVThumbImageFile(ImageFile.ImageFile):
|
|||
|
||||
# check magic
|
||||
if not _accept(self.fp.read(6)):
|
||||
raise SyntaxError("not an XV thumbnail file")
|
||||
msg = "not an XV thumbnail file"
|
||||
raise SyntaxError(msg)
|
||||
|
||||
# Skip to beginning of next line
|
||||
self.fp.readline()
|
||||
|
@ -58,7 +59,8 @@ class XVThumbImageFile(ImageFile.ImageFile):
|
|||
while True:
|
||||
s = self.fp.readline()
|
||||
if not s:
|
||||
raise SyntaxError("Unexpected EOF reading XV thumbnail file")
|
||||
msg = "Unexpected EOF reading XV thumbnail file"
|
||||
raise SyntaxError(msg)
|
||||
if s[0] != 35: # ie. when not a comment: '#'
|
||||
break
|
||||
|
||||
|
|
|
@ -53,7 +53,8 @@ class XbmImageFile(ImageFile.ImageFile):
|
|||
m = xbm_head.match(self.fp.read(512))
|
||||
|
||||
if not m:
|
||||
raise SyntaxError("not a XBM file")
|
||||
msg = "not a XBM file"
|
||||
raise SyntaxError(msg)
|
||||
|
||||
xsize = int(m.group("width"))
|
||||
ysize = int(m.group("height"))
|
||||
|
@ -70,7 +71,8 @@ class XbmImageFile(ImageFile.ImageFile):
|
|||
def _save(im, fp, filename):
|
||||
|
||||
if im.mode != "1":
|
||||
raise OSError(f"cannot write mode {im.mode} as XBM")
|
||||
msg = f"cannot write mode {im.mode} as XBM"
|
||||
raise OSError(msg)
|
||||
|
||||
fp.write(f"#define im_width {im.size[0]}\n".encode("ascii"))
|
||||
fp.write(f"#define im_height {im.size[1]}\n".encode("ascii"))
|
||||
|
|
|
@ -40,13 +40,15 @@ class XpmImageFile(ImageFile.ImageFile):
|
|||
def _open(self):
|
||||
|
||||
if not _accept(self.fp.read(9)):
|
||||
raise SyntaxError("not an XPM file")
|
||||
msg = "not an XPM file"
|
||||
raise SyntaxError(msg)
|
||||
|
||||
# skip forward to next string
|
||||
while True:
|
||||
s = self.fp.readline()
|
||||
if not s:
|
||||
raise SyntaxError("broken XPM file")
|
||||
msg = "broken XPM file"
|
||||
raise SyntaxError(msg)
|
||||
m = xpm_head.match(s)
|
||||
if m:
|
||||
break
|
||||
|
@ -57,7 +59,8 @@ class XpmImageFile(ImageFile.ImageFile):
|
|||
bpp = int(m.group(4))
|
||||
|
||||
if pal > 256 or bpp != 1:
|
||||
raise ValueError("cannot read this XPM file")
|
||||
msg = "cannot read this XPM file"
|
||||
raise ValueError(msg)
|
||||
|
||||
#
|
||||
# load palette description
|
||||
|
@ -91,13 +94,15 @@ class XpmImageFile(ImageFile.ImageFile):
|
|||
)
|
||||
else:
|
||||
# unknown colour
|
||||
raise ValueError("cannot read this XPM file")
|
||||
msg = "cannot read this XPM file"
|
||||
raise ValueError(msg)
|
||||
break
|
||||
|
||||
else:
|
||||
|
||||
# missing colour key
|
||||
raise ValueError("cannot read this XPM file")
|
||||
msg = "cannot read this XPM file"
|
||||
raise ValueError(msg)
|
||||
|
||||
self.mode = "P"
|
||||
self.palette = ImagePalette.raw("RGB", b"".join(palette))
|
||||
|
|
|
@ -43,14 +43,17 @@ def deprecate(
|
|||
if when is None:
|
||||
removed = "a future version"
|
||||
elif when <= int(__version__.split(".")[0]):
|
||||
raise RuntimeError(f"{deprecated} {is_} deprecated and should be removed.")
|
||||
msg = f"{deprecated} {is_} deprecated and should be removed."
|
||||
raise RuntimeError(msg)
|
||||
elif when == 10:
|
||||
removed = "Pillow 10 (2023-07-01)"
|
||||
else:
|
||||
raise ValueError(f"Unknown removal version, update {__name__}?")
|
||||
msg = f"Unknown removal version, update {__name__}?"
|
||||
raise ValueError(msg)
|
||||
|
||||
if replacement and action:
|
||||
raise ValueError("Use only one of 'replacement' and 'action'")
|
||||
msg = "Use only one of 'replacement' and 'action'"
|
||||
raise ValueError(msg)
|
||||
|
||||
if replacement:
|
||||
action = f". Use {replacement} instead."
|
||||
|
|
|
@ -25,7 +25,8 @@ def check_module(feature):
|
|||
:raises ValueError: If the module is not defined in this version of Pillow.
|
||||
"""
|
||||
if not (feature in modules):
|
||||
raise ValueError(f"Unknown module {feature}")
|
||||
msg = f"Unknown module {feature}"
|
||||
raise ValueError(msg)
|
||||
|
||||
module, ver = modules[feature]
|
||||
|
||||
|
@ -78,7 +79,8 @@ def check_codec(feature):
|
|||
:raises ValueError: If the codec is not defined in this version of Pillow.
|
||||
"""
|
||||
if feature not in codecs:
|
||||
raise ValueError(f"Unknown codec {feature}")
|
||||
msg = f"Unknown codec {feature}"
|
||||
raise ValueError(msg)
|
||||
|
||||
codec, lib = codecs[feature]
|
||||
|
||||
|
@ -135,7 +137,8 @@ def check_feature(feature):
|
|||
:raises ValueError: If the feature is not defined in this version of Pillow.
|
||||
"""
|
||||
if feature not in features:
|
||||
raise ValueError(f"Unknown feature {feature}")
|
||||
msg = f"Unknown feature {feature}"
|
||||
raise ValueError(msg)
|
||||
|
||||
module, flag, ver = features[feature]
|
||||
|
||||
|
|
|
@ -1531,25 +1531,21 @@ if (PySequence_Check(op)) { \
|
|||
PyErr_SetString(PyExc_TypeError, must_be_sequence);
|
||||
return NULL;
|
||||
}
|
||||
int endian = strncmp(image->mode, "I;16", 4) == 0 ? (strcmp(image->mode, "I;16B") == 0 ? 2 : 1) : 0;
|
||||
double value;
|
||||
if (scale == 1.0 && offset == 0.0) {
|
||||
/* Clipped data */
|
||||
for (i = x = y = 0; i < n; i++) {
|
||||
set_value_to_item(seq, i);
|
||||
image->image8[y][x] = (UINT8)CLIP8(value);
|
||||
if (++x >= (int)image->xsize) {
|
||||
x = 0, y++;
|
||||
}
|
||||
for (i = x = y = 0; i < n; i++) {
|
||||
set_value_to_item(seq, i);
|
||||
if (scale != 1.0 || offset != 0.0) {
|
||||
value = value * scale + offset;
|
||||
}
|
||||
|
||||
} else {
|
||||
/* Scaled and clipped data */
|
||||
for (i = x = y = 0; i < n; i++) {
|
||||
set_value_to_item(seq, i);
|
||||
image->image8[y][x] = CLIP8(value * scale + offset);
|
||||
if (++x >= (int)image->xsize) {
|
||||
x = 0, y++;
|
||||
}
|
||||
if (endian == 0) {
|
||||
image->image8[y][x] = (UINT8)CLIP8(value);
|
||||
} else {
|
||||
image->image8[y][x * 2 + (endian == 2 ? 1 : 0)] = CLIP8((int)value % 256);
|
||||
image->image8[y][x * 2 + (endian == 2 ? 0 : 1)] = CLIP8((int)value >> 8);
|
||||
}
|
||||
if (++x >= (int)image->xsize) {
|
||||
x = 0, y++;
|
||||
}
|
||||
}
|
||||
PyErr_Clear(); /* Avoid weird exceptions */
|
||||
|
|
|
@ -1212,11 +1212,12 @@ PyImaging_Jpeg2KEncoderNew(PyObject *self, PyObject *args) {
|
|||
char *cinema_mode = "no";
|
||||
OPJ_CINEMA_MODE cine_mode;
|
||||
char mct = 0;
|
||||
int sgnd = 0;
|
||||
Py_ssize_t fd = -1;
|
||||
|
||||
if (!PyArg_ParseTuple(
|
||||
args,
|
||||
"ss|OOOsOnOOOssbn",
|
||||
"ss|OOOsOnOOOssbbn",
|
||||
&mode,
|
||||
&format,
|
||||
&offset,
|
||||
|
@ -1231,6 +1232,7 @@ PyImaging_Jpeg2KEncoderNew(PyObject *self, PyObject *args) {
|
|||
&progression,
|
||||
&cinema_mode,
|
||||
&mct,
|
||||
&sgnd,
|
||||
&fd)) {
|
||||
return NULL;
|
||||
}
|
||||
|
@ -1329,6 +1331,7 @@ PyImaging_Jpeg2KEncoderNew(PyObject *self, PyObject *args) {
|
|||
context->progression = prog_order;
|
||||
context->cinema_mode = cine_mode;
|
||||
context->mct = mct;
|
||||
context->sgnd = sgnd;
|
||||
|
||||
return (PyObject *)encoder;
|
||||
}
|
||||
|
|
|
@ -479,6 +479,25 @@ rgba2rgbA(UINT8 *out, const UINT8 *in, int xsize) {
|
|||
}
|
||||
}
|
||||
|
||||
static void
|
||||
rgba2rgb_(UINT8 *out, const UINT8 *in, int xsize) {
|
||||
int x;
|
||||
unsigned int alpha;
|
||||
for (x = 0; x < xsize; x++, in += 4) {
|
||||
alpha = in[3];
|
||||
if (alpha == 255 || alpha == 0) {
|
||||
*out++ = in[0];
|
||||
*out++ = in[1];
|
||||
*out++ = in[2];
|
||||
} else {
|
||||
*out++ = CLIP8((255 * in[0]) / alpha);
|
||||
*out++ = CLIP8((255 * in[1]) / alpha);
|
||||
*out++ = CLIP8((255 * in[2]) / alpha);
|
||||
}
|
||||
*out++ = 255;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Conversion of RGB + single transparent color to RGBA,
|
||||
* where any pixel that matches the color will have the
|
||||
|
@ -934,6 +953,7 @@ static struct {
|
|||
{"RGBA", "HSV", rgb2hsv},
|
||||
|
||||
{"RGBa", "RGBA", rgba2rgbA},
|
||||
{"RGBa", "RGB", rgba2rgb_},
|
||||
|
||||
{"RGBX", "1", rgb2bit},
|
||||
{"RGBX", "L", rgb2l},
|
||||
|
|
|
@ -85,6 +85,9 @@ typedef struct {
|
|||
/* Set multiple component transformation */
|
||||
char mct;
|
||||
|
||||
/* Signed */
|
||||
int sgnd;
|
||||
|
||||
/* Progression order (LRCP/RLCP/RPCL/PCRL/CPRL) */
|
||||
OPJ_PROG_ORDER progression;
|
||||
|
||||
|
|
|
@ -343,7 +343,7 @@ j2k_encode_entry(Imaging im, ImagingCodecState state) {
|
|||
image_params[n].x0 = image_params[n].y0 = 0;
|
||||
image_params[n].prec = prec;
|
||||
image_params[n].bpp = bpp;
|
||||
image_params[n].sgnd = 0;
|
||||
image_params[n].sgnd = context->sgnd == 0 ? 0 : 1;
|
||||
}
|
||||
|
||||
image = opj_image_create(components, image_params, color_space);
|
||||
|
|
|
@ -289,7 +289,7 @@ deps = {
|
|||
# "bins": [r"objs\{msbuild_arch}\Release\freetype.dll"],
|
||||
},
|
||||
"lcms2": {
|
||||
"url": SF_PROJECTS + "/lcms/files/lcms/2.13/lcms2-2.14.tar.gz/download",
|
||||
"url": SF_PROJECTS + "/lcms/files/lcms/2.14/lcms2-2.14.tar.gz/download",
|
||||
"filename": "lcms2-2.14.tar.gz",
|
||||
"dir": "lcms2-2.14",
|
||||
"license": "COPYING",
|
||||
|
@ -319,6 +319,11 @@ deps = {
|
|||
"filename": "openjpeg-2.5.0.tar.gz",
|
||||
"dir": "openjpeg-2.5.0",
|
||||
"license": "LICENSE",
|
||||
"patch": {
|
||||
r"src\lib\openjp2\ht_dec.c": {
|
||||
"#ifdef OPJ_COMPILER_MSVC\n return (OPJ_UINT32)__popcnt(val);": "#if defined(OPJ_COMPILER_MSVC) && (defined(_M_IX86) || defined(_M_AMD64))\n return (OPJ_UINT32)__popcnt(val);", # noqa: E501
|
||||
}
|
||||
},
|
||||
"build": [
|
||||
cmd_cmake(("-DBUILD_CODEC:BOOL=OFF", "-DBUILD_SHARED_LIBS:BOOL=OFF")),
|
||||
cmd_nmake(target="clean"),
|
||||
|
@ -473,7 +478,8 @@ def extract_dep(url, filename):
|
|||
member_abspath = os.path.abspath(os.path.join(sources_dir, member))
|
||||
member_prefix = os.path.commonpath([sources_dir_abs, member_abspath])
|
||||
if sources_dir_abs != member_prefix:
|
||||
raise RuntimeError("Attempted Path Traversal in Zip File")
|
||||
msg = "Attempted Path Traversal in Zip File"
|
||||
raise RuntimeError(msg)
|
||||
zf.extractall(sources_dir)
|
||||
elif filename.endswith(".tar.gz") or filename.endswith(".tgz"):
|
||||
with tarfile.open(file, "r:gz") as tgz:
|
||||
|
@ -481,10 +487,12 @@ def extract_dep(url, filename):
|
|||
member_abspath = os.path.abspath(os.path.join(sources_dir, member))
|
||||
member_prefix = os.path.commonpath([sources_dir_abs, member_abspath])
|
||||
if sources_dir_abs != member_prefix:
|
||||
raise RuntimeError("Attempted Path Traversal in Tar File")
|
||||
msg = "Attempted Path Traversal in Tar File"
|
||||
raise RuntimeError(msg)
|
||||
tgz.extractall(sources_dir)
|
||||
else:
|
||||
raise RuntimeError("Unknown archive type: " + filename)
|
||||
msg = "Unknown archive type: " + filename
|
||||
raise RuntimeError(msg)
|
||||
|
||||
|
||||
def write_script(name, lines):
|
||||
|
@ -621,7 +629,8 @@ if __name__ == "__main__":
|
|||
elif arg == "--srcdir":
|
||||
sources_dir = os.path.sep + "src"
|
||||
else:
|
||||
raise ValueError("Unknown parameter: " + arg)
|
||||
msg = "Unknown parameter: " + arg
|
||||
raise ValueError(msg)
|
||||
|
||||
# dependency cache directory
|
||||
os.makedirs(depends_dir, exist_ok=True)
|
||||
|
@ -637,9 +646,8 @@ if __name__ == "__main__":
|
|||
|
||||
msvs = find_msvs()
|
||||
if msvs is None:
|
||||
raise RuntimeError(
|
||||
"Visual Studio not found. Please install Visual Studio 2017 or newer."
|
||||
)
|
||||
msg = "Visual Studio not found. Please install Visual Studio 2017 or newer."
|
||||
raise RuntimeError(msg)
|
||||
print("Found Visual Studio at:", msvs["vs_dir"])
|
||||
|
||||
print("Using output directory:", build_dir)
|
||||
|
|
Loading…
Reference in New Issue
Block a user