81 lines
2.5 KiB
TypeScript
81 lines
2.5 KiB
TypeScript
import imageCompression from 'browser-image-compression';
|
|
|
|
/**
|
|
* Interface for the processed image result
|
|
*/
|
|
export interface ProcessedImage {
|
|
file: File; // The compressed WebP file (ready for Supabase storage)
|
|
base64: string; // The Base64 string (ready for LLM API calls)
|
|
originalFile: File; // Pass through the original file
|
|
}
|
|
|
|
/**
|
|
* Converts a File or Blob object to a Base64 string.
|
|
*
|
|
* @param file - The file or blob to convert
|
|
* @returns A promise that resolves to the Base64 string
|
|
*/
|
|
export function fileToBase64(file: File | Blob): Promise<string> {
|
|
return new Promise((resolve, reject) => {
|
|
const reader = new FileReader();
|
|
reader.onload = () => {
|
|
if (typeof reader.result === 'string') {
|
|
resolve(reader.result);
|
|
} else {
|
|
reject(new Error('Failed to convert file to Base64 string'));
|
|
}
|
|
};
|
|
reader.onerror = (error) => reject(error);
|
|
reader.readAsDataURL(file);
|
|
});
|
|
}
|
|
|
|
/**
|
|
* Processes an image file for AI analysis and storage.
|
|
*
|
|
* Logic:
|
|
* 1. Resize to max 1024x1024 (maintains aspect ratio)
|
|
* 2. Convert to WebP format
|
|
* 3. Limit file size to approx 0.4MB
|
|
* 4. Uses WebWorker to prevent UI freezing
|
|
*
|
|
* @param file - The raw File object from an HTML input
|
|
* @returns A promise that resolves to a ProcessedImage object
|
|
*/
|
|
export async function processImageForAI(file: File): Promise<ProcessedImage> {
|
|
const options = {
|
|
maxSizeMB: 0.4,
|
|
maxWidthOrHeight: 1024,
|
|
useWebWorker: true,
|
|
fileType: 'image/webp'
|
|
};
|
|
|
|
try {
|
|
console.log(`[processImageForAI] Original size: ${(file.size / 1024 / 1024).toFixed(2)} MB`);
|
|
|
|
// Compress the image
|
|
const compressedBlob = await imageCompression(file, options);
|
|
|
|
// Create a new File object from the compressed Blob with .webp extension
|
|
const compressedFile = new File(
|
|
[compressedBlob],
|
|
file.name.replace(/\.[^/.]+$/, "") + ".webp",
|
|
{ type: 'image/webp' }
|
|
);
|
|
|
|
console.log(`[processImageForAI] Compressed size: ${(compressedFile.size / 1024 / 1024).toFixed(2)} MB`);
|
|
|
|
// Convert to Base64 for AI API calls
|
|
const base64 = await fileToBase64(compressedFile);
|
|
|
|
return {
|
|
file: compressedFile,
|
|
base64,
|
|
originalFile: file
|
|
};
|
|
} catch (error) {
|
|
console.error('[processImageForAI] Error processing image:', error);
|
|
throw error;
|
|
}
|
|
}
|