import { removeBackground } from "https://cdn.jsdelivr.net/npm/@imgly/background-removal@1.0.0/dist/index.mjs"; document.addEventListener('DOMContentLoaded', () => { const dropArea = document.getElementById('drop-area'); const fileInput = document.getElementById('file-input'); const browseBtn = document.getElementById('browse-btn'); const uploadUI = document.getElementById('upload-ui'); const processingUI = document.getElementById('processing-ui'); const originalImage = document.getElementById('original-image'); const resultImage = document.getElementById('result-image'); const downloadBtn = document.getElementById('download-btn'); const downloadSection = document.getElementById('download-section'); const progressText = document.getElementById('progress-text'); const progressBar = document.getElementById('progress-bar'); const firstRunNotice = document.getElementById('first-run-notice'); let isFirstRun = true; let processing = false; let currentFile = null; // Prevent default drag behaviors ['dragenter', 'dragover', 'dragleave', 'drop'].forEach(eventName => { dropArea.addEventListener(eventName, preventDefaults, false); }); function preventDefaults(e) { e.preventDefault(); e.stopPropagation(); } // Highlight drop area when item is dragged over it ['dragenter', 'dragover'].forEach(eventName => { dropArea.addEventListener(eventName, highlight, false); }); ['dragleave', 'drop'].forEach(eventName => { dropArea.addEventListener(eventName, unhighlight, false); }); function highlight() { dropArea.classList.add('highlight'); } function unhighlight() { dropArea.classList.remove('highlight'); } // Handle dropped files dropArea.addEventListener('drop', handleDrop, false); function handleDrop(e) { const dt = e.dataTransfer; const files = dt.files; if (files.length && !processing) { handleFiles(files); } } // Handle file input fileInput.addEventListener('change', function() { if (this.files.length && !processing) { handleFiles(this.files); } }); // Browse button click browseBtn.addEventListener('click', () => { fileInput.click(); }); // Handle file processing async function handleFiles(files) { const file = files[0]; if (!file.type.match('image.*')) { alert('Please select an image file'); return; } currentFile = file; processing = true; // Show original image const reader = new FileReader(); reader.onload = function(e) { originalImage.src = e.target.result; originalImage.classList.remove('hidden'); }; reader.readAsDataURL(file); // Show processing UI uploadUI.classList.add('hidden'); processingUI.classList.remove('hidden'); if (isFirstRun) { progressText.textContent = 'Loading models for the first time (20-40MB)...'; progressBar.style.width = '10%'; } else { progressText.textContent = 'Processing image...'; progressBar.style.width = '30%'; } try { // Initialize the background removal const blobURL = URL.createObjectURL(file); // Revoke the blob URL after use to prevent memory leaks setTimeout(() => URL.revokeObjectURL(blobURL), 1000); const progressCallback = (progress) => { const percent = Math.floor(progress * 100); progressBar.style.width = `${percent}%`; if (isFirstRun) { if (progress < 0.9) { progressText.textContent = `Downloading models... ${percent}%`; } else { progressText.textContent = 'Processing image...'; } } else { progressText.textContent = `Processing... ${percent}%`; } }; // Convert file to Blob URL const blob = await fetch(blobURL).then(r => r.blob()); // Use the imported removeBackground function const result = await removeBackground(blob, { progress: progressCallback, publicPath: 'https://cdn.jsdelivr.net/npm/@imgly/background-removal@1.0.0/dist/', // Required for loading models debug: true }); // Convert Blob to URL for display // Convert result to PNG if it's not already const pngBlob = await result.convertToBlob('image/png'); const resultURL = URL.createObjectURL(pngBlob); // Display result resultImage.src = resultURL; resultImage.classList.remove('hidden'); // Enable download button downloadBtn.onclick = function() { const a = document.createElement('a'); a.href = resultURL; a.download = `background-removed-${file.name}`; document.body.appendChild(a); a.click(); document.body.removeChild(a); setTimeout(() => URL.revokeObjectURL(resultURL), 100); }; downloadSection.classList.remove('hidden'); // Reset UI processing = false; uploadUI.classList.remove('hidden'); processingUI.classList.add('hidden'); if (isFirstRun) { isFirstRun = false; firstRunNotice.classList.add('hidden'); } } catch (error) { console.error('Error during background removal:', error); // Show error message progressText.textContent = `Error: ${error.message || 'Failed to process image'}`; progressBar.style.width = '0%'; progressBar.classList.add('bg-red-500'); // Show retry button const retryBtn = document.createElement('button'); retryBtn.className = 'bg-primary-500 hover:bg-primary-600 text-white font-medium py-2 px-6 rounded-lg transition-colors duration-200 mt-4'; retryBtn.textContent = 'Try Again'; retryBtn.onclick = () => { if (currentFile) { handleFiles([currentFile]); } }; processingUI.querySelector('.flex').appendChild(retryBtn); setTimeout(() => { // Reset UI if user doesn't retry processing = false; uploadUI.classList.remove('hidden'); processingUI.classList.add('hidden'); progressBar.classList.remove('bg-red-500'); if (processingUI.contains(retryBtn)) { processingUI.querySelector('.flex').removeChild(retryBtn); } }, 8000); } } });