mirror of
https://github.com/python-pillow/Pillow.git
synced 2024-12-25 17:36:18 +03:00
Improve exception traceback readability
This commit is contained in:
parent
77f6f54ac4
commit
2ae55ccbda
|
@ -35,7 +35,8 @@ repos:
|
||||||
rev: 6.0.0
|
rev: 6.0.0
|
||||||
hooks:
|
hooks:
|
||||||
- id: flake8
|
- 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
|
- repo: https://github.com/pre-commit/pygrep-hooks
|
||||||
rev: v1.9.0
|
rev: v1.9.0
|
||||||
|
|
|
@ -211,13 +211,16 @@ class DdsImageFile(ImageFile.ImageFile):
|
||||||
|
|
||||||
def _open(self):
|
def _open(self):
|
||||||
if not _accept(self.fp.read(4)):
|
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))
|
(header_size,) = struct.unpack("<I", self.fp.read(4))
|
||||||
if header_size != 124:
|
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)
|
header_bytes = self.fp.read(header_size - 4)
|
||||||
if len(header_bytes) != 120:
|
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)
|
header = BytesIO(header_bytes)
|
||||||
|
|
||||||
flags, height, width = struct.unpack("<3I", header.read(12))
|
flags, height, width = struct.unpack("<3I", header.read(12))
|
||||||
|
@ -237,7 +240,8 @@ class DdsImageFile(ImageFile.ImageFile):
|
||||||
elif fourcc == b"DXT5":
|
elif fourcc == b"DXT5":
|
||||||
self.decoder = "DXT5"
|
self.decoder = "DXT5"
|
||||||
else:
|
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))]
|
self.tile = [(self.decoder, (0, 0) + self.size, 0, (self.mode, 0, 1))]
|
||||||
|
|
||||||
|
@ -252,7 +256,8 @@ class DXT1Decoder(ImageFile.PyDecoder):
|
||||||
try:
|
try:
|
||||||
self.set_as_raw(_dxt1(self.fd, self.state.xsize, self.state.ysize))
|
self.set_as_raw(_dxt1(self.fd, self.state.xsize, self.state.ysize))
|
||||||
except struct.error as e:
|
except struct.error as e:
|
||||||
raise OSError("Truncated DDS file") from e
|
msg = "Truncated DDS file"
|
||||||
|
raise OSError(msg) from e
|
||||||
return -1, 0
|
return -1, 0
|
||||||
|
|
||||||
|
|
||||||
|
@ -263,7 +268,8 @@ class DXT5Decoder(ImageFile.PyDecoder):
|
||||||
try:
|
try:
|
||||||
self.set_as_raw(_dxt5(self.fd, self.state.xsize, self.state.ysize))
|
self.set_as_raw(_dxt5(self.fd, self.state.xsize, self.state.ysize))
|
||||||
except struct.error as e:
|
except struct.error as e:
|
||||||
raise OSError("Truncated DDS file") from e
|
msg = "Truncated DDS file"
|
||||||
|
raise OSError(msg) from e
|
||||||
return -1, 0
|
return -1, 0
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -78,7 +78,8 @@ true color.
|
||||||
elif bits == 24:
|
elif bits == 24:
|
||||||
self.mode = "RGB"
|
self.mode = "RGB"
|
||||||
else:
|
else:
|
||||||
raise SyntaxError("unknown number of bits")
|
msg = "unknown number of bits"
|
||||||
|
raise SyntaxError(msg)
|
||||||
|
|
||||||
# data descriptor
|
# data descriptor
|
||||||
self.tile = [("raw", (0, 0) + self.size, 128, (self.mode, 0, 1))]
|
self.tile = [("raw", (0, 0) + self.size, 128, (self.mode, 0, 1))]
|
||||||
|
|
18
setup.py
18
setup.py
|
@ -362,15 +362,15 @@ class pil_build_ext(build_ext):
|
||||||
self.feature.required.discard(x)
|
self.feature.required.discard(x)
|
||||||
_dbg("Disabling %s", x)
|
_dbg("Disabling %s", x)
|
||||||
if getattr(self, f"enable_{x}"):
|
if getattr(self, f"enable_{x}"):
|
||||||
raise ValueError(
|
msg = f"Conflicting options: --enable-{x} and --disable-{x}"
|
||||||
f"Conflicting options: --enable-{x} and --disable-{x}"
|
raise ValueError(msg)
|
||||||
)
|
|
||||||
if x == "freetype":
|
if x == "freetype":
|
||||||
_dbg("--disable-freetype implies --disable-raqm")
|
_dbg("--disable-freetype implies --disable-raqm")
|
||||||
if getattr(self, "enable_raqm"):
|
if getattr(self, "enable_raqm"):
|
||||||
raise ValueError(
|
msg = (
|
||||||
"Conflicting options: --enable-raqm and --disable-freetype"
|
"Conflicting options: --enable-raqm and --disable-freetype"
|
||||||
)
|
)
|
||||||
|
raise ValueError(msg)
|
||||||
setattr(self, "disable_raqm", True)
|
setattr(self, "disable_raqm", True)
|
||||||
if getattr(self, f"enable_{x}"):
|
if getattr(self, f"enable_{x}"):
|
||||||
_dbg("Requiring %s", x)
|
_dbg("Requiring %s", x)
|
||||||
|
@ -381,13 +381,11 @@ class pil_build_ext(build_ext):
|
||||||
for x in ("raqm", "fribidi"):
|
for x in ("raqm", "fribidi"):
|
||||||
if getattr(self, f"vendor_{x}"):
|
if getattr(self, f"vendor_{x}"):
|
||||||
if getattr(self, "disable_raqm"):
|
if getattr(self, "disable_raqm"):
|
||||||
raise ValueError(
|
msg = f"Conflicting options: --vendor-{x} and --disable-raqm"
|
||||||
f"Conflicting options: --vendor-{x} and --disable-raqm"
|
raise ValueError(msg)
|
||||||
)
|
|
||||||
if x == "fribidi" and not getattr(self, "vendor_raqm"):
|
if x == "fribidi" and not getattr(self, "vendor_raqm"):
|
||||||
raise ValueError(
|
msg = f"Conflicting options: --vendor-{x} and not --vendor-raqm"
|
||||||
f"Conflicting options: --vendor-{x} and not --vendor-raqm"
|
raise ValueError(msg)
|
||||||
)
|
|
||||||
_dbg("Using vendored version of %s", x)
|
_dbg("Using vendored version of %s", x)
|
||||||
self.feature.vendor.add(x)
|
self.feature.vendor.add(x)
|
||||||
|
|
||||||
|
|
|
@ -86,7 +86,8 @@ class BdfFontFile(FontFile.FontFile):
|
||||||
|
|
||||||
s = fp.readline()
|
s = fp.readline()
|
||||||
if s[:13] != b"STARTFONT 2.1":
|
if s[:13] != b"STARTFONT 2.1":
|
||||||
raise SyntaxError("not a valid BDF file")
|
msg = "not a valid BDF file"
|
||||||
|
raise SyntaxError(msg)
|
||||||
|
|
||||||
props = {}
|
props = {}
|
||||||
comments = []
|
comments = []
|
||||||
|
|
|
@ -65,7 +65,8 @@ def __getattr__(name):
|
||||||
if name in enum.__members__:
|
if name in enum.__members__:
|
||||||
deprecate(f"{prefix}{name}", 10, f"{enum.__name__}.{name}")
|
deprecate(f"{prefix}{name}", 10, f"{enum.__name__}.{name}")
|
||||||
return enum[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):
|
def unpack_565(i):
|
||||||
|
@ -278,7 +279,8 @@ class BlpImageFile(ImageFile.ImageFile):
|
||||||
if self.magic in (b"BLP1", b"BLP2"):
|
if self.magic in (b"BLP1", b"BLP2"):
|
||||||
decoder = self.magic.decode()
|
decoder = self.magic.decode()
|
||||||
else:
|
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.mode = "RGBA" if self._blp_alpha_depth else "RGB"
|
||||||
self.tile = [(decoder, (0, 0) + self.size, 0, (self.mode, 0, 1))]
|
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._read_blp_header()
|
||||||
self._load()
|
self._load()
|
||||||
except struct.error as e:
|
except struct.error as e:
|
||||||
raise OSError("Truncated BLP file") from e
|
msg = "Truncated BLP file"
|
||||||
|
raise OSError(msg) from e
|
||||||
return -1, 0
|
return -1, 0
|
||||||
|
|
||||||
def _read_blp_header(self):
|
def _read_blp_header(self):
|
||||||
|
@ -354,13 +357,11 @@ class BLP1Decoder(_BLPBaseDecoder):
|
||||||
data = self._read_bgra(palette)
|
data = self._read_bgra(palette)
|
||||||
self.set_as_raw(bytes(data))
|
self.set_as_raw(bytes(data))
|
||||||
else:
|
else:
|
||||||
raise BLPFormatError(
|
msg = f"Unsupported BLP encoding {repr(self._blp_encoding)}"
|
||||||
f"Unsupported BLP encoding {repr(self._blp_encoding)}"
|
raise BLPFormatError(msg)
|
||||||
)
|
|
||||||
else:
|
else:
|
||||||
raise BLPFormatError(
|
msg = f"Unsupported BLP compression {repr(self._blp_encoding)}"
|
||||||
f"Unsupported BLP compression {repr(self._blp_encoding)}"
|
raise BLPFormatError(msg)
|
||||||
)
|
|
||||||
|
|
||||||
def _decode_jpeg_stream(self):
|
def _decode_jpeg_stream(self):
|
||||||
from .JpegImagePlugin import JpegImageFile
|
from .JpegImagePlugin import JpegImageFile
|
||||||
|
@ -415,16 +416,15 @@ class BLP2Decoder(_BLPBaseDecoder):
|
||||||
for d in decode_dxt5(self._safe_read(linesize)):
|
for d in decode_dxt5(self._safe_read(linesize)):
|
||||||
data += d
|
data += d
|
||||||
else:
|
else:
|
||||||
raise BLPFormatError(
|
msg = f"Unsupported alpha encoding {repr(self._blp_alpha_encoding)}"
|
||||||
f"Unsupported alpha encoding {repr(self._blp_alpha_encoding)}"
|
raise BLPFormatError(msg)
|
||||||
)
|
|
||||||
else:
|
else:
|
||||||
raise BLPFormatError(f"Unknown BLP encoding {repr(self._blp_encoding)}")
|
msg = f"Unknown BLP encoding {repr(self._blp_encoding)}"
|
||||||
|
raise BLPFormatError(msg)
|
||||||
|
|
||||||
else:
|
else:
|
||||||
raise BLPFormatError(
|
msg = f"Unknown BLP compression {repr(self._blp_compression)}"
|
||||||
f"Unknown BLP compression {repr(self._blp_compression)}"
|
raise BLPFormatError(msg)
|
||||||
)
|
|
||||||
|
|
||||||
self.set_as_raw(bytes(data))
|
self.set_as_raw(bytes(data))
|
||||||
|
|
||||||
|
@ -460,7 +460,8 @@ class BLPEncoder(ImageFile.PyEncoder):
|
||||||
|
|
||||||
def _save(im, fp, filename, save_all=False):
|
def _save(im, fp, filename, save_all=False):
|
||||||
if im.mode != "P":
|
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"
|
magic = b"BLP1" if im.encoderinfo.get("blp_version") == "BLP1" else b"BLP2"
|
||||||
fp.write(magic)
|
fp.write(magic)
|
||||||
|
|
|
@ -146,7 +146,8 @@ class BmpImageFile(ImageFile.ImageFile):
|
||||||
file_info["a_mask"],
|
file_info["a_mask"],
|
||||||
)
|
)
|
||||||
else:
|
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
|
# ------------------ Special case : header is reported 40, which
|
||||||
# ---------------------- is shorter than real size for bpp >= 16
|
# ---------------------- is shorter than real size for bpp >= 16
|
||||||
|
@ -164,7 +165,8 @@ class BmpImageFile(ImageFile.ImageFile):
|
||||||
# ---------------------- Check bit depth for unusual unsupported values
|
# ---------------------- Check bit depth for unusual unsupported values
|
||||||
self.mode, raw_mode = BIT2MODE.get(file_info["bits"], (None, None))
|
self.mode, raw_mode = BIT2MODE.get(file_info["bits"], (None, None))
|
||||||
if self.mode is None:
|
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)
|
# ---------------- Process BMP with Bitfields compression (not palette)
|
||||||
decoder_name = "raw"
|
decoder_name = "raw"
|
||||||
|
@ -205,23 +207,27 @@ class BmpImageFile(ImageFile.ImageFile):
|
||||||
):
|
):
|
||||||
raw_mode = MASK_MODES[(file_info["bits"], file_info["rgb_mask"])]
|
raw_mode = MASK_MODES[(file_info["bits"], file_info["rgb_mask"])]
|
||||||
else:
|
else:
|
||||||
raise OSError("Unsupported BMP bitfields layout")
|
msg = "Unsupported BMP bitfields layout"
|
||||||
|
raise OSError(msg)
|
||||||
else:
|
else:
|
||||||
raise OSError("Unsupported BMP bitfields layout")
|
msg = "Unsupported BMP bitfields layout"
|
||||||
|
raise OSError(msg)
|
||||||
elif file_info["compression"] == self.RAW:
|
elif file_info["compression"] == self.RAW:
|
||||||
if file_info["bits"] == 32 and header == 22: # 32-bit .cur offset
|
if file_info["bits"] == 32 and header == 22: # 32-bit .cur offset
|
||||||
raw_mode, self.mode = "BGRA", "RGBA"
|
raw_mode, self.mode = "BGRA", "RGBA"
|
||||||
elif file_info["compression"] in (self.RLE8, self.RLE4):
|
elif file_info["compression"] in (self.RLE8, self.RLE4):
|
||||||
decoder_name = "bmp_rle"
|
decoder_name = "bmp_rle"
|
||||||
else:
|
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
|
# --------------- Once the header is processed, process the palette/LUT
|
||||||
if self.mode == "P": # Paletted for 1, 4 and 8 bit images
|
if self.mode == "P": # Paletted for 1, 4 and 8 bit images
|
||||||
|
|
||||||
# ---------------------------------------------------- 1-bit images
|
# ---------------------------------------------------- 1-bit images
|
||||||
if not (0 < file_info["colors"] <= 65536):
|
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:
|
else:
|
||||||
padding = file_info["palette_padding"]
|
padding = file_info["palette_padding"]
|
||||||
palette = read(padding * file_info["colors"])
|
palette = read(padding * file_info["colors"])
|
||||||
|
@ -271,7 +277,8 @@ class BmpImageFile(ImageFile.ImageFile):
|
||||||
head_data = self.fp.read(14)
|
head_data = self.fp.read(14)
|
||||||
# choke if the file does not have the required magic bytes
|
# choke if the file does not have the required magic bytes
|
||||||
if not _accept(head_data):
|
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)
|
# read the start position of the BMP image data (u32)
|
||||||
offset = i32(head_data, 10)
|
offset = i32(head_data, 10)
|
||||||
# load bitmap information (offset=raster info)
|
# load bitmap information (offset=raster info)
|
||||||
|
@ -383,7 +390,8 @@ def _save(im, fp, filename, bitmap_header=True):
|
||||||
try:
|
try:
|
||||||
rawmode, bits, colors = SAVE[im.mode]
|
rawmode, bits, colors = SAVE[im.mode]
|
||||||
except KeyError as e:
|
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
|
info = im.encoderinfo
|
||||||
|
|
||||||
|
@ -411,7 +419,8 @@ def _save(im, fp, filename, bitmap_header=True):
|
||||||
offset = 14 + header + colors * 4
|
offset = 14 + header + colors * 4
|
||||||
file_size = offset + image
|
file_size = offset + image
|
||||||
if file_size > 2**32 - 1:
|
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(
|
fp.write(
|
||||||
b"BM" # file type (magic)
|
b"BM" # file type (magic)
|
||||||
+ o32(file_size) # file size
|
+ o32(file_size) # file size
|
||||||
|
|
|
@ -42,7 +42,8 @@ class BufrStubImageFile(ImageFile.StubImageFile):
|
||||||
offset = self.fp.tell()
|
offset = self.fp.tell()
|
||||||
|
|
||||||
if not _accept(self.fp.read(4)):
|
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)
|
self.fp.seek(offset)
|
||||||
|
|
||||||
|
@ -60,7 +61,8 @@ class BufrStubImageFile(ImageFile.StubImageFile):
|
||||||
|
|
||||||
def _save(im, fp, filename):
|
def _save(im, fp, filename):
|
||||||
if _handler is None or not hasattr(_handler, "save"):
|
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)
|
_handler.save(im, fp, filename)
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -43,7 +43,8 @@ class CurImageFile(BmpImagePlugin.BmpImageFile):
|
||||||
# check magic
|
# check magic
|
||||||
s = self.fp.read(6)
|
s = self.fp.read(6)
|
||||||
if not _accept(s):
|
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
|
# pick the largest cursor in the file
|
||||||
m = b""
|
m = b""
|
||||||
|
@ -54,7 +55,8 @@ class CurImageFile(BmpImagePlugin.BmpImageFile):
|
||||||
elif s[0] > m[0] and s[1] > m[1]:
|
elif s[0] > m[0] and s[1] > m[1]:
|
||||||
m = s
|
m = s
|
||||||
if not m:
|
if not m:
|
||||||
raise TypeError("No cursors were found")
|
msg = "No cursors were found"
|
||||||
|
raise TypeError(msg)
|
||||||
|
|
||||||
# load as bitmap
|
# load as bitmap
|
||||||
self._bitmap(i32(m, 12) + offset)
|
self._bitmap(i32(m, 12) + offset)
|
||||||
|
|
|
@ -47,7 +47,8 @@ class DcxImageFile(PcxImageFile):
|
||||||
# Header
|
# Header
|
||||||
s = self.fp.read(4)
|
s = self.fp.read(4)
|
||||||
if not _accept(s):
|
if not _accept(s):
|
||||||
raise SyntaxError("not a DCX file")
|
msg = "not a DCX file"
|
||||||
|
raise SyntaxError(msg)
|
||||||
|
|
||||||
# Component directory
|
# Component directory
|
||||||
self._offset = []
|
self._offset = []
|
||||||
|
|
|
@ -114,13 +114,16 @@ class DdsImageFile(ImageFile.ImageFile):
|
||||||
|
|
||||||
def _open(self):
|
def _open(self):
|
||||||
if not _accept(self.fp.read(4)):
|
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))
|
(header_size,) = struct.unpack("<I", self.fp.read(4))
|
||||||
if header_size != 124:
|
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)
|
header_bytes = self.fp.read(header_size - 4)
|
||||||
if len(header_bytes) != 120:
|
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)
|
header = BytesIO(header_bytes)
|
||||||
|
|
||||||
flags, height, width = struct.unpack("<3I", header.read(12))
|
flags, height, width = struct.unpack("<3I", header.read(12))
|
||||||
|
@ -216,11 +219,11 @@ class DdsImageFile(ImageFile.ImageFile):
|
||||||
self.info["gamma"] = 1 / 2.2
|
self.info["gamma"] = 1 / 2.2
|
||||||
return
|
return
|
||||||
else:
|
else:
|
||||||
raise NotImplementedError(
|
msg = f"Unimplemented DXGI format {dxgi_format}"
|
||||||
f"Unimplemented DXGI format {dxgi_format}"
|
raise NotImplementedError(msg)
|
||||||
)
|
|
||||||
else:
|
else:
|
||||||
raise NotImplementedError(f"Unimplemented pixel format {repr(fourcc)}")
|
msg = f"Unimplemented pixel format {repr(fourcc)}"
|
||||||
|
raise NotImplementedError(msg)
|
||||||
|
|
||||||
self.tile = [
|
self.tile = [
|
||||||
("bcn", (0, 0) + self.size, data_start, (n, self.pixel_format))
|
("bcn", (0, 0) + self.size, data_start, (n, self.pixel_format))
|
||||||
|
@ -232,7 +235,8 @@ class DdsImageFile(ImageFile.ImageFile):
|
||||||
|
|
||||||
def _save(im, fp, filename):
|
def _save(im, fp, filename):
|
||||||
if im.mode not in ("RGB", "RGBA", "L", "LA"):
|
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
|
rawmode = im.mode
|
||||||
masks = [0xFF0000, 0xFF00, 0xFF]
|
masks = [0xFF0000, 0xFF00, 0xFF]
|
||||||
|
|
|
@ -133,7 +133,8 @@ def Ghostscript(tile, size, fp, scale=1, transparency=False):
|
||||||
|
|
||||||
if gs_windows_binary is not None:
|
if gs_windows_binary is not None:
|
||||||
if not gs_windows_binary:
|
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
|
command[0] = gs_windows_binary
|
||||||
|
|
||||||
# push data through Ghostscript
|
# push data through Ghostscript
|
||||||
|
@ -229,12 +230,14 @@ class EpsImageFile(ImageFile.ImageFile):
|
||||||
while s_raw:
|
while s_raw:
|
||||||
if s:
|
if s:
|
||||||
if len(s) > 255:
|
if len(s) > 255:
|
||||||
raise SyntaxError("not an EPS file")
|
msg = "not an EPS file"
|
||||||
|
raise SyntaxError(msg)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
m = split.match(s)
|
m = split.match(s)
|
||||||
except re.error as e:
|
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:
|
if m:
|
||||||
k, v = m.group(1, 2)
|
k, v = m.group(1, 2)
|
||||||
|
@ -268,7 +271,8 @@ class EpsImageFile(ImageFile.ImageFile):
|
||||||
# tools mistakenly put in the Comments section
|
# tools mistakenly put in the Comments section
|
||||||
pass
|
pass
|
||||||
else:
|
else:
|
||||||
raise OSError("bad EPS header")
|
msg = "bad EPS header"
|
||||||
|
raise OSError(msg)
|
||||||
|
|
||||||
s_raw = fp.readline()
|
s_raw = fp.readline()
|
||||||
s = s_raw.strip("\r\n")
|
s = s_raw.strip("\r\n")
|
||||||
|
@ -282,7 +286,8 @@ class EpsImageFile(ImageFile.ImageFile):
|
||||||
while s[:1] == "%":
|
while s[:1] == "%":
|
||||||
|
|
||||||
if len(s) > 255:
|
if len(s) > 255:
|
||||||
raise SyntaxError("not an EPS file")
|
msg = "not an EPS file"
|
||||||
|
raise SyntaxError(msg)
|
||||||
|
|
||||||
if s[:11] == "%ImageData:":
|
if s[:11] == "%ImageData:":
|
||||||
# Encoded bitmapped image.
|
# Encoded bitmapped image.
|
||||||
|
@ -306,7 +311,8 @@ class EpsImageFile(ImageFile.ImageFile):
|
||||||
break
|
break
|
||||||
|
|
||||||
if not box:
|
if not box:
|
||||||
raise OSError("cannot determine EPS bounding box")
|
msg = "cannot determine EPS bounding box"
|
||||||
|
raise OSError(msg)
|
||||||
|
|
||||||
def _find_offset(self, fp):
|
def _find_offset(self, fp):
|
||||||
|
|
||||||
|
@ -326,7 +332,8 @@ class EpsImageFile(ImageFile.ImageFile):
|
||||||
offset = i32(s, 4)
|
offset = i32(s, 4)
|
||||||
length = i32(s, 8)
|
length = i32(s, 8)
|
||||||
else:
|
else:
|
||||||
raise SyntaxError("not an EPS file")
|
msg = "not an EPS file"
|
||||||
|
raise SyntaxError(msg)
|
||||||
|
|
||||||
return length, offset
|
return length, offset
|
||||||
|
|
||||||
|
@ -365,7 +372,8 @@ def _save(im, fp, filename, eps=1):
|
||||||
elif im.mode == "CMYK":
|
elif im.mode == "CMYK":
|
||||||
operator = (8, 4, b"false 4 colorimage")
|
operator = (8, 4, b"false 4 colorimage")
|
||||||
else:
|
else:
|
||||||
raise ValueError("image mode is not supported")
|
msg = "image mode is not supported"
|
||||||
|
raise ValueError(msg)
|
||||||
|
|
||||||
if eps:
|
if eps:
|
||||||
#
|
#
|
||||||
|
|
|
@ -28,7 +28,8 @@ class FitsImageFile(ImageFile.ImageFile):
|
||||||
while True:
|
while True:
|
||||||
header = self.fp.read(80)
|
header = self.fp.read(80)
|
||||||
if not header:
|
if not header:
|
||||||
raise OSError("Truncated FITS file")
|
msg = "Truncated FITS file"
|
||||||
|
raise OSError(msg)
|
||||||
keyword = header[:8].strip()
|
keyword = header[:8].strip()
|
||||||
if keyword == b"END":
|
if keyword == b"END":
|
||||||
break
|
break
|
||||||
|
@ -36,12 +37,14 @@ class FitsImageFile(ImageFile.ImageFile):
|
||||||
if value.startswith(b"="):
|
if value.startswith(b"="):
|
||||||
value = value[1:].strip()
|
value = value[1:].strip()
|
||||||
if not headers and (not _accept(keyword) or value != b"T"):
|
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
|
headers[keyword] = value
|
||||||
|
|
||||||
naxis = int(headers[b"NAXIS"])
|
naxis = int(headers[b"NAXIS"])
|
||||||
if naxis == 0:
|
if naxis == 0:
|
||||||
raise ValueError("No image data")
|
msg = "No image data"
|
||||||
|
raise ValueError(msg)
|
||||||
elif naxis == 1:
|
elif naxis == 1:
|
||||||
self._size = 1, int(headers[b"NAXIS1"])
|
self._size = 1, int(headers[b"NAXIS1"])
|
||||||
else:
|
else:
|
||||||
|
|
|
@ -67,7 +67,8 @@ class FITSStubImageFile(ImageFile.StubImageFile):
|
||||||
|
|
||||||
|
|
||||||
def _save(im, fp, filename):
|
def _save(im, fp, filename):
|
||||||
raise OSError("FITS save handler not installed")
|
msg = "FITS save handler not installed"
|
||||||
|
raise OSError(msg)
|
||||||
|
|
||||||
|
|
||||||
# --------------------------------------------------------------------
|
# --------------------------------------------------------------------
|
||||||
|
|
|
@ -50,7 +50,8 @@ class FliImageFile(ImageFile.ImageFile):
|
||||||
# HEAD
|
# HEAD
|
||||||
s = self.fp.read(128)
|
s = self.fp.read(128)
|
||||||
if not (_accept(s) and s[20:22] == b"\x00\x00"):
|
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
|
# frames
|
||||||
self.n_frames = i16(s, 6)
|
self.n_frames = i16(s, 6)
|
||||||
|
@ -141,7 +142,8 @@ class FliImageFile(ImageFile.ImageFile):
|
||||||
self.load()
|
self.load()
|
||||||
|
|
||||||
if frame != self.__frame + 1:
|
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
|
self.__frame = frame
|
||||||
|
|
||||||
# move to next frame
|
# move to next frame
|
||||||
|
|
|
@ -60,10 +60,12 @@ class FpxImageFile(ImageFile.ImageFile):
|
||||||
try:
|
try:
|
||||||
self.ole = olefile.OleFileIO(self.fp)
|
self.ole = olefile.OleFileIO(self.fp)
|
||||||
except OSError as e:
|
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":
|
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)
|
self._open_index(1)
|
||||||
|
|
||||||
|
@ -99,7 +101,8 @@ class FpxImageFile(ImageFile.ImageFile):
|
||||||
colors = []
|
colors = []
|
||||||
bands = i32(s, 4)
|
bands = i32(s, 4)
|
||||||
if bands > 4:
|
if bands > 4:
|
||||||
raise OSError("Invalid number of bands")
|
msg = "Invalid number of bands"
|
||||||
|
raise OSError(msg)
|
||||||
for i in range(bands):
|
for i in range(bands):
|
||||||
# note: for now, we ignore the "uncalibrated" flag
|
# note: for now, we ignore the "uncalibrated" flag
|
||||||
colors.append(i32(s, 8 + i * 4) & 0x7FFFFFFF)
|
colors.append(i32(s, 8 + i * 4) & 0x7FFFFFFF)
|
||||||
|
@ -141,7 +144,8 @@ class FpxImageFile(ImageFile.ImageFile):
|
||||||
length = i32(s, 32)
|
length = i32(s, 32)
|
||||||
|
|
||||||
if size != self.size:
|
if size != self.size:
|
||||||
raise OSError("subimage mismatch")
|
msg = "subimage mismatch"
|
||||||
|
raise OSError(msg)
|
||||||
|
|
||||||
# get tile descriptors
|
# get tile descriptors
|
||||||
fp.seek(28 + offset)
|
fp.seek(28 + offset)
|
||||||
|
@ -217,7 +221,8 @@ class FpxImageFile(ImageFile.ImageFile):
|
||||||
self.tile_prefix = self.jpeg[jpeg_tables]
|
self.tile_prefix = self.jpeg[jpeg_tables]
|
||||||
|
|
||||||
else:
|
else:
|
||||||
raise OSError("unknown/invalid compression")
|
msg = "unknown/invalid compression"
|
||||||
|
raise OSError(msg)
|
||||||
|
|
||||||
x = x + xtile
|
x = x + xtile
|
||||||
if x >= xsize:
|
if x >= xsize:
|
||||||
|
|
|
@ -73,7 +73,8 @@ def __getattr__(name):
|
||||||
if name in enum.__members__:
|
if name in enum.__members__:
|
||||||
deprecate(f"{prefix}{name}", 10, f"{enum.__name__}.{name}")
|
deprecate(f"{prefix}{name}", 10, f"{enum.__name__}.{name}")
|
||||||
return enum[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):
|
class FtexImageFile(ImageFile.ImageFile):
|
||||||
|
@ -82,7 +83,8 @@ class FtexImageFile(ImageFile.ImageFile):
|
||||||
|
|
||||||
def _open(self):
|
def _open(self):
|
||||||
if not _accept(self.fp.read(4)):
|
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
|
struct.unpack("<i", self.fp.read(4)) # version
|
||||||
self._size = struct.unpack("<2i", self.fp.read(8))
|
self._size = struct.unpack("<2i", self.fp.read(8))
|
||||||
mipmap_count, format_count = 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:
|
elif format == Format.UNCOMPRESSED:
|
||||||
self.tile = [("raw", (0, 0) + self.size, 0, ("RGB", 0, 1))]
|
self.tile = [("raw", (0, 0) + self.size, 0, ("RGB", 0, 1))]
|
||||||
else:
|
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.close()
|
||||||
self.fp = BytesIO(data)
|
self.fp = BytesIO(data)
|
||||||
|
|
|
@ -44,18 +44,22 @@ class GbrImageFile(ImageFile.ImageFile):
|
||||||
def _open(self):
|
def _open(self):
|
||||||
header_size = i32(self.fp.read(4))
|
header_size = i32(self.fp.read(4))
|
||||||
if header_size < 20:
|
if header_size < 20:
|
||||||
raise SyntaxError("not a GIMP brush")
|
msg = "not a GIMP brush"
|
||||||
|
raise SyntaxError(msg)
|
||||||
version = i32(self.fp.read(4))
|
version = i32(self.fp.read(4))
|
||||||
if version not in (1, 2):
|
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))
|
width = i32(self.fp.read(4))
|
||||||
height = i32(self.fp.read(4))
|
height = i32(self.fp.read(4))
|
||||||
color_depth = i32(self.fp.read(4))
|
color_depth = i32(self.fp.read(4))
|
||||||
if width <= 0 or height <= 0:
|
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):
|
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:
|
if version == 1:
|
||||||
comment_length = header_size - 20
|
comment_length = header_size - 20
|
||||||
|
@ -63,7 +67,8 @@ class GbrImageFile(ImageFile.ImageFile):
|
||||||
comment_length = header_size - 28
|
comment_length = header_size - 28
|
||||||
magic_number = self.fp.read(4)
|
magic_number = self.fp.read(4)
|
||||||
if magic_number != b"GIMP":
|
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))
|
self.info["spacing"] = i32(self.fp.read(4))
|
||||||
|
|
||||||
comment = self.fp.read(comment_length)[:-1]
|
comment = self.fp.read(comment_length)[:-1]
|
||||||
|
|
|
@ -49,7 +49,8 @@ class GdImageFile(ImageFile.ImageFile):
|
||||||
s = self.fp.read(1037)
|
s = self.fp.read(1037)
|
||||||
|
|
||||||
if not i16(s) in [65534, 65535]:
|
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.mode = "L" # FIXME: "P"
|
||||||
self._size = i16(s, 2), i16(s, 4)
|
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.
|
:raises OSError: If the image could not be read.
|
||||||
"""
|
"""
|
||||||
if mode != "r":
|
if mode != "r":
|
||||||
raise ValueError("bad mode")
|
msg = "bad mode"
|
||||||
|
raise ValueError(msg)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
return GdImageFile(fp)
|
return GdImageFile(fp)
|
||||||
except SyntaxError as e:
|
except SyntaxError as e:
|
||||||
raise UnidentifiedImageError("cannot identify this image file") from e
|
msg = "cannot identify this image file"
|
||||||
|
raise UnidentifiedImageError(msg) from e
|
||||||
|
|
|
@ -85,7 +85,8 @@ class GifImageFile(ImageFile.ImageFile):
|
||||||
# Screen
|
# Screen
|
||||||
s = self.fp.read(13)
|
s = self.fp.read(13)
|
||||||
if not _accept(s):
|
if not _accept(s):
|
||||||
raise SyntaxError("not a GIF file")
|
msg = "not a GIF file"
|
||||||
|
raise SyntaxError(msg)
|
||||||
|
|
||||||
self.info["version"] = s[:6]
|
self.info["version"] = s[:6]
|
||||||
self._size = i16(s, 6), i16(s, 8)
|
self._size = i16(s, 6), i16(s, 8)
|
||||||
|
@ -152,7 +153,8 @@ class GifImageFile(ImageFile.ImageFile):
|
||||||
self._seek(f)
|
self._seek(f)
|
||||||
except EOFError as e:
|
except EOFError as e:
|
||||||
self.seek(last_frame)
|
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):
|
def _seek(self, frame, update_image=True):
|
||||||
|
|
||||||
|
@ -171,7 +173,8 @@ class GifImageFile(ImageFile.ImageFile):
|
||||||
self.load()
|
self.load()
|
||||||
|
|
||||||
if frame != self.__frame + 1:
|
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
|
self.fp = self._fp
|
||||||
if self.__offset:
|
if self.__offset:
|
||||||
|
|
|
@ -107,7 +107,8 @@ class GimpGradientFile(GradientFile):
|
||||||
def __init__(self, fp):
|
def __init__(self, fp):
|
||||||
|
|
||||||
if fp.readline()[:13] != b"GIMP Gradient":
|
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()
|
line = fp.readline()
|
||||||
|
|
||||||
|
@ -133,7 +134,8 @@ class GimpGradientFile(GradientFile):
|
||||||
cspace = int(s[12])
|
cspace = int(s[12])
|
||||||
|
|
||||||
if cspace != 0:
|
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))
|
gradient.append((x0, x1, xm, rgb0, rgb1, segment))
|
||||||
|
|
||||||
|
|
|
@ -29,7 +29,8 @@ class GimpPaletteFile:
|
||||||
self.palette = [o8(i) * 3 for i in range(256)]
|
self.palette = [o8(i) * 3 for i in range(256)]
|
||||||
|
|
||||||
if fp.readline()[:12] != b"GIMP Palette":
|
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):
|
for i in range(256):
|
||||||
|
|
||||||
|
@ -41,11 +42,13 @@ class GimpPaletteFile:
|
||||||
if re.match(rb"\w+:|#", s):
|
if re.match(rb"\w+:|#", s):
|
||||||
continue
|
continue
|
||||||
if len(s) > 100:
|
if len(s) > 100:
|
||||||
raise SyntaxError("bad palette file")
|
msg = "bad palette file"
|
||||||
|
raise SyntaxError(msg)
|
||||||
|
|
||||||
v = tuple(map(int, s.split()[:3]))
|
v = tuple(map(int, s.split()[:3]))
|
||||||
if len(v) != 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])
|
self.palette[i] = o8(v[0]) + o8(v[1]) + o8(v[2])
|
||||||
|
|
||||||
|
|
|
@ -42,7 +42,8 @@ class GribStubImageFile(ImageFile.StubImageFile):
|
||||||
offset = self.fp.tell()
|
offset = self.fp.tell()
|
||||||
|
|
||||||
if not _accept(self.fp.read(8)):
|
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)
|
self.fp.seek(offset)
|
||||||
|
|
||||||
|
@ -60,7 +61,8 @@ class GribStubImageFile(ImageFile.StubImageFile):
|
||||||
|
|
||||||
def _save(im, fp, filename):
|
def _save(im, fp, filename):
|
||||||
if _handler is None or not hasattr(_handler, "save"):
|
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)
|
_handler.save(im, fp, filename)
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -42,7 +42,8 @@ class HDF5StubImageFile(ImageFile.StubImageFile):
|
||||||
offset = self.fp.tell()
|
offset = self.fp.tell()
|
||||||
|
|
||||||
if not _accept(self.fp.read(8)):
|
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)
|
self.fp.seek(offset)
|
||||||
|
|
||||||
|
@ -60,7 +61,8 @@ class HDF5StubImageFile(ImageFile.StubImageFile):
|
||||||
|
|
||||||
def _save(im, fp, filename):
|
def _save(im, fp, filename):
|
||||||
if _handler is None or not hasattr(_handler, "save"):
|
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)
|
_handler.save(im, fp, filename)
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -42,7 +42,8 @@ def read_32t(fobj, start_length, size):
|
||||||
fobj.seek(start)
|
fobj.seek(start)
|
||||||
sig = fobj.read(4)
|
sig = fobj.read(4)
|
||||||
if sig != b"\x00\x00\x00\x00":
|
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)
|
return read_32(fobj, (start + 4, length - 4), size)
|
||||||
|
|
||||||
|
|
||||||
|
@ -82,7 +83,8 @@ def read_32(fobj, start_length, size):
|
||||||
if bytesleft <= 0:
|
if bytesleft <= 0:
|
||||||
break
|
break
|
||||||
if bytesleft != 0:
|
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)
|
band = Image.frombuffer("L", pixel_size, b"".join(data), "raw", "L", 0, 1)
|
||||||
im.im.putband(band.im, band_ix)
|
im.im.putband(band.im, band_ix)
|
||||||
return {"RGB": im}
|
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"
|
or sig == b"\x00\x00\x00\x0cjP \x0d\x0a\x87\x0a"
|
||||||
):
|
):
|
||||||
if not enable_jpeg2k:
|
if not enable_jpeg2k:
|
||||||
raise ValueError(
|
msg = (
|
||||||
"Unsupported icon subimage format (rebuild PIL "
|
"Unsupported icon subimage format (rebuild PIL "
|
||||||
"with JPEG 2000 support to fix this)"
|
"with JPEG 2000 support to fix this)"
|
||||||
)
|
)
|
||||||
|
raise ValueError(msg)
|
||||||
# j2k, jpc or j2c
|
# j2k, jpc or j2c
|
||||||
fobj.seek(start)
|
fobj.seek(start)
|
||||||
jp2kstream = fobj.read(length)
|
jp2kstream = fobj.read(length)
|
||||||
|
@ -127,7 +130,8 @@ def read_png_or_jpeg2000(fobj, start_length, size):
|
||||||
im = im.convert("RGBA")
|
im = im.convert("RGBA")
|
||||||
return {"RGBA": im}
|
return {"RGBA": im}
|
||||||
else:
|
else:
|
||||||
raise ValueError("Unsupported icon subimage format")
|
msg = "Unsupported icon subimage format"
|
||||||
|
raise ValueError(msg)
|
||||||
|
|
||||||
|
|
||||||
class IcnsFile:
|
class IcnsFile:
|
||||||
|
@ -168,12 +172,14 @@ class IcnsFile:
|
||||||
self.fobj = fobj
|
self.fobj = fobj
|
||||||
sig, filesize = nextheader(fobj)
|
sig, filesize = nextheader(fobj)
|
||||||
if not _accept(sig):
|
if not _accept(sig):
|
||||||
raise SyntaxError("not an icns file")
|
msg = "not an icns file"
|
||||||
|
raise SyntaxError(msg)
|
||||||
i = HEADERSIZE
|
i = HEADERSIZE
|
||||||
while i < filesize:
|
while i < filesize:
|
||||||
sig, blocksize = nextheader(fobj)
|
sig, blocksize = nextheader(fobj)
|
||||||
if blocksize <= 0:
|
if blocksize <= 0:
|
||||||
raise SyntaxError("invalid block header")
|
msg = "invalid block header"
|
||||||
|
raise SyntaxError(msg)
|
||||||
i += HEADERSIZE
|
i += HEADERSIZE
|
||||||
blocksize -= HEADERSIZE
|
blocksize -= HEADERSIZE
|
||||||
dct[sig] = (i, blocksize)
|
dct[sig] = (i, blocksize)
|
||||||
|
@ -192,7 +198,8 @@ class IcnsFile:
|
||||||
def bestsize(self):
|
def bestsize(self):
|
||||||
sizes = self.itersizes()
|
sizes = self.itersizes()
|
||||||
if not sizes:
|
if not sizes:
|
||||||
raise SyntaxError("No 32bit icon resources found")
|
msg = "No 32bit icon resources found"
|
||||||
|
raise SyntaxError(msg)
|
||||||
return max(sizes)
|
return max(sizes)
|
||||||
|
|
||||||
def dataforsize(self, size):
|
def dataforsize(self, size):
|
||||||
|
@ -275,7 +282,8 @@ class IcnsImageFile(ImageFile.ImageFile):
|
||||||
if value in simple_sizes:
|
if value in simple_sizes:
|
||||||
info_size = self.info["sizes"][simple_sizes.index(value)]
|
info_size = self.info["sizes"][simple_sizes.index(value)]
|
||||||
if info_size not in self.info["sizes"]:
|
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
|
self._size = value
|
||||||
|
|
||||||
def load(self):
|
def load(self):
|
||||||
|
|
|
@ -127,7 +127,8 @@ class IcoFile:
|
||||||
# check magic
|
# check magic
|
||||||
s = buf.read(6)
|
s = buf.read(6)
|
||||||
if not _accept(s):
|
if not _accept(s):
|
||||||
raise SyntaxError("not an ICO file")
|
msg = "not an ICO file"
|
||||||
|
raise SyntaxError(msg)
|
||||||
|
|
||||||
self.buf = buf
|
self.buf = buf
|
||||||
self.entry = []
|
self.entry = []
|
||||||
|
@ -316,7 +317,8 @@ class IcoImageFile(ImageFile.ImageFile):
|
||||||
@size.setter
|
@size.setter
|
||||||
def size(self, value):
|
def size(self, value):
|
||||||
if value not in self.info["sizes"]:
|
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
|
self._size = value
|
||||||
|
|
||||||
def load(self):
|
def load(self):
|
||||||
|
|
|
@ -126,7 +126,8 @@ class ImImageFile(ImageFile.ImageFile):
|
||||||
# 100 bytes, this is (probably) not a text header.
|
# 100 bytes, this is (probably) not a text header.
|
||||||
|
|
||||||
if b"\n" not in self.fp.read(100):
|
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)
|
self.fp.seek(0)
|
||||||
|
|
||||||
n = 0
|
n = 0
|
||||||
|
@ -153,7 +154,8 @@ class ImImageFile(ImageFile.ImageFile):
|
||||||
s = s + self.fp.readline()
|
s = s + self.fp.readline()
|
||||||
|
|
||||||
if len(s) > 100:
|
if len(s) > 100:
|
||||||
raise SyntaxError("not an IM file")
|
msg = "not an IM file"
|
||||||
|
raise SyntaxError(msg)
|
||||||
|
|
||||||
if s[-2:] == b"\r\n":
|
if s[-2:] == b"\r\n":
|
||||||
s = s[:-2]
|
s = s[:-2]
|
||||||
|
@ -163,7 +165,8 @@ class ImImageFile(ImageFile.ImageFile):
|
||||||
try:
|
try:
|
||||||
m = split.match(s)
|
m = split.match(s)
|
||||||
except re.error as e:
|
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:
|
if m:
|
||||||
|
|
||||||
|
@ -203,7 +206,8 @@ class ImImageFile(ImageFile.ImageFile):
|
||||||
)
|
)
|
||||||
|
|
||||||
if not n:
|
if not n:
|
||||||
raise SyntaxError("Not an IM file")
|
msg = "Not an IM file"
|
||||||
|
raise SyntaxError(msg)
|
||||||
|
|
||||||
# Basic attributes
|
# Basic attributes
|
||||||
self._size = self.info[SIZE]
|
self._size = self.info[SIZE]
|
||||||
|
@ -213,7 +217,8 @@ class ImImageFile(ImageFile.ImageFile):
|
||||||
while s and s[:1] != b"\x1A":
|
while s and s[:1] != b"\x1A":
|
||||||
s = self.fp.read(1)
|
s = self.fp.read(1)
|
||||||
if not s:
|
if not s:
|
||||||
raise SyntaxError("File truncated")
|
msg = "File truncated"
|
||||||
|
raise SyntaxError(msg)
|
||||||
|
|
||||||
if LUT in self.info:
|
if LUT in self.info:
|
||||||
# convert lookup table to palette or lut attribute
|
# convert lookup table to palette or lut attribute
|
||||||
|
@ -332,7 +337,8 @@ def _save(im, fp, filename):
|
||||||
try:
|
try:
|
||||||
image_type, rawmode = SAVE[im.mode]
|
image_type, rawmode = SAVE[im.mode]
|
||||||
except KeyError as e:
|
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)
|
frames = im.encoderinfo.get("frames", 1)
|
||||||
|
|
||||||
|
|
154
src/PIL/Image.py
154
src/PIL/Image.py
|
@ -80,7 +80,8 @@ def __getattr__(name):
|
||||||
if name in enum.__members__:
|
if name in enum.__members__:
|
||||||
deprecate(name, 10, f"{enum.__name__}.{name}")
|
deprecate(name, 10, f"{enum.__name__}.{name}")
|
||||||
return enum[name]
|
return enum[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__)
|
logger = logging.getLogger(__name__)
|
||||||
|
@ -107,11 +108,12 @@ try:
|
||||||
from . import _imaging as core
|
from . import _imaging as core
|
||||||
|
|
||||||
if __version__ != getattr(core, "PILLOW_VERSION", None):
|
if __version__ != getattr(core, "PILLOW_VERSION", None):
|
||||||
raise ImportError(
|
msg = (
|
||||||
"The _imaging extension was built for another version of Pillow or PIL:\n"
|
"The _imaging extension was built for another version of Pillow or PIL:\n"
|
||||||
f"Core version: {getattr(core, 'PILLOW_VERSION', None)}\n"
|
f"Core version: {getattr(core, 'PILLOW_VERSION', None)}\n"
|
||||||
f"Pillow version: {__version__}"
|
f"Pillow version: {__version__}"
|
||||||
)
|
)
|
||||||
|
raise ImportError(msg)
|
||||||
|
|
||||||
except ImportError as v:
|
except ImportError as v:
|
||||||
core = DeferredError(ImportError("The _imaging C module is not installed."))
|
core = DeferredError(ImportError("The _imaging C module is not installed."))
|
||||||
|
@ -406,7 +408,8 @@ def _getdecoder(mode, decoder_name, args, extra=()):
|
||||||
# get decoder
|
# get decoder
|
||||||
decoder = getattr(core, decoder_name + "_decoder")
|
decoder = getattr(core, decoder_name + "_decoder")
|
||||||
except AttributeError as e:
|
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)
|
return decoder(mode, *args + extra)
|
||||||
|
|
||||||
|
|
||||||
|
@ -429,7 +432,8 @@ def _getencoder(mode, encoder_name, args, extra=()):
|
||||||
# get encoder
|
# get encoder
|
||||||
encoder = getattr(core, encoder_name + "_encoder")
|
encoder = getattr(core, encoder_name + "_encoder")
|
||||||
except AttributeError as e:
|
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)
|
return encoder(mode, *args + extra)
|
||||||
|
|
||||||
|
|
||||||
|
@ -675,7 +679,8 @@ class Image:
|
||||||
try:
|
try:
|
||||||
self.save(b, "PNG")
|
self.save(b, "PNG")
|
||||||
except Exception as e:
|
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()
|
return b.getvalue()
|
||||||
|
|
||||||
@property
|
@property
|
||||||
|
@ -767,7 +772,8 @@ class Image:
|
||||||
if s:
|
if s:
|
||||||
break
|
break
|
||||||
if s < 0:
|
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)
|
return b"".join(data)
|
||||||
|
|
||||||
|
@ -784,7 +790,8 @@ class Image:
|
||||||
|
|
||||||
self.load()
|
self.load()
|
||||||
if self.mode != "1":
|
if self.mode != "1":
|
||||||
raise ValueError("not a bitmap")
|
msg = "not a bitmap"
|
||||||
|
raise ValueError(msg)
|
||||||
data = self.tobytes("xbm")
|
data = self.tobytes("xbm")
|
||||||
return b"".join(
|
return b"".join(
|
||||||
[
|
[
|
||||||
|
@ -818,9 +825,11 @@ class Image:
|
||||||
s = d.decode(data)
|
s = d.decode(data)
|
||||||
|
|
||||||
if s[0] >= 0:
|
if s[0] >= 0:
|
||||||
raise ValueError("not enough image data")
|
msg = "not enough image data"
|
||||||
|
raise ValueError(msg)
|
||||||
if s[1] != 0:
|
if s[1] != 0:
|
||||||
raise ValueError("cannot decode image data")
|
msg = "cannot decode image data"
|
||||||
|
raise ValueError(msg)
|
||||||
|
|
||||||
def load(self):
|
def load(self):
|
||||||
"""
|
"""
|
||||||
|
@ -941,7 +950,8 @@ class Image:
|
||||||
if matrix:
|
if matrix:
|
||||||
# matrix conversion
|
# matrix conversion
|
||||||
if mode not in ("L", "RGB"):
|
if mode not in ("L", "RGB"):
|
||||||
raise ValueError("illegal conversion")
|
msg = "illegal conversion"
|
||||||
|
raise ValueError(msg)
|
||||||
im = self.im.convert_matrix(mode, matrix)
|
im = self.im.convert_matrix(mode, matrix)
|
||||||
new = self._new(im)
|
new = self._new(im)
|
||||||
if has_transparency and self.im.bands == 3:
|
if has_transparency and self.im.bands == 3:
|
||||||
|
@ -1026,7 +1036,8 @@ class Image:
|
||||||
elif isinstance(t, int):
|
elif isinstance(t, int):
|
||||||
self.im.putpalettealpha(t, 0)
|
self.im.putpalettealpha(t, 0)
|
||||||
else:
|
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:
|
if mode == "P" and palette == Palette.ADAPTIVE:
|
||||||
im = self.im.quantize(colors)
|
im = self.im.quantize(colors)
|
||||||
|
@ -1076,7 +1087,8 @@ class Image:
|
||||||
im = self.im.convert(modebase)
|
im = self.im.convert(modebase)
|
||||||
im = im.convert(mode, dither)
|
im = im.convert(mode, dither)
|
||||||
except KeyError as e:
|
except KeyError as e:
|
||||||
raise ValueError("illegal conversion") from e
|
msg = "illegal conversion"
|
||||||
|
raise ValueError(msg) from e
|
||||||
|
|
||||||
new_im = self._new(im)
|
new_im = self._new(im)
|
||||||
if mode == "P" and palette != Palette.ADAPTIVE:
|
if mode == "P" and palette != Palette.ADAPTIVE:
|
||||||
|
@ -1151,20 +1163,21 @@ class Image:
|
||||||
Quantize.LIBIMAGEQUANT,
|
Quantize.LIBIMAGEQUANT,
|
||||||
):
|
):
|
||||||
# Caller specified an invalid mode.
|
# Caller specified an invalid mode.
|
||||||
raise ValueError(
|
msg = (
|
||||||
"Fast Octree (method == 2) and libimagequant (method == 3) "
|
"Fast Octree (method == 2) and libimagequant (method == 3) "
|
||||||
"are the only valid methods for quantizing RGBA images"
|
"are the only valid methods for quantizing RGBA images"
|
||||||
)
|
)
|
||||||
|
raise ValueError(msg)
|
||||||
|
|
||||||
if palette:
|
if palette:
|
||||||
# use palette from reference image
|
# use palette from reference image
|
||||||
palette.load()
|
palette.load()
|
||||||
if palette.mode != "P":
|
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":
|
if self.mode != "RGB" and self.mode != "L":
|
||||||
raise ValueError(
|
msg = "only RGB or L mode images can be quantized to a palette"
|
||||||
"only RGB or L mode images can be quantized to a palette"
|
raise ValueError(msg)
|
||||||
)
|
|
||||||
im = self.im.convert("P", dither, palette.im)
|
im = self.im.convert("P", dither, palette.im)
|
||||||
new_im = self._new(im)
|
new_im = self._new(im)
|
||||||
new_im.palette = palette.palette.copy()
|
new_im.palette = palette.palette.copy()
|
||||||
|
@ -1210,9 +1223,11 @@ class Image:
|
||||||
return self.copy()
|
return self.copy()
|
||||||
|
|
||||||
if box[2] < box[0]:
|
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]:
|
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()
|
self.load()
|
||||||
return self._new(self._crop(self.im, box))
|
return self._new(self._crop(self.im, box))
|
||||||
|
@ -1280,9 +1295,8 @@ class Image:
|
||||||
if isinstance(filter, Callable):
|
if isinstance(filter, Callable):
|
||||||
filter = filter()
|
filter = filter()
|
||||||
if not hasattr(filter, "filter"):
|
if not hasattr(filter, "filter"):
|
||||||
raise TypeError(
|
msg = "filter argument should be ImageFilter.Filter instance or class"
|
||||||
"filter argument should be ImageFilter.Filter instance or class"
|
raise TypeError(msg)
|
||||||
)
|
|
||||||
|
|
||||||
multiband = isinstance(filter, ImageFilter.MultibandFilter)
|
multiband = isinstance(filter, ImageFilter.MultibandFilter)
|
||||||
if self.im.bands == 1 or multiband:
|
if self.im.bands == 1 or multiband:
|
||||||
|
@ -1691,7 +1705,8 @@ class Image:
|
||||||
size = mask.size
|
size = mask.size
|
||||||
else:
|
else:
|
||||||
# FIXME: use self.size here?
|
# 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])
|
box += (box[0] + size[0], box[1] + size[1])
|
||||||
|
|
||||||
if isinstance(im, str):
|
if isinstance(im, str):
|
||||||
|
@ -1730,15 +1745,20 @@ class Image:
|
||||||
"""
|
"""
|
||||||
|
|
||||||
if not isinstance(source, (list, tuple)):
|
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)):
|
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):
|
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:
|
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:
|
if min(source) < 0:
|
||||||
raise ValueError("Source must be non-negative")
|
msg = "Source must be non-negative"
|
||||||
|
raise ValueError(msg)
|
||||||
|
|
||||||
if len(source) == 2:
|
if len(source) == 2:
|
||||||
source = source + im.size
|
source = source + im.size
|
||||||
|
@ -1803,7 +1823,8 @@ class Image:
|
||||||
|
|
||||||
if self.mode == "F":
|
if self.mode == "F":
|
||||||
# FIXME: _imaging returns a confusing error message for this case
|
# 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":
|
if mode != "F":
|
||||||
lut = [round(i) for i in lut]
|
lut = [round(i) for i in lut]
|
||||||
|
@ -1837,7 +1858,8 @@ class Image:
|
||||||
self.pyaccess = None
|
self.pyaccess = None
|
||||||
self.mode = self.im.mode
|
self.mode = self.im.mode
|
||||||
except KeyError as e:
|
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"):
|
if self.mode in ("LA", "PA"):
|
||||||
band = 1
|
band = 1
|
||||||
|
@ -1847,7 +1869,8 @@ class Image:
|
||||||
if isImageType(alpha):
|
if isImageType(alpha):
|
||||||
# alpha layer
|
# alpha layer
|
||||||
if alpha.mode not in ("1", "L"):
|
if alpha.mode not in ("1", "L"):
|
||||||
raise ValueError("illegal image mode")
|
msg = "illegal image mode"
|
||||||
|
raise ValueError(msg)
|
||||||
alpha.load()
|
alpha.load()
|
||||||
if alpha.mode == "1":
|
if alpha.mode == "1":
|
||||||
alpha = alpha.convert("L")
|
alpha = alpha.convert("L")
|
||||||
|
@ -1903,7 +1926,8 @@ class Image:
|
||||||
from . import ImagePalette
|
from . import ImagePalette
|
||||||
|
|
||||||
if self.mode not in ("L", "LA", "P", "PA"):
|
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):
|
if isinstance(data, ImagePalette.ImagePalette):
|
||||||
palette = ImagePalette.raw(data.rawmode, data.palette)
|
palette = ImagePalette.raw(data.rawmode, data.palette)
|
||||||
else:
|
else:
|
||||||
|
@ -1972,7 +1996,8 @@ class Image:
|
||||||
from . import ImagePalette
|
from . import ImagePalette
|
||||||
|
|
||||||
if self.mode not in ("L", "P"):
|
if self.mode not in ("L", "P"):
|
||||||
raise ValueError("illegal image mode")
|
msg = "illegal image mode"
|
||||||
|
raise ValueError(msg)
|
||||||
|
|
||||||
bands = 3
|
bands = 3
|
||||||
palette_mode = "RGB"
|
palette_mode = "RGB"
|
||||||
|
@ -2122,7 +2147,8 @@ class Image:
|
||||||
)
|
)
|
||||||
|
|
||||||
if reducing_gap is not None and reducing_gap < 1.0:
|
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)
|
size = tuple(size)
|
||||||
|
|
||||||
|
@ -2380,7 +2406,8 @@ class Image:
|
||||||
try:
|
try:
|
||||||
format = EXTENSION[ext]
|
format = EXTENSION[ext]
|
||||||
except KeyError as e:
|
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:
|
if format.upper() not in SAVE:
|
||||||
init()
|
init()
|
||||||
|
@ -2494,7 +2521,8 @@ class Image:
|
||||||
try:
|
try:
|
||||||
channel = self.getbands().index(channel)
|
channel = self.getbands().index(channel)
|
||||||
except ValueError as e:
|
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))
|
return self._new(self.im.getband(channel))
|
||||||
|
|
||||||
|
@ -2665,7 +2693,8 @@ class Image:
|
||||||
method, data = method.getdata()
|
method, data = method.getdata()
|
||||||
|
|
||||||
if data is None:
|
if data is None:
|
||||||
raise ValueError("missing method data")
|
msg = "missing method data"
|
||||||
|
raise ValueError(msg)
|
||||||
|
|
||||||
im = new(self.mode, size, fillcolor)
|
im = new(self.mode, size, fillcolor)
|
||||||
if self.mode == "P" and self.palette:
|
if self.mode == "P" and self.palette:
|
||||||
|
@ -2726,7 +2755,8 @@ class Image:
|
||||||
)
|
)
|
||||||
|
|
||||||
else:
|
else:
|
||||||
raise ValueError("unknown transformation method")
|
msg = "unknown transformation method"
|
||||||
|
raise ValueError(msg)
|
||||||
|
|
||||||
if resample not in (
|
if resample not in (
|
||||||
Resampling.NEAREST,
|
Resampling.NEAREST,
|
||||||
|
@ -2791,7 +2821,8 @@ class Image:
|
||||||
from . import ImageQt
|
from . import ImageQt
|
||||||
|
|
||||||
if not ImageQt.qt_is_installed:
|
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)
|
return ImageQt.toqimage(self)
|
||||||
|
|
||||||
def toqpixmap(self):
|
def toqpixmap(self):
|
||||||
|
@ -2799,7 +2830,8 @@ class Image:
|
||||||
from . import ImageQt
|
from . import ImageQt
|
||||||
|
|
||||||
if not ImageQt.qt_is_installed:
|
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)
|
return ImageQt.toqpixmap(self)
|
||||||
|
|
||||||
|
|
||||||
|
@ -2847,11 +2879,14 @@ def _check_size(size):
|
||||||
"""
|
"""
|
||||||
|
|
||||||
if not isinstance(size, (list, tuple)):
|
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:
|
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:
|
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
|
return True
|
||||||
|
|
||||||
|
@ -3037,7 +3072,8 @@ def fromarray(obj, mode=None):
|
||||||
try:
|
try:
|
||||||
typekey = (1, 1) + shape[2:], arr["typestr"]
|
typekey = (1, 1) + shape[2:], arr["typestr"]
|
||||||
except KeyError as e:
|
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:
|
try:
|
||||||
mode, rawmode = _fromarray_typemap[typekey]
|
mode, rawmode = _fromarray_typemap[typekey]
|
||||||
except KeyError as e:
|
except KeyError as e:
|
||||||
|
@ -3051,7 +3087,8 @@ def fromarray(obj, mode=None):
|
||||||
else:
|
else:
|
||||||
ndmax = 4
|
ndmax = 4
|
||||||
if ndim > ndmax:
|
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]
|
size = 1 if ndim == 1 else shape[1], shape[0]
|
||||||
if strides is not None:
|
if strides is not None:
|
||||||
|
@ -3068,7 +3105,8 @@ def fromqimage(im):
|
||||||
from . import ImageQt
|
from . import ImageQt
|
||||||
|
|
||||||
if not ImageQt.qt_is_installed:
|
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)
|
return ImageQt.fromqimage(im)
|
||||||
|
|
||||||
|
|
||||||
|
@ -3077,7 +3115,8 @@ def fromqpixmap(im):
|
||||||
from . import ImageQt
|
from . import ImageQt
|
||||||
|
|
||||||
if not ImageQt.qt_is_installed:
|
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)
|
return ImageQt.fromqpixmap(im)
|
||||||
|
|
||||||
|
|
||||||
|
@ -3115,10 +3154,11 @@ def _decompression_bomb_check(size):
|
||||||
pixels = size[0] * size[1]
|
pixels = size[0] * size[1]
|
||||||
|
|
||||||
if pixels > 2 * MAX_IMAGE_PIXELS:
|
if pixels > 2 * MAX_IMAGE_PIXELS:
|
||||||
raise DecompressionBombError(
|
msg = (
|
||||||
f"Image size ({pixels} pixels) exceeds limit of {2 * MAX_IMAGE_PIXELS} "
|
f"Image size ({pixels} pixels) exceeds limit of {2 * MAX_IMAGE_PIXELS} "
|
||||||
"pixels, could be decompression bomb DOS attack."
|
"pixels, could be decompression bomb DOS attack."
|
||||||
)
|
)
|
||||||
|
raise DecompressionBombError(msg)
|
||||||
|
|
||||||
if pixels > MAX_IMAGE_PIXELS:
|
if pixels > MAX_IMAGE_PIXELS:
|
||||||
warnings.warn(
|
warnings.warn(
|
||||||
|
@ -3158,17 +3198,20 @@ def open(fp, mode="r", formats=None):
|
||||||
"""
|
"""
|
||||||
|
|
||||||
if mode != "r":
|
if mode != "r":
|
||||||
raise ValueError(f"bad mode {repr(mode)}")
|
msg = f"bad mode {repr(mode)}"
|
||||||
|
raise ValueError(msg)
|
||||||
elif isinstance(fp, io.StringIO):
|
elif isinstance(fp, io.StringIO):
|
||||||
raise ValueError(
|
msg = (
|
||||||
"StringIO cannot be used to open an image. "
|
"StringIO cannot be used to open an image. "
|
||||||
"Binary data must be used instead."
|
"Binary data must be used instead."
|
||||||
)
|
)
|
||||||
|
raise ValueError(msg)
|
||||||
|
|
||||||
if formats is None:
|
if formats is None:
|
||||||
formats = ID
|
formats = ID
|
||||||
elif not isinstance(formats, (list, tuple)):
|
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
|
exclusive_fp = False
|
||||||
filename = ""
|
filename = ""
|
||||||
|
@ -3326,12 +3369,15 @@ def merge(mode, bands):
|
||||||
"""
|
"""
|
||||||
|
|
||||||
if getmodebands(mode) != len(bands) or "*" in mode:
|
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:]:
|
for band in bands[1:]:
|
||||||
if band.mode != getmodetype(mode):
|
if band.mode != getmodetype(mode):
|
||||||
raise ValueError("mode mismatch")
|
msg = "mode mismatch"
|
||||||
|
raise ValueError(msg)
|
||||||
if band.size != bands[0].size:
|
if band.size != bands[0].size:
|
||||||
raise ValueError("size mismatch")
|
msg = "size mismatch"
|
||||||
|
raise ValueError(msg)
|
||||||
for band in bands:
|
for band in bands:
|
||||||
band.load()
|
band.load()
|
||||||
return bands[0]._new(core.merge(mode, *[b.im for b in bands]))
|
return bands[0]._new(core.merge(mode, *[b.im for b in bands]))
|
||||||
|
|
|
@ -124,7 +124,8 @@ def __getattr__(name):
|
||||||
if name in enum.__members__:
|
if name in enum.__members__:
|
||||||
deprecate(f"{prefix}{name}", 10, f"{enum.__name__}.{name}")
|
deprecate(f"{prefix}{name}", 10, f"{enum.__name__}.{name}")
|
||||||
return enum[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):
|
elif isinstance(profile, _imagingcms.CmsProfile):
|
||||||
self._set(profile)
|
self._set(profile)
|
||||||
else:
|
else:
|
||||||
raise TypeError("Invalid type for Profile")
|
msg = "Invalid type for Profile"
|
||||||
|
raise TypeError(msg)
|
||||||
|
|
||||||
def _set(self, profile, filename=None):
|
def _set(self, profile, filename=None):
|
||||||
self.profile = profile
|
self.profile = profile
|
||||||
|
@ -269,7 +271,8 @@ class ImageCmsTransform(Image.ImagePointHandler):
|
||||||
def apply_in_place(self, im):
|
def apply_in_place(self, im):
|
||||||
im.load()
|
im.load()
|
||||||
if im.mode != self.output_mode:
|
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)
|
self.transform.apply(im.im.id, im.im.id)
|
||||||
im.info["icc_profile"] = self.output_profile.tobytes()
|
im.info["icc_profile"] = self.output_profile.tobytes()
|
||||||
return im
|
return im
|
||||||
|
@ -374,10 +377,12 @@ def profileToProfile(
|
||||||
outputMode = im.mode
|
outputMode = im.mode
|
||||||
|
|
||||||
if not isinstance(renderingIntent, int) or not (0 <= renderingIntent <= 3):
|
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):
|
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:
|
try:
|
||||||
if not isinstance(inputProfile, ImageCmsProfile):
|
if not isinstance(inputProfile, ImageCmsProfile):
|
||||||
|
@ -489,7 +494,8 @@ def buildTransform(
|
||||||
"""
|
"""
|
||||||
|
|
||||||
if not isinstance(renderingIntent, int) or not (0 <= renderingIntent <= 3):
|
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):
|
if not isinstance(flags, int) or not (0 <= flags <= _MAX_FLAG):
|
||||||
raise PyCMSError("flags must be an integer between 0 and %s" + _MAX_FLAG)
|
raise PyCMSError("flags must be an integer between 0 and %s" + _MAX_FLAG)
|
||||||
|
@ -591,7 +597,8 @@ def buildProofTransform(
|
||||||
"""
|
"""
|
||||||
|
|
||||||
if not isinstance(renderingIntent, int) or not (0 <= renderingIntent <= 3):
|
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):
|
if not isinstance(flags, int) or not (0 <= flags <= _MAX_FLAG):
|
||||||
raise PyCMSError("flags must be an integer between 0 and %s" + _MAX_FLAG)
|
raise PyCMSError("flags must be an integer between 0 and %s" + _MAX_FLAG)
|
||||||
|
@ -705,17 +712,17 @@ def createProfile(colorSpace, colorTemp=-1):
|
||||||
"""
|
"""
|
||||||
|
|
||||||
if colorSpace not in ["LAB", "XYZ", "sRGB"]:
|
if colorSpace not in ["LAB", "XYZ", "sRGB"]:
|
||||||
raise PyCMSError(
|
msg = (
|
||||||
f"Color space not supported for on-the-fly profile creation ({colorSpace})"
|
f"Color space not supported for on-the-fly profile creation ({colorSpace})"
|
||||||
)
|
)
|
||||||
|
raise PyCMSError(msg)
|
||||||
|
|
||||||
if colorSpace == "LAB":
|
if colorSpace == "LAB":
|
||||||
try:
|
try:
|
||||||
colorTemp = float(colorTemp)
|
colorTemp = float(colorTemp)
|
||||||
except (TypeError, ValueError) as e:
|
except (TypeError, ValueError) as e:
|
||||||
raise PyCMSError(
|
msg = f'Color temperature must be numeric, "{colorTemp}" not valid'
|
||||||
f'Color temperature must be numeric, "{colorTemp}" not valid'
|
raise PyCMSError(msg) from e
|
||||||
) from e
|
|
||||||
|
|
||||||
try:
|
try:
|
||||||
return core.createProfile(colorSpace, colorTemp)
|
return core.createProfile(colorSpace, colorTemp)
|
||||||
|
|
|
@ -33,7 +33,8 @@ def getrgb(color):
|
||||||
:return: ``(red, green, blue[, alpha])``
|
:return: ``(red, green, blue[, alpha])``
|
||||||
"""
|
"""
|
||||||
if len(color) > 100:
|
if len(color) > 100:
|
||||||
raise ValueError("color specifier is too long")
|
msg = "color specifier is too long"
|
||||||
|
raise ValueError(msg)
|
||||||
color = color.lower()
|
color = color.lower()
|
||||||
|
|
||||||
rgb = colormap.get(color, None)
|
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)
|
m = re.match(r"rgba\(\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*\)$", color)
|
||||||
if m:
|
if m:
|
||||||
return int(m.group(1)), int(m.group(2)), int(m.group(3)), int(m.group(4))
|
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):
|
def getcolor(color, mode):
|
||||||
|
|
|
@ -69,7 +69,8 @@ class ImageDraw:
|
||||||
if mode == "RGBA" and im.mode == "RGB":
|
if mode == "RGBA" and im.mode == "RGB":
|
||||||
blend = 1
|
blend = 1
|
||||||
else:
|
else:
|
||||||
raise ValueError("mode mismatch")
|
msg = "mode mismatch"
|
||||||
|
raise ValueError(msg)
|
||||||
if mode == "P":
|
if mode == "P":
|
||||||
self.palette = im.palette
|
self.palette = im.palette
|
||||||
else:
|
else:
|
||||||
|
@ -437,7 +438,8 @@ class ImageDraw:
|
||||||
)
|
)
|
||||||
|
|
||||||
if embedded_color and self.mode not in ("RGB", "RGBA"):
|
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:
|
if font is None:
|
||||||
font = self.getfont()
|
font = self.getfont()
|
||||||
|
@ -534,14 +536,17 @@ class ImageDraw:
|
||||||
embedded_color=False,
|
embedded_color=False,
|
||||||
):
|
):
|
||||||
if direction == "ttb":
|
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:
|
if anchor is None:
|
||||||
anchor = "la"
|
anchor = "la"
|
||||||
elif len(anchor) != 2:
|
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":
|
elif anchor[1] in "tb":
|
||||||
raise ValueError("anchor not supported for multiline text")
|
msg = "anchor not supported for multiline text"
|
||||||
|
raise ValueError(msg)
|
||||||
|
|
||||||
widths = []
|
widths = []
|
||||||
max_width = 0
|
max_width = 0
|
||||||
|
@ -578,7 +583,8 @@ class ImageDraw:
|
||||||
elif align == "right":
|
elif align == "right":
|
||||||
left += width_difference
|
left += width_difference
|
||||||
else:
|
else:
|
||||||
raise ValueError('align must be "left", "center" or "right"')
|
msg = 'align must be "left", "center" or "right"'
|
||||||
|
raise ValueError(msg)
|
||||||
|
|
||||||
self.text(
|
self.text(
|
||||||
(left, top),
|
(left, top),
|
||||||
|
@ -672,9 +678,11 @@ class ImageDraw:
|
||||||
):
|
):
|
||||||
"""Get the length of a given string, in pixels with 1/64 precision."""
|
"""Get the length of a given string, in pixels with 1/64 precision."""
|
||||||
if self._multiline_check(text):
|
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"):
|
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:
|
if font is None:
|
||||||
font = self.getfont()
|
font = self.getfont()
|
||||||
|
@ -712,7 +720,8 @@ class ImageDraw:
|
||||||
):
|
):
|
||||||
"""Get the bounding box of a given string, in pixels."""
|
"""Get the bounding box of a given string, in pixels."""
|
||||||
if embedded_color and self.mode not in ("RGB", "RGBA"):
|
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):
|
if self._multiline_check(text):
|
||||||
return self.multiline_textbbox(
|
return self.multiline_textbbox(
|
||||||
|
@ -752,14 +761,17 @@ class ImageDraw:
|
||||||
embedded_color=False,
|
embedded_color=False,
|
||||||
):
|
):
|
||||||
if direction == "ttb":
|
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:
|
if anchor is None:
|
||||||
anchor = "la"
|
anchor = "la"
|
||||||
elif len(anchor) != 2:
|
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":
|
elif anchor[1] in "tb":
|
||||||
raise ValueError("anchor not supported for multiline text")
|
msg = "anchor not supported for multiline text"
|
||||||
|
raise ValueError(msg)
|
||||||
|
|
||||||
widths = []
|
widths = []
|
||||||
max_width = 0
|
max_width = 0
|
||||||
|
@ -803,7 +815,8 @@ class ImageDraw:
|
||||||
elif align == "right":
|
elif align == "right":
|
||||||
left += width_difference
|
left += width_difference
|
||||||
else:
|
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(
|
bbox_line = self.textbbox(
|
||||||
(left, top),
|
(left, top),
|
||||||
|
@ -979,38 +992,44 @@ def _compute_regular_polygon_vertices(bounding_circle, n_sides, rotation):
|
||||||
# 1. Error Handling
|
# 1. Error Handling
|
||||||
# 1.1 Check `n_sides` has an appropriate value
|
# 1.1 Check `n_sides` has an appropriate value
|
||||||
if not isinstance(n_sides, int):
|
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:
|
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
|
# 1.2 Check `bounding_circle` has an appropriate value
|
||||||
if not isinstance(bounding_circle, (list, tuple)):
|
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:
|
if len(bounding_circle) == 3:
|
||||||
*centroid, polygon_radius = bounding_circle
|
*centroid, polygon_radius = bounding_circle
|
||||||
elif len(bounding_circle) == 2:
|
elif len(bounding_circle) == 2:
|
||||||
centroid, polygon_radius = bounding_circle
|
centroid, polygon_radius = bounding_circle
|
||||||
else:
|
else:
|
||||||
raise ValueError(
|
msg = (
|
||||||
"bounding_circle should contain 2D coordinates "
|
"bounding_circle should contain 2D coordinates "
|
||||||
"and a radius (e.g. (x, y, r) or ((x, y), r) )"
|
"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)):
|
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:
|
if not len(centroid) == 2:
|
||||||
raise ValueError(
|
msg = "bounding_circle centre should contain 2D coordinates (e.g. (x, y))"
|
||||||
"bounding_circle centre should contain 2D coordinates (e.g. (x, y))"
|
raise ValueError(msg)
|
||||||
)
|
|
||||||
|
|
||||||
if polygon_radius <= 0:
|
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
|
# 1.3 Check `rotation` has an appropriate value
|
||||||
if not isinstance(rotation, (int, float)):
|
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
|
# 2. Define Helper Functions
|
||||||
def _apply_rotation(point, degrees, centroid):
|
def _apply_rotation(point, degrees, centroid):
|
||||||
|
|
|
@ -124,7 +124,8 @@ class ImageFile(Image.Image):
|
||||||
raise SyntaxError(v) from v
|
raise SyntaxError(v) from v
|
||||||
|
|
||||||
if not self.mode or self.size[0] <= 0 or self.size[1] <= 0:
|
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:
|
except BaseException:
|
||||||
# close the file only if we have opened it this constructor
|
# close the file only if we have opened it this constructor
|
||||||
if self._exclusive_fp:
|
if self._exclusive_fp:
|
||||||
|
@ -154,7 +155,8 @@ class ImageFile(Image.Image):
|
||||||
"""Load image data based on tile list"""
|
"""Load image data based on tile list"""
|
||||||
|
|
||||||
if self.tile is None:
|
if self.tile is None:
|
||||||
raise OSError("cannot load this image")
|
msg = "cannot load this image"
|
||||||
|
raise OSError(msg)
|
||||||
|
|
||||||
pixel = Image.Image.load(self)
|
pixel = Image.Image.load(self)
|
||||||
if not self.tile:
|
if not self.tile:
|
||||||
|
@ -249,16 +251,18 @@ class ImageFile(Image.Image):
|
||||||
if LOAD_TRUNCATED_IMAGES:
|
if LOAD_TRUNCATED_IMAGES:
|
||||||
break
|
break
|
||||||
else:
|
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 not s: # truncated jpeg
|
||||||
if LOAD_TRUNCATED_IMAGES:
|
if LOAD_TRUNCATED_IMAGES:
|
||||||
break
|
break
|
||||||
else:
|
else:
|
||||||
raise OSError(
|
msg = (
|
||||||
"image file is truncated "
|
"image file is truncated "
|
||||||
f"({len(b)} bytes not processed)"
|
f"({len(b)} bytes not processed)"
|
||||||
)
|
)
|
||||||
|
raise OSError(msg)
|
||||||
|
|
||||||
b = b + s
|
b = b + s
|
||||||
n, err_code = decoder.decode(b)
|
n, err_code = decoder.decode(b)
|
||||||
|
@ -314,7 +318,8 @@ class ImageFile(Image.Image):
|
||||||
and frame >= self.n_frames + self._min_frame
|
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
|
return self.tell() != frame
|
||||||
|
|
||||||
|
@ -328,12 +333,14 @@ class StubImageFile(ImageFile):
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def _open(self):
|
def _open(self):
|
||||||
raise NotImplementedError("StubImageFile subclass must implement _open")
|
msg = "StubImageFile subclass must implement _open"
|
||||||
|
raise NotImplementedError(msg)
|
||||||
|
|
||||||
def load(self):
|
def load(self):
|
||||||
loader = self._load()
|
loader = self._load()
|
||||||
if loader is None:
|
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)
|
image = loader.load(self)
|
||||||
assert image is not None
|
assert image is not None
|
||||||
# become the other object (!)
|
# become the other object (!)
|
||||||
|
@ -343,7 +350,8 @@ class StubImageFile(ImageFile):
|
||||||
|
|
||||||
def _load(self):
|
def _load(self):
|
||||||
"""(Hook) Find actual image loader."""
|
"""(Hook) Find actual image loader."""
|
||||||
raise NotImplementedError("StubImageFile subclass must implement _load")
|
msg = "StubImageFile subclass must implement _load"
|
||||||
|
raise NotImplementedError(msg)
|
||||||
|
|
||||||
|
|
||||||
class Parser:
|
class Parser:
|
||||||
|
@ -468,9 +476,11 @@ class Parser:
|
||||||
self.feed(b"")
|
self.feed(b"")
|
||||||
self.data = self.decoder = None
|
self.data = self.decoder = None
|
||||||
if not self.finished:
|
if not self.finished:
|
||||||
raise OSError("image was incomplete")
|
msg = "image was incomplete"
|
||||||
|
raise OSError(msg)
|
||||||
if not self.image:
|
if not self.image:
|
||||||
raise OSError("cannot parse this image")
|
msg = "cannot parse this image"
|
||||||
|
raise OSError(msg)
|
||||||
if self.data:
|
if self.data:
|
||||||
# incremental parsing not possible; reopen the file
|
# incremental parsing not possible; reopen the file
|
||||||
# not that we have all data
|
# not that we have all data
|
||||||
|
@ -535,7 +545,8 @@ def _encode_tile(im, fp, tile, bufsize, fh, exc=None):
|
||||||
# slight speedup: compress to real file object
|
# slight speedup: compress to real file object
|
||||||
s = encoder.encode_to_file(fh, bufsize)
|
s = encoder.encode_to_file(fh, bufsize)
|
||||||
if s < 0:
|
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:
|
finally:
|
||||||
encoder.cleanup()
|
encoder.cleanup()
|
||||||
|
|
||||||
|
@ -558,7 +569,8 @@ def _safe_read(fp, size):
|
||||||
if size <= SAFEBLOCK:
|
if size <= SAFEBLOCK:
|
||||||
data = fp.read(size)
|
data = fp.read(size)
|
||||||
if len(data) < size:
|
if len(data) < size:
|
||||||
raise OSError("Truncated File Read")
|
msg = "Truncated File Read"
|
||||||
|
raise OSError(msg)
|
||||||
return data
|
return data
|
||||||
data = []
|
data = []
|
||||||
remaining_size = size
|
remaining_size = size
|
||||||
|
@ -569,7 +581,8 @@ def _safe_read(fp, size):
|
||||||
data.append(block)
|
data.append(block)
|
||||||
remaining_size -= len(block)
|
remaining_size -= len(block)
|
||||||
if sum(len(d) for d in data) < size:
|
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)
|
return b"".join(data)
|
||||||
|
|
||||||
|
|
||||||
|
@ -645,13 +658,15 @@ class PyCodec:
|
||||||
self.state.ysize = y1 - y0
|
self.state.ysize = y1 - y0
|
||||||
|
|
||||||
if self.state.xsize <= 0 or self.state.ysize <= 0:
|
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 (
|
if (
|
||||||
self.state.xsize + self.state.xoff > self.im.size[0]
|
self.state.xsize + self.state.xoff > self.im.size[0]
|
||||||
or self.state.ysize + self.state.yoff > self.im.size[1]
|
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):
|
class PyDecoder(PyCodec):
|
||||||
|
@ -696,9 +711,11 @@ class PyDecoder(PyCodec):
|
||||||
s = d.decode(data)
|
s = d.decode(data)
|
||||||
|
|
||||||
if s[0] >= 0:
|
if s[0] >= 0:
|
||||||
raise ValueError("not enough image data")
|
msg = "not enough image data"
|
||||||
|
raise ValueError(msg)
|
||||||
if s[1] != 0:
|
if s[1] != 0:
|
||||||
raise ValueError("cannot decode image data")
|
msg = "cannot decode image data"
|
||||||
|
raise ValueError(msg)
|
||||||
|
|
||||||
|
|
||||||
class PyEncoder(PyCodec):
|
class PyEncoder(PyCodec):
|
||||||
|
|
|
@ -28,7 +28,8 @@ class MultibandFilter(Filter):
|
||||||
class BuiltinFilter(MultibandFilter):
|
class BuiltinFilter(MultibandFilter):
|
||||||
def filter(self, image):
|
def filter(self, image):
|
||||||
if image.mode == "P":
|
if image.mode == "P":
|
||||||
raise ValueError("cannot filter palette images")
|
msg = "cannot filter palette images"
|
||||||
|
raise ValueError(msg)
|
||||||
return image.filter(*self.filterargs)
|
return image.filter(*self.filterargs)
|
||||||
|
|
||||||
|
|
||||||
|
@ -57,7 +58,8 @@ class Kernel(BuiltinFilter):
|
||||||
# default scale is sum of kernel
|
# default scale is sum of kernel
|
||||||
scale = functools.reduce(lambda a, b: a + b, kernel)
|
scale = functools.reduce(lambda a, b: a + b, kernel)
|
||||||
if size[0] * size[1] != len(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
|
self.filterargs = size, scale, offset, kernel
|
||||||
|
|
||||||
|
|
||||||
|
@ -80,7 +82,8 @@ class RankFilter(Filter):
|
||||||
|
|
||||||
def filter(self, image):
|
def filter(self, image):
|
||||||
if image.mode == "P":
|
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)
|
image = image.expand(self.size // 2, self.size // 2)
|
||||||
return image.rankfilter(self.size, self.rank)
|
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):
|
def __init__(self, size, table, channels=3, target_mode=None, **kwargs):
|
||||||
if channels not in (3, 4):
|
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.size = size = self._check_size(size)
|
||||||
self.channels = channels
|
self.channels = channels
|
||||||
self.mode = target_mode
|
self.mode = target_mode
|
||||||
|
@ -395,19 +399,21 @@ class Color3DLUT(MultibandFilter):
|
||||||
table, raw_table = [], table
|
table, raw_table = [], table
|
||||||
for pixel in raw_table:
|
for pixel in raw_table:
|
||||||
if len(pixel) != channels:
|
if len(pixel) != channels:
|
||||||
raise ValueError(
|
msg = (
|
||||||
"The elements of the table should "
|
"The elements of the table should "
|
||||||
"have a length of {}.".format(channels)
|
f"have a length of {channels}."
|
||||||
)
|
)
|
||||||
|
raise ValueError(msg)
|
||||||
table.extend(pixel)
|
table.extend(pixel)
|
||||||
|
|
||||||
if wrong_size or len(table) != items * channels:
|
if wrong_size or len(table) != items * channels:
|
||||||
raise ValueError(
|
msg = (
|
||||||
"The table should have either channels * size**3 float items "
|
"The table should have either channels * size**3 float items "
|
||||||
"or size**3 items of channels-sized tuples with floats. "
|
"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"Table should be: {channels}x{size[0]}x{size[1]}x{size[2]}. "
|
||||||
f"Actual length: {len(table)}"
|
f"Actual length: {len(table)}"
|
||||||
)
|
)
|
||||||
|
raise ValueError(msg)
|
||||||
self.table = table
|
self.table = table
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
|
@ -415,15 +421,15 @@ class Color3DLUT(MultibandFilter):
|
||||||
try:
|
try:
|
||||||
_, _, _ = size
|
_, _, _ = size
|
||||||
except ValueError as e:
|
except ValueError as e:
|
||||||
raise ValueError(
|
msg = "Size should be either an integer or a tuple of three integers."
|
||||||
"Size should be either an integer or a tuple of three integers."
|
raise ValueError(msg) from e
|
||||||
) from e
|
|
||||||
except TypeError:
|
except TypeError:
|
||||||
size = (size, size, size)
|
size = (size, size, size)
|
||||||
size = [int(x) for x in size]
|
size = [int(x) for x in size]
|
||||||
for size_1d in size:
|
for size_1d in size:
|
||||||
if not 2 <= size_1d <= 65:
|
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
|
return size
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
|
@ -441,7 +447,8 @@ class Color3DLUT(MultibandFilter):
|
||||||
"""
|
"""
|
||||||
size_1d, size_2d, size_3d = cls._check_size(size)
|
size_1d, size_2d, size_3d = cls._check_size(size)
|
||||||
if channels not in (3, 4):
|
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)
|
table = [0] * (size_1d * size_2d * size_3d * channels)
|
||||||
idx_out = 0
|
idx_out = 0
|
||||||
|
@ -481,7 +488,8 @@ class Color3DLUT(MultibandFilter):
|
||||||
lookup table.
|
lookup table.
|
||||||
"""
|
"""
|
||||||
if channels not in (None, 3, 4):
|
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_in = self.channels
|
||||||
ch_out = channels or ch_in
|
ch_out = channels or ch_in
|
||||||
size_1d, size_2d, size_3d = self.size
|
size_1d, size_2d, size_3d = self.size
|
||||||
|
|
|
@ -50,13 +50,15 @@ def __getattr__(name):
|
||||||
if name in enum.__members__:
|
if name in enum.__members__:
|
||||||
deprecate(f"{prefix}{name}", 10, f"{enum.__name__}.{name}")
|
deprecate(f"{prefix}{name}", 10, f"{enum.__name__}.{name}")
|
||||||
return enum[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:
|
class _ImagingFtNotInstalled:
|
||||||
# module placeholder
|
# module placeholder
|
||||||
def __getattr__(self, id):
|
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:
|
try:
|
||||||
|
@ -105,7 +107,8 @@ class ImageFont:
|
||||||
else:
|
else:
|
||||||
if image:
|
if image:
|
||||||
image.close()
|
image.close()
|
||||||
raise OSError("cannot find glyph data file")
|
msg = "cannot find glyph data file"
|
||||||
|
raise OSError(msg)
|
||||||
|
|
||||||
self.file = fullname
|
self.file = fullname
|
||||||
|
|
||||||
|
@ -116,7 +119,8 @@ class ImageFont:
|
||||||
|
|
||||||
# read PILfont header
|
# read PILfont header
|
||||||
if file.readline() != b"PILfont\n":
|
if file.readline() != b"PILfont\n":
|
||||||
raise SyntaxError("Not a PILfont file")
|
msg = "Not a PILfont file"
|
||||||
|
raise SyntaxError(msg)
|
||||||
file.readline().split(b";")
|
file.readline().split(b";")
|
||||||
self.info = [] # FIXME: should be a dictionary
|
self.info = [] # FIXME: should be a dictionary
|
||||||
while True:
|
while True:
|
||||||
|
@ -130,7 +134,8 @@ class ImageFont:
|
||||||
|
|
||||||
# check image
|
# check image
|
||||||
if image.mode not in ("1", "L"):
|
if image.mode not in ("1", "L"):
|
||||||
raise TypeError("invalid font image mode")
|
msg = "invalid font image mode"
|
||||||
|
raise TypeError(msg)
|
||||||
|
|
||||||
image.load()
|
image.load()
|
||||||
|
|
||||||
|
@ -817,7 +822,8 @@ class FreeTypeFont:
|
||||||
try:
|
try:
|
||||||
names = self.font.getvarnames()
|
names = self.font.getvarnames()
|
||||||
except AttributeError as e:
|
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]
|
return [name.replace(b"\x00", b"") for name in names]
|
||||||
|
|
||||||
def set_variation_by_name(self, name):
|
def set_variation_by_name(self, name):
|
||||||
|
@ -847,7 +853,8 @@ class FreeTypeFont:
|
||||||
try:
|
try:
|
||||||
axes = self.font.getvaraxes()
|
axes = self.font.getvaraxes()
|
||||||
except AttributeError as e:
|
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:
|
for axis in axes:
|
||||||
axis["name"] = axis["name"].replace(b"\x00", b"")
|
axis["name"] = axis["name"].replace(b"\x00", b"")
|
||||||
return axes
|
return axes
|
||||||
|
@ -860,7 +867,8 @@ class FreeTypeFont:
|
||||||
try:
|
try:
|
||||||
self.font.setvaraxes(axes)
|
self.font.setvaraxes(axes)
|
||||||
except AttributeError as e:
|
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:
|
class TransposedFont:
|
||||||
|
@ -914,9 +922,8 @@ class TransposedFont:
|
||||||
|
|
||||||
def getlength(self, text, *args, **kwargs):
|
def getlength(self, text, *args, **kwargs):
|
||||||
if self.orientation in (Image.Transpose.ROTATE_90, Image.Transpose.ROTATE_270):
|
if self.orientation in (Image.Transpose.ROTATE_90, Image.Transpose.ROTATE_270):
|
||||||
raise ValueError(
|
msg = "text length is undefined for text rotated by 90 or 270 degrees"
|
||||||
"text length is undefined for text rotated by 90 or 270 degrees"
|
raise ValueError(msg)
|
||||||
)
|
|
||||||
return self.font.getlength(text, *args, **kwargs)
|
return self.font.getlength(text, *args, **kwargs)
|
||||||
|
|
||||||
|
|
||||||
|
@ -1061,7 +1068,8 @@ def load_path(filename):
|
||||||
return load(os.path.join(directory, filename))
|
return load(os.path.join(directory, filename))
|
||||||
except OSError:
|
except OSError:
|
||||||
pass
|
pass
|
||||||
raise OSError("cannot find font file")
|
msg = "cannot find font file"
|
||||||
|
raise OSError(msg)
|
||||||
|
|
||||||
|
|
||||||
def load_default():
|
def load_default():
|
||||||
|
|
|
@ -75,7 +75,8 @@ def grab(bbox=None, include_layered_windows=False, all_screens=False, xdisplay=N
|
||||||
return im
|
return im
|
||||||
# use xdisplay=None for default display on non-win32/macOS systems
|
# use xdisplay=None for default display on non-win32/macOS systems
|
||||||
if not Image.core.HAVE_XCB:
|
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)
|
size, data = Image.core.grabscreen_x11(xdisplay)
|
||||||
im = Image.frombytes("RGB", size, data, "raw", "BGRX", size[0] * 4, 1)
|
im = Image.frombytes("RGB", size, data, "raw", "BGRX", size[0] * 4, 1)
|
||||||
if bbox:
|
if bbox:
|
||||||
|
@ -137,9 +138,8 @@ def grabclipboard():
|
||||||
elif shutil.which("xclip"):
|
elif shutil.which("xclip"):
|
||||||
args = ["xclip", "-selection", "clipboard", "-t", "image/png", "-o"]
|
args = ["xclip", "-selection", "clipboard", "-t", "image/png", "-o"]
|
||||||
else:
|
else:
|
||||||
raise NotImplementedError(
|
msg = "wl-paste or xclip is required for ImageGrab.grabclipboard() on Linux"
|
||||||
"wl-paste or xclip is required for ImageGrab.grabclipboard() on Linux"
|
raise NotImplementedError(msg)
|
||||||
)
|
|
||||||
fh, filepath = tempfile.mkstemp()
|
fh, filepath = tempfile.mkstemp()
|
||||||
subprocess.call(args, stdout=fh)
|
subprocess.call(args, stdout=fh)
|
||||||
os.close(fh)
|
os.close(fh)
|
||||||
|
|
|
@ -39,7 +39,8 @@ class _Operand:
|
||||||
elif im1.im.mode in ("I", "F"):
|
elif im1.im.mode in ("I", "F"):
|
||||||
return im1.im
|
return im1.im
|
||||||
else:
|
else:
|
||||||
raise ValueError(f"unsupported mode: {im1.im.mode}")
|
msg = f"unsupported mode: {im1.im.mode}"
|
||||||
|
raise ValueError(msg)
|
||||||
else:
|
else:
|
||||||
# argument was a constant
|
# argument was a constant
|
||||||
if _isconstant(im1) and self.im.mode in ("1", "L", "I"):
|
if _isconstant(im1) and self.im.mode in ("1", "L", "I"):
|
||||||
|
@ -56,7 +57,8 @@ class _Operand:
|
||||||
try:
|
try:
|
||||||
op = getattr(_imagingmath, op + "_" + im1.mode)
|
op = getattr(_imagingmath, op + "_" + im1.mode)
|
||||||
except AttributeError as e:
|
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)
|
_imagingmath.unop(op, out.im.id, im1.im.id)
|
||||||
else:
|
else:
|
||||||
# binary operation
|
# binary operation
|
||||||
|
@ -80,7 +82,8 @@ class _Operand:
|
||||||
try:
|
try:
|
||||||
op = getattr(_imagingmath, op + "_" + im1.mode)
|
op = getattr(_imagingmath, op + "_" + im1.mode)
|
||||||
except AttributeError as e:
|
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)
|
_imagingmath.binop(op, out.im.id, im1.im.id, im2.im.id)
|
||||||
return _Operand(out)
|
return _Operand(out)
|
||||||
|
|
||||||
|
@ -249,7 +252,8 @@ def eval(expression, _dict={}, **kw):
|
||||||
|
|
||||||
for name in code.co_names:
|
for name in code.co_names:
|
||||||
if name not in args and name != "abs":
|
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)
|
scan(compiled_code)
|
||||||
out = builtins.eval(expression, {"__builtins": {"abs": abs}}, args)
|
out = builtins.eval(expression, {"__builtins": {"abs": abs}}, args)
|
||||||
|
|
|
@ -81,7 +81,8 @@ class LutBuilder:
|
||||||
],
|
],
|
||||||
}
|
}
|
||||||
if op_name not in known_patterns:
|
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]
|
self.patterns = known_patterns[op_name]
|
||||||
|
|
||||||
|
@ -193,10 +194,12 @@ class MorphOp:
|
||||||
Returns a tuple of the number of changed pixels and the
|
Returns a tuple of the number of changed pixels and the
|
||||||
morphed image"""
|
morphed image"""
|
||||||
if self.lut is None:
|
if self.lut is None:
|
||||||
raise Exception("No operator loaded")
|
msg = "No operator loaded"
|
||||||
|
raise Exception(msg)
|
||||||
|
|
||||||
if image.mode != "L":
|
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)
|
outimage = Image.new(image.mode, image.size, None)
|
||||||
count = _imagingmorph.apply(bytes(self.lut), image.im.id, outimage.im.id)
|
count = _imagingmorph.apply(bytes(self.lut), image.im.id, outimage.im.id)
|
||||||
return count, outimage
|
return count, outimage
|
||||||
|
@ -208,10 +211,12 @@ class MorphOp:
|
||||||
Returns a list of tuples of (x,y) coordinates
|
Returns a list of tuples of (x,y) coordinates
|
||||||
of all matching pixels. See :ref:`coordinate-system`."""
|
of all matching pixels. See :ref:`coordinate-system`."""
|
||||||
if self.lut is None:
|
if self.lut is None:
|
||||||
raise Exception("No operator loaded")
|
msg = "No operator loaded"
|
||||||
|
raise Exception(msg)
|
||||||
|
|
||||||
if image.mode != "L":
|
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)
|
return _imagingmorph.match(bytes(self.lut), image.im.id)
|
||||||
|
|
||||||
def get_on_pixels(self, image):
|
def get_on_pixels(self, image):
|
||||||
|
@ -221,7 +226,8 @@ class MorphOp:
|
||||||
of all matching pixels. See :ref:`coordinate-system`."""
|
of all matching pixels. See :ref:`coordinate-system`."""
|
||||||
|
|
||||||
if image.mode != "L":
|
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)
|
return _imagingmorph.get_on_pixels(image.im.id)
|
||||||
|
|
||||||
def load_lut(self, filename):
|
def load_lut(self, filename):
|
||||||
|
@ -231,12 +237,14 @@ class MorphOp:
|
||||||
|
|
||||||
if len(self.lut) != LUT_SIZE:
|
if len(self.lut) != LUT_SIZE:
|
||||||
self.lut = None
|
self.lut = None
|
||||||
raise Exception("Wrong size operator file!")
|
msg = "Wrong size operator file!"
|
||||||
|
raise Exception(msg)
|
||||||
|
|
||||||
def save_lut(self, filename):
|
def save_lut(self, filename):
|
||||||
"""Save an operator to an mrl file"""
|
"""Save an operator to an mrl file"""
|
||||||
if self.lut is None:
|
if self.lut is None:
|
||||||
raise Exception("No operator loaded")
|
msg = "No operator loaded"
|
||||||
|
raise Exception(msg)
|
||||||
with open(filename, "wb") as f:
|
with open(filename, "wb") as f:
|
||||||
f.write(self.lut)
|
f.write(self.lut)
|
||||||
|
|
||||||
|
|
|
@ -49,13 +49,15 @@ def _color(color, mode):
|
||||||
def _lut(image, lut):
|
def _lut(image, lut):
|
||||||
if image.mode == "P":
|
if image.mode == "P":
|
||||||
# FIXME: apply to lookup table, not image data
|
# 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"):
|
elif image.mode in ("L", "RGB"):
|
||||||
if image.mode == "RGB" and len(lut) == 256:
|
if image.mode == "RGB" and len(lut) == 256:
|
||||||
lut = lut + lut + lut
|
lut = lut + lut + lut
|
||||||
return image.point(lut)
|
return image.point(lut)
|
||||||
else:
|
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:
|
if factor == 1:
|
||||||
return image.copy()
|
return image.copy()
|
||||||
elif factor <= 0:
|
elif factor <= 0:
|
||||||
raise ValueError("the factor must be greater than 0")
|
msg = "the factor must be greater than 0"
|
||||||
|
raise ValueError(msg)
|
||||||
else:
|
else:
|
||||||
size = (round(factor * image.width), round(factor * image.height))
|
size = (round(factor * image.width), round(factor * image.height))
|
||||||
return image.resize(size, resample)
|
return image.resize(size, resample)
|
||||||
|
|
|
@ -42,7 +42,8 @@ class ImagePalette:
|
||||||
if size != 0:
|
if size != 0:
|
||||||
deprecate("The size parameter", 10, None)
|
deprecate("The size parameter", 10, None)
|
||||||
if size != len(self.palette):
|
if size != len(self.palette):
|
||||||
raise ValueError("wrong palette size")
|
msg = "wrong palette size"
|
||||||
|
raise ValueError(msg)
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def palette(self):
|
def palette(self):
|
||||||
|
@ -97,7 +98,8 @@ class ImagePalette:
|
||||||
.. warning:: This method is experimental.
|
.. warning:: This method is experimental.
|
||||||
"""
|
"""
|
||||||
if self.rawmode:
|
if self.rawmode:
|
||||||
raise ValueError("palette contains raw palette data")
|
msg = "palette contains raw palette data"
|
||||||
|
raise ValueError(msg)
|
||||||
if isinstance(self.palette, bytes):
|
if isinstance(self.palette, bytes):
|
||||||
return self.palette
|
return self.palette
|
||||||
arr = array.array("B", self.palette)
|
arr = array.array("B", self.palette)
|
||||||
|
@ -112,14 +114,14 @@ class ImagePalette:
|
||||||
.. warning:: This method is experimental.
|
.. warning:: This method is experimental.
|
||||||
"""
|
"""
|
||||||
if self.rawmode:
|
if self.rawmode:
|
||||||
raise ValueError("palette contains raw palette data")
|
msg = "palette contains raw palette data"
|
||||||
|
raise ValueError(msg)
|
||||||
if isinstance(color, tuple):
|
if isinstance(color, tuple):
|
||||||
if self.mode == "RGB":
|
if self.mode == "RGB":
|
||||||
if len(color) == 4:
|
if len(color) == 4:
|
||||||
if color[3] != 255:
|
if color[3] != 255:
|
||||||
raise ValueError(
|
msg = "cannot add non-opaque RGBA color to RGB palette"
|
||||||
"cannot add non-opaque RGBA color to RGB palette"
|
raise ValueError(msg)
|
||||||
)
|
|
||||||
color = color[:3]
|
color = color[:3]
|
||||||
elif self.mode == "RGBA":
|
elif self.mode == "RGBA":
|
||||||
if len(color) == 3:
|
if len(color) == 3:
|
||||||
|
@ -147,7 +149,8 @@ class ImagePalette:
|
||||||
index = i
|
index = i
|
||||||
break
|
break
|
||||||
if index >= 256:
|
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
|
self.colors[color] = index
|
||||||
if index * 3 < len(self.palette):
|
if index * 3 < len(self.palette):
|
||||||
self._palette = (
|
self._palette = (
|
||||||
|
@ -160,7 +163,8 @@ class ImagePalette:
|
||||||
self.dirty = 1
|
self.dirty = 1
|
||||||
return index
|
return index
|
||||||
else:
|
else:
|
||||||
raise ValueError(f"unknown color specifier: {repr(color)}")
|
msg = f"unknown color specifier: {repr(color)}"
|
||||||
|
raise ValueError(msg)
|
||||||
|
|
||||||
def save(self, fp):
|
def save(self, fp):
|
||||||
"""Save palette to text file.
|
"""Save palette to text file.
|
||||||
|
@ -168,7 +172,8 @@ class ImagePalette:
|
||||||
.. warning:: This method is experimental.
|
.. warning:: This method is experimental.
|
||||||
"""
|
"""
|
||||||
if self.rawmode:
|
if self.rawmode:
|
||||||
raise ValueError("palette contains raw palette data")
|
msg = "palette contains raw palette data"
|
||||||
|
raise ValueError(msg)
|
||||||
if isinstance(fp, str):
|
if isinstance(fp, str):
|
||||||
fp = open(fp, "w")
|
fp = open(fp, "w")
|
||||||
fp.write("# Palette\n")
|
fp.write("# Palette\n")
|
||||||
|
@ -263,6 +268,7 @@ def load(filename):
|
||||||
# traceback.print_exc()
|
# traceback.print_exc()
|
||||||
pass
|
pass
|
||||||
else:
|
else:
|
||||||
raise OSError("cannot load palette")
|
msg = "cannot load palette"
|
||||||
|
raise OSError(msg)
|
||||||
|
|
||||||
return lut # data, rawmode
|
return lut # data, rawmode
|
||||||
|
|
|
@ -179,7 +179,8 @@ def _toqclass_helper(im):
|
||||||
else:
|
else:
|
||||||
if exclusive_fp:
|
if exclusive_fp:
|
||||||
im.close()
|
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
|
size = im.size
|
||||||
__data = data or align8to32(im.tobytes(), size[0], im.mode)
|
__data = data or align8to32(im.tobytes(), size[0], im.mode)
|
||||||
|
|
|
@ -30,7 +30,8 @@ class Iterator:
|
||||||
|
|
||||||
def __init__(self, im):
|
def __init__(self, im):
|
||||||
if not hasattr(im, "seek"):
|
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.im = im
|
||||||
self.position = getattr(self.im, "_min_frame", 0)
|
self.position = getattr(self.im, "_min_frame", 0)
|
||||||
|
|
||||||
|
|
|
@ -124,7 +124,8 @@ class Viewer:
|
||||||
deprecate("The 'file' argument", 10, "'path'")
|
deprecate("The 'file' argument", 10, "'path'")
|
||||||
path = options.pop("file")
|
path = options.pop("file")
|
||||||
else:
|
else:
|
||||||
raise TypeError("Missing required argument: 'path'")
|
msg = "Missing required argument: 'path'"
|
||||||
|
raise TypeError(msg)
|
||||||
os.system(self.get_command(path, **options)) # nosec
|
os.system(self.get_command(path, **options)) # nosec
|
||||||
return 1
|
return 1
|
||||||
|
|
||||||
|
@ -176,7 +177,8 @@ class MacViewer(Viewer):
|
||||||
deprecate("The 'file' argument", 10, "'path'")
|
deprecate("The 'file' argument", 10, "'path'")
|
||||||
path = options.pop("file")
|
path = options.pop("file")
|
||||||
else:
|
else:
|
||||||
raise TypeError("Missing required argument: 'path'")
|
msg = "Missing required argument: 'path'"
|
||||||
|
raise TypeError(msg)
|
||||||
subprocess.call(["open", "-a", "Preview.app", path])
|
subprocess.call(["open", "-a", "Preview.app", path])
|
||||||
executable = sys.executable or shutil.which("python3")
|
executable = sys.executable or shutil.which("python3")
|
||||||
if executable:
|
if executable:
|
||||||
|
@ -226,7 +228,8 @@ class XDGViewer(UnixViewer):
|
||||||
deprecate("The 'file' argument", 10, "'path'")
|
deprecate("The 'file' argument", 10, "'path'")
|
||||||
path = options.pop("file")
|
path = options.pop("file")
|
||||||
else:
|
else:
|
||||||
raise TypeError("Missing required argument: 'path'")
|
msg = "Missing required argument: 'path'"
|
||||||
|
raise TypeError(msg)
|
||||||
subprocess.Popen(["xdg-open", path])
|
subprocess.Popen(["xdg-open", path])
|
||||||
return 1
|
return 1
|
||||||
|
|
||||||
|
@ -255,7 +258,8 @@ class DisplayViewer(UnixViewer):
|
||||||
deprecate("The 'file' argument", 10, "'path'")
|
deprecate("The 'file' argument", 10, "'path'")
|
||||||
path = options.pop("file")
|
path = options.pop("file")
|
||||||
else:
|
else:
|
||||||
raise TypeError("Missing required argument: 'path'")
|
msg = "Missing required argument: 'path'"
|
||||||
|
raise TypeError(msg)
|
||||||
args = ["display"]
|
args = ["display"]
|
||||||
title = options.get("title")
|
title = options.get("title")
|
||||||
if title:
|
if title:
|
||||||
|
@ -286,7 +290,8 @@ class GmDisplayViewer(UnixViewer):
|
||||||
deprecate("The 'file' argument", 10, "'path'")
|
deprecate("The 'file' argument", 10, "'path'")
|
||||||
path = options.pop("file")
|
path = options.pop("file")
|
||||||
else:
|
else:
|
||||||
raise TypeError("Missing required argument: 'path'")
|
msg = "Missing required argument: 'path'"
|
||||||
|
raise TypeError(msg)
|
||||||
subprocess.Popen(["gm", "display", path])
|
subprocess.Popen(["gm", "display", path])
|
||||||
return 1
|
return 1
|
||||||
|
|
||||||
|
@ -311,7 +316,8 @@ class EogViewer(UnixViewer):
|
||||||
deprecate("The 'file' argument", 10, "'path'")
|
deprecate("The 'file' argument", 10, "'path'")
|
||||||
path = options.pop("file")
|
path = options.pop("file")
|
||||||
else:
|
else:
|
||||||
raise TypeError("Missing required argument: 'path'")
|
msg = "Missing required argument: 'path'"
|
||||||
|
raise TypeError(msg)
|
||||||
subprocess.Popen(["eog", "-n", path])
|
subprocess.Popen(["eog", "-n", path])
|
||||||
return 1
|
return 1
|
||||||
|
|
||||||
|
@ -342,7 +348,8 @@ class XVViewer(UnixViewer):
|
||||||
deprecate("The 'file' argument", 10, "'path'")
|
deprecate("The 'file' argument", 10, "'path'")
|
||||||
path = options.pop("file")
|
path = options.pop("file")
|
||||||
else:
|
else:
|
||||||
raise TypeError("Missing required argument: 'path'")
|
msg = "Missing required argument: 'path'"
|
||||||
|
raise TypeError(msg)
|
||||||
args = ["xv"]
|
args = ["xv"]
|
||||||
title = options.get("title")
|
title = options.get("title")
|
||||||
if title:
|
if title:
|
||||||
|
|
|
@ -36,7 +36,8 @@ class Stat:
|
||||||
except AttributeError:
|
except AttributeError:
|
||||||
self.h = image_or_list # assume it to be a histogram list
|
self.h = image_or_list # assume it to be a histogram list
|
||||||
if not isinstance(self.h, 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))
|
self.bands = list(range(len(self.h) // 256))
|
||||||
|
|
||||||
def __getattr__(self, id):
|
def __getattr__(self, id):
|
||||||
|
|
|
@ -284,7 +284,8 @@ def _show(image, title):
|
||||||
super().__init__(master, image=self.image, bg="black", bd=0)
|
super().__init__(master, image=self.image, bg="black", bd=0)
|
||||||
|
|
||||||
if not tkinter._default_root:
|
if not tkinter._default_root:
|
||||||
raise OSError("tkinter not initialized")
|
msg = "tkinter not initialized"
|
||||||
|
raise OSError(msg)
|
||||||
top = tkinter.Toplevel()
|
top = tkinter.Toplevel()
|
||||||
if title:
|
if title:
|
||||||
top.title(title)
|
top.title(title)
|
||||||
|
|
|
@ -41,7 +41,8 @@ class ImtImageFile(ImageFile.ImageFile):
|
||||||
|
|
||||||
buffer = self.fp.read(100)
|
buffer = self.fp.read(100)
|
||||||
if b"\n" not in buffer:
|
if b"\n" not in buffer:
|
||||||
raise SyntaxError("not an IM file")
|
msg = "not an IM file"
|
||||||
|
raise SyntaxError(msg)
|
||||||
|
|
||||||
xsize = ysize = 0
|
xsize = ysize = 0
|
||||||
|
|
||||||
|
|
|
@ -66,12 +66,14 @@ class IptcImageFile(ImageFile.ImageFile):
|
||||||
|
|
||||||
# syntax
|
# syntax
|
||||||
if s[0] != 0x1C or tag[0] < 1 or tag[0] > 9:
|
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
|
# field size
|
||||||
size = s[3]
|
size = s[3]
|
||||||
if size > 132:
|
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:
|
elif size == 128:
|
||||||
size = 0
|
size = 0
|
||||||
elif size > 128:
|
elif size > 128:
|
||||||
|
@ -122,7 +124,8 @@ class IptcImageFile(ImageFile.ImageFile):
|
||||||
try:
|
try:
|
||||||
compression = COMPRESSION[self.getint((3, 120))]
|
compression = COMPRESSION[self.getint((3, 120))]
|
||||||
except KeyError as e:
|
except KeyError as e:
|
||||||
raise OSError("Unknown IPTC image compression") from e
|
msg = "Unknown IPTC image compression"
|
||||||
|
raise OSError(msg) from e
|
||||||
|
|
||||||
# tile
|
# tile
|
||||||
if tag == (8, 10):
|
if tag == (8, 10):
|
||||||
|
|
|
@ -44,13 +44,13 @@ class BoxReader:
|
||||||
|
|
||||||
def _read_bytes(self, num_bytes):
|
def _read_bytes(self, num_bytes):
|
||||||
if not self._can_read(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)
|
data = self.fp.read(num_bytes)
|
||||||
if len(data) < num_bytes:
|
if len(data) < num_bytes:
|
||||||
raise OSError(
|
msg = f"Expected to read {num_bytes} bytes but only got {len(data)}."
|
||||||
f"Expected to read {num_bytes} bytes but only got {len(data)}."
|
raise OSError(msg)
|
||||||
)
|
|
||||||
|
|
||||||
if self.remaining_in_box > 0:
|
if self.remaining_in_box > 0:
|
||||||
self.remaining_in_box -= num_bytes
|
self.remaining_in_box -= num_bytes
|
||||||
|
@ -87,7 +87,8 @@ class BoxReader:
|
||||||
hlen = 8
|
hlen = 8
|
||||||
|
|
||||||
if lbox < hlen or not self._can_read(lbox - hlen):
|
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
|
self.remaining_in_box = lbox - hlen
|
||||||
return tbox
|
return tbox
|
||||||
|
@ -189,7 +190,8 @@ def _parse_jp2_header(fp):
|
||||||
break
|
break
|
||||||
|
|
||||||
if size is None or mode is None:
|
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
|
return size, mode, mimetype, dpi
|
||||||
|
|
||||||
|
@ -217,10 +219,12 @@ class Jpeg2KImageFile(ImageFile.ImageFile):
|
||||||
if dpi is not None:
|
if dpi is not None:
|
||||||
self.info["dpi"] = dpi
|
self.info["dpi"] = dpi
|
||||||
else:
|
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:
|
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._reduce = 0
|
||||||
self.layers = 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)
|
num_resolutions = info.get("num_resolutions", 0)
|
||||||
cblk_size = info.get("codeblock_size", None)
|
cblk_size = info.get("codeblock_size", None)
|
||||||
|
|
|
@ -204,7 +204,8 @@ def SOF(self, marker):
|
||||||
|
|
||||||
self.bits = s[0]
|
self.bits = s[0]
|
||||||
if self.bits != 8:
|
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]
|
self.layers = s[5]
|
||||||
if self.layers == 1:
|
if self.layers == 1:
|
||||||
|
@ -214,7 +215,8 @@ def SOF(self, marker):
|
||||||
elif self.layers == 4:
|
elif self.layers == 4:
|
||||||
self.mode = "CMYK"
|
self.mode = "CMYK"
|
||||||
else:
|
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]:
|
if marker in [0xFFC2, 0xFFC6, 0xFFCA, 0xFFCE]:
|
||||||
self.info["progressive"] = self.info["progression"] = 1
|
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
|
precision = 1 if (v // 16 == 0) else 2 # in bytes
|
||||||
qt_length = 1 + precision * 64
|
qt_length = 1 + precision * 64
|
||||||
if len(s) < qt_length:
|
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])
|
data = array.array("B" if precision == 1 else "H", s[1:qt_length])
|
||||||
if sys.byteorder == "little" and precision > 1:
|
if sys.byteorder == "little" and precision > 1:
|
||||||
data.byteswap() # the values are always big-endian
|
data.byteswap() # the values are always big-endian
|
||||||
|
@ -350,7 +353,8 @@ class JpegImageFile(ImageFile.ImageFile):
|
||||||
s = self.fp.read(3)
|
s = self.fp.read(3)
|
||||||
|
|
||||||
if not _accept(s):
|
if not _accept(s):
|
||||||
raise SyntaxError("not a JPEG file")
|
msg = "not a JPEG file"
|
||||||
|
raise SyntaxError(msg)
|
||||||
s = b"\xFF"
|
s = b"\xFF"
|
||||||
|
|
||||||
# Create attributes
|
# Create attributes
|
||||||
|
@ -394,7 +398,8 @@ class JpegImageFile(ImageFile.ImageFile):
|
||||||
elif i == 0xFF00: # Skip extraneous data (escaped 0xFF)
|
elif i == 0xFF00: # Skip extraneous data (escaped 0xFF)
|
||||||
s = self.fp.read(1)
|
s = self.fp.read(1)
|
||||||
else:
|
else:
|
||||||
raise SyntaxError("no marker found")
|
msg = "no marker found"
|
||||||
|
raise SyntaxError(msg)
|
||||||
|
|
||||||
def load_read(self, read_bytes):
|
def load_read(self, read_bytes):
|
||||||
"""
|
"""
|
||||||
|
@ -458,7 +463,8 @@ class JpegImageFile(ImageFile.ImageFile):
|
||||||
if os.path.exists(self.filename):
|
if os.path.exists(self.filename):
|
||||||
subprocess.check_call(["djpeg", "-outfile", path, self.filename])
|
subprocess.check_call(["djpeg", "-outfile", path, self.filename])
|
||||||
else:
|
else:
|
||||||
raise ValueError("Invalid Filename")
|
msg = "Invalid Filename"
|
||||||
|
raise ValueError(msg)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
with Image.open(path) as _im:
|
with Image.open(path) as _im:
|
||||||
|
@ -524,12 +530,14 @@ def _getmp(self):
|
||||||
info.load(file_contents)
|
info.load(file_contents)
|
||||||
mp = dict(info)
|
mp = dict(info)
|
||||||
except Exception as e:
|
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
|
# it's an error not to have a number of images
|
||||||
try:
|
try:
|
||||||
quant = mp[0xB001]
|
quant = mp[0xB001]
|
||||||
except KeyError as e:
|
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
|
# get MP entries
|
||||||
mpentries = []
|
mpentries = []
|
||||||
try:
|
try:
|
||||||
|
@ -551,7 +559,8 @@ def _getmp(self):
|
||||||
if mpentryattr["ImageDataFormat"] == 0:
|
if mpentryattr["ImageDataFormat"] == 0:
|
||||||
mpentryattr["ImageDataFormat"] = "JPEG"
|
mpentryattr["ImageDataFormat"] = "JPEG"
|
||||||
else:
|
else:
|
||||||
raise SyntaxError("unsupported picture format in MPO")
|
msg = "unsupported picture format in MPO"
|
||||||
|
raise SyntaxError(msg)
|
||||||
mptypemap = {
|
mptypemap = {
|
||||||
0x000000: "Undefined",
|
0x000000: "Undefined",
|
||||||
0x010001: "Large Thumbnail (VGA Equivalent)",
|
0x010001: "Large Thumbnail (VGA Equivalent)",
|
||||||
|
@ -566,7 +575,8 @@ def _getmp(self):
|
||||||
mpentries.append(mpentry)
|
mpentries.append(mpentry)
|
||||||
mp[0xB002] = mpentries
|
mp[0xB002] = mpentries
|
||||||
except KeyError as e:
|
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;
|
# 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
|
# we don't because I've never seen this actually used in a real MPO
|
||||||
# file and so can't test it.
|
# file and so can't test it.
|
||||||
|
@ -626,12 +636,14 @@ def get_sampling(im):
|
||||||
|
|
||||||
def _save(im, fp, filename):
|
def _save(im, fp, filename):
|
||||||
if im.width == 0 or im.height == 0:
|
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:
|
try:
|
||||||
rawmode = RAWMODE[im.mode]
|
rawmode = RAWMODE[im.mode]
|
||||||
except KeyError as e:
|
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
|
info = im.encoderinfo
|
||||||
|
|
||||||
|
@ -651,7 +663,8 @@ def _save(im, fp, filename):
|
||||||
subsampling = preset.get("subsampling", -1)
|
subsampling = preset.get("subsampling", -1)
|
||||||
qtables = preset.get("quantization")
|
qtables = preset.get("quantization")
|
||||||
elif not isinstance(quality, int):
|
elif not isinstance(quality, int):
|
||||||
raise ValueError("Invalid quality setting")
|
msg = "Invalid quality setting"
|
||||||
|
raise ValueError(msg)
|
||||||
else:
|
else:
|
||||||
if subsampling in presets:
|
if subsampling in presets:
|
||||||
subsampling = presets[subsampling].get("subsampling", -1)
|
subsampling = presets[subsampling].get("subsampling", -1)
|
||||||
|
@ -670,7 +683,8 @@ def _save(im, fp, filename):
|
||||||
subsampling = 2
|
subsampling = 2
|
||||||
elif subsampling == "keep":
|
elif subsampling == "keep":
|
||||||
if im.format != "JPEG":
|
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)
|
subsampling = get_sampling(im)
|
||||||
|
|
||||||
def validate_qtables(qtables):
|
def validate_qtables(qtables):
|
||||||
|
@ -684,7 +698,8 @@ def _save(im, fp, filename):
|
||||||
for num in line.split("#", 1)[0].split()
|
for num in line.split("#", 1)[0].split()
|
||||||
]
|
]
|
||||||
except ValueError as e:
|
except ValueError as e:
|
||||||
raise ValueError("Invalid quantization table") from e
|
msg = "Invalid quantization table"
|
||||||
|
raise ValueError(msg) from e
|
||||||
else:
|
else:
|
||||||
qtables = [lines[s : s + 64] for s in range(0, len(lines), 64)]
|
qtables = [lines[s : s + 64] for s in range(0, len(lines), 64)]
|
||||||
if isinstance(qtables, (tuple, list, dict)):
|
if isinstance(qtables, (tuple, list, dict)):
|
||||||
|
@ -695,21 +710,24 @@ def _save(im, fp, filename):
|
||||||
elif isinstance(qtables, tuple):
|
elif isinstance(qtables, tuple):
|
||||||
qtables = list(qtables)
|
qtables = list(qtables)
|
||||||
if not (0 < len(qtables) < 5):
|
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):
|
for idx, table in enumerate(qtables):
|
||||||
try:
|
try:
|
||||||
if len(table) != 64:
|
if len(table) != 64:
|
||||||
raise TypeError
|
raise TypeError
|
||||||
table = array.array("H", table)
|
table = array.array("H", table)
|
||||||
except TypeError as e:
|
except TypeError as e:
|
||||||
raise ValueError("Invalid quantization table") from e
|
msg = "Invalid quantization table"
|
||||||
|
raise ValueError(msg) from e
|
||||||
else:
|
else:
|
||||||
qtables[idx] = list(table)
|
qtables[idx] = list(table)
|
||||||
return qtables
|
return qtables
|
||||||
|
|
||||||
if qtables == "keep":
|
if qtables == "keep":
|
||||||
if im.format != "JPEG":
|
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 = getattr(im, "quantization", None)
|
||||||
qtables = validate_qtables(qtables)
|
qtables = validate_qtables(qtables)
|
||||||
|
|
||||||
|
|
|
@ -39,7 +39,8 @@ class McIdasImageFile(ImageFile.ImageFile):
|
||||||
# parse area file directory
|
# parse area file directory
|
||||||
s = self.fp.read(256)
|
s = self.fp.read(256)
|
||||||
if not _accept(s) or len(s) != 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_raw = s
|
||||||
self.area_descriptor = w = [0] + list(struct.unpack("!64i", s))
|
self.area_descriptor = w = [0] + list(struct.unpack("!64i", s))
|
||||||
|
@ -56,7 +57,8 @@ class McIdasImageFile(ImageFile.ImageFile):
|
||||||
mode = "I"
|
mode = "I"
|
||||||
rawmode = "I;32B"
|
rawmode = "I;32B"
|
||||||
else:
|
else:
|
||||||
raise SyntaxError("unsupported McIdas format")
|
msg = "unsupported McIdas format"
|
||||||
|
raise SyntaxError(msg)
|
||||||
|
|
||||||
self.mode = mode
|
self.mode = mode
|
||||||
self._size = w[10], w[9]
|
self._size = w[10], w[9]
|
||||||
|
|
|
@ -47,7 +47,8 @@ class MicImageFile(TiffImagePlugin.TiffImageFile):
|
||||||
try:
|
try:
|
||||||
self.ole = olefile.OleFileIO(self.fp)
|
self.ole = olefile.OleFileIO(self.fp)
|
||||||
except OSError as e:
|
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
|
# find ACI subfiles with Image members (maybe not the
|
||||||
# best way to identify MIC files, but what 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
|
# if we didn't find any images, this is probably not
|
||||||
# an MIC file.
|
# an MIC file.
|
||||||
if not self.images:
|
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.frame = None
|
||||||
self._n_frames = len(self.images)
|
self._n_frames = len(self.images)
|
||||||
|
@ -77,7 +79,8 @@ class MicImageFile(TiffImagePlugin.TiffImageFile):
|
||||||
try:
|
try:
|
||||||
filename = self.images[frame]
|
filename = self.images[frame]
|
||||||
except IndexError as e:
|
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)
|
self.fp = self.ole.openstream(filename)
|
||||||
|
|
||||||
|
|
|
@ -67,7 +67,8 @@ class MpegImageFile(ImageFile.ImageFile):
|
||||||
s = BitStream(self.fp)
|
s = BitStream(self.fp)
|
||||||
|
|
||||||
if s.read(32) != 0x1B3:
|
if s.read(32) != 0x1B3:
|
||||||
raise SyntaxError("not an MPEG file")
|
msg = "not an MPEG file"
|
||||||
|
raise SyntaxError(msg)
|
||||||
|
|
||||||
self.mode = "RGB"
|
self.mode = "RGB"
|
||||||
self._size = s.read(12), s.read(12)
|
self._size = s.read(12), s.read(12)
|
||||||
|
|
|
@ -143,7 +143,8 @@ class MpoImageFile(JpegImagePlugin.JpegImageFile):
|
||||||
self.fp.seek(self.offset + 2) # skip SOI marker
|
self.fp.seek(self.offset + 2) # skip SOI marker
|
||||||
segment = self.fp.read(2)
|
segment = self.fp.read(2)
|
||||||
if not segment:
|
if not segment:
|
||||||
raise ValueError("No data found for frame")
|
msg = "No data found for frame"
|
||||||
|
raise ValueError(msg)
|
||||||
self._size = self._initial_size
|
self._size = self._initial_size
|
||||||
if i16(segment) == 0xFFE1: # APP1
|
if i16(segment) == 0xFFE1: # APP1
|
||||||
n = i16(self.fp.read(2)) - 2
|
n = i16(self.fp.read(2)) - 2
|
||||||
|
|
|
@ -53,14 +53,16 @@ class MspImageFile(ImageFile.ImageFile):
|
||||||
# Header
|
# Header
|
||||||
s = self.fp.read(32)
|
s = self.fp.read(32)
|
||||||
if not _accept(s):
|
if not _accept(s):
|
||||||
raise SyntaxError("not an MSP file")
|
msg = "not an MSP file"
|
||||||
|
raise SyntaxError(msg)
|
||||||
|
|
||||||
# Header checksum
|
# Header checksum
|
||||||
checksum = 0
|
checksum = 0
|
||||||
for i in range(0, 32, 2):
|
for i in range(0, 32, 2):
|
||||||
checksum = checksum ^ i16(s, i)
|
checksum = checksum ^ i16(s, i)
|
||||||
if checksum != 0:
|
if checksum != 0:
|
||||||
raise SyntaxError("bad MSP checksum")
|
msg = "bad MSP checksum"
|
||||||
|
raise SyntaxError(msg)
|
||||||
|
|
||||||
self.mode = "1"
|
self.mode = "1"
|
||||||
self._size = i16(s, 4), i16(s, 6)
|
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)
|
f"<{self.state.ysize}H", self.fd.read(self.state.ysize * 2)
|
||||||
)
|
)
|
||||||
except struct.error as e:
|
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):
|
for x, rowlen in enumerate(rowmap):
|
||||||
try:
|
try:
|
||||||
|
@ -127,9 +130,8 @@ class MspDecoder(ImageFile.PyDecoder):
|
||||||
continue
|
continue
|
||||||
row = self.fd.read(rowlen)
|
row = self.fd.read(rowlen)
|
||||||
if len(row) != rowlen:
|
if len(row) != rowlen:
|
||||||
raise OSError(
|
msg = f"Truncated MSP file, expected {rowlen} bytes on row {x}"
|
||||||
"Truncated MSP file, expected %d bytes on row %s", (rowlen, x)
|
raise OSError(msg)
|
||||||
)
|
|
||||||
idx = 0
|
idx = 0
|
||||||
while idx < rowlen:
|
while idx < rowlen:
|
||||||
runtype = row[idx]
|
runtype = row[idx]
|
||||||
|
@ -144,7 +146,8 @@ class MspDecoder(ImageFile.PyDecoder):
|
||||||
idx += runcount
|
idx += runcount
|
||||||
|
|
||||||
except struct.error as e:
|
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))
|
self.set_as_raw(img.getvalue(), ("1", 0, 1))
|
||||||
|
|
||||||
|
@ -161,7 +164,8 @@ Image.register_decoder("MSP", MspDecoder)
|
||||||
def _save(im, fp, filename):
|
def _save(im, fp, filename):
|
||||||
|
|
||||||
if im.mode != "1":
|
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
|
# create MSP header
|
||||||
header = [0] * 16
|
header = [0] * 16
|
||||||
|
|
|
@ -34,7 +34,8 @@ class PaletteFile:
|
||||||
if s[:1] == b"#":
|
if s[:1] == b"#":
|
||||||
continue
|
continue
|
||||||
if len(s) > 100:
|
if len(s) > 100:
|
||||||
raise SyntaxError("bad palette file")
|
msg = "bad palette file"
|
||||||
|
raise SyntaxError(msg)
|
||||||
|
|
||||||
v = [int(x) for x in s.split()]
|
v = [int(x) for x in s.split()]
|
||||||
try:
|
try:
|
||||||
|
|
|
@ -138,7 +138,8 @@ def _save(im, fp, filename):
|
||||||
bpp = im.info["bpp"]
|
bpp = im.info["bpp"]
|
||||||
im = im.point(lambda x, maxval=(1 << bpp) - 1: maxval - (x & maxval))
|
im = im.point(lambda x, maxval=(1 << bpp) - 1: maxval - (x & maxval))
|
||||||
else:
|
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
|
# we ignore the palette here
|
||||||
im.mode = "P"
|
im.mode = "P"
|
||||||
|
@ -154,7 +155,8 @@ def _save(im, fp, filename):
|
||||||
|
|
||||||
else:
|
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
|
# make sure image data is available
|
||||||
|
|
|
@ -35,7 +35,8 @@ class PcdImageFile(ImageFile.ImageFile):
|
||||||
s = self.fp.read(2048)
|
s = self.fp.read(2048)
|
||||||
|
|
||||||
if s[:4] != b"PCD_":
|
if s[:4] != b"PCD_":
|
||||||
raise SyntaxError("not a PCD file")
|
msg = "not a PCD file"
|
||||||
|
raise SyntaxError(msg)
|
||||||
|
|
||||||
orientation = s[1538] & 3
|
orientation = s[1538] & 3
|
||||||
self.tile_post_rotate = None
|
self.tile_post_rotate = None
|
||||||
|
|
|
@ -63,7 +63,8 @@ class PcfFontFile(FontFile.FontFile):
|
||||||
|
|
||||||
magic = l32(fp.read(4))
|
magic = l32(fp.read(4))
|
||||||
if magic != PCF_MAGIC:
|
if magic != PCF_MAGIC:
|
||||||
raise SyntaxError("not a PCF file")
|
msg = "not a PCF file"
|
||||||
|
raise SyntaxError(msg)
|
||||||
|
|
||||||
super().__init__()
|
super().__init__()
|
||||||
|
|
||||||
|
@ -186,7 +187,8 @@ class PcfFontFile(FontFile.FontFile):
|
||||||
nbitmaps = i32(fp.read(4))
|
nbitmaps = i32(fp.read(4))
|
||||||
|
|
||||||
if nbitmaps != len(metrics):
|
if nbitmaps != len(metrics):
|
||||||
raise OSError("Wrong number of bitmaps")
|
msg = "Wrong number of bitmaps"
|
||||||
|
raise OSError(msg)
|
||||||
|
|
||||||
offsets = []
|
offsets = []
|
||||||
for i in range(nbitmaps):
|
for i in range(nbitmaps):
|
||||||
|
|
|
@ -54,12 +54,14 @@ class PcxImageFile(ImageFile.ImageFile):
|
||||||
# header
|
# header
|
||||||
s = self.fp.read(128)
|
s = self.fp.read(128)
|
||||||
if not _accept(s):
|
if not _accept(s):
|
||||||
raise SyntaxError("not a PCX file")
|
msg = "not a PCX file"
|
||||||
|
raise SyntaxError(msg)
|
||||||
|
|
||||||
# image
|
# image
|
||||||
bbox = i16(s, 4), i16(s, 6), i16(s, 8) + 1, i16(s, 10) + 1
|
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]:
|
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)
|
logger.debug("BBox: %s %s %s %s", *bbox)
|
||||||
|
|
||||||
# format
|
# format
|
||||||
|
@ -105,7 +107,8 @@ class PcxImageFile(ImageFile.ImageFile):
|
||||||
rawmode = "RGB;L"
|
rawmode = "RGB;L"
|
||||||
|
|
||||||
else:
|
else:
|
||||||
raise OSError("unknown PCX mode")
|
msg = "unknown PCX mode"
|
||||||
|
raise OSError(msg)
|
||||||
|
|
||||||
self.mode = mode
|
self.mode = mode
|
||||||
self._size = bbox[2] - bbox[0], bbox[3] - bbox[1]
|
self._size = bbox[2] - bbox[0], bbox[3] - bbox[1]
|
||||||
|
@ -144,7 +147,8 @@ def _save(im, fp, filename):
|
||||||
try:
|
try:
|
||||||
version, bits, planes, rawmode = SAVE[im.mode]
|
version, bits, planes, rawmode = SAVE[im.mode]
|
||||||
except KeyError as e:
|
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
|
# bytes per plane
|
||||||
stride = (im.size[0] * bits + 7) // 8
|
stride = (im.size[0] * bits + 7) // 8
|
||||||
|
|
|
@ -174,7 +174,8 @@ def _save(im, fp, filename, save_all=False):
|
||||||
procset = "ImageC" # color images
|
procset = "ImageC" # color images
|
||||||
decode = [1, 0, 1, 0, 1, 0, 1, 0]
|
decode = [1, 0, 1, 0, 1, 0, 1, 0]
|
||||||
else:
|
else:
|
||||||
raise ValueError(f"cannot save mode {im.mode}")
|
msg = f"cannot save mode {im.mode}"
|
||||||
|
raise ValueError(msg)
|
||||||
|
|
||||||
#
|
#
|
||||||
# image
|
# image
|
||||||
|
@ -198,7 +199,8 @@ def _save(im, fp, filename, save_all=False):
|
||||||
elif filter == "RunLengthDecode":
|
elif filter == "RunLengthDecode":
|
||||||
ImageFile._save(im, op, [("packbits", (0, 0) + im.size, 0, im.mode)])
|
ImageFile._save(im, op, [("packbits", (0, 0) + im.size, 0, im.mode)])
|
||||||
else:
|
else:
|
||||||
raise ValueError(f"unsupported PDF filter ({filter})")
|
msg = f"unsupported PDF filter ({filter})"
|
||||||
|
raise ValueError(msg)
|
||||||
|
|
||||||
stream = op.getvalue()
|
stream = op.getvalue()
|
||||||
if filter == "CCITTFaxDecode":
|
if filter == "CCITTFaxDecode":
|
||||||
|
|
|
@ -138,9 +138,10 @@ class XrefTable:
|
||||||
elif key in self.deleted_entries:
|
elif key in self.deleted_entries:
|
||||||
generation = self.deleted_entries[key]
|
generation = self.deleted_entries[key]
|
||||||
else:
|
else:
|
||||||
raise IndexError(
|
msg = (
|
||||||
"object ID " + str(key) + " cannot be deleted because it doesn't exist"
|
"object ID " + str(key) + " cannot be deleted because it doesn't exist"
|
||||||
)
|
)
|
||||||
|
raise IndexError(msg)
|
||||||
|
|
||||||
def __contains__(self, key):
|
def __contains__(self, key):
|
||||||
return key in self.existing_entries or key in self.new_entries
|
return key in self.existing_entries or key in self.new_entries
|
||||||
|
@ -314,9 +315,8 @@ class PdfStream:
|
||||||
expected_length = self.dictionary.Length
|
expected_length = self.dictionary.Length
|
||||||
return zlib.decompress(self.buf, bufsize=int(expected_length))
|
return zlib.decompress(self.buf, bufsize=int(expected_length))
|
||||||
else:
|
else:
|
||||||
raise NotImplementedError(
|
msg = f"stream filter {repr(self.dictionary.Filter)} unknown/unsupported"
|
||||||
f"stream filter {repr(self.dictionary.Filter)} unknown/unsupported"
|
raise NotImplementedError(msg)
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
def pdf_repr(x):
|
def pdf_repr(x):
|
||||||
|
@ -358,7 +358,8 @@ class PdfParser:
|
||||||
|
|
||||||
def __init__(self, filename=None, f=None, buf=None, start_offset=0, mode="rb"):
|
def __init__(self, filename=None, f=None, buf=None, start_offset=0, mode="rb"):
|
||||||
if buf and f:
|
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.filename = filename
|
||||||
self.buf = buf
|
self.buf = buf
|
||||||
self.f = f
|
self.f = f
|
||||||
|
@ -920,7 +921,8 @@ class PdfParser:
|
||||||
result.extend(b")")
|
result.extend(b")")
|
||||||
nesting_depth -= 1
|
nesting_depth -= 1
|
||||||
offset = m.end()
|
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_section_start = re.compile(whitespace_optional + rb"xref" + newline)
|
||||||
re_xref_subsection_start = re.compile(
|
re_xref_subsection_start = re.compile(
|
||||||
|
|
|
@ -44,7 +44,8 @@ class PixarImageFile(ImageFile.ImageFile):
|
||||||
# assuming a 4-byte magic label
|
# assuming a 4-byte magic label
|
||||||
s = self.fp.read(4)
|
s = self.fp.read(4)
|
||||||
if not _accept(s):
|
if not _accept(s):
|
||||||
raise SyntaxError("not a PIXAR file")
|
msg = "not a PIXAR file"
|
||||||
|
raise SyntaxError(msg)
|
||||||
|
|
||||||
# read rest of header
|
# read rest of header
|
||||||
s = s + self.fp.read(508)
|
s = s + self.fp.read(508)
|
||||||
|
|
|
@ -138,14 +138,16 @@ def __getattr__(name):
|
||||||
if name in enum.__members__:
|
if name in enum.__members__:
|
||||||
deprecate(f"{prefix}{name}", 10, f"{enum.__name__}.{name}")
|
deprecate(f"{prefix}{name}", 10, f"{enum.__name__}.{name}")
|
||||||
return enum[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):
|
def _safe_zlib_decompress(s):
|
||||||
dobj = zlib.decompressobj()
|
dobj = zlib.decompressobj()
|
||||||
plaintext = dobj.decompress(s, MAX_TEXT_CHUNK)
|
plaintext = dobj.decompress(s, MAX_TEXT_CHUNK)
|
||||||
if dobj.unconsumed_tail:
|
if dobj.unconsumed_tail:
|
||||||
raise ValueError("Decompressed Data Too Large")
|
msg = "Decompressed Data Too Large"
|
||||||
|
raise ValueError(msg)
|
||||||
return plaintext
|
return plaintext
|
||||||
|
|
||||||
|
|
||||||
|
@ -178,7 +180,8 @@ class ChunkStream:
|
||||||
|
|
||||||
if not is_cid(cid):
|
if not is_cid(cid):
|
||||||
if not ImageFile.LOAD_TRUNCATED_IMAGES:
|
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
|
return cid, pos, length
|
||||||
|
|
||||||
|
@ -215,13 +218,11 @@ class ChunkStream:
|
||||||
crc1 = _crc32(data, _crc32(cid))
|
crc1 = _crc32(data, _crc32(cid))
|
||||||
crc2 = i32(self.fp.read(4))
|
crc2 = i32(self.fp.read(4))
|
||||||
if crc1 != crc2:
|
if crc1 != crc2:
|
||||||
raise SyntaxError(
|
msg = f"broken PNG file (bad header checksum in {repr(cid)})"
|
||||||
f"broken PNG file (bad header checksum in {repr(cid)})"
|
raise SyntaxError(msg)
|
||||||
)
|
|
||||||
except struct.error as e:
|
except struct.error as e:
|
||||||
raise SyntaxError(
|
msg = f"broken PNG file (incomplete checksum in {repr(cid)})"
|
||||||
f"broken PNG file (incomplete checksum in {repr(cid)})"
|
raise SyntaxError(msg) from e
|
||||||
) from e
|
|
||||||
|
|
||||||
def crc_skip(self, cid, data):
|
def crc_skip(self, cid, data):
|
||||||
"""Read checksum"""
|
"""Read checksum"""
|
||||||
|
@ -239,7 +240,8 @@ class ChunkStream:
|
||||||
try:
|
try:
|
||||||
cid, pos, length = self.read()
|
cid, pos, length = self.read()
|
||||||
except struct.error as e:
|
except struct.error as e:
|
||||||
raise OSError("truncated PNG file") from e
|
msg = "truncated PNG file"
|
||||||
|
raise OSError(msg) from e
|
||||||
|
|
||||||
if cid == endchunk:
|
if cid == endchunk:
|
||||||
break
|
break
|
||||||
|
@ -376,10 +378,11 @@ class PngStream(ChunkStream):
|
||||||
def check_text_memory(self, chunklen):
|
def check_text_memory(self, chunklen):
|
||||||
self.text_memory += chunklen
|
self.text_memory += chunklen
|
||||||
if self.text_memory > MAX_TEXT_MEMORY:
|
if self.text_memory > MAX_TEXT_MEMORY:
|
||||||
raise ValueError(
|
msg = (
|
||||||
"Too much memory used in text chunks: "
|
"Too much memory used in text chunks: "
|
||||||
f"{self.text_memory}>MAX_TEXT_MEMORY"
|
f"{self.text_memory}>MAX_TEXT_MEMORY"
|
||||||
)
|
)
|
||||||
|
raise ValueError(msg)
|
||||||
|
|
||||||
def save_rewind(self):
|
def save_rewind(self):
|
||||||
self.rewind_state = {
|
self.rewind_state = {
|
||||||
|
@ -407,7 +410,8 @@ class PngStream(ChunkStream):
|
||||||
logger.debug("Compression method %s", s[i])
|
logger.debug("Compression method %s", s[i])
|
||||||
comp_method = s[i]
|
comp_method = s[i]
|
||||||
if comp_method != 0:
|
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:
|
try:
|
||||||
icc_profile = _safe_zlib_decompress(s[i + 2 :])
|
icc_profile = _safe_zlib_decompress(s[i + 2 :])
|
||||||
except ValueError:
|
except ValueError:
|
||||||
|
@ -427,7 +431,8 @@ class PngStream(ChunkStream):
|
||||||
if length < 13:
|
if length < 13:
|
||||||
if ImageFile.LOAD_TRUNCATED_IMAGES:
|
if ImageFile.LOAD_TRUNCATED_IMAGES:
|
||||||
return s
|
return s
|
||||||
raise ValueError("Truncated IHDR chunk")
|
msg = "Truncated IHDR chunk"
|
||||||
|
raise ValueError(msg)
|
||||||
self.im_size = i32(s, 0), i32(s, 4)
|
self.im_size = i32(s, 0), i32(s, 4)
|
||||||
try:
|
try:
|
||||||
self.im_mode, self.im_rawmode = _MODES[(s[8], s[9])]
|
self.im_mode, self.im_rawmode = _MODES[(s[8], s[9])]
|
||||||
|
@ -436,7 +441,8 @@ class PngStream(ChunkStream):
|
||||||
if s[12]:
|
if s[12]:
|
||||||
self.im_info["interlace"] = 1
|
self.im_info["interlace"] = 1
|
||||||
if s[11]:
|
if s[11]:
|
||||||
raise SyntaxError("unknown filter category")
|
msg = "unknown filter category"
|
||||||
|
raise SyntaxError(msg)
|
||||||
return s
|
return s
|
||||||
|
|
||||||
def chunk_IDAT(self, pos, length):
|
def chunk_IDAT(self, pos, length):
|
||||||
|
@ -512,7 +518,8 @@ class PngStream(ChunkStream):
|
||||||
if length < 1:
|
if length < 1:
|
||||||
if ImageFile.LOAD_TRUNCATED_IMAGES:
|
if ImageFile.LOAD_TRUNCATED_IMAGES:
|
||||||
return s
|
return s
|
||||||
raise ValueError("Truncated sRGB chunk")
|
msg = "Truncated sRGB chunk"
|
||||||
|
raise ValueError(msg)
|
||||||
self.im_info["srgb"] = s[0]
|
self.im_info["srgb"] = s[0]
|
||||||
return s
|
return s
|
||||||
|
|
||||||
|
@ -523,7 +530,8 @@ class PngStream(ChunkStream):
|
||||||
if length < 9:
|
if length < 9:
|
||||||
if ImageFile.LOAD_TRUNCATED_IMAGES:
|
if ImageFile.LOAD_TRUNCATED_IMAGES:
|
||||||
return s
|
return s
|
||||||
raise ValueError("Truncated pHYs chunk")
|
msg = "Truncated pHYs chunk"
|
||||||
|
raise ValueError(msg)
|
||||||
px, py = i32(s, 0), i32(s, 4)
|
px, py = i32(s, 0), i32(s, 4)
|
||||||
unit = s[8]
|
unit = s[8]
|
||||||
if unit == 1: # meter
|
if unit == 1: # meter
|
||||||
|
@ -567,7 +575,8 @@ class PngStream(ChunkStream):
|
||||||
else:
|
else:
|
||||||
comp_method = 0
|
comp_method = 0
|
||||||
if 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:
|
try:
|
||||||
v = _safe_zlib_decompress(v[1:])
|
v = _safe_zlib_decompress(v[1:])
|
||||||
except ValueError:
|
except ValueError:
|
||||||
|
@ -639,7 +648,8 @@ class PngStream(ChunkStream):
|
||||||
if length < 8:
|
if length < 8:
|
||||||
if ImageFile.LOAD_TRUNCATED_IMAGES:
|
if ImageFile.LOAD_TRUNCATED_IMAGES:
|
||||||
return s
|
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:
|
if self.im_n_frames is not None:
|
||||||
self.im_n_frames = None
|
self.im_n_frames = None
|
||||||
warnings.warn("Invalid APNG, will use default PNG image if possible")
|
warnings.warn("Invalid APNG, will use default PNG image if possible")
|
||||||
|
@ -658,18 +668,21 @@ class PngStream(ChunkStream):
|
||||||
if length < 26:
|
if length < 26:
|
||||||
if ImageFile.LOAD_TRUNCATED_IMAGES:
|
if ImageFile.LOAD_TRUNCATED_IMAGES:
|
||||||
return s
|
return s
|
||||||
raise ValueError("APNG contains truncated fcTL chunk")
|
msg = "APNG contains truncated fcTL chunk"
|
||||||
|
raise ValueError(msg)
|
||||||
seq = i32(s)
|
seq = i32(s)
|
||||||
if (self._seq_num is None and seq != 0) or (
|
if (self._seq_num is None and seq != 0) or (
|
||||||
self._seq_num is not None and self._seq_num != seq - 1
|
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
|
self._seq_num = seq
|
||||||
width, height = i32(s, 4), i32(s, 8)
|
width, height = i32(s, 4), i32(s, 8)
|
||||||
px, py = i32(s, 12), i32(s, 16)
|
px, py = i32(s, 12), i32(s, 16)
|
||||||
im_w, im_h = self.im_size
|
im_w, im_h = self.im_size
|
||||||
if px + width > im_w or py + height > im_h:
|
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)
|
self.im_info["bbox"] = (px, py, px + width, py + height)
|
||||||
delay_num, delay_den = i16(s, 20), i16(s, 22)
|
delay_num, delay_den = i16(s, 20), i16(s, 22)
|
||||||
if delay_den == 0:
|
if delay_den == 0:
|
||||||
|
@ -684,11 +697,13 @@ class PngStream(ChunkStream):
|
||||||
if ImageFile.LOAD_TRUNCATED_IMAGES:
|
if ImageFile.LOAD_TRUNCATED_IMAGES:
|
||||||
s = ImageFile._safe_read(self.fp, length)
|
s = ImageFile._safe_read(self.fp, length)
|
||||||
return s
|
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)
|
s = ImageFile._safe_read(self.fp, 4)
|
||||||
seq = i32(s)
|
seq = i32(s)
|
||||||
if self._seq_num != seq - 1:
|
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
|
self._seq_num = seq
|
||||||
return self.chunk_IDAT(pos + 4, length - 4)
|
return self.chunk_IDAT(pos + 4, length - 4)
|
||||||
|
|
||||||
|
@ -713,7 +728,8 @@ class PngImageFile(ImageFile.ImageFile):
|
||||||
def _open(self):
|
def _open(self):
|
||||||
|
|
||||||
if not _accept(self.fp.read(8)):
|
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._fp = self.fp
|
||||||
self.__frame = 0
|
self.__frame = 0
|
||||||
|
|
||||||
|
@ -797,7 +813,8 @@ class PngImageFile(ImageFile.ImageFile):
|
||||||
"""Verify PNG file"""
|
"""Verify PNG file"""
|
||||||
|
|
||||||
if self.fp is None:
|
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
|
# back up to beginning of IDAT block
|
||||||
self.fp.seek(self.tile[0][2] - 8)
|
self.fp.seek(self.tile[0][2] - 8)
|
||||||
|
@ -821,7 +838,8 @@ class PngImageFile(ImageFile.ImageFile):
|
||||||
self._seek(f)
|
self._seek(f)
|
||||||
except EOFError as e:
|
except EOFError as e:
|
||||||
self.seek(last_frame)
|
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):
|
def _seek(self, frame, rewind=False):
|
||||||
if frame == 0:
|
if frame == 0:
|
||||||
|
@ -844,7 +862,8 @@ class PngImageFile(ImageFile.ImageFile):
|
||||||
self.__frame = 0
|
self.__frame = 0
|
||||||
else:
|
else:
|
||||||
if frame != self.__frame + 1:
|
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
|
# ensure previous frame was loaded
|
||||||
self.load()
|
self.load()
|
||||||
|
@ -869,11 +888,13 @@ class PngImageFile(ImageFile.ImageFile):
|
||||||
break
|
break
|
||||||
|
|
||||||
if cid == b"IEND":
|
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 cid == b"fcTL":
|
||||||
if frame_start:
|
if frame_start:
|
||||||
# there must be at least one fdAT chunk between fcTL chunks
|
# 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
|
frame_start = True
|
||||||
|
|
||||||
try:
|
try:
|
||||||
|
@ -1277,7 +1298,8 @@ def _save(im, fp, filename, chunk=putchunk, save_all=False):
|
||||||
try:
|
try:
|
||||||
rawmode, mode = _OUTMODES[mode]
|
rawmode, mode = _OUTMODES[mode]
|
||||||
except KeyError as e:
|
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
|
# write minimal PNG file
|
||||||
|
@ -1358,7 +1380,8 @@ def _save(im, fp, filename, chunk=putchunk, save_all=False):
|
||||||
if "transparency" in im.encoderinfo:
|
if "transparency" in im.encoderinfo:
|
||||||
# don't bother with transparency if it's an RGBA
|
# don't bother with transparency if it's an RGBA
|
||||||
# and it's in the info dict. It's probably just stale.
|
# 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:
|
else:
|
||||||
if im.mode == "P" and im.im.getpalettemode() == "RGBA":
|
if im.mode == "P" and im.im.getpalettemode() == "RGBA":
|
||||||
alpha = im.im.getpalette("RGBA", "A")
|
alpha = im.im.getpalette("RGBA", "A")
|
||||||
|
|
|
@ -84,9 +84,11 @@ class PpmImageFile(ImageFile.ImageFile):
|
||||||
token += c
|
token += c
|
||||||
if not token:
|
if not token:
|
||||||
# Token was not even 1 byte
|
# 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:
|
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
|
return token
|
||||||
|
|
||||||
def _open(self):
|
def _open(self):
|
||||||
|
@ -94,7 +96,8 @@ class PpmImageFile(ImageFile.ImageFile):
|
||||||
try:
|
try:
|
||||||
mode = MODES[magic_number]
|
mode = MODES[magic_number]
|
||||||
except KeyError:
|
except KeyError:
|
||||||
raise SyntaxError("not a PPM file")
|
msg = "not a PPM file"
|
||||||
|
raise SyntaxError(msg)
|
||||||
|
|
||||||
if magic_number in (b"P1", b"P4"):
|
if magic_number in (b"P1", b"P4"):
|
||||||
self.custom_mimetype = "image/x-portable-bitmap"
|
self.custom_mimetype = "image/x-portable-bitmap"
|
||||||
|
@ -122,9 +125,8 @@ class PpmImageFile(ImageFile.ImageFile):
|
||||||
elif ix == 2: # token is maxval
|
elif ix == 2: # token is maxval
|
||||||
maxval = token
|
maxval = token
|
||||||
if not 0 < maxval < 65536:
|
if not 0 < maxval < 65536:
|
||||||
raise ValueError(
|
msg = "maxval must be greater than 0 and less than 65536"
|
||||||
"maxval must be greater than 0 and less than 65536"
|
raise ValueError(msg)
|
||||||
)
|
|
||||||
if maxval > 255 and mode == "L":
|
if maxval > 255 and mode == "L":
|
||||||
self.mode = "I"
|
self.mode = "I"
|
||||||
|
|
||||||
|
@ -208,9 +210,8 @@ class PpmPlainDecoder(ImageFile.PyDecoder):
|
||||||
tokens = b"".join(block.split())
|
tokens = b"".join(block.split())
|
||||||
for token in tokens:
|
for token in tokens:
|
||||||
if token not in (48, 49):
|
if token not in (48, 49):
|
||||||
raise ValueError(
|
msg = b"Invalid token for this mode: %s" % bytes([token])
|
||||||
b"Invalid token for this mode: %s" % bytes([token])
|
raise ValueError(msg)
|
||||||
)
|
|
||||||
data = (data + tokens)[:total_bytes]
|
data = (data + tokens)[:total_bytes]
|
||||||
invert = bytes.maketrans(b"01", b"\xFF\x00")
|
invert = bytes.maketrans(b"01", b"\xFF\x00")
|
||||||
return data.translate(invert)
|
return data.translate(invert)
|
||||||
|
@ -243,18 +244,19 @@ class PpmPlainDecoder(ImageFile.PyDecoder):
|
||||||
if block and not block[-1:].isspace(): # block might split token
|
if block and not block[-1:].isspace(): # block might split token
|
||||||
half_token = tokens.pop() # save half token for later
|
half_token = tokens.pop() # save half token for later
|
||||||
if len(half_token) > max_len: # prevent buildup of half_token
|
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]
|
b"Token too long found in data: %s" % half_token[: max_len + 1]
|
||||||
)
|
)
|
||||||
|
raise ValueError(msg)
|
||||||
|
|
||||||
for token in tokens:
|
for token in tokens:
|
||||||
if len(token) > max_len:
|
if len(token) > max_len:
|
||||||
raise ValueError(
|
msg = b"Token too long found in data: %s" % token[: max_len + 1]
|
||||||
b"Token too long found in data: %s" % token[: max_len + 1]
|
raise ValueError(msg)
|
||||||
)
|
|
||||||
value = int(token)
|
value = int(token)
|
||||||
if value > maxval:
|
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)
|
value = round(value / maxval * out_max)
|
||||||
data += o32(value) if self.mode == "I" else o8(value)
|
data += o32(value) if self.mode == "I" else o8(value)
|
||||||
if len(data) == total_bytes: # finished!
|
if len(data) == total_bytes: # finished!
|
||||||
|
@ -314,7 +316,8 @@ def _save(im, fp, filename):
|
||||||
elif im.mode in ("RGB", "RGBA"):
|
elif im.mode in ("RGB", "RGBA"):
|
||||||
rawmode, head = "RGB", b"P6"
|
rawmode, head = "RGB", b"P6"
|
||||||
else:
|
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)
|
fp.write(head + b"\n%d %d\n" % im.size)
|
||||||
if head == b"P6":
|
if head == b"P6":
|
||||||
fp.write(b"255\n")
|
fp.write(b"255\n")
|
||||||
|
|
|
@ -65,7 +65,8 @@ class PsdImageFile(ImageFile.ImageFile):
|
||||||
|
|
||||||
s = read(26)
|
s = read(26)
|
||||||
if not _accept(s) or i16(s, 4) != 1:
|
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_bits = i16(s, 22)
|
||||||
psd_channels = i16(s, 12)
|
psd_channels = i16(s, 12)
|
||||||
|
@ -74,7 +75,8 @@ class PsdImageFile(ImageFile.ImageFile):
|
||||||
mode, channels = MODES[(psd_mode, psd_bits)]
|
mode, channels = MODES[(psd_mode, psd_bits)]
|
||||||
|
|
||||||
if channels > psd_channels:
|
if channels > psd_channels:
|
||||||
raise OSError("not enough channels")
|
msg = "not enough channels"
|
||||||
|
raise OSError(msg)
|
||||||
if mode == "RGB" and psd_channels == 4:
|
if mode == "RGB" and psd_channels == 4:
|
||||||
mode = "RGBA"
|
mode = "RGBA"
|
||||||
channels = 4
|
channels = 4
|
||||||
|
@ -152,7 +154,8 @@ class PsdImageFile(ImageFile.ImageFile):
|
||||||
self.fp = self._fp
|
self.fp = self._fp
|
||||||
return name, bbox
|
return name, bbox
|
||||||
except IndexError as e:
|
except IndexError as e:
|
||||||
raise EOFError("no such layer") from e
|
msg = "no such layer"
|
||||||
|
raise EOFError(msg) from e
|
||||||
|
|
||||||
def tell(self):
|
def tell(self):
|
||||||
# return layer number (0=image, 1..max=layers)
|
# return layer number (0=image, 1..max=layers)
|
||||||
|
@ -170,7 +173,8 @@ def _layerinfo(fp, ct_bytes):
|
||||||
|
|
||||||
# sanity check
|
# sanity check
|
||||||
if ct_bytes < (abs(ct) * 20):
|
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)):
|
for _ in range(abs(ct)):
|
||||||
|
|
||||||
|
|
|
@ -79,7 +79,8 @@ class PyAccess:
|
||||||
:param color: The pixel value.
|
:param color: The pixel value.
|
||||||
"""
|
"""
|
||||||
if self.readonly:
|
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
|
(x, y) = xy
|
||||||
if x < 0:
|
if x < 0:
|
||||||
x = self.xsize + x
|
x = self.xsize + x
|
||||||
|
@ -127,7 +128,8 @@ class PyAccess:
|
||||||
def check_xy(self, xy):
|
def check_xy(self, xy):
|
||||||
(x, y) = xy
|
(x, y) = xy
|
||||||
if not (0 <= x < self.xsize and 0 <= y < self.ysize):
|
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
|
return xy
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -60,7 +60,8 @@ class SgiImageFile(ImageFile.ImageFile):
|
||||||
s = self.fp.read(headlen)
|
s = self.fp.read(headlen)
|
||||||
|
|
||||||
if not _accept(s):
|
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 : verbatim or RLE
|
||||||
compression = s[2]
|
compression = s[2]
|
||||||
|
@ -91,7 +92,8 @@ class SgiImageFile(ImageFile.ImageFile):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
if rawmode == "":
|
if rawmode == "":
|
||||||
raise ValueError("Unsupported SGI image mode")
|
msg = "Unsupported SGI image mode"
|
||||||
|
raise ValueError(msg)
|
||||||
|
|
||||||
self._size = xsize, ysize
|
self._size = xsize, ysize
|
||||||
self.mode = rawmode.split(";")[0]
|
self.mode = rawmode.split(";")[0]
|
||||||
|
@ -124,7 +126,8 @@ class SgiImageFile(ImageFile.ImageFile):
|
||||||
|
|
||||||
def _save(im, fp, filename):
|
def _save(im, fp, filename):
|
||||||
if im.mode != "RGB" and im.mode != "RGBA" and im.mode != "L":
|
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
|
# Get the keyword arguments
|
||||||
info = im.encoderinfo
|
info = im.encoderinfo
|
||||||
|
@ -133,7 +136,8 @@ def _save(im, fp, filename):
|
||||||
bpc = info.get("bpc", 1)
|
bpc = info.get("bpc", 1)
|
||||||
|
|
||||||
if bpc not in (1, 2):
|
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
|
# Flip the image, since the origin of SGI file is the bottom-left corner
|
||||||
orientation = -1
|
orientation = -1
|
||||||
|
@ -158,9 +162,8 @@ def _save(im, fp, filename):
|
||||||
|
|
||||||
# assert we've got the right number of bands.
|
# assert we've got the right number of bands.
|
||||||
if len(im.getbands()) != z:
|
if len(im.getbands()) != z:
|
||||||
raise ValueError(
|
msg = f"incorrect number of bands in SGI write: {z} vs {len(im.getbands())}"
|
||||||
f"incorrect number of bands in SGI write: {z} vs {len(im.getbands())}"
|
raise ValueError(msg)
|
||||||
)
|
|
||||||
|
|
||||||
# Minimum Byte value
|
# Minimum Byte value
|
||||||
pinmin = 0
|
pinmin = 0
|
||||||
|
|
|
@ -110,14 +110,17 @@ class SpiderImageFile(ImageFile.ImageFile):
|
||||||
t = struct.unpack("<27f", f) # little-endian
|
t = struct.unpack("<27f", f) # little-endian
|
||||||
hdrlen = isSpiderHeader(t)
|
hdrlen = isSpiderHeader(t)
|
||||||
if hdrlen == 0:
|
if hdrlen == 0:
|
||||||
raise SyntaxError("not a valid Spider file")
|
msg = "not a valid Spider file"
|
||||||
|
raise SyntaxError(msg)
|
||||||
except struct.error as e:
|
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
|
h = (99,) + t # add 1 value : spider header index starts at 1
|
||||||
iform = int(h[5])
|
iform = int(h[5])
|
||||||
if iform != 1:
|
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._size = int(h[12]), int(h[2]) # size in pixels (width, height)
|
||||||
self.istack = int(h[24])
|
self.istack = int(h[24])
|
||||||
|
@ -140,7 +143,8 @@ class SpiderImageFile(ImageFile.ImageFile):
|
||||||
offset = hdrlen + self.stkoffset
|
offset = hdrlen + self.stkoffset
|
||||||
self.istack = 2 # So Image knows it's still a stack
|
self.istack = 2 # So Image knows it's still a stack
|
||||||
else:
|
else:
|
||||||
raise SyntaxError("inconsistent stack header values")
|
msg = "inconsistent stack header values"
|
||||||
|
raise SyntaxError(msg)
|
||||||
|
|
||||||
if self.bigendian:
|
if self.bigendian:
|
||||||
self.rawmode = "F;32BF"
|
self.rawmode = "F;32BF"
|
||||||
|
@ -168,7 +172,8 @@ class SpiderImageFile(ImageFile.ImageFile):
|
||||||
|
|
||||||
def seek(self, frame):
|
def seek(self, frame):
|
||||||
if self.istack == 0:
|
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):
|
if not self._seek_check(frame):
|
||||||
return
|
return
|
||||||
self.stkoffset = self.hdrlen + frame * (self.hdrlen + self.imgbytes)
|
self.stkoffset = self.hdrlen + frame * (self.hdrlen + self.imgbytes)
|
||||||
|
@ -260,7 +265,8 @@ def _save(im, fp, filename):
|
||||||
|
|
||||||
hdr = makeSpiderHeader(im)
|
hdr = makeSpiderHeader(im)
|
||||||
if len(hdr) < 256:
|
if len(hdr) < 256:
|
||||||
raise OSError("Error creating Spider header")
|
msg = "Error creating Spider header"
|
||||||
|
raise OSError(msg)
|
||||||
|
|
||||||
# write the SPIDER header
|
# write the SPIDER header
|
||||||
fp.writelines(hdr)
|
fp.writelines(hdr)
|
||||||
|
|
|
@ -54,7 +54,8 @@ class SunImageFile(ImageFile.ImageFile):
|
||||||
# HEAD
|
# HEAD
|
||||||
s = self.fp.read(32)
|
s = self.fp.read(32)
|
||||||
if not _accept(s):
|
if not _accept(s):
|
||||||
raise SyntaxError("not an SUN raster file")
|
msg = "not an SUN raster file"
|
||||||
|
raise SyntaxError(msg)
|
||||||
|
|
||||||
offset = 32
|
offset = 32
|
||||||
|
|
||||||
|
@ -83,14 +84,17 @@ class SunImageFile(ImageFile.ImageFile):
|
||||||
else:
|
else:
|
||||||
self.mode, rawmode = "RGB", "BGRX"
|
self.mode, rawmode = "RGB", "BGRX"
|
||||||
else:
|
else:
|
||||||
raise SyntaxError("Unsupported Mode/Bit Depth")
|
msg = "Unsupported Mode/Bit Depth"
|
||||||
|
raise SyntaxError(msg)
|
||||||
|
|
||||||
if palette_length:
|
if palette_length:
|
||||||
if palette_length > 1024:
|
if palette_length > 1024:
|
||||||
raise SyntaxError("Unsupported Color Palette Length")
|
msg = "Unsupported Color Palette Length"
|
||||||
|
raise SyntaxError(msg)
|
||||||
|
|
||||||
if palette_type != 1:
|
if palette_type != 1:
|
||||||
raise SyntaxError("Unsupported Palette Type")
|
msg = "Unsupported Palette Type"
|
||||||
|
raise SyntaxError(msg)
|
||||||
|
|
||||||
offset = offset + palette_length
|
offset = offset + palette_length
|
||||||
self.palette = ImagePalette.raw("RGB;L", self.fp.read(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:
|
elif file_type == 2:
|
||||||
self.tile = [("sun_rle", (0, 0) + self.size, offset, rawmode)]
|
self.tile = [("sun_rle", (0, 0) + self.size, offset, rawmode)]
|
||||||
else:
|
else:
|
||||||
raise SyntaxError("Unsupported Sun Raster file type")
|
msg = "Unsupported Sun Raster file type"
|
||||||
|
raise SyntaxError(msg)
|
||||||
|
|
||||||
|
|
||||||
#
|
#
|
||||||
|
|
|
@ -35,12 +35,14 @@ class TarIO(ContainerIO.ContainerIO):
|
||||||
|
|
||||||
s = self.fh.read(512)
|
s = self.fh.read(512)
|
||||||
if len(s) != 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")
|
name = s[:100].decode("utf-8")
|
||||||
i = name.find("\0")
|
i = name.find("\0")
|
||||||
if i == 0:
|
if i == 0:
|
||||||
raise OSError("cannot find subfile")
|
msg = "cannot find subfile"
|
||||||
|
raise OSError(msg)
|
||||||
if i > 0:
|
if i > 0:
|
||||||
name = name[:i]
|
name = name[:i]
|
||||||
|
|
||||||
|
|
|
@ -73,7 +73,8 @@ class TgaImageFile(ImageFile.ImageFile):
|
||||||
or self.size[1] <= 0
|
or self.size[1] <= 0
|
||||||
or depth not in (1, 8, 16, 24, 32)
|
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
|
# image mode
|
||||||
if imagetype in (3, 11):
|
if imagetype in (3, 11):
|
||||||
|
@ -89,7 +90,8 @@ class TgaImageFile(ImageFile.ImageFile):
|
||||||
if depth == 32:
|
if depth == 32:
|
||||||
self.mode = "RGBA"
|
self.mode = "RGBA"
|
||||||
else:
|
else:
|
||||||
raise SyntaxError("unknown TGA mode")
|
msg = "unknown TGA mode"
|
||||||
|
raise SyntaxError(msg)
|
||||||
|
|
||||||
# orientation
|
# orientation
|
||||||
orientation = flags & 0x30
|
orientation = flags & 0x30
|
||||||
|
@ -99,7 +101,8 @@ class TgaImageFile(ImageFile.ImageFile):
|
||||||
elif orientation in [0, 0x10]:
|
elif orientation in [0, 0x10]:
|
||||||
orientation = -1
|
orientation = -1
|
||||||
else:
|
else:
|
||||||
raise SyntaxError("unknown TGA orientation")
|
msg = "unknown TGA orientation"
|
||||||
|
raise SyntaxError(msg)
|
||||||
|
|
||||||
self.info["orientation"] = orientation
|
self.info["orientation"] = orientation
|
||||||
|
|
||||||
|
@ -175,7 +178,8 @@ def _save(im, fp, filename):
|
||||||
try:
|
try:
|
||||||
rawmode, bits, colormaptype, imagetype = SAVE[im.mode]
|
rawmode, bits, colormaptype, imagetype = SAVE[im.mode]
|
||||||
except KeyError as e:
|
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:
|
if "rle" in im.encoderinfo:
|
||||||
rle = im.encoderinfo["rle"]
|
rle = im.encoderinfo["rle"]
|
||||||
|
|
|
@ -500,14 +500,16 @@ class ImageFileDirectory_v2(MutableMapping):
|
||||||
:param prefix: Override the endianness of the file.
|
:param prefix: Override the endianness of the file.
|
||||||
"""
|
"""
|
||||||
if not _accept(ifh):
|
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]
|
self._prefix = prefix if prefix is not None else ifh[:2]
|
||||||
if self._prefix == MM:
|
if self._prefix == MM:
|
||||||
self._endian = ">"
|
self._endian = ">"
|
||||||
elif self._prefix == II:
|
elif self._prefix == II:
|
||||||
self._endian = "<"
|
self._endian = "<"
|
||||||
else:
|
else:
|
||||||
raise SyntaxError("not a TIFF IFD")
|
msg = "not a TIFF IFD"
|
||||||
|
raise SyntaxError(msg)
|
||||||
self._bigtiff = ifh[2] == 43
|
self._bigtiff = ifh[2] == 43
|
||||||
self.group = group
|
self.group = group
|
||||||
self.tagtype = {}
|
self.tagtype = {}
|
||||||
|
@ -524,7 +526,8 @@ class ImageFileDirectory_v2(MutableMapping):
|
||||||
|
|
||||||
@legacy_api.setter
|
@legacy_api.setter
|
||||||
def legacy_api(self, value):
|
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):
|
def reset(self):
|
||||||
self._tags_v1 = {} # will remain empty if legacy_api is false
|
self._tags_v1 = {} # will remain empty if legacy_api is false
|
||||||
|
@ -780,10 +783,11 @@ class ImageFileDirectory_v2(MutableMapping):
|
||||||
def _ensure_read(self, fp, size):
|
def _ensure_read(self, fp, size):
|
||||||
ret = fp.read(size)
|
ret = fp.read(size)
|
||||||
if len(ret) != size:
|
if len(ret) != size:
|
||||||
raise OSError(
|
msg = (
|
||||||
"Corrupt EXIF data. "
|
"Corrupt EXIF data. "
|
||||||
f"Expecting to read {size} bytes but only got {len(ret)}. "
|
f"Expecting to read {size} bytes but only got {len(ret)}. "
|
||||||
)
|
)
|
||||||
|
raise OSError(msg)
|
||||||
return ret
|
return ret
|
||||||
|
|
||||||
def load(self, fp):
|
def load(self, fp):
|
||||||
|
@ -910,7 +914,8 @@ class ImageFileDirectory_v2(MutableMapping):
|
||||||
if stripoffsets is not None:
|
if stripoffsets is not None:
|
||||||
tag, typ, count, value, data = entries[stripoffsets]
|
tag, typ, count, value, data = entries[stripoffsets]
|
||||||
if data:
|
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)
|
value = self._pack("L", self._unpack("L", value)[0] + offset)
|
||||||
entries[stripoffsets] = tag, typ, count, value, data
|
entries[stripoffsets] = tag, typ, count, value, data
|
||||||
|
|
||||||
|
@ -1123,7 +1128,8 @@ class TiffImageFile(ImageFile.ImageFile):
|
||||||
|
|
||||||
while len(self._frame_pos) <= frame:
|
while len(self._frame_pos) <= frame:
|
||||||
if not self.__next:
|
if not self.__next:
|
||||||
raise EOFError("no more images in TIFF file")
|
msg = "no more images in TIFF file"
|
||||||
|
raise EOFError(msg)
|
||||||
logger.debug(
|
logger.debug(
|
||||||
f"Seeking to frame {frame}, on frame {self.__frame}, "
|
f"Seeking to frame {frame}, on frame {self.__frame}, "
|
||||||
f"__next {self.__next}, location: {self.fp.tell()}"
|
f"__next {self.__next}, location: {self.fp.tell()}"
|
||||||
|
@ -1230,7 +1236,8 @@ class TiffImageFile(ImageFile.ImageFile):
|
||||||
self.load_prepare()
|
self.load_prepare()
|
||||||
|
|
||||||
if not len(self.tile) == 1:
|
if not len(self.tile) == 1:
|
||||||
raise OSError("Not exactly one tile")
|
msg = "Not exactly one tile"
|
||||||
|
raise OSError(msg)
|
||||||
|
|
||||||
# (self._compression, (extents tuple),
|
# (self._compression, (extents tuple),
|
||||||
# 0, (rawmode, self._compression, fp))
|
# 0, (rawmode, self._compression, fp))
|
||||||
|
@ -1262,7 +1269,8 @@ class TiffImageFile(ImageFile.ImageFile):
|
||||||
try:
|
try:
|
||||||
decoder.setimage(self.im, extents)
|
decoder.setimage(self.im, extents)
|
||||||
except ValueError as e:
|
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
|
close_self_fp = self._exclusive_fp and not self.is_animated
|
||||||
if hasattr(self.fp, "getvalue"):
|
if hasattr(self.fp, "getvalue"):
|
||||||
|
@ -1316,7 +1324,8 @@ class TiffImageFile(ImageFile.ImageFile):
|
||||||
"""Setup this image object based on current tags"""
|
"""Setup this image object based on current tags"""
|
||||||
|
|
||||||
if 0xBC01 in self.tag_v2:
|
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
|
# extract relevant tags
|
||||||
self._compression = COMPRESSION_INFO[self.tag_v2.get(COMPRESSION, 1)]
|
self._compression = COMPRESSION_INFO[self.tag_v2.get(COMPRESSION, 1)]
|
||||||
|
@ -1375,7 +1384,8 @@ class TiffImageFile(ImageFile.ImageFile):
|
||||||
logger.error(
|
logger.error(
|
||||||
"More samples per pixel than can be decoded: %s", samples_per_pixel
|
"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 samples_per_pixel < bps_actual_count:
|
||||||
# If a file has more values in bps_tuple than expected,
|
# If a file has more values in bps_tuple than expected,
|
||||||
|
@ -1387,7 +1397,8 @@ class TiffImageFile(ImageFile.ImageFile):
|
||||||
bps_tuple = bps_tuple * samples_per_pixel
|
bps_tuple = bps_tuple * samples_per_pixel
|
||||||
|
|
||||||
if len(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
|
# mode: check photometric interpretation and bits per pixel
|
||||||
key = (
|
key = (
|
||||||
|
@ -1403,7 +1414,8 @@ class TiffImageFile(ImageFile.ImageFile):
|
||||||
self.mode, rawmode = OPEN_INFO[key]
|
self.mode, rawmode = OPEN_INFO[key]
|
||||||
except KeyError as e:
|
except KeyError as e:
|
||||||
logger.debug("- unsupported format")
|
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"- raw mode: {rawmode}")
|
||||||
logger.debug(f"- pil mode: {self.mode}")
|
logger.debug(f"- pil mode: {self.mode}")
|
||||||
|
@ -1519,7 +1531,8 @@ class TiffImageFile(ImageFile.ImageFile):
|
||||||
layer += 1
|
layer += 1
|
||||||
else:
|
else:
|
||||||
logger.debug("- unsupported data organization")
|
logger.debug("- unsupported data organization")
|
||||||
raise SyntaxError("unknown data organization")
|
msg = "unknown data organization"
|
||||||
|
raise SyntaxError(msg)
|
||||||
|
|
||||||
# Fix up info.
|
# Fix up info.
|
||||||
if ICCPROFILE in self.tag_v2:
|
if ICCPROFILE in self.tag_v2:
|
||||||
|
@ -1571,7 +1584,8 @@ def _save(im, fp, filename):
|
||||||
try:
|
try:
|
||||||
rawmode, prefix, photo, format, bits, extra = SAVE_INFO[im.mode]
|
rawmode, prefix, photo, format, bits, extra = SAVE_INFO[im.mode]
|
||||||
except KeyError as e:
|
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)
|
ifd = ImageFileDirectory_v2(prefix=prefix)
|
||||||
|
|
||||||
|
@ -1736,11 +1750,11 @@ def _save(im, fp, filename):
|
||||||
if "quality" in encoderinfo:
|
if "quality" in encoderinfo:
|
||||||
quality = encoderinfo["quality"]
|
quality = encoderinfo["quality"]
|
||||||
if not isinstance(quality, int) or quality < 0 or quality > 100:
|
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":
|
if compression != "jpeg":
|
||||||
raise ValueError(
|
msg = "quality setting only supported for 'jpeg' compression"
|
||||||
"quality setting only supported for 'jpeg' compression"
|
raise ValueError(msg)
|
||||||
)
|
|
||||||
ifd[JPEGQUALITY] = quality
|
ifd[JPEGQUALITY] = quality
|
||||||
|
|
||||||
logger.debug("Saving using libtiff encoder")
|
logger.debug("Saving using libtiff encoder")
|
||||||
|
@ -1837,7 +1851,8 @@ def _save(im, fp, filename):
|
||||||
if s:
|
if s:
|
||||||
break
|
break
|
||||||
if s < 0:
|
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:
|
else:
|
||||||
for tag in blocklist:
|
for tag in blocklist:
|
||||||
|
@ -1912,7 +1927,8 @@ class AppendingTiffWriter:
|
||||||
elif iimm == b"MM\x00\x2a":
|
elif iimm == b"MM\x00\x2a":
|
||||||
self.setEndian(">")
|
self.setEndian(">")
|
||||||
else:
|
else:
|
||||||
raise RuntimeError("Invalid TIFF file header")
|
msg = "Invalid TIFF file header"
|
||||||
|
raise RuntimeError(msg)
|
||||||
|
|
||||||
self.skipIFDs()
|
self.skipIFDs()
|
||||||
self.goToEnd()
|
self.goToEnd()
|
||||||
|
@ -1926,12 +1942,14 @@ class AppendingTiffWriter:
|
||||||
|
|
||||||
iimm = self.f.read(4)
|
iimm = self.f.read(4)
|
||||||
if not iimm:
|
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.
|
# Make it easy to finish a frame without committing to a new one.
|
||||||
return
|
return
|
||||||
|
|
||||||
if iimm != self.IIMM:
|
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.readLong()
|
||||||
ifd_offset += self.offsetOfNewPage
|
ifd_offset += self.offsetOfNewPage
|
||||||
|
@ -2005,29 +2023,34 @@ class AppendingTiffWriter:
|
||||||
self.f.seek(-2, os.SEEK_CUR)
|
self.f.seek(-2, os.SEEK_CUR)
|
||||||
bytes_written = self.f.write(struct.pack(self.longFmt, value))
|
bytes_written = self.f.write(struct.pack(self.longFmt, value))
|
||||||
if bytes_written is not None and bytes_written != 4:
|
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):
|
def rewriteLastShort(self, value):
|
||||||
self.f.seek(-2, os.SEEK_CUR)
|
self.f.seek(-2, os.SEEK_CUR)
|
||||||
bytes_written = self.f.write(struct.pack(self.shortFmt, value))
|
bytes_written = self.f.write(struct.pack(self.shortFmt, value))
|
||||||
if bytes_written is not None and bytes_written != 2:
|
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):
|
def rewriteLastLong(self, value):
|
||||||
self.f.seek(-4, os.SEEK_CUR)
|
self.f.seek(-4, os.SEEK_CUR)
|
||||||
bytes_written = self.f.write(struct.pack(self.longFmt, value))
|
bytes_written = self.f.write(struct.pack(self.longFmt, value))
|
||||||
if bytes_written is not None and bytes_written != 4:
|
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):
|
def writeShort(self, value):
|
||||||
bytes_written = self.f.write(struct.pack(self.shortFmt, value))
|
bytes_written = self.f.write(struct.pack(self.shortFmt, value))
|
||||||
if bytes_written is not None and bytes_written != 2:
|
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):
|
def writeLong(self, value):
|
||||||
bytes_written = self.f.write(struct.pack(self.longFmt, value))
|
bytes_written = self.f.write(struct.pack(self.longFmt, value))
|
||||||
if bytes_written is not None and bytes_written != 4:
|
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):
|
def close(self):
|
||||||
self.finalize()
|
self.finalize()
|
||||||
|
@ -2070,7 +2093,8 @@ class AppendingTiffWriter:
|
||||||
|
|
||||||
def fixOffsets(self, count, isShort=False, isLong=False):
|
def fixOffsets(self, count, isShort=False, isLong=False):
|
||||||
if not isShort and not isLong:
|
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):
|
for i in range(count):
|
||||||
offset = self.readShort() if isShort else self.readLong()
|
offset = self.readShort() if isShort else self.readLong()
|
||||||
|
@ -2078,7 +2102,8 @@ class AppendingTiffWriter:
|
||||||
if isShort and offset >= 65536:
|
if isShort and offset >= 65536:
|
||||||
# offset is now too large - we must convert shorts to longs
|
# offset is now too large - we must convert shorts to longs
|
||||||
if count != 1:
|
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
|
# simple case - the offset is just one and therefore it is
|
||||||
# local (not referenced with another offset)
|
# local (not referenced with another offset)
|
||||||
|
|
|
@ -130,7 +130,8 @@ class WebPImageFile(ImageFile.ImageFile):
|
||||||
if ret is None:
|
if ret is None:
|
||||||
self._reset() # Reset just to be safe
|
self._reset() # Reset just to be safe
|
||||||
self.seek(0)
|
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
|
# Compute duration
|
||||||
data, timestamp = ret
|
data, timestamp = ret
|
||||||
|
@ -233,9 +234,8 @@ def _save_all(im, fp, filename):
|
||||||
or len(background) != 4
|
or len(background) != 4
|
||||||
or not all(0 <= v < 256 for v in background)
|
or not all(0 <= v < 256 for v in background)
|
||||||
):
|
):
|
||||||
raise OSError(
|
msg = f"Background color is not an RGBA tuple clamped to (0-255): {background}"
|
||||||
f"Background color is not an RGBA tuple clamped to (0-255): {background}"
|
raise OSError(msg)
|
||||||
)
|
|
||||||
|
|
||||||
# Convert to packed uint
|
# Convert to packed uint
|
||||||
bg_r, bg_g, bg_b, bg_a = background
|
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
|
# Get the final output from the encoder
|
||||||
data = enc.assemble(icc_profile, exif, xmp)
|
data = enc.assemble(icc_profile, exif, xmp)
|
||||||
if data is None:
|
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)
|
fp.write(data)
|
||||||
|
|
||||||
|
@ -351,7 +352,8 @@ def _save(im, fp, filename):
|
||||||
xmp,
|
xmp,
|
||||||
)
|
)
|
||||||
if data is None:
|
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)
|
fp.write(data)
|
||||||
|
|
||||||
|
|
|
@ -109,7 +109,8 @@ class WmfStubImageFile(ImageFile.StubImageFile):
|
||||||
|
|
||||||
# sanity check (standard metafile header)
|
# sanity check (standard metafile header)
|
||||||
if s[22:26] != b"\x01\x00\t\x00":
|
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":
|
elif s[:4] == b"\x01\x00\x00\x00" and s[40:44] == b" EMF":
|
||||||
# enhanced metafile
|
# enhanced metafile
|
||||||
|
@ -137,7 +138,8 @@ class WmfStubImageFile(ImageFile.StubImageFile):
|
||||||
self.info["dpi"] = xdpi, ydpi
|
self.info["dpi"] = xdpi, ydpi
|
||||||
|
|
||||||
else:
|
else:
|
||||||
raise SyntaxError("Unsupported file format")
|
msg = "Unsupported file format"
|
||||||
|
raise SyntaxError(msg)
|
||||||
|
|
||||||
self.mode = "RGB"
|
self.mode = "RGB"
|
||||||
self._size = size
|
self._size = size
|
||||||
|
@ -162,7 +164,8 @@ class WmfStubImageFile(ImageFile.StubImageFile):
|
||||||
|
|
||||||
def _save(im, fp, filename):
|
def _save(im, fp, filename):
|
||||||
if _handler is None or not hasattr(_handler, "save"):
|
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)
|
_handler.save(im, fp, filename)
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -49,7 +49,8 @@ class XVThumbImageFile(ImageFile.ImageFile):
|
||||||
|
|
||||||
# check magic
|
# check magic
|
||||||
if not _accept(self.fp.read(6)):
|
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
|
# Skip to beginning of next line
|
||||||
self.fp.readline()
|
self.fp.readline()
|
||||||
|
@ -58,7 +59,8 @@ class XVThumbImageFile(ImageFile.ImageFile):
|
||||||
while True:
|
while True:
|
||||||
s = self.fp.readline()
|
s = self.fp.readline()
|
||||||
if not s:
|
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: '#'
|
if s[0] != 35: # ie. when not a comment: '#'
|
||||||
break
|
break
|
||||||
|
|
||||||
|
|
|
@ -53,7 +53,8 @@ class XbmImageFile(ImageFile.ImageFile):
|
||||||
m = xbm_head.match(self.fp.read(512))
|
m = xbm_head.match(self.fp.read(512))
|
||||||
|
|
||||||
if not m:
|
if not m:
|
||||||
raise SyntaxError("not a XBM file")
|
msg = "not a XBM file"
|
||||||
|
raise SyntaxError(msg)
|
||||||
|
|
||||||
xsize = int(m.group("width"))
|
xsize = int(m.group("width"))
|
||||||
ysize = int(m.group("height"))
|
ysize = int(m.group("height"))
|
||||||
|
@ -70,7 +71,8 @@ class XbmImageFile(ImageFile.ImageFile):
|
||||||
def _save(im, fp, filename):
|
def _save(im, fp, filename):
|
||||||
|
|
||||||
if im.mode != "1":
|
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_width {im.size[0]}\n".encode("ascii"))
|
||||||
fp.write(f"#define im_height {im.size[1]}\n".encode("ascii"))
|
fp.write(f"#define im_height {im.size[1]}\n".encode("ascii"))
|
||||||
|
|
|
@ -40,13 +40,15 @@ class XpmImageFile(ImageFile.ImageFile):
|
||||||
def _open(self):
|
def _open(self):
|
||||||
|
|
||||||
if not _accept(self.fp.read(9)):
|
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
|
# skip forward to next string
|
||||||
while True:
|
while True:
|
||||||
s = self.fp.readline()
|
s = self.fp.readline()
|
||||||
if not s:
|
if not s:
|
||||||
raise SyntaxError("broken XPM file")
|
msg = "broken XPM file"
|
||||||
|
raise SyntaxError(msg)
|
||||||
m = xpm_head.match(s)
|
m = xpm_head.match(s)
|
||||||
if m:
|
if m:
|
||||||
break
|
break
|
||||||
|
@ -57,7 +59,8 @@ class XpmImageFile(ImageFile.ImageFile):
|
||||||
bpp = int(m.group(4))
|
bpp = int(m.group(4))
|
||||||
|
|
||||||
if pal > 256 or bpp != 1:
|
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
|
# load palette description
|
||||||
|
@ -91,13 +94,15 @@ class XpmImageFile(ImageFile.ImageFile):
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
# unknown colour
|
# unknown colour
|
||||||
raise ValueError("cannot read this XPM file")
|
msg = "cannot read this XPM file"
|
||||||
|
raise ValueError(msg)
|
||||||
break
|
break
|
||||||
|
|
||||||
else:
|
else:
|
||||||
|
|
||||||
# missing colour key
|
# missing colour key
|
||||||
raise ValueError("cannot read this XPM file")
|
msg = "cannot read this XPM file"
|
||||||
|
raise ValueError(msg)
|
||||||
|
|
||||||
self.mode = "P"
|
self.mode = "P"
|
||||||
self.palette = ImagePalette.raw("RGB", b"".join(palette))
|
self.palette = ImagePalette.raw("RGB", b"".join(palette))
|
||||||
|
|
|
@ -43,14 +43,17 @@ def deprecate(
|
||||||
if when is None:
|
if when is None:
|
||||||
removed = "a future version"
|
removed = "a future version"
|
||||||
elif when <= int(__version__.split(".")[0]):
|
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:
|
elif when == 10:
|
||||||
removed = "Pillow 10 (2023-07-01)"
|
removed = "Pillow 10 (2023-07-01)"
|
||||||
else:
|
else:
|
||||||
raise ValueError(f"Unknown removal version, update {__name__}?")
|
msg = f"Unknown removal version, update {__name__}?"
|
||||||
|
raise ValueError(msg)
|
||||||
|
|
||||||
if replacement and action:
|
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:
|
if replacement:
|
||||||
action = f". Use {replacement} instead."
|
action = f". Use {replacement} instead."
|
||||||
|
|
|
@ -25,7 +25,8 @@ def check_module(feature):
|
||||||
:raises ValueError: If the module is not defined in this version of Pillow.
|
:raises ValueError: If the module is not defined in this version of Pillow.
|
||||||
"""
|
"""
|
||||||
if not (feature in modules):
|
if not (feature in modules):
|
||||||
raise ValueError(f"Unknown module {feature}")
|
msg = f"Unknown module {feature}"
|
||||||
|
raise ValueError(msg)
|
||||||
|
|
||||||
module, ver = modules[feature]
|
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.
|
:raises ValueError: If the codec is not defined in this version of Pillow.
|
||||||
"""
|
"""
|
||||||
if feature not in codecs:
|
if feature not in codecs:
|
||||||
raise ValueError(f"Unknown codec {feature}")
|
msg = f"Unknown codec {feature}"
|
||||||
|
raise ValueError(msg)
|
||||||
|
|
||||||
codec, lib = codecs[feature]
|
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.
|
:raises ValueError: If the feature is not defined in this version of Pillow.
|
||||||
"""
|
"""
|
||||||
if feature not in features:
|
if feature not in features:
|
||||||
raise ValueError(f"Unknown feature {feature}")
|
msg = f"Unknown feature {feature}"
|
||||||
|
raise ValueError(msg)
|
||||||
|
|
||||||
module, flag, ver = features[feature]
|
module, flag, ver = features[feature]
|
||||||
|
|
||||||
|
|
|
@ -478,7 +478,8 @@ def extract_dep(url, filename):
|
||||||
member_abspath = os.path.abspath(os.path.join(sources_dir, member))
|
member_abspath = os.path.abspath(os.path.join(sources_dir, member))
|
||||||
member_prefix = os.path.commonpath([sources_dir_abs, member_abspath])
|
member_prefix = os.path.commonpath([sources_dir_abs, member_abspath])
|
||||||
if sources_dir_abs != member_prefix:
|
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)
|
zf.extractall(sources_dir)
|
||||||
elif filename.endswith(".tar.gz") or filename.endswith(".tgz"):
|
elif filename.endswith(".tar.gz") or filename.endswith(".tgz"):
|
||||||
with tarfile.open(file, "r:gz") as tgz:
|
with tarfile.open(file, "r:gz") as tgz:
|
||||||
|
@ -486,7 +487,8 @@ def extract_dep(url, filename):
|
||||||
member_abspath = os.path.abspath(os.path.join(sources_dir, member))
|
member_abspath = os.path.abspath(os.path.join(sources_dir, member))
|
||||||
member_prefix = os.path.commonpath([sources_dir_abs, member_abspath])
|
member_prefix = os.path.commonpath([sources_dir_abs, member_abspath])
|
||||||
if sources_dir_abs != member_prefix:
|
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)
|
tgz.extractall(sources_dir)
|
||||||
else:
|
else:
|
||||||
raise RuntimeError("Unknown archive type: " + filename)
|
raise RuntimeError("Unknown archive type: " + filename)
|
||||||
|
@ -642,9 +644,8 @@ if __name__ == "__main__":
|
||||||
|
|
||||||
msvs = find_msvs()
|
msvs = find_msvs()
|
||||||
if msvs is None:
|
if msvs is None:
|
||||||
raise RuntimeError(
|
msg = "Visual Studio not found. Please install Visual Studio 2017 or newer."
|
||||||
"Visual Studio not found. Please install Visual Studio 2017 or newer."
|
raise RuntimeError(msg)
|
||||||
)
|
|
||||||
print("Found Visual Studio at:", msvs["vs_dir"])
|
print("Found Visual Studio at:", msvs["vs_dir"])
|
||||||
|
|
||||||
print("Using output directory:", build_dir)
|
print("Using output directory:", build_dir)
|
||||||
|
|
Loading…
Reference in New Issue
Block a user