piclets / src /lib /utils /professionalImageProcessing.ts
Fraser's picture
better bck rm
edc4c90
/**
* Professional background removal using industry-standard libraries
* This replaces the custom algorithm with proven solutions
*/
import { removeBackground as removeBackgroundLib } from '@imgly/background-removal';
// Type definitions for the background removal library
interface BackgroundRemovalConfig {
model?: 'small' | 'medium' | 'large';
output?: {
format?: string;
quality?: number;
};
debug?: boolean;
}
/**
* Remove background using AI-powered background removal
* This is the preferred method for high-quality results
*/
export async function removeBackgroundAI(imageUrl: string): Promise<string> {
try {
// Fetch the image as a blob
const response = await fetch(imageUrl);
if (!response.ok) {
throw new Error(`Failed to fetch image: ${response.statusText}`);
}
const imageBlob = await response.blob();
// Remove background using AI (using default configuration for simplicity)
const resultBlob = await removeBackgroundLib(imageBlob);
// Convert result blob to data URL
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'}`);
}
}
/**
* Simple fallback method for basic white background removal
* Use this when the AI method is not available
*/
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;
// Simple white background removal
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 pixel is close to white, make it transparent
if (r > whiteThreshold && g > whiteThreshold && b > whiteThreshold) {
data[i + 3] = 0; // Set alpha to 0
}
}
ctx.putImageData(imageData, 0, 0);
resolve(canvas.toDataURL('image/png'));
};
img.onerror = () => {
reject(new Error('Failed to load image'));
};
img.src = imageUrl;
});
}
/**
* Main function that tries AI method first, then falls back to simple method
* This provides the best results while maintaining compatibility
*/
export async function removeBackground(imageUrl: string): Promise<string> {
try {
// Try AI method first
return await removeBackgroundAI(imageUrl);
} catch (aiError) {
console.warn('AI background removal failed, falling back to simple method:', aiError);
try {
// Fallback to simple method
return await removeWhiteBackgroundSimple(imageUrl);
} catch (fallbackError) {
console.error('All background removal methods failed:', fallbackError);
throw new Error('Background removal failed with all methods');
}
}
}
/**
* Check if the AI background removal library is available
*/
export async function isAIBackgroundRemovalAvailable(): Promise<boolean> {
return true; // Library is now installed as a dependency
}
/**
* Batch process multiple images with progress callback
*/
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;
}