File size: 7,148 Bytes
e8333f6
 
 
e92cdc4
 
 
 
 
 
 
 
 
 
 
e8333f6
 
 
e92cdc4
 
e8333f6
e92cdc4
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
577a788
 
 
e92cdc4
 
 
 
 
 
 
 
 
 
 
 
 
577a788
 
e8333f6
 
4301a5c
577a788
e92cdc4
 
577a788
 
 
 
 
e92cdc4
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
76993e7
e92cdc4
76993e7
e92cdc4
 
76993e7
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
e92cdc4
76993e7
e92cdc4
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
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189

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