Update engine.py

This commit is contained in:
2026-01-20 12:35:01 +01:00
parent 8528ea73bf
commit 77aaae6491

View File

@@ -1,10 +1,7 @@
import os
import shutil
import sqlite3
import threading
import hashlib
from contextlib import contextmanager
from functools import lru_cache
from PIL import Image
from io import BytesIO
from typing import Dict, List, Optional, Tuple
@@ -285,33 +282,12 @@ class SorterEngine:
return fid
# ==========================================
# IMAGE COMPRESSION (OPTIMIZED WITH CACHING)
# IMAGE COMPRESSION
# ==========================================
# Simple in-memory cache for thumbnails
_thumbnail_cache: Dict[str, bytes] = {}
_cache_max_items = 500
_cache_lock = threading.Lock()
@classmethod
def _get_cache_key(cls, path: str, quality: int, target_size: Optional[int]) -> str:
"""Generate cache key including file modification time."""
try:
mtime = os.path.getmtime(path)
except OSError:
mtime = 0
return hashlib.md5(f"{path}:{quality}:{target_size}:{mtime}".encode()).hexdigest()
@classmethod
def compress_for_web(cls, path: str, quality: int, target_size: Optional[int] = None) -> Optional[bytes]:
"""Loads image, resizes smart, and saves as WebP with caching."""
cache_key = cls._get_cache_key(path, quality, target_size)
# Check cache first
with cls._cache_lock:
if cache_key in cls._thumbnail_cache:
return cls._thumbnail_cache[cache_key]
"""Loads image, resizes smart, and saves as WebP."""
try:
with Image.open(path) as img:
# Keep RGBA for WebP support, only convert unusual modes
@@ -326,19 +302,8 @@ class SorterEngine:
# Save as WebP
buf = BytesIO()
img.save(buf, format="WEBP", quality=quality, method=4) # method=4 is faster
result = buf.getvalue()
# Cache the result
with cls._cache_lock:
if len(cls._thumbnail_cache) >= cls._cache_max_items:
# Simple eviction: remove oldest 20%
keys_to_remove = list(cls._thumbnail_cache.keys())[:cls._cache_max_items // 5]
for k in keys_to_remove:
del cls._thumbnail_cache[k]
cls._thumbnail_cache[cache_key] = result
return result
img.save(buf, format="WEBP", quality=quality)
return buf.getvalue()
except Exception:
return None
@@ -350,7 +315,8 @@ class SorterEngine:
def process_one(path):
return path, SorterEngine.compress_for_web(path, quality)
with concurrent.futures.ThreadPoolExecutor(max_workers=8) as executor:
# Reduced from 8 to 2 workers to prevent memory issues
with concurrent.futures.ThreadPoolExecutor(max_workers=2) as executor:
future_to_path = {executor.submit(process_one, p): p for p in image_paths}
for future in concurrent.futures.as_completed(future_to_path):
try: