from pathlib import Path from fastapi import UploadFile, HTTPException from PIL import Image, UnidentifiedImageError from io import BytesIO from app.config import ALLOWED_IMAGE_EXTENSIONS, SUPPORTED_CROPS def validate_crop(crop: str) -> str: crop = crop.lower().strip() if crop not in SUPPORTED_CROPS: raise HTTPException( status_code=400, detail=f"Unsupported crop '{crop}'. Supported crops: {SUPPORTED_CROPS}", ) return crop async def read_image_file(file: UploadFile) -> Image.Image: filename = file.filename or "" extension = Path(filename).suffix.lower() if extension not in ALLOWED_IMAGE_EXTENSIONS: raise HTTPException( status_code=400, detail=f"Unsupported image type '{extension}'. Allowed: {sorted(ALLOWED_IMAGE_EXTENSIONS)}", ) content = await file.read() if not content: raise HTTPException(status_code=400, detail="Uploaded image is empty.") try: image = Image.open(BytesIO(content)).convert("RGB") return image except UnidentifiedImageError: raise HTTPException(status_code=400, detail="Uploaded file is not a valid image.")