Reparatur der venv.

This commit is contained in:
2024-07-15 11:11:46 +02:00
parent a7955bc775
commit bfe8d4c2a7
203 changed files with 2375 additions and 1588 deletions

View File

@@ -42,6 +42,7 @@ import subprocess
import sys
import tempfile
import warnings
from typing import IO, Any
from . import Image, ImageFile
from ._binary import i16be as i16
@@ -54,7 +55,7 @@ from .JpegPresets import presets
# Parser
def Skip(self, marker):
def Skip(self: JpegImageFile, marker: int) -> None:
n = i16(self.fp.read(2)) - 2
ImageFile._safe_read(self.fp, n)
@@ -94,6 +95,8 @@ def APP(self, marker):
else:
self.info["exif"] = s
self._exif_offset = self.fp.tell() - n + 6
elif marker == 0xFFE1 and s[:29] == b"http://ns.adobe.com/xap/1.0/\x00":
self.info["xmp"] = s.split(b"\x00", 1)[1]
elif marker == 0xFFE2 and s[:5] == b"FPXR\0":
# extract FlashPix information (incomplete)
self.info["flashpix"] = s # FIXME: value will change
@@ -158,40 +161,8 @@ def APP(self, marker):
# plus constant header size
self.info["mpoffset"] = self.fp.tell() - n + 4
# If DPI isn't in JPEG header, fetch from EXIF
if "dpi" not in self.info and "exif" in self.info:
try:
exif = self.getexif()
resolution_unit = exif[0x0128]
x_resolution = exif[0x011A]
try:
dpi = float(x_resolution[0]) / x_resolution[1]
except TypeError:
dpi = x_resolution
if math.isnan(dpi):
msg = "DPI is not a number"
raise ValueError(msg)
if resolution_unit == 3: # cm
# 1 dpcm = 2.54 dpi
dpi *= 2.54
self.info["dpi"] = dpi, dpi
except (
struct.error,
KeyError,
SyntaxError,
TypeError,
ValueError,
ZeroDivisionError,
):
# struct.error for truncated EXIF
# KeyError for dpi not included
# SyntaxError for invalid/unreadable EXIF
# ValueError or TypeError for dpi being an invalid float
# ZeroDivisionError for invalid dpi rational value
self.info["dpi"] = 72, 72
def COM(self, marker):
def COM(self: JpegImageFile, marker: int) -> None:
#
# Comment marker. Store these in the APP dictionary.
n = i16(self.fp.read(2)) - 2
@@ -202,7 +173,7 @@ def COM(self, marker):
self.applist.append(("COM", s))
def SOF(self, marker):
def SOF(self: JpegImageFile, marker: int) -> None:
#
# Start of frame marker. Defines the size and mode of the
# image. JPEG is colour blind, so we use some simple
@@ -250,7 +221,7 @@ def SOF(self, marker):
self.layer.append((t[0], t[1] // 16, t[1] & 15, t[2]))
def DQT(self, marker):
def DQT(self: JpegImageFile, marker: int) -> None:
#
# Define quantization table. Note that there might be more
# than one table in each marker.
@@ -344,7 +315,7 @@ MARKER = {
}
def _accept(prefix):
def _accept(prefix: bytes) -> bool:
# Magic number was taken from https://en.wikipedia.org/wiki/JPEG
return prefix[:3] == b"\xFF\xD8\xFF"
@@ -408,7 +379,9 @@ class JpegImageFile(ImageFile.ImageFile):
msg = "no marker found"
raise SyntaxError(msg)
def load_read(self, read_bytes):
self._read_dpi_from_exif()
def load_read(self, read_bytes: int) -> bytes:
"""
internal: read more image data
For premature EOF and LOAD_TRUNCATED_IMAGES adds EOI marker
@@ -424,13 +397,15 @@ class JpegImageFile(ImageFile.ImageFile):
return s
def draft(self, mode, size):
def draft(
self, mode: str | None, size: tuple[int, int] | None
) -> tuple[str, tuple[int, int, float, float]] | None:
if len(self.tile) != 1:
return
return None
# Protect from second call
if self.decoderconfig:
return
return None
d, e, o, a = self.tile[0]
scale = 1
@@ -460,7 +435,7 @@ class JpegImageFile(ImageFile.ImageFile):
box = (0, 0, original_size[0] / scale, original_size[1] / scale)
return self.mode, box
def load_djpeg(self):
def load_djpeg(self) -> None:
# ALTERNATIVE: handle JPEGs via the IJG command line utilities
f, path = tempfile.mkstemp()
@@ -491,29 +466,43 @@ class JpegImageFile(ImageFile.ImageFile):
self.tile = []
def _getexif(self):
def _getexif(self) -> dict[str, Any] | None:
return _getexif(self)
def _read_dpi_from_exif(self) -> None:
# If DPI isn't in JPEG header, fetch from EXIF
if "dpi" in self.info or "exif" not in self.info:
return
try:
exif = self.getexif()
resolution_unit = exif[0x0128]
x_resolution = exif[0x011A]
try:
dpi = float(x_resolution[0]) / x_resolution[1]
except TypeError:
dpi = x_resolution
if math.isnan(dpi):
msg = "DPI is not a number"
raise ValueError(msg)
if resolution_unit == 3: # cm
# 1 dpcm = 2.54 dpi
dpi *= 2.54
self.info["dpi"] = dpi, dpi
except (
struct.error, # truncated EXIF
KeyError, # dpi not included
SyntaxError, # invalid/unreadable EXIF
TypeError, # dpi is an invalid float
ValueError, # dpi is an invalid float
ZeroDivisionError, # invalid dpi rational value
):
self.info["dpi"] = 72, 72
def _getmp(self):
return _getmp(self)
def getxmp(self):
"""
Returns a dictionary containing the XMP tags.
Requires defusedxml to be installed.
:returns: XMP tags in a dictionary.
"""
for segment, content in self.applist:
if segment == "APP1":
marker, xmp_tags = content.split(b"\x00")[:2]
if marker == b"http://ns.adobe.com/xap/1.0/":
return self._getxmp(xmp_tags)
return {}
def _getexif(self):
def _getexif(self) -> dict[str, Any] | None:
if "exif" not in self.info:
return None
return self.getexif()._get_merged_dict()
@@ -641,7 +630,7 @@ def get_sampling(im):
return samplings.get(sampling, -1)
def _save(im, fp, filename):
def _save(im: Image.Image, fp: IO[bytes], filename: str | bytes) -> None:
if im.width == 0 or im.height == 0:
msg = "cannot write empty image as JPEG"
raise ValueError(msg)
@@ -824,7 +813,7 @@ def _save(im, fp, filename):
ImageFile._save(im, fp, [("jpeg", (0, 0) + im.size, 0, rawmode)], bufsize)
def _save_cjpeg(im, fp, filename):
def _save_cjpeg(im: Image.Image, fp: IO[bytes], filename: str | bytes) -> None:
# ALTERNATIVE: handle JPEGs via the IJG command line utilities.
tempfile = im._dump()
subprocess.check_call(["cjpeg", "-outfile", filename, tempfile])
@@ -841,6 +830,10 @@ def jpeg_factory(fp=None, filename=None):
try:
mpheader = im._getmp()
if mpheader[45057] > 1:
for segment, content in im.applist:
if segment == "APP1" and b' hdrgm:Version="' in content:
# Ultra HDR images are not yet supported
return im
# It's actually an MPO
from .MpoImagePlugin import MpoImageFile