lightweight image tools
1import Replicate from "replicate";
2
3export default {
4 async fetch(request, env, ctx) {
5 const url = new URL(request.url);
6
7 // Handle CORS preflight
8 if (request.method === "OPTIONS") {
9 return new Response(null, {
10 headers: corsHeaders(),
11 });
12 }
13
14 // Handle API routes
15 if (url.pathname === "/api/remove-bg" && request.method === "POST") {
16 return handleRemoveBg(request, env);
17 }
18
19 if (url.pathname === "/api/ic-light-background" && request.method === "POST") {
20 return handleIcLightBackground(request, env);
21 }
22
23 // For non-API routes, return 404 to let assets handle it
24 return new Response("Not Found", { status: 404 });
25 },
26};
27
28async function handleRemoveBg(request, env) {
29 try {
30 const { image, token, model } = await request.json();
31
32 if (!token) {
33 return jsonResponse({ error: "Missing token" }, 400);
34 }
35
36 if (!image) {
37 return jsonResponse({ error: "Missing image" }, 400);
38 }
39
40 const replicate = new Replicate({
41 auth: token,
42 baseUrl: "https://ai.hackclub.com/proxy/v1/replicate",
43 });
44
45 const input = { image };
46
47 // Select model based on parameter
48 const modelId = model === '851labs'
49 ? "851-labs/background-remover:a029dff38972b5fda4ec5d75d7d1cd25aeff621d2cf4946a41055d7db66b80bc"
50 : "lucataco/remove-bg:95fcc2a26d3899cd6c2691c900465aaeff466285a65c14638cc5f36f34befaf1";
51
52 const output = await replicate.run(modelId, { input });
53
54 // Handle different output formats
55 let outputUrl;
56 if (typeof output === "string") {
57 outputUrl = output;
58 } else if (output && typeof output.url === "function") {
59 outputUrl = output.url();
60 } else if (output && output.url) {
61 outputUrl = output.url;
62 } else {
63 outputUrl = output;
64 }
65
66 return jsonResponse({ output: outputUrl });
67 } catch (e) {
68 console.error("Error:", e);
69 return jsonResponse({ error: e.message }, 500);
70 }
71}
72
73async function handleIcLightBackground(request, env) {
74 try {
75 const {
76 subject_image,
77 background_image,
78 token,
79 prompt = "high quality relit image",
80 appended_prompt = "best quality",
81 negative_prompt = "lowres, bad anatomy, bad hands, cropped, worst quality",
82 width = 512,
83 height = 640,
84 steps = 25,
85 cfg = 2,
86 highres_scale = 1.5,
87 highres_denoise = 0.5,
88 light_source = "Use Background Image",
89 output_format = "png",
90 output_quality = 90
91 } = await request.json();
92
93 if (!token) {
94 return jsonResponse({ error: "Missing token" }, 400);
95 }
96
97 if (!subject_image) {
98 return jsonResponse({ error: "Missing subject_image" }, 400);
99 }
100
101 if (!background_image) {
102 return jsonResponse({ error: "Missing background_image" }, 400);
103 }
104
105 const replicate = new Replicate({
106 auth: token,
107 baseUrl: "https://ai.hackclub.com/proxy/v1/replicate",
108 });
109
110 const input = {
111 subject_image,
112 background_image,
113 prompt,
114 appended_prompt,
115 negative_prompt,
116 width,
117 height,
118 steps,
119 cfg,
120 highres_scale,
121 highres_denoise,
122 light_source,
123 output_format,
124 output_quality
125 };
126
127 const modelId = "zsxkib/ic-light-background:60015df78a8a795470da6494822982140d57b150b9ef14354e79302ff89f69e3";
128
129 const output = await replicate.run(modelId, { input });
130
131 // Handle different output formats - IC-Light returns an array
132 let outputUrl;
133 if (Array.isArray(output) && output.length > 0) {
134 outputUrl = output[0];
135 } else if (typeof output === "string") {
136 outputUrl = output;
137 } else if (output && typeof output.url === "function") {
138 outputUrl = output.url();
139 } else if (output && output.url) {
140 outputUrl = output.url;
141 } else {
142 outputUrl = output;
143 }
144
145 return jsonResponse({ output: outputUrl });
146 } catch (e) {
147 console.error("IC-Light Error:", e);
148 return jsonResponse({ error: e.message }, 500);
149 }
150}
151
152function corsHeaders() {
153 return {
154 "Access-Control-Allow-Origin": "*",
155 "Access-Control-Allow-Methods": "GET, POST, OPTIONS",
156 "Access-Control-Allow-Headers": "Content-Type",
157 };
158}
159
160function jsonResponse(data, status = 200) {
161 return new Response(JSON.stringify(data), {
162 status,
163 headers: {
164 "Content-Type": "application/json",
165 ...corsHeaders(),
166 },
167 });
168}