This commit is contained in:
Mateusz Gruszczyński committed 2026-10-23 16:06:29 +02:00
1 parent 6a821c7512
commit 594d9e1df3
5 files changed
+173 -5

No files matched your search

+14 -1
View File
@@ -10,6 +10,7 @@ import tempfile
from pathlib import Path
from PIL import Image, ImageOps, PngImagePlugin
from image_safety import DEFAULT_MAX_IMAGE_PIXELS, ImagePixelLimitExceeded, safe_image_open
class ImageOptimizationError(Exception):
@@ -43,6 +44,7 @@ def create_optimized_candidate(
min_jpeg_quality=85,
min_gain_percent=5.0,
temp_dir=None,
max_pixels=DEFAULT_MAX_IMAGE_PIXELS,
):
"""Zwraca {status,reason,before,after,width,height,quality,temp_path}.
@@ -57,7 +59,7 @@ def create_optimized_candidate(
}
temp_path = None
try:
with Image.open(path) as source:
with safe_image_open(path, max_pixels=max_pixels) as source:
fmt = source.format
ext = Path(path).suffix.lower()
if fmt not in ('JPEG', 'PNG'):
@@ -79,6 +81,13 @@ def create_optimized_candidate(
result['reason'] = 'obraz juz spelnia limity'
return result
# Duze JPEG-i dekodujemy w mozliwie mniejszej rozdzielczosci.
# JPEG draft korzysta z dekodera DCT i zapobiega alokacji
# kilkuset MB / kilku GB przy wejsciu rzedu 200 MP.
# Nie stosujemy draft do JPEG bez planowanego skalowania.
if fmt == 'JPEG' and (original_width > max_width or original_height > max_height):
source.draft(None, (max_width, max_height))
# EXIF Orientation ma znaczenie zwlaszcza dla pionowych skanow.
working = ImageOps.exif_transpose(source)
if (fmt == 'PNG' and working.mode == 'P' and
@@ -144,6 +153,10 @@ def create_optimized_candidate(
result['temp_path'] = temp_path
temp_path = None # przekazujemy plik wywolujacemu
return result
except ImagePixelLimitExceeded as exc:
result['status'] = 'skip'
result['reason'] = str(exc)
return result
except Exception as exc:
result['status'] = 'error'
result['reason'] = f'{type(exc).__name__}: {exc}'