Merge branch 'main' into enum

This commit is contained in:
Andrew Murray 2022-12-31 09:37:56 +11:00
commit b4347daa3c
93 changed files with 1051 additions and 547 deletions

View File

@ -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

View File

@ -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]

View File

@ -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:

View File

@ -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):

View File

@ -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

View File

@ -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]

View File

@ -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()

View File

@ -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

View File

@ -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
-----------

View File

@ -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),

View File

@ -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))]

View File

@ -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
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

View File

@ -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)

View File

@ -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 = []

View File

@ -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)

View File

@ -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

View File

@ -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)

View File

@ -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)

View File

@ -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 = []

View File

@ -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]

View File

@ -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:
#

View File

@ -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:

View File

@ -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)
# --------------------------------------------------------------------

View File

@ -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

View File

@ -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:

View File

@ -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)

View File

@ -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]

View File

@ -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

View File

@ -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:

View File

@ -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))

View File

@ -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])

View File

@ -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)

View File

@ -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)

View File

@ -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):

View File

@ -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):

View File

@ -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)

View File

@ -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))

View File

@ -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)

View File

@ -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):

View File

@ -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):

View File

@ -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):

View File

@ -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

View File

@ -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():

View File

@ -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

View File

@ -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)

View File

@ -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)

View File

@ -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)

View File

@ -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

View File

@ -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)

View File

@ -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)

View File

@ -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:

View File

@ -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):

View File

@ -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)

View File

@ -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

View File

@ -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):

View File

@ -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,
)

View File

@ -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)

View File

@ -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]

View File

@ -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)

View File

@ -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)

View File

@ -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

View File

@ -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

View File

@ -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:

View File

@ -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

View File

@ -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

View File

@ -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):

View File

@ -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

View File

@ -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":

View File

@ -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(

View File

@ -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)

View File

@ -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")

View File

@ -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")

View File

@ -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)):

View File

@ -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

View File

@ -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

View File

@ -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)

View File

@ -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)
#

View File

@ -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]

View File

@ -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"]

View File

@ -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)

View File

@ -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)

View File

@ -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)

View File

@ -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

View File

@ -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"))

View File

@ -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))

View File

@ -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."

View File

@ -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]

View File

@ -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 */

View File

@ -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;
}

View File

@ -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},

View File

@ -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;

View File

@ -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);

View File

@ -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)