lightweight image tools

feat: allow choosing model

dunkirk.sh 95e1c87d d8175cbf

verified
+40 -8
+33 -3
public/index.html
··· 83 83 display: inline-block; 84 84 border-radius: 4px; 85 85 } 86 - #previewCanvas { max-width: 100%; max-height: 500px; } 86 + #previewCanvas { max-width: 100%; max-height: 500px; display: block; } 87 87 88 88 /* Crop mode */ 89 89 #cropMode { ··· 198 198 <button onclick="startCrop()" id="cropBtn">Crop</button> 199 199 </div> 200 200 <div class="toolbar-group"> 201 + <label> 202 + Model: 203 + <select id="bgRemoverModel"> 204 + <option value="lucataco">Lucataco (default)</option> 205 + <option value="851labs">851-labs</option> 206 + </select> 207 + </label> 201 208 <button onclick="removeBg()" id="removeBgBtn">Remove BG</button> 202 209 </div> 203 210 <div class="toolbar-group"> ··· 221 228 <input type="number" id="maxDimension" value="2048" min="100" max="8192" style="width: 70px;"> 222 229 px 223 230 </label> 231 + <label style="font-size: 0.75rem; color: #999;">(scales down only)</label> 224 232 <button onclick="optimizeImage()">Optimize</button> 225 233 </div> 226 234 <div class="toolbar-group"> ··· 372 380 function updatePreview() { 373 381 if (!currentImage) return; 374 382 383 + // Calculate dimensions to fit the screen while maintaining aspect ratio 384 + const maxDisplayWidth = Math.min(700, window.innerWidth - 80); 385 + const maxDisplayHeight = 500; 386 + const imgAspect = currentImage.width / currentImage.height; 387 + const maxAspect = maxDisplayWidth / maxDisplayHeight; 388 + 389 + let displayWidth, displayHeight; 390 + if (imgAspect > maxAspect) { 391 + displayWidth = Math.min(currentImage.width, maxDisplayWidth); 392 + displayHeight = displayWidth / imgAspect; 393 + } else { 394 + displayHeight = Math.min(currentImage.height, maxDisplayHeight); 395 + displayWidth = displayHeight * imgAspect; 396 + } 397 + 375 398 const ctx = previewCanvas.getContext('2d'); 376 399 previewCanvas.width = currentImage.width; 377 400 previewCanvas.height = currentImage.height; 401 + previewCanvas.style.width = displayWidth + 'px'; 402 + previewCanvas.style.height = displayHeight + 'px'; 378 403 379 404 ctx.clearRect(0, 0, previewCanvas.width, previewCanvas.height); 380 405 ··· 610 635 tempCanvas.getContext('2d').drawImage(currentImage, 0, 0); 611 636 const dataUrl = tempCanvas.toDataURL('image/png'); 612 637 638 + // Get selected model 639 + const selectedModel = document.getElementById('bgRemoverModel').value; 640 + 613 641 try { 614 642 const res = await fetch('/api/remove-bg', { 615 643 method: 'POST', 616 644 headers: { 'Content-Type': 'application/json' }, 617 - body: JSON.stringify({ image: dataUrl, token: tk }) 645 + body: JSON.stringify({ image: dataUrl, token: tk, model: selectedModel }) 618 646 }); 619 647 const data = await res.json(); 620 648 if (!res.ok) throw new Error(typeof data.error === 'string' ? data.error : JSON.stringify(data.error)); ··· 703 731 const quality = document.getElementById('optimizeQuality').value / 100; 704 732 const maxDim = parseInt(document.getElementById('maxDimension').value) || 2048; 705 733 706 - // Calculate new dimensions (maintain aspect ratio) 734 + // Calculate new dimensions (only scale down if larger than maxDim) 707 735 let newW = currentImage.width; 708 736 let newH = currentImage.height; 709 737 738 + // Only resize if image exceeds maxDim 710 739 if (newW > maxDim || newH > maxDim) { 711 740 if (newW > newH) { 712 741 newH = Math.round(newH * (maxDim / newW)); ··· 716 745 newH = maxDim; 717 746 } 718 747 } 748 + // If image is already smaller than maxDim, keep original dimensions 719 749 720 750 // Create optimized canvas 721 751 const tempCanvas = document.createElement('canvas');
+7 -5
src/index.js
··· 23 23 24 24 async function handleRemoveBg(request, env) { 25 25 try { 26 - const { image, token } = await request.json(); 26 + const { image, token, model } = await request.json(); 27 27 28 28 if (!token) { 29 29 return jsonResponse({ error: "Missing token" }, 400); ··· 40 40 41 41 const input = { image }; 42 42 43 - const output = await replicate.run( 44 - "lucataco/remove-bg:95fcc2a26d3899cd6c2691c900465aaeff466285a65c14638cc5f36f34befaf1", 45 - { input } 46 - ); 43 + // Select model based on parameter 44 + const modelId = model === '851labs' 45 + ? "851-labs/background-remover:a029dff38972b5fda4ec5d75d7d1cd25aeff621d2cf4946a41055d7db66b80bc" 46 + : "lucataco/remove-bg:95fcc2a26d3899cd6c2691c900465aaeff466285a65c14638cc5f36f34befaf1"; 47 + 48 + const output = await replicate.run(modelId, { input }); 47 49 48 50 // Handle different output formats 49 51 let outputUrl;