| |
| |
| |
| |
|
|
| import { removeBackground as removeBackgroundLib } from '@imgly/background-removal'; |
|
|
| |
| interface BackgroundRemovalConfig { |
| model?: 'small' | 'medium' | 'large'; |
| output?: { |
| format?: string; |
| quality?: number; |
| }; |
| debug?: boolean; |
| } |
|
|
| |
| |
| |
| |
| export async function removeBackgroundAI(imageUrl: string): Promise<string> { |
| try { |
| |
| const response = await fetch(imageUrl); |
| if (!response.ok) { |
| throw new Error(`Failed to fetch image: ${response.statusText}`); |
| } |
| const imageBlob = await response.blob(); |
| |
| |
| const resultBlob = await removeBackgroundLib(imageBlob); |
| |
| |
| return new Promise((resolve, reject) => { |
| const reader = new FileReader(); |
| reader.onload = () => resolve(reader.result as string); |
| reader.onerror = () => reject(new Error('Failed to convert result to data URL')); |
| reader.readAsDataURL(resultBlob); |
| }); |
| |
| } catch (error) { |
| console.error('AI background removal failed:', error); |
| throw new Error(`Background removal failed: ${error instanceof Error ? error.message : 'Unknown error'}`); |
| } |
| } |
|
|
| |
| |
| |
| |
| export async function removeWhiteBackgroundSimple(imageUrl: string): Promise<string> { |
| return new Promise((resolve, reject) => { |
| const img = new Image(); |
| img.crossOrigin = 'anonymous'; |
| |
| img.onload = () => { |
| const canvas = document.createElement('canvas'); |
| const ctx = canvas.getContext('2d'); |
| |
| if (!ctx) { |
| reject(new Error('Failed to get canvas context')); |
| return; |
| } |
| |
| canvas.width = img.width; |
| canvas.height = img.height; |
| ctx.drawImage(img, 0, 0); |
| |
| const imageData = ctx.getImageData(0, 0, canvas.width, canvas.height); |
| const data = imageData.data; |
| |
| |
| const whiteThreshold = 240; |
| for (let i = 0; i < data.length; i += 4) { |
| const r = data[i]; |
| const g = data[i + 1]; |
| const b = data[i + 2]; |
| |
| |
| if (r > whiteThreshold && g > whiteThreshold && b > whiteThreshold) { |
| data[i + 3] = 0; |
| } |
| } |
| |
| ctx.putImageData(imageData, 0, 0); |
| resolve(canvas.toDataURL('image/png')); |
| }; |
| |
| img.onerror = () => { |
| reject(new Error('Failed to load image')); |
| }; |
| |
| img.src = imageUrl; |
| }); |
| } |
|
|
| |
| |
| |
| |
| export async function removeBackground(imageUrl: string): Promise<string> { |
| try { |
| |
| return await removeBackgroundAI(imageUrl); |
| } catch (aiError) { |
| console.warn('AI background removal failed, falling back to simple method:', aiError); |
| |
| try { |
| |
| return await removeWhiteBackgroundSimple(imageUrl); |
| } catch (fallbackError) { |
| console.error('All background removal methods failed:', fallbackError); |
| throw new Error('Background removal failed with all methods'); |
| } |
| } |
| } |
|
|
| |
| |
| |
| export async function isAIBackgroundRemovalAvailable(): Promise<boolean> { |
| return true; |
| } |
|
|
| |
| |
| |
| export async function removeBackgroundBatch( |
| imageUrls: string[], |
| onProgress?: (completed: number, total: number, currentImage: string) => void |
| ): Promise<{ url: string; result?: string; error?: string }[]> { |
| const results: { url: string; result?: string; error?: string }[] = []; |
| |
| for (let i = 0; i < imageUrls.length; i++) { |
| const imageUrl = imageUrls[i]; |
| |
| try { |
| const result = await removeBackground(imageUrl); |
| results.push({ url: imageUrl, result }); |
| } catch (error) { |
| const errorMessage = error instanceof Error ? error.message : 'Unknown error'; |
| results.push({ url: imageUrl, error: errorMessage }); |
| } |
| |
| if (onProgress) { |
| onProgress(i + 1, imageUrls.length, imageUrl); |
| } |
| } |
| |
| return results; |
| } |