mirror of
https://github.com/python-pillow/Pillow.git
synced 2025-05-26 00:33:06 +03:00
Added type hints
This commit is contained in:
parent
0da83a1164
commit
e419fd7ab4
|
@ -472,7 +472,7 @@ class DdsImageFile(ImageFile.ImageFile):
|
||||||
else:
|
else:
|
||||||
self.tile = [ImageFile._Tile("raw", extents, 0, rawmode or self.mode)]
|
self.tile = [ImageFile._Tile("raw", extents, 0, rawmode or self.mode)]
|
||||||
|
|
||||||
def load_seek(self, pos):
|
def load_seek(self, pos: int) -> None:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -42,7 +42,7 @@ gs_binary: str | bool | None = None
|
||||||
gs_windows_binary = None
|
gs_windows_binary = None
|
||||||
|
|
||||||
|
|
||||||
def has_ghostscript():
|
def has_ghostscript() -> bool:
|
||||||
global gs_binary, gs_windows_binary
|
global gs_binary, gs_windows_binary
|
||||||
if gs_binary is None:
|
if gs_binary is None:
|
||||||
if sys.platform.startswith("win"):
|
if sys.platform.startswith("win"):
|
||||||
|
@ -404,7 +404,7 @@ class EpsImageFile(ImageFile.ImageFile):
|
||||||
self.tile = []
|
self.tile = []
|
||||||
return Image.Image.load(self)
|
return Image.Image.load(self)
|
||||||
|
|
||||||
def load_seek(self, pos):
|
def load_seek(self, pos: int) -> None:
|
||||||
# we can't incrementally load, so force ImageFile.parser to
|
# we can't incrementally load, so force ImageFile.parser to
|
||||||
# use our custom load method by defining this method.
|
# use our custom load method by defining this method.
|
||||||
pass
|
pass
|
||||||
|
|
|
@ -103,7 +103,7 @@ class FtexImageFile(ImageFile.ImageFile):
|
||||||
self.fp.close()
|
self.fp.close()
|
||||||
self.fp = BytesIO(data)
|
self.fp = BytesIO(data)
|
||||||
|
|
||||||
def load_seek(self, pos):
|
def load_seek(self, pos: int) -> None:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -341,7 +341,7 @@ class IcoImageFile(ImageFile.ImageFile):
|
||||||
|
|
||||||
self.size = im.size
|
self.size = im.size
|
||||||
|
|
||||||
def load_seek(self, pos):
|
def load_seek(self, pos: int) -> None:
|
||||||
# Flag the ImageFile.Parser so that it
|
# Flag the ImageFile.Parser so that it
|
||||||
# just does all the decode at the end.
|
# just does all the decode at the end.
|
||||||
pass
|
pass
|
||||||
|
|
|
@ -324,11 +324,11 @@ class ImageFile(Image.Image):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
# may be defined for contained formats
|
# may be defined for contained formats
|
||||||
# def load_seek(self, pos):
|
# def load_seek(self, pos: int) -> None:
|
||||||
# pass
|
# pass
|
||||||
|
|
||||||
# may be defined for blocked formats (e.g. PNG)
|
# may be defined for blocked formats (e.g. PNG)
|
||||||
# def load_read(self, read_bytes):
|
# def load_read(self, read_bytes: int) -> bytes:
|
||||||
# pass
|
# pass
|
||||||
|
|
||||||
def _seek_check(self, frame):
|
def _seek_check(self, frame):
|
||||||
|
|
|
@ -408,7 +408,7 @@ class JpegImageFile(ImageFile.ImageFile):
|
||||||
msg = "no marker found"
|
msg = "no marker found"
|
||||||
raise SyntaxError(msg)
|
raise SyntaxError(msg)
|
||||||
|
|
||||||
def load_read(self, read_bytes):
|
def load_read(self, read_bytes: int) -> bytes:
|
||||||
"""
|
"""
|
||||||
internal: read more image data
|
internal: read more image data
|
||||||
For premature EOF and LOAD_TRUNCATED_IMAGES adds EOI marker
|
For premature EOF and LOAD_TRUNCATED_IMAGES adds EOI marker
|
||||||
|
|
|
@ -124,7 +124,7 @@ class MpoImageFile(JpegImagePlugin.JpegImageFile):
|
||||||
# for now we can only handle reading and individual frame extraction
|
# for now we can only handle reading and individual frame extraction
|
||||||
self.readonly = 1
|
self.readonly = 1
|
||||||
|
|
||||||
def load_seek(self, pos):
|
def load_seek(self, pos: int) -> None:
|
||||||
self._fp.seek(pos)
|
self._fp.seek(pos)
|
||||||
|
|
||||||
def seek(self, frame: int) -> None:
|
def seek(self, frame: int) -> None:
|
||||||
|
|
|
@ -39,6 +39,7 @@ import struct
|
||||||
import warnings
|
import warnings
|
||||||
import zlib
|
import zlib
|
||||||
from enum import IntEnum
|
from enum import IntEnum
|
||||||
|
from typing import IO
|
||||||
|
|
||||||
from . import Image, ImageChops, ImageFile, ImagePalette, ImageSequence
|
from . import Image, ImageChops, ImageFile, ImagePalette, ImageSequence
|
||||||
from ._binary import i16be as i16
|
from ._binary import i16be as i16
|
||||||
|
@ -149,14 +150,15 @@ def _crc32(data, seed=0):
|
||||||
|
|
||||||
|
|
||||||
class ChunkStream:
|
class ChunkStream:
|
||||||
def __init__(self, fp):
|
def __init__(self, fp: IO[bytes]) -> None:
|
||||||
self.fp = fp
|
self.fp: IO[bytes] | None = fp
|
||||||
self.queue = []
|
self.queue: list[tuple[bytes, int, int]] | None = []
|
||||||
|
|
||||||
def read(self):
|
def read(self) -> tuple[bytes, int, int]:
|
||||||
"""Fetch a new chunk. Returns header information."""
|
"""Fetch a new chunk. Returns header information."""
|
||||||
cid = None
|
cid = None
|
||||||
|
|
||||||
|
assert self.fp is not None
|
||||||
if self.queue:
|
if self.queue:
|
||||||
cid, pos, length = self.queue.pop()
|
cid, pos, length = self.queue.pop()
|
||||||
self.fp.seek(pos)
|
self.fp.seek(pos)
|
||||||
|
@ -173,7 +175,7 @@ class ChunkStream:
|
||||||
|
|
||||||
return cid, pos, length
|
return cid, pos, length
|
||||||
|
|
||||||
def __enter__(self):
|
def __enter__(self) -> ChunkStream:
|
||||||
return self
|
return self
|
||||||
|
|
||||||
def __exit__(self, *args):
|
def __exit__(self, *args):
|
||||||
|
@ -182,7 +184,8 @@ class ChunkStream:
|
||||||
def close(self) -> None:
|
def close(self) -> None:
|
||||||
self.queue = self.fp = None
|
self.queue = self.fp = None
|
||||||
|
|
||||||
def push(self, cid, pos, length):
|
def push(self, cid: bytes, pos: int, length: int) -> None:
|
||||||
|
assert self.queue is not None
|
||||||
self.queue.append((cid, pos, length))
|
self.queue.append((cid, pos, length))
|
||||||
|
|
||||||
def call(self, cid, pos, length):
|
def call(self, cid, pos, length):
|
||||||
|
@ -191,7 +194,7 @@ class ChunkStream:
|
||||||
logger.debug("STREAM %r %s %s", cid, pos, length)
|
logger.debug("STREAM %r %s %s", cid, pos, length)
|
||||||
return getattr(self, f"chunk_{cid.decode('ascii')}")(pos, length)
|
return getattr(self, f"chunk_{cid.decode('ascii')}")(pos, length)
|
||||||
|
|
||||||
def crc(self, cid, data):
|
def crc(self, cid: bytes, data: bytes) -> None:
|
||||||
"""Read and verify checksum"""
|
"""Read and verify checksum"""
|
||||||
|
|
||||||
# Skip CRC checks for ancillary chunks if allowed to load truncated
|
# Skip CRC checks for ancillary chunks if allowed to load truncated
|
||||||
|
@ -201,6 +204,7 @@ class ChunkStream:
|
||||||
self.crc_skip(cid, data)
|
self.crc_skip(cid, data)
|
||||||
return
|
return
|
||||||
|
|
||||||
|
assert self.fp is not None
|
||||||
try:
|
try:
|
||||||
crc1 = _crc32(data, _crc32(cid))
|
crc1 = _crc32(data, _crc32(cid))
|
||||||
crc2 = i32(self.fp.read(4))
|
crc2 = i32(self.fp.read(4))
|
||||||
|
@ -211,12 +215,13 @@ class ChunkStream:
|
||||||
msg = f"broken PNG file (incomplete checksum in {repr(cid)})"
|
msg = f"broken PNG file (incomplete checksum in {repr(cid)})"
|
||||||
raise SyntaxError(msg) from e
|
raise SyntaxError(msg) from e
|
||||||
|
|
||||||
def crc_skip(self, cid, data):
|
def crc_skip(self, cid: bytes, data: bytes) -> None:
|
||||||
"""Read checksum"""
|
"""Read checksum"""
|
||||||
|
|
||||||
|
assert self.fp is not None
|
||||||
self.fp.read(4)
|
self.fp.read(4)
|
||||||
|
|
||||||
def verify(self, endchunk=b"IEND"):
|
def verify(self, endchunk: bytes = b"IEND") -> list[bytes]:
|
||||||
# Simple approach; just calculate checksum for all remaining
|
# Simple approach; just calculate checksum for all remaining
|
||||||
# blocks. Must be called directly after open.
|
# blocks. Must be called directly after open.
|
||||||
|
|
||||||
|
@ -361,7 +366,7 @@ class PngStream(ChunkStream):
|
||||||
|
|
||||||
self.text_memory = 0
|
self.text_memory = 0
|
||||||
|
|
||||||
def check_text_memory(self, chunklen):
|
def check_text_memory(self, chunklen: int) -> None:
|
||||||
self.text_memory += chunklen
|
self.text_memory += chunklen
|
||||||
if self.text_memory > MAX_TEXT_MEMORY:
|
if self.text_memory > MAX_TEXT_MEMORY:
|
||||||
msg = (
|
msg = (
|
||||||
|
@ -382,7 +387,7 @@ class PngStream(ChunkStream):
|
||||||
self.im_tile = self.rewind_state["tile"]
|
self.im_tile = self.rewind_state["tile"]
|
||||||
self._seq_num = self.rewind_state["seq_num"]
|
self._seq_num = self.rewind_state["seq_num"]
|
||||||
|
|
||||||
def chunk_iCCP(self, pos, length):
|
def chunk_iCCP(self, pos: int, length: int) -> bytes:
|
||||||
# ICC profile
|
# ICC profile
|
||||||
s = ImageFile._safe_read(self.fp, length)
|
s = ImageFile._safe_read(self.fp, length)
|
||||||
# according to PNG spec, the iCCP chunk contains:
|
# according to PNG spec, the iCCP chunk contains:
|
||||||
|
@ -409,7 +414,7 @@ class PngStream(ChunkStream):
|
||||||
self.im_info["icc_profile"] = icc_profile
|
self.im_info["icc_profile"] = icc_profile
|
||||||
return s
|
return s
|
||||||
|
|
||||||
def chunk_IHDR(self, pos, length):
|
def chunk_IHDR(self, pos: int, length: int) -> bytes:
|
||||||
# image header
|
# image header
|
||||||
s = ImageFile._safe_read(self.fp, length)
|
s = ImageFile._safe_read(self.fp, length)
|
||||||
if length < 13:
|
if length < 13:
|
||||||
|
@ -446,14 +451,14 @@ class PngStream(ChunkStream):
|
||||||
msg = "end of PNG image"
|
msg = "end of PNG image"
|
||||||
raise EOFError(msg)
|
raise EOFError(msg)
|
||||||
|
|
||||||
def chunk_PLTE(self, pos, length):
|
def chunk_PLTE(self, pos: int, length: int) -> bytes:
|
||||||
# palette
|
# palette
|
||||||
s = ImageFile._safe_read(self.fp, length)
|
s = ImageFile._safe_read(self.fp, length)
|
||||||
if self.im_mode == "P":
|
if self.im_mode == "P":
|
||||||
self.im_palette = "RGB", s
|
self.im_palette = "RGB", s
|
||||||
return s
|
return s
|
||||||
|
|
||||||
def chunk_tRNS(self, pos, length):
|
def chunk_tRNS(self, pos: int, length: int) -> bytes:
|
||||||
# transparency
|
# transparency
|
||||||
s = ImageFile._safe_read(self.fp, length)
|
s = ImageFile._safe_read(self.fp, length)
|
||||||
if self.im_mode == "P":
|
if self.im_mode == "P":
|
||||||
|
@ -473,13 +478,13 @@ class PngStream(ChunkStream):
|
||||||
self.im_info["transparency"] = i16(s), i16(s, 2), i16(s, 4)
|
self.im_info["transparency"] = i16(s), i16(s, 2), i16(s, 4)
|
||||||
return s
|
return s
|
||||||
|
|
||||||
def chunk_gAMA(self, pos, length):
|
def chunk_gAMA(self, pos: int, length: int) -> bytes:
|
||||||
# gamma setting
|
# gamma setting
|
||||||
s = ImageFile._safe_read(self.fp, length)
|
s = ImageFile._safe_read(self.fp, length)
|
||||||
self.im_info["gamma"] = i32(s) / 100000.0
|
self.im_info["gamma"] = i32(s) / 100000.0
|
||||||
return s
|
return s
|
||||||
|
|
||||||
def chunk_cHRM(self, pos, length):
|
def chunk_cHRM(self, pos: int, length: int) -> bytes:
|
||||||
# chromaticity, 8 unsigned ints, actual value is scaled by 100,000
|
# chromaticity, 8 unsigned ints, actual value is scaled by 100,000
|
||||||
# WP x,y, Red x,y, Green x,y Blue x,y
|
# WP x,y, Red x,y, Green x,y Blue x,y
|
||||||
|
|
||||||
|
@ -488,7 +493,7 @@ class PngStream(ChunkStream):
|
||||||
self.im_info["chromaticity"] = tuple(elt / 100000.0 for elt in raw_vals)
|
self.im_info["chromaticity"] = tuple(elt / 100000.0 for elt in raw_vals)
|
||||||
return s
|
return s
|
||||||
|
|
||||||
def chunk_sRGB(self, pos, length):
|
def chunk_sRGB(self, pos: int, length: int) -> bytes:
|
||||||
# srgb rendering intent, 1 byte
|
# srgb rendering intent, 1 byte
|
||||||
# 0 perceptual
|
# 0 perceptual
|
||||||
# 1 relative colorimetric
|
# 1 relative colorimetric
|
||||||
|
@ -504,7 +509,7 @@ class PngStream(ChunkStream):
|
||||||
self.im_info["srgb"] = s[0]
|
self.im_info["srgb"] = s[0]
|
||||||
return s
|
return s
|
||||||
|
|
||||||
def chunk_pHYs(self, pos, length):
|
def chunk_pHYs(self, pos: int, length: int) -> bytes:
|
||||||
# pixels per unit
|
# pixels per unit
|
||||||
s = ImageFile._safe_read(self.fp, length)
|
s = ImageFile._safe_read(self.fp, length)
|
||||||
if length < 9:
|
if length < 9:
|
||||||
|
@ -521,7 +526,7 @@ class PngStream(ChunkStream):
|
||||||
self.im_info["aspect"] = px, py
|
self.im_info["aspect"] = px, py
|
||||||
return s
|
return s
|
||||||
|
|
||||||
def chunk_tEXt(self, pos, length):
|
def chunk_tEXt(self, pos: int, length: int) -> bytes:
|
||||||
# text
|
# text
|
||||||
s = ImageFile._safe_read(self.fp, length)
|
s = ImageFile._safe_read(self.fp, length)
|
||||||
try:
|
try:
|
||||||
|
@ -540,7 +545,7 @@ class PngStream(ChunkStream):
|
||||||
|
|
||||||
return s
|
return s
|
||||||
|
|
||||||
def chunk_zTXt(self, pos, length):
|
def chunk_zTXt(self, pos: int, length: int) -> bytes:
|
||||||
# compressed text
|
# compressed text
|
||||||
s = ImageFile._safe_read(self.fp, length)
|
s = ImageFile._safe_read(self.fp, length)
|
||||||
try:
|
try:
|
||||||
|
@ -574,7 +579,7 @@ class PngStream(ChunkStream):
|
||||||
|
|
||||||
return s
|
return s
|
||||||
|
|
||||||
def chunk_iTXt(self, pos, length):
|
def chunk_iTXt(self, pos: int, length: int) -> bytes:
|
||||||
# international text
|
# international text
|
||||||
r = s = ImageFile._safe_read(self.fp, length)
|
r = s = ImageFile._safe_read(self.fp, length)
|
||||||
try:
|
try:
|
||||||
|
@ -614,13 +619,13 @@ class PngStream(ChunkStream):
|
||||||
|
|
||||||
return s
|
return s
|
||||||
|
|
||||||
def chunk_eXIf(self, pos, length):
|
def chunk_eXIf(self, pos: int, length: int) -> bytes:
|
||||||
s = ImageFile._safe_read(self.fp, length)
|
s = ImageFile._safe_read(self.fp, length)
|
||||||
self.im_info["exif"] = b"Exif\x00\x00" + s
|
self.im_info["exif"] = b"Exif\x00\x00" + s
|
||||||
return s
|
return s
|
||||||
|
|
||||||
# APNG chunks
|
# APNG chunks
|
||||||
def chunk_acTL(self, pos, length):
|
def chunk_acTL(self, pos: int, length: int) -> bytes:
|
||||||
s = ImageFile._safe_read(self.fp, length)
|
s = ImageFile._safe_read(self.fp, length)
|
||||||
if length < 8:
|
if length < 8:
|
||||||
if ImageFile.LOAD_TRUNCATED_IMAGES:
|
if ImageFile.LOAD_TRUNCATED_IMAGES:
|
||||||
|
@ -640,7 +645,7 @@ class PngStream(ChunkStream):
|
||||||
self.im_custom_mimetype = "image/apng"
|
self.im_custom_mimetype = "image/apng"
|
||||||
return s
|
return s
|
||||||
|
|
||||||
def chunk_fcTL(self, pos, length):
|
def chunk_fcTL(self, pos: int, length: int) -> bytes:
|
||||||
s = ImageFile._safe_read(self.fp, length)
|
s = ImageFile._safe_read(self.fp, length)
|
||||||
if length < 26:
|
if length < 26:
|
||||||
if ImageFile.LOAD_TRUNCATED_IMAGES:
|
if ImageFile.LOAD_TRUNCATED_IMAGES:
|
||||||
|
@ -669,7 +674,7 @@ class PngStream(ChunkStream):
|
||||||
self.im_info["blend"] = s[25]
|
self.im_info["blend"] = s[25]
|
||||||
return s
|
return s
|
||||||
|
|
||||||
def chunk_fdAT(self, pos, length):
|
def chunk_fdAT(self, pos: int, length: int) -> bytes:
|
||||||
if length < 4:
|
if length < 4:
|
||||||
if ImageFile.LOAD_TRUNCATED_IMAGES:
|
if ImageFile.LOAD_TRUNCATED_IMAGES:
|
||||||
s = ImageFile._safe_read(self.fp, length)
|
s = ImageFile._safe_read(self.fp, length)
|
||||||
|
@ -701,7 +706,7 @@ class PngImageFile(ImageFile.ImageFile):
|
||||||
format = "PNG"
|
format = "PNG"
|
||||||
format_description = "Portable network graphics"
|
format_description = "Portable network graphics"
|
||||||
|
|
||||||
def _open(self):
|
def _open(self) -> None:
|
||||||
if not _accept(self.fp.read(8)):
|
if not _accept(self.fp.read(8)):
|
||||||
msg = "not a PNG file"
|
msg = "not a PNG file"
|
||||||
raise SyntaxError(msg)
|
raise SyntaxError(msg)
|
||||||
|
@ -711,8 +716,8 @@ class PngImageFile(ImageFile.ImageFile):
|
||||||
#
|
#
|
||||||
# Parse headers up to the first IDAT or fDAT chunk
|
# Parse headers up to the first IDAT or fDAT chunk
|
||||||
|
|
||||||
self.private_chunks = []
|
self.private_chunks: list[tuple[bytes, bytes] | tuple[bytes, bytes, bool]] = []
|
||||||
self.png = PngStream(self.fp)
|
self.png: PngStream | None = PngStream(self.fp)
|
||||||
|
|
||||||
while True:
|
while True:
|
||||||
#
|
#
|
||||||
|
@ -793,6 +798,7 @@ class PngImageFile(ImageFile.ImageFile):
|
||||||
# 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)
|
||||||
|
|
||||||
|
assert self.png is not None
|
||||||
self.png.verify()
|
self.png.verify()
|
||||||
self.png.close()
|
self.png.close()
|
||||||
|
|
||||||
|
@ -921,9 +927,10 @@ class PngImageFile(ImageFile.ImageFile):
|
||||||
self.__idat = self.__prepare_idat # used by load_read()
|
self.__idat = self.__prepare_idat # used by load_read()
|
||||||
ImageFile.ImageFile.load_prepare(self)
|
ImageFile.ImageFile.load_prepare(self)
|
||||||
|
|
||||||
def load_read(self, read_bytes):
|
def load_read(self, read_bytes: int) -> bytes:
|
||||||
"""internal: read more image data"""
|
"""internal: read more image data"""
|
||||||
|
|
||||||
|
assert self.png is not None
|
||||||
while self.__idat == 0:
|
while self.__idat == 0:
|
||||||
# end of chunk, skip forward to next one
|
# end of chunk, skip forward to next one
|
||||||
|
|
||||||
|
@ -956,6 +963,7 @@ class PngImageFile(ImageFile.ImageFile):
|
||||||
|
|
||||||
def load_end(self) -> None:
|
def load_end(self) -> None:
|
||||||
"""internal: finished reading image data"""
|
"""internal: finished reading image data"""
|
||||||
|
assert self.png is not None
|
||||||
if self.__idat != 0:
|
if self.__idat != 0:
|
||||||
self.fp.read(self.__idat)
|
self.fp.read(self.__idat)
|
||||||
while True:
|
while True:
|
||||||
|
@ -1079,7 +1087,7 @@ class _idat:
|
||||||
self.fp = fp
|
self.fp = fp
|
||||||
self.chunk = chunk
|
self.chunk = chunk
|
||||||
|
|
||||||
def write(self, data):
|
def write(self, data: bytes) -> None:
|
||||||
self.chunk(self.fp, b"IDAT", data)
|
self.chunk(self.fp, b"IDAT", data)
|
||||||
|
|
||||||
|
|
||||||
|
@ -1091,7 +1099,7 @@ class _fdat:
|
||||||
self.chunk = chunk
|
self.chunk = chunk
|
||||||
self.seq_num = seq_num
|
self.seq_num = seq_num
|
||||||
|
|
||||||
def write(self, data):
|
def write(self, data: bytes) -> None:
|
||||||
self.chunk(self.fp, b"fdAT", o32(self.seq_num), data)
|
self.chunk(self.fp, b"fdAT", o32(self.seq_num), data)
|
||||||
self.seq_num += 1
|
self.seq_num += 1
|
||||||
|
|
||||||
|
@ -1436,10 +1444,10 @@ def getchunks(im, **params):
|
||||||
class collector:
|
class collector:
|
||||||
data = []
|
data = []
|
||||||
|
|
||||||
def write(self, data):
|
def write(self, data: bytes) -> None:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
def append(self, chunk):
|
def append(self, chunk: bytes) -> None:
|
||||||
self.data.append(chunk)
|
self.data.append(chunk)
|
||||||
|
|
||||||
def append(fp, cid, *data):
|
def append(fp, cid, *data):
|
||||||
|
|
|
@ -171,7 +171,7 @@ class WebPImageFile(ImageFile.ImageFile):
|
||||||
|
|
||||||
return super().load()
|
return super().load()
|
||||||
|
|
||||||
def load_seek(self, pos):
|
def load_seek(self, pos: int) -> None:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
def tell(self) -> int:
|
def tell(self) -> int:
|
||||||
|
|
|
@ -103,16 +103,13 @@ class XpmImageFile(ImageFile.ImageFile):
|
||||||
|
|
||||||
self.tile = [("raw", (0, 0) + self.size, self.fp.tell(), ("P", 0, 1))]
|
self.tile = [("raw", (0, 0) + self.size, self.fp.tell(), ("P", 0, 1))]
|
||||||
|
|
||||||
def load_read(self, read_bytes):
|
def load_read(self, read_bytes: int) -> bytes:
|
||||||
#
|
#
|
||||||
# load all image data in one chunk
|
# load all image data in one chunk
|
||||||
|
|
||||||
xsize, ysize = self.size
|
xsize, ysize = self.size
|
||||||
|
|
||||||
s = [None] * ysize
|
s = [self.fp.readline()[1 : xsize + 1].ljust(xsize) for i in range(ysize)]
|
||||||
|
|
||||||
for i in range(ysize):
|
|
||||||
s[i] = self.fp.readline()[1 : xsize + 1].ljust(xsize)
|
|
||||||
|
|
||||||
return b"".join(s)
|
return b"".join(s)
|
||||||
|
|
||||||
|
|
|
@ -18,7 +18,7 @@ modules = {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
def check_module(feature):
|
def check_module(feature: str) -> bool:
|
||||||
"""
|
"""
|
||||||
Checks if a module is available.
|
Checks if a module is available.
|
||||||
|
|
||||||
|
@ -42,7 +42,7 @@ def check_module(feature):
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
|
||||||
def version_module(feature):
|
def version_module(feature: str) -> str | None:
|
||||||
"""
|
"""
|
||||||
:param feature: The module to check for.
|
:param feature: The module to check for.
|
||||||
:returns:
|
:returns:
|
||||||
|
@ -54,13 +54,10 @@ def version_module(feature):
|
||||||
|
|
||||||
module, ver = modules[feature]
|
module, ver = modules[feature]
|
||||||
|
|
||||||
if ver is None:
|
|
||||||
return None
|
|
||||||
|
|
||||||
return getattr(__import__(module, fromlist=[ver]), ver)
|
return getattr(__import__(module, fromlist=[ver]), ver)
|
||||||
|
|
||||||
|
|
||||||
def get_supported_modules():
|
def get_supported_modules() -> list[str]:
|
||||||
"""
|
"""
|
||||||
:returns: A list of all supported modules.
|
:returns: A list of all supported modules.
|
||||||
"""
|
"""
|
||||||
|
@ -75,7 +72,7 @@ codecs = {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
def check_codec(feature):
|
def check_codec(feature: str) -> bool:
|
||||||
"""
|
"""
|
||||||
Checks if a codec is available.
|
Checks if a codec is available.
|
||||||
|
|
||||||
|
@ -92,7 +89,7 @@ def check_codec(feature):
|
||||||
return f"{codec}_encoder" in dir(Image.core)
|
return f"{codec}_encoder" in dir(Image.core)
|
||||||
|
|
||||||
|
|
||||||
def version_codec(feature):
|
def version_codec(feature: str) -> str | None:
|
||||||
"""
|
"""
|
||||||
:param feature: The codec to check for.
|
:param feature: The codec to check for.
|
||||||
:returns:
|
:returns:
|
||||||
|
@ -113,7 +110,7 @@ def version_codec(feature):
|
||||||
return version
|
return version
|
||||||
|
|
||||||
|
|
||||||
def get_supported_codecs():
|
def get_supported_codecs() -> list[str]:
|
||||||
"""
|
"""
|
||||||
:returns: A list of all supported codecs.
|
:returns: A list of all supported codecs.
|
||||||
"""
|
"""
|
||||||
|
@ -133,7 +130,7 @@ features = {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
def check_feature(feature):
|
def check_feature(feature: str) -> bool | None:
|
||||||
"""
|
"""
|
||||||
Checks if a feature is available.
|
Checks if a feature is available.
|
||||||
|
|
||||||
|
@ -157,7 +154,7 @@ def check_feature(feature):
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
|
||||||
def version_feature(feature):
|
def version_feature(feature: str) -> str | None:
|
||||||
"""
|
"""
|
||||||
:param feature: The feature to check for.
|
:param feature: The feature to check for.
|
||||||
:returns: The version number as a string, or ``None`` if not available.
|
:returns: The version number as a string, or ``None`` if not available.
|
||||||
|
@ -174,14 +171,14 @@ def version_feature(feature):
|
||||||
return getattr(__import__(module, fromlist=[ver]), ver)
|
return getattr(__import__(module, fromlist=[ver]), ver)
|
||||||
|
|
||||||
|
|
||||||
def get_supported_features():
|
def get_supported_features() -> list[str]:
|
||||||
"""
|
"""
|
||||||
:returns: A list of all supported features.
|
:returns: A list of all supported features.
|
||||||
"""
|
"""
|
||||||
return [f for f in features if check_feature(f)]
|
return [f for f in features if check_feature(f)]
|
||||||
|
|
||||||
|
|
||||||
def check(feature):
|
def check(feature: str) -> bool | None:
|
||||||
"""
|
"""
|
||||||
:param feature: A module, codec, or feature name.
|
:param feature: A module, codec, or feature name.
|
||||||
:returns:
|
:returns:
|
||||||
|
@ -199,7 +196,7 @@ def check(feature):
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
|
||||||
def version(feature):
|
def version(feature: str) -> str | None:
|
||||||
"""
|
"""
|
||||||
:param feature:
|
:param feature:
|
||||||
The module, codec, or feature to check for.
|
The module, codec, or feature to check for.
|
||||||
|
@ -215,7 +212,7 @@ def version(feature):
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
|
||||||
def get_supported():
|
def get_supported() -> list[str]:
|
||||||
"""
|
"""
|
||||||
:returns: A list of all supported modules, features, and codecs.
|
:returns: A list of all supported modules, features, and codecs.
|
||||||
"""
|
"""
|
||||||
|
|
Loading…
Reference in New Issue
Block a user