mirror of
https://github.com/python-pillow/Pillow.git
synced 2025-01-24 16:24:11 +03:00
Added type hints
This commit is contained in:
parent
7b8a031ec1
commit
6420f73613
|
@ -2052,7 +2052,11 @@ class Image:
|
||||||
msg = "illegal image mode"
|
msg = "illegal image mode"
|
||||||
raise ValueError(msg)
|
raise ValueError(msg)
|
||||||
if isinstance(data, ImagePalette.ImagePalette):
|
if isinstance(data, ImagePalette.ImagePalette):
|
||||||
palette = ImagePalette.raw(data.rawmode, data.palette)
|
if data.rawmode is not None:
|
||||||
|
palette = ImagePalette.raw(data.rawmode, data.palette)
|
||||||
|
else:
|
||||||
|
palette = ImagePalette.ImagePalette(palette=data.palette)
|
||||||
|
palette.dirty = 1
|
||||||
else:
|
else:
|
||||||
if not isinstance(data, bytes):
|
if not isinstance(data, bytes):
|
||||||
data = bytes(data)
|
data = bytes(data)
|
||||||
|
|
|
@ -167,7 +167,7 @@ class Draw:
|
||||||
"""
|
"""
|
||||||
self.render("polygon", xy, *options)
|
self.render("polygon", xy, *options)
|
||||||
|
|
||||||
def rectangle(self, xy: Coords, *options) -> None:
|
def rectangle(self, xy: Coords, *options: Any) -> None:
|
||||||
"""
|
"""
|
||||||
Draws a rectangle.
|
Draws a rectangle.
|
||||||
|
|
||||||
|
|
|
@ -269,12 +269,12 @@ class FreeTypeFont:
|
||||||
else:
|
else:
|
||||||
load_from_bytes(font)
|
load_from_bytes(font)
|
||||||
|
|
||||||
def __getstate__(self):
|
def __getstate__(self) -> list[Any]:
|
||||||
return [self.path, self.size, self.index, self.encoding, self.layout_engine]
|
return [self.path, self.size, self.index, self.encoding, self.layout_engine]
|
||||||
|
|
||||||
def __setstate__(self, state):
|
def __setstate__(self, state: list[Any]) -> None:
|
||||||
path, size, index, encoding, layout_engine = state
|
path, size, index, encoding, layout_engine = state
|
||||||
self.__init__(path, size, index, encoding, layout_engine)
|
FreeTypeFont.__init__(self, path, size, index, encoding, layout_engine)
|
||||||
|
|
||||||
def getname(self) -> tuple[str | None, str | None]:
|
def getname(self) -> tuple[str | None, str | None]:
|
||||||
"""
|
"""
|
||||||
|
|
|
@ -208,7 +208,7 @@ class ImagePalette:
|
||||||
# Internal
|
# Internal
|
||||||
|
|
||||||
|
|
||||||
def raw(rawmode, data: Sequence[int] | bytes | bytearray) -> ImagePalette:
|
def raw(rawmode: str, data: Sequence[int] | bytes | bytearray) -> ImagePalette:
|
||||||
palette = ImagePalette()
|
palette = ImagePalette()
|
||||||
palette.rawmode = rawmode
|
palette.rawmode = rawmode
|
||||||
palette.palette = data
|
palette.palette = data
|
||||||
|
|
|
@ -324,7 +324,7 @@ class Jpeg2KImageFile(ImageFile.ImageFile):
|
||||||
return self._reduce or super().reduce
|
return self._reduce or super().reduce
|
||||||
|
|
||||||
@reduce.setter
|
@reduce.setter
|
||||||
def reduce(self, value):
|
def reduce(self, value: int) -> None:
|
||||||
self._reduce = value
|
self._reduce = value
|
||||||
|
|
||||||
def load(self) -> Image.core.PixelAccess | None:
|
def load(self) -> Image.core.PixelAccess | None:
|
||||||
|
|
|
@ -25,7 +25,7 @@ import io
|
||||||
import math
|
import math
|
||||||
import os
|
import os
|
||||||
import time
|
import time
|
||||||
from typing import IO
|
from typing import IO, Any
|
||||||
|
|
||||||
from . import Image, ImageFile, ImageSequence, PdfParser, __version__, features
|
from . import Image, ImageFile, ImageSequence, PdfParser, __version__, features
|
||||||
|
|
||||||
|
@ -48,7 +48,12 @@ def _save_all(im: Image.Image, fp: IO[bytes], filename: str | bytes) -> None:
|
||||||
# (Internal) Image save plugin for the PDF format.
|
# (Internal) Image save plugin for the PDF format.
|
||||||
|
|
||||||
|
|
||||||
def _write_image(im, filename, existing_pdf, image_refs):
|
def _write_image(
|
||||||
|
im: Image.Image,
|
||||||
|
filename: str | bytes,
|
||||||
|
existing_pdf: PdfParser.PdfParser,
|
||||||
|
image_refs: list[PdfParser.IndirectReference],
|
||||||
|
) -> tuple[PdfParser.IndirectReference, str]:
|
||||||
# FIXME: Should replace ASCIIHexDecode with RunLengthDecode
|
# FIXME: Should replace ASCIIHexDecode with RunLengthDecode
|
||||||
# (packbits) or LZWDecode (tiff/lzw compression). Note that
|
# (packbits) or LZWDecode (tiff/lzw compression). Note that
|
||||||
# PDF 1.2 also supports Flatedecode (zip compression).
|
# PDF 1.2 also supports Flatedecode (zip compression).
|
||||||
|
@ -61,10 +66,10 @@ def _write_image(im, filename, existing_pdf, image_refs):
|
||||||
|
|
||||||
width, height = im.size
|
width, height = im.size
|
||||||
|
|
||||||
dict_obj = {"BitsPerComponent": 8}
|
dict_obj: dict[str, Any] = {"BitsPerComponent": 8}
|
||||||
if im.mode == "1":
|
if im.mode == "1":
|
||||||
if features.check("libtiff"):
|
if features.check("libtiff"):
|
||||||
filter = "CCITTFaxDecode"
|
decode_filter = "CCITTFaxDecode"
|
||||||
dict_obj["BitsPerComponent"] = 1
|
dict_obj["BitsPerComponent"] = 1
|
||||||
params = PdfParser.PdfArray(
|
params = PdfParser.PdfArray(
|
||||||
[
|
[
|
||||||
|
@ -79,22 +84,23 @@ def _write_image(im, filename, existing_pdf, image_refs):
|
||||||
]
|
]
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
filter = "DCTDecode"
|
decode_filter = "DCTDecode"
|
||||||
dict_obj["ColorSpace"] = PdfParser.PdfName("DeviceGray")
|
dict_obj["ColorSpace"] = PdfParser.PdfName("DeviceGray")
|
||||||
procset = "ImageB" # grayscale
|
procset = "ImageB" # grayscale
|
||||||
elif im.mode == "L":
|
elif im.mode == "L":
|
||||||
filter = "DCTDecode"
|
decode_filter = "DCTDecode"
|
||||||
# params = f"<< /Predictor 15 /Columns {width-2} >>"
|
# params = f"<< /Predictor 15 /Columns {width-2} >>"
|
||||||
dict_obj["ColorSpace"] = PdfParser.PdfName("DeviceGray")
|
dict_obj["ColorSpace"] = PdfParser.PdfName("DeviceGray")
|
||||||
procset = "ImageB" # grayscale
|
procset = "ImageB" # grayscale
|
||||||
elif im.mode == "LA":
|
elif im.mode == "LA":
|
||||||
filter = "JPXDecode"
|
decode_filter = "JPXDecode"
|
||||||
# params = f"<< /Predictor 15 /Columns {width-2} >>"
|
# params = f"<< /Predictor 15 /Columns {width-2} >>"
|
||||||
procset = "ImageB" # grayscale
|
procset = "ImageB" # grayscale
|
||||||
dict_obj["SMaskInData"] = 1
|
dict_obj["SMaskInData"] = 1
|
||||||
elif im.mode == "P":
|
elif im.mode == "P":
|
||||||
filter = "ASCIIHexDecode"
|
decode_filter = "ASCIIHexDecode"
|
||||||
palette = im.getpalette()
|
palette = im.getpalette()
|
||||||
|
assert palette is not None
|
||||||
dict_obj["ColorSpace"] = [
|
dict_obj["ColorSpace"] = [
|
||||||
PdfParser.PdfName("Indexed"),
|
PdfParser.PdfName("Indexed"),
|
||||||
PdfParser.PdfName("DeviceRGB"),
|
PdfParser.PdfName("DeviceRGB"),
|
||||||
|
@ -110,15 +116,15 @@ def _write_image(im, filename, existing_pdf, image_refs):
|
||||||
image_ref = _write_image(smask, filename, existing_pdf, image_refs)[0]
|
image_ref = _write_image(smask, filename, existing_pdf, image_refs)[0]
|
||||||
dict_obj["SMask"] = image_ref
|
dict_obj["SMask"] = image_ref
|
||||||
elif im.mode == "RGB":
|
elif im.mode == "RGB":
|
||||||
filter = "DCTDecode"
|
decode_filter = "DCTDecode"
|
||||||
dict_obj["ColorSpace"] = PdfParser.PdfName("DeviceRGB")
|
dict_obj["ColorSpace"] = PdfParser.PdfName("DeviceRGB")
|
||||||
procset = "ImageC" # color images
|
procset = "ImageC" # color images
|
||||||
elif im.mode == "RGBA":
|
elif im.mode == "RGBA":
|
||||||
filter = "JPXDecode"
|
decode_filter = "JPXDecode"
|
||||||
procset = "ImageC" # color images
|
procset = "ImageC" # color images
|
||||||
dict_obj["SMaskInData"] = 1
|
dict_obj["SMaskInData"] = 1
|
||||||
elif im.mode == "CMYK":
|
elif im.mode == "CMYK":
|
||||||
filter = "DCTDecode"
|
decode_filter = "DCTDecode"
|
||||||
dict_obj["ColorSpace"] = PdfParser.PdfName("DeviceCMYK")
|
dict_obj["ColorSpace"] = PdfParser.PdfName("DeviceCMYK")
|
||||||
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]
|
||||||
|
@ -131,9 +137,9 @@ def _write_image(im, filename, existing_pdf, image_refs):
|
||||||
|
|
||||||
op = io.BytesIO()
|
op = io.BytesIO()
|
||||||
|
|
||||||
if filter == "ASCIIHexDecode":
|
if decode_filter == "ASCIIHexDecode":
|
||||||
ImageFile._save(im, op, [("hex", (0, 0) + im.size, 0, im.mode)])
|
ImageFile._save(im, op, [("hex", (0, 0) + im.size, 0, im.mode)])
|
||||||
elif filter == "CCITTFaxDecode":
|
elif decode_filter == "CCITTFaxDecode":
|
||||||
im.save(
|
im.save(
|
||||||
op,
|
op,
|
||||||
"TIFF",
|
"TIFF",
|
||||||
|
@ -141,21 +147,22 @@ def _write_image(im, filename, existing_pdf, image_refs):
|
||||||
# use a single strip
|
# use a single strip
|
||||||
strip_size=math.ceil(width / 8) * height,
|
strip_size=math.ceil(width / 8) * height,
|
||||||
)
|
)
|
||||||
elif filter == "DCTDecode":
|
elif decode_filter == "DCTDecode":
|
||||||
Image.SAVE["JPEG"](im, op, filename)
|
Image.SAVE["JPEG"](im, op, filename)
|
||||||
elif filter == "JPXDecode":
|
elif decode_filter == "JPXDecode":
|
||||||
del dict_obj["BitsPerComponent"]
|
del dict_obj["BitsPerComponent"]
|
||||||
Image.SAVE["JPEG2000"](im, op, filename)
|
Image.SAVE["JPEG2000"](im, op, filename)
|
||||||
else:
|
else:
|
||||||
msg = f"unsupported PDF filter ({filter})"
|
msg = f"unsupported PDF filter ({decode_filter})"
|
||||||
raise ValueError(msg)
|
raise ValueError(msg)
|
||||||
|
|
||||||
stream = op.getvalue()
|
stream = op.getvalue()
|
||||||
if filter == "CCITTFaxDecode":
|
filter: PdfParser.PdfArray | PdfParser.PdfName
|
||||||
|
if decode_filter == "CCITTFaxDecode":
|
||||||
stream = stream[8:]
|
stream = stream[8:]
|
||||||
filter = PdfParser.PdfArray([PdfParser.PdfName(filter)])
|
filter = PdfParser.PdfArray([PdfParser.PdfName(decode_filter)])
|
||||||
else:
|
else:
|
||||||
filter = PdfParser.PdfName(filter)
|
filter = PdfParser.PdfName(decode_filter)
|
||||||
|
|
||||||
image_ref = image_refs.pop(0)
|
image_ref = image_refs.pop(0)
|
||||||
existing_pdf.write_obj(
|
existing_pdf.write_obj(
|
||||||
|
|
|
@ -47,16 +47,18 @@ import math
|
||||||
import os
|
import os
|
||||||
import struct
|
import struct
|
||||||
import warnings
|
import warnings
|
||||||
from collections.abc import MutableMapping
|
from collections.abc import Iterator, MutableMapping
|
||||||
from fractions import Fraction
|
from fractions import Fraction
|
||||||
from numbers import Number, Rational
|
from numbers import Number, Rational
|
||||||
from typing import IO, TYPE_CHECKING, Any, Callable, NoReturn
|
from typing import IO, TYPE_CHECKING, Any, Callable, NoReturn, cast
|
||||||
|
|
||||||
from . import ExifTags, Image, ImageFile, ImageOps, ImagePalette, TiffTags
|
from . import ExifTags, Image, ImageFile, ImageOps, ImagePalette, TiffTags
|
||||||
from ._binary import i16be as i16
|
from ._binary import i16be as i16
|
||||||
from ._binary import i32be as i32
|
from ._binary import i32be as i32
|
||||||
from ._binary import o8
|
from ._binary import o8
|
||||||
from ._deprecate import deprecate
|
from ._deprecate import deprecate
|
||||||
|
from ._typing import StrOrBytesPath
|
||||||
|
from ._util import is_path
|
||||||
from .TiffTags import TYPES
|
from .TiffTags import TYPES
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
@ -313,7 +315,7 @@ _load_dispatch = {}
|
||||||
_write_dispatch = {}
|
_write_dispatch = {}
|
||||||
|
|
||||||
|
|
||||||
def _delegate(op):
|
def _delegate(op: str):
|
||||||
def delegate(self, *args):
|
def delegate(self, *args):
|
||||||
return getattr(self._val, op)(*args)
|
return getattr(self._val, op)(*args)
|
||||||
|
|
||||||
|
@ -334,7 +336,9 @@ class IFDRational(Rational):
|
||||||
|
|
||||||
__slots__ = ("_numerator", "_denominator", "_val")
|
__slots__ = ("_numerator", "_denominator", "_val")
|
||||||
|
|
||||||
def __init__(self, value, denominator: int = 1) -> None:
|
def __init__(
|
||||||
|
self, value: float | Fraction | IFDRational, denominator: int = 1
|
||||||
|
) -> None:
|
||||||
"""
|
"""
|
||||||
:param value: either an integer numerator, a
|
:param value: either an integer numerator, a
|
||||||
float/rational/other number, or an IFDRational
|
float/rational/other number, or an IFDRational
|
||||||
|
@ -358,18 +362,20 @@ class IFDRational(Rational):
|
||||||
self._val = float("nan")
|
self._val = float("nan")
|
||||||
elif denominator == 1:
|
elif denominator == 1:
|
||||||
self._val = Fraction(value)
|
self._val = Fraction(value)
|
||||||
|
elif int(value) == value:
|
||||||
|
self._val = Fraction(int(value), denominator)
|
||||||
else:
|
else:
|
||||||
self._val = Fraction(value, denominator)
|
self._val = Fraction(value / denominator)
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def numerator(self):
|
def numerator(self):
|
||||||
return self._numerator
|
return self._numerator
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def denominator(self):
|
def denominator(self) -> int:
|
||||||
return self._denominator
|
return self._denominator
|
||||||
|
|
||||||
def limit_rational(self, max_denominator):
|
def limit_rational(self, max_denominator: int) -> tuple[float, int]:
|
||||||
"""
|
"""
|
||||||
|
|
||||||
:param max_denominator: Integer, the maximum denominator value
|
:param max_denominator: Integer, the maximum denominator value
|
||||||
|
@ -379,6 +385,7 @@ class IFDRational(Rational):
|
||||||
if self.denominator == 0:
|
if self.denominator == 0:
|
||||||
return self.numerator, self.denominator
|
return self.numerator, self.denominator
|
||||||
|
|
||||||
|
assert isinstance(self._val, Fraction)
|
||||||
f = self._val.limit_denominator(max_denominator)
|
f = self._val.limit_denominator(max_denominator)
|
||||||
return f.numerator, f.denominator
|
return f.numerator, f.denominator
|
||||||
|
|
||||||
|
@ -396,14 +403,15 @@ class IFDRational(Rational):
|
||||||
val = float(val)
|
val = float(val)
|
||||||
return val == other
|
return val == other
|
||||||
|
|
||||||
def __getstate__(self):
|
def __getstate__(self) -> list[float | Fraction]:
|
||||||
return [self._val, self._numerator, self._denominator]
|
return [self._val, self._numerator, self._denominator]
|
||||||
|
|
||||||
def __setstate__(self, state):
|
def __setstate__(self, state: list[float | Fraction]) -> None:
|
||||||
IFDRational.__init__(self, 0)
|
IFDRational.__init__(self, 0)
|
||||||
_val, _numerator, _denominator = state
|
_val, _numerator, _denominator = state
|
||||||
self._val = _val
|
self._val = _val
|
||||||
self._numerator = _numerator
|
self._numerator = _numerator
|
||||||
|
assert isinstance(_denominator, int)
|
||||||
self._denominator = _denominator
|
self._denominator = _denominator
|
||||||
|
|
||||||
""" a = ['add','radd', 'sub', 'rsub', 'mul', 'rmul',
|
""" a = ['add','radd', 'sub', 'rsub', 'mul', 'rmul',
|
||||||
|
@ -730,13 +738,13 @@ class ImageFileDirectory_v2(_IFDv2Base):
|
||||||
self._tags_v1.pop(tag, None)
|
self._tags_v1.pop(tag, None)
|
||||||
self._tagdata.pop(tag, None)
|
self._tagdata.pop(tag, None)
|
||||||
|
|
||||||
def __iter__(self):
|
def __iter__(self) -> Iterator[int]:
|
||||||
return iter(set(self._tagdata) | set(self._tags_v2))
|
return iter(set(self._tagdata) | set(self._tags_v2))
|
||||||
|
|
||||||
def _unpack(self, fmt: str, data: bytes):
|
def _unpack(self, fmt: str, data: bytes):
|
||||||
return struct.unpack(self._endian + fmt, data)
|
return struct.unpack(self._endian + fmt, data)
|
||||||
|
|
||||||
def _pack(self, fmt: str, *values):
|
def _pack(self, fmt: str, *values) -> bytes:
|
||||||
return struct.pack(self._endian + fmt, *values)
|
return struct.pack(self._endian + fmt, *values)
|
||||||
|
|
||||||
list(
|
list(
|
||||||
|
@ -787,7 +795,7 @@ class ImageFileDirectory_v2(_IFDv2Base):
|
||||||
def load_rational(self, data, legacy_api: bool = True):
|
def load_rational(self, data, legacy_api: bool = True):
|
||||||
vals = self._unpack(f"{len(data) // 4}L", data)
|
vals = self._unpack(f"{len(data) // 4}L", data)
|
||||||
|
|
||||||
def combine(a, b):
|
def combine(a: int, b: int) -> tuple[int, int] | IFDRational:
|
||||||
return (a, b) if legacy_api else IFDRational(a, b)
|
return (a, b) if legacy_api else IFDRational(a, b)
|
||||||
|
|
||||||
return tuple(combine(num, denom) for num, denom in zip(vals[::2], vals[1::2]))
|
return tuple(combine(num, denom) for num, denom in zip(vals[::2], vals[1::2]))
|
||||||
|
@ -814,7 +822,7 @@ class ImageFileDirectory_v2(_IFDv2Base):
|
||||||
def load_signed_rational(self, data: bytes, legacy_api: bool = True):
|
def load_signed_rational(self, data: bytes, legacy_api: bool = True):
|
||||||
vals = self._unpack(f"{len(data) // 4}l", data)
|
vals = self._unpack(f"{len(data) // 4}l", data)
|
||||||
|
|
||||||
def combine(a, b):
|
def combine(a: int, b: int) -> tuple[int, int] | IFDRational:
|
||||||
return (a, b) if legacy_api else IFDRational(a, b)
|
return (a, b) if legacy_api else IFDRational(a, b)
|
||||||
|
|
||||||
return tuple(combine(num, denom) for num, denom in zip(vals[::2], vals[1::2]))
|
return tuple(combine(num, denom) for num, denom in zip(vals[::2], vals[1::2]))
|
||||||
|
@ -903,11 +911,11 @@ class ImageFileDirectory_v2(_IFDv2Base):
|
||||||
warnings.warn(str(msg))
|
warnings.warn(str(msg))
|
||||||
return
|
return
|
||||||
|
|
||||||
def tobytes(self, offset=0):
|
def tobytes(self, offset: int = 0) -> bytes:
|
||||||
# FIXME What about tagdata?
|
# FIXME What about tagdata?
|
||||||
result = self._pack("H", len(self._tags_v2))
|
result = self._pack("H", len(self._tags_v2))
|
||||||
|
|
||||||
entries = []
|
entries: list[tuple[int, int, int, bytes, bytes]] = []
|
||||||
offset = offset + len(result) + len(self._tags_v2) * 12 + 4
|
offset = offset + len(result) + len(self._tags_v2) * 12 + 4
|
||||||
stripoffsets = None
|
stripoffsets = None
|
||||||
|
|
||||||
|
@ -916,7 +924,7 @@ class ImageFileDirectory_v2(_IFDv2Base):
|
||||||
for tag, value in sorted(self._tags_v2.items()):
|
for tag, value in sorted(self._tags_v2.items()):
|
||||||
if tag == STRIPOFFSETS:
|
if tag == STRIPOFFSETS:
|
||||||
stripoffsets = len(entries)
|
stripoffsets = len(entries)
|
||||||
typ = self.tagtype.get(tag)
|
typ = self.tagtype[tag]
|
||||||
logger.debug("Tag %s, Type: %s, Value: %s", tag, typ, repr(value))
|
logger.debug("Tag %s, Type: %s, Value: %s", tag, typ, repr(value))
|
||||||
is_ifd = typ == TiffTags.LONG and isinstance(value, dict)
|
is_ifd = typ == TiffTags.LONG and isinstance(value, dict)
|
||||||
if is_ifd:
|
if is_ifd:
|
||||||
|
@ -1072,7 +1080,7 @@ class ImageFileDirectory_v1(ImageFileDirectory_v2):
|
||||||
def __len__(self) -> int:
|
def __len__(self) -> int:
|
||||||
return len(set(self._tagdata) | set(self._tags_v1))
|
return len(set(self._tagdata) | set(self._tags_v1))
|
||||||
|
|
||||||
def __iter__(self):
|
def __iter__(self) -> Iterator[int]:
|
||||||
return iter(set(self._tagdata) | set(self._tags_v1))
|
return iter(set(self._tagdata) | set(self._tags_v1))
|
||||||
|
|
||||||
def __setitem__(self, tag: int, value) -> None:
|
def __setitem__(self, tag: int, value) -> None:
|
||||||
|
@ -1943,17 +1951,18 @@ class AppendingTiffWriter:
|
||||||
521, # JPEGACTables
|
521, # JPEGACTables
|
||||||
}
|
}
|
||||||
|
|
||||||
def __init__(self, fn, new: bool = False) -> None:
|
def __init__(self, fn: StrOrBytesPath | IO[bytes], new: bool = False) -> None:
|
||||||
if hasattr(fn, "read"):
|
self.f: IO[bytes]
|
||||||
self.f = fn
|
if is_path(fn):
|
||||||
self.close_fp = False
|
|
||||||
else:
|
|
||||||
self.name = fn
|
self.name = fn
|
||||||
self.close_fp = True
|
self.close_fp = True
|
||||||
try:
|
try:
|
||||||
self.f = open(fn, "w+b" if new else "r+b")
|
self.f = open(fn, "w+b" if new else "r+b")
|
||||||
except OSError:
|
except OSError:
|
||||||
self.f = open(fn, "w+b")
|
self.f = open(fn, "w+b")
|
||||||
|
else:
|
||||||
|
self.f = cast(IO[bytes], fn)
|
||||||
|
self.close_fp = False
|
||||||
self.beginning = self.f.tell()
|
self.beginning = self.f.tell()
|
||||||
self.setup()
|
self.setup()
|
||||||
|
|
||||||
|
@ -1961,7 +1970,7 @@ class AppendingTiffWriter:
|
||||||
# Reset everything.
|
# Reset everything.
|
||||||
self.f.seek(self.beginning, os.SEEK_SET)
|
self.f.seek(self.beginning, os.SEEK_SET)
|
||||||
|
|
||||||
self.whereToWriteNewIFDOffset = None
|
self.whereToWriteNewIFDOffset: int | None = None
|
||||||
self.offsetOfNewPage = 0
|
self.offsetOfNewPage = 0
|
||||||
|
|
||||||
self.IIMM = iimm = self.f.read(4)
|
self.IIMM = iimm = self.f.read(4)
|
||||||
|
@ -2000,6 +2009,7 @@ class AppendingTiffWriter:
|
||||||
|
|
||||||
ifd_offset = self.readLong()
|
ifd_offset = self.readLong()
|
||||||
ifd_offset += self.offsetOfNewPage
|
ifd_offset += self.offsetOfNewPage
|
||||||
|
assert self.whereToWriteNewIFDOffset is not None
|
||||||
self.f.seek(self.whereToWriteNewIFDOffset)
|
self.f.seek(self.whereToWriteNewIFDOffset)
|
||||||
self.writeLong(ifd_offset)
|
self.writeLong(ifd_offset)
|
||||||
self.f.seek(ifd_offset)
|
self.f.seek(ifd_offset)
|
||||||
|
@ -2020,7 +2030,7 @@ class AppendingTiffWriter:
|
||||||
def tell(self) -> int:
|
def tell(self) -> int:
|
||||||
return self.f.tell() - self.offsetOfNewPage
|
return self.f.tell() - self.offsetOfNewPage
|
||||||
|
|
||||||
def seek(self, offset: int, whence=io.SEEK_SET) -> int:
|
def seek(self, offset: int, whence: int = io.SEEK_SET) -> int:
|
||||||
if whence == os.SEEK_SET:
|
if whence == os.SEEK_SET:
|
||||||
offset += self.offsetOfNewPage
|
offset += self.offsetOfNewPage
|
||||||
|
|
||||||
|
@ -2111,7 +2121,6 @@ class AppendingTiffWriter:
|
||||||
field_size = self.fieldSizes[field_type]
|
field_size = self.fieldSizes[field_type]
|
||||||
total_size = field_size * count
|
total_size = field_size * count
|
||||||
is_local = total_size <= 4
|
is_local = total_size <= 4
|
||||||
offset: int | None
|
|
||||||
if not is_local:
|
if not is_local:
|
||||||
offset = self.readLong() + self.offsetOfNewPage
|
offset = self.readLong() + self.offsetOfNewPage
|
||||||
self.rewriteLastLong(offset)
|
self.rewriteLastLong(offset)
|
||||||
|
@ -2131,8 +2140,6 @@ class AppendingTiffWriter:
|
||||||
)
|
)
|
||||||
self.f.seek(cur_pos)
|
self.f.seek(cur_pos)
|
||||||
|
|
||||||
offset = cur_pos = None
|
|
||||||
|
|
||||||
elif is_local:
|
elif is_local:
|
||||||
# skip the locally stored value that is not an offset
|
# skip the locally stored value that is not an offset
|
||||||
self.f.seek(4, os.SEEK_CUR)
|
self.f.seek(4, os.SEEK_CUR)
|
||||||
|
|
Loading…
Reference in New Issue
Block a user