47 lines
1.6 KiB
Python
47 lines
1.6 KiB
Python
import logging
|
|
from pathlib import Path
|
|
|
|
from app.celery_app import celery_app
|
|
from app.core.config import settings
|
|
|
|
logger = logging.getLogger(__name__)
|
|
|
|
THUMB_SIZES = [(400, 400), (200, 200)]
|
|
|
|
|
|
@celery_app.task(bind=True, max_retries=3, default_retry_delay=10)
|
|
def generate_thumbnail(self, image_path: str):
|
|
"""Generate thumbnail variants for an uploaded image."""
|
|
try:
|
|
from PIL import Image
|
|
|
|
if settings.STORAGE_BACKEND != "local":
|
|
logger.info("Thumbnail generation skipped for non-local storage: %s", image_path)
|
|
return {"status": "skipped", "reason": "non-local storage"}
|
|
|
|
full_path = Path(settings.LOCAL_STORAGE_PATH) / image_path.lstrip("/")
|
|
if not full_path.exists():
|
|
logger.warning("Image not found: %s", full_path)
|
|
return {"status": "error", "reason": "file not found"}
|
|
|
|
results = []
|
|
img = Image.open(full_path)
|
|
if img.mode in ("RGBA", "P"):
|
|
img = img.convert("RGB")
|
|
|
|
for w, h in THUMB_SIZES:
|
|
thumb = img.copy()
|
|
thumb.thumbnail((w, h), Image.LANCZOS)
|
|
suffix = full_path.suffix or ".jpg"
|
|
thumb_name = f"{full_path.stem}_{w}x{h}{suffix}"
|
|
thumb_path = full_path.parent / thumb_name
|
|
thumb.save(str(thumb_path), quality=85, optimize=True)
|
|
results.append(str(thumb_path))
|
|
logger.info("Generated thumbnail: %s", thumb_path)
|
|
|
|
return {"status": "ok", "thumbnails": results}
|
|
|
|
except Exception as exc:
|
|
logger.exception("Thumbnail generation failed for %s", image_path)
|
|
raise self.retry(exc=exc)
|