from fastapi import APIRouter, UploadFile, File, Form from fastapi.responses import StreamingResponse, JSONResponse import io import traceback from shadow_generator import initialize_once, generate_shadow_rgba router = APIRouter() # initialize on import / startup initialize_once() @router.get("/health") async def health(): return {"ok": True} @router.get("/params") async def params_info(): return { "angle_deg": "float. 0 = right, 90 = down. default 135.0", "distance": "float px offset of shadow. default 40.0", "softness": "float blur radius. default 25.0", "opacity": "float 0..1. default 0.7", "color": "hex color for shadow. default '#000000'", "spread": "float px. positive expands alpha, negative contracts. default 0.0", "shadow_type": "string. 'drop' or 'contact'. default 'drop'", } @router.post("/generate-shadow") async def generate_shadow_endpoint( image: UploadFile = File(..., description="RGBA PNG with transparent background"), angle_deg: float = Form(135.0), distance: float = Form(40.0), softness: float = Form(25.0), opacity: float = Form(0.7), color: str = Form("#000000"), spread: float = Form(0.0), shadow_type: str = Form("drop"), use_ssn: bool = Form(True) ): """ Returns: PNG (RGBA) bytes stream containing object + generated shadow. """ try: data = await image.read() params = { "angle_deg": angle_deg, "distance": distance, "softness": softness, "opacity": opacity, "color": color, "spread": spread, "shadow_type": shadow_type, "prefer_ssn": use_ssn } out_bytes = generate_shadow_rgba(data, params=params) return StreamingResponse(io.BytesIO(out_bytes), media_type="image/png") except Exception as exc: traceback.print_exc() return JSONResponse(status_code=500, content={"error": str(exc)})