fixes
This commit is contained in:
1 parent
6a821c7512
commit
594d9e1df3
5 files changed
+173
-5
No files matched your search
@@ -0,0 +1,58 @@
|
||||
"""Ograniczona obsluga duzych obrazow Pillow.
|
||||
|
||||
Pillow domyslnie ostrzega powyzej ~89 MP i zglasza blad powyzej ~179 MP.
|
||||
Dla skanow dopuszczamy konfigurowalny limit, ale PRZED dekodowaniem
|
||||
odrzucamy wszystko, co ten limit przekracza. Nie wylaczamy ochrony globalnie.
|
||||
|
||||
Narzędzie CLI wykonuje operacje obrazow sekwencyjnie; prog PIL jest globalny,
|
||||
ale zmieniamy go tylko na czas kontrolowanego otwarcia i przywracamy po nim.
|
||||
"""
|
||||
from __future__ import annotations
|
||||
|
||||
import warnings
|
||||
from contextlib import contextmanager
|
||||
|
||||
from PIL import Image
|
||||
|
||||
|
||||
DEFAULT_MAX_IMAGE_PIXELS = 220_000_000 # 220 MP; obejmuje skany ~200 MP
|
||||
|
||||
|
||||
class ImagePixelLimitExceeded(ValueError):
|
||||
"""Obraz nie zostal zdekodowany, bo przekracza ustalony limit."""
|
||||
|
||||
|
||||
@contextmanager
|
||||
def safe_image_open(path, *, max_pixels=DEFAULT_MAX_IMAGE_PIXELS, check_pixels=True):
|
||||
"""Otworz naglowek obrazu z limitem, zanim Pillow zdekoduje piksele.
|
||||
|
||||
Ostrzezenie Pillow dot. progu zostaje zastapione JAWNYM sprawdzeniem
|
||||
wielkosci (i statusem SKIP w callerze). Pozostale ostrzezenia pozostaja
|
||||
widoczne. Dla samego odczytu wymiarow check_pixels=False nie dekoduje.
|
||||
"""
|
||||
max_pixels = int(max_pixels)
|
||||
if max_pixels <= 0:
|
||||
raise ValueError('max_pixels musi byc wieksze od zera')
|
||||
old_limit = Image.MAX_IMAGE_PIXELS
|
||||
with warnings.catch_warnings():
|
||||
warnings.filterwarnings('ignore', category=Image.DecompressionBombWarning)
|
||||
Image.MAX_IMAGE_PIXELS = max_pixels
|
||||
try:
|
||||
try:
|
||||
with Image.open(path) as image:
|
||||
pixels = image.width * image.height
|
||||
if check_pixels and pixels > max_pixels:
|
||||
raise ImagePixelLimitExceeded(
|
||||
f'{image.width}x{image.height} ({pixels / 1_000_000:.1f} MP) '
|
||||
f'przekracza --max-image-mpixels={max_pixels / 1_000_000:g}; '
|
||||
'pominieto dla ochrony pamieci RAM'
|
||||
)
|
||||
yield image
|
||||
except Image.DecompressionBombError as exc:
|
||||
# Bardzo duze obrazy Pillow moze odrzucic juz przy Image.open.
|
||||
raise ImagePixelLimitExceeded(
|
||||
f'Pillow odrzucil obraz przekraczajacy limit '
|
||||
f'--max-image-mpixels={max_pixels / 1_000_000:g}: {exc}'
|
||||
) from exc
|
||||
finally:
|
||||
Image.MAX_IMAGE_PIXELS = old_limit
|
||||
Reference in new issue
Block a user