File size: 4,382 Bytes
3470f3e
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
968d5e5
 
 
 
 
3470f3e
968d5e5
 
 
3470f3e
 
 
 
 
 
 
 
968d5e5
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
3470f3e
 
 
 
 
 
968d5e5
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
# 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)})


from fastapi import APIRouter, UploadFile, File, Form
from fastapi.responses import StreamingResponse, JSONResponse
import io
import traceback

from shadow_generator import load_ssn_once, generate_shadow_rgba

router = APIRouter()

# Lazy initialization placeholder
_ssn_wrapper = None

def get_ssn_wrapper():
    global _ssn_wrapper
    if _ssn_wrapper is None:
        _ssn_wrapper = load_ssn_once()
    return _ssn_wrapper

@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)
):
    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
        }

        # Lazy load SSN model
        ssn = get_ssn_wrapper()
        if not ssn.available():
            return JSONResponse(status_code=503, content={"error": "SSN model is still loading. Try again shortly."})

        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)})