diff --git a/src/lib/utils/imageCompression.ts b/src/lib/utils/imageCompression.ts index a7400fb..8c63f16 100644 --- a/src/lib/utils/imageCompression.ts +++ b/src/lib/utils/imageCompression.ts @@ -56,8 +56,15 @@ export async function compressImage( // Draw and compress the image ctx?.drawImage(img, 0, 0, width, height); - // Try different quality levels if file is still too large - const tryCompress = (currentQuality: number): void => { + // Try different quality levels and dimensions if file is still too large + const tryCompress = (currentQuality: number, currentWidth: number, currentHeight: number): void => { + // Update canvas dimensions + canvas.width = currentWidth; + canvas.height = currentHeight; + + // Redraw with new dimensions + ctx?.drawImage(img, 0, 0, currentWidth, currentHeight); + canvas.toBlob( (blob) => { if (!blob) { @@ -67,10 +74,28 @@ export async function compressImage( const sizeKB = blob.size / 1024; - // If still too large and we can reduce quality further, try again - if (sizeKB > maxSizeKB && currentQuality > 0.3) { - tryCompress(currentQuality - 0.1); - return; + console.log(`Compression attempt: ${currentWidth}x${currentHeight}, quality: ${currentQuality}, size: ${sizeKB.toFixed(1)}KB, target: ${maxSizeKB}KB`); + + // If still too large, try more aggressive compression + if (sizeKB > maxSizeKB) { + // First try reducing quality more aggressively + if (currentQuality > 0.1) { + tryCompress(Math.max(0.1, currentQuality - 0.15), currentWidth, currentHeight); + return; + } + // Then try reducing dimensions + else if (currentWidth > 400 && currentHeight > 300) { + const newWidth = Math.max(400, Math.floor(currentWidth * 0.8)); + const newHeight = Math.max(300, Math.floor(currentHeight * 0.8)); + tryCompress(0.1, newWidth, newHeight); + return; + } + // If we've exhausted all compression options and still too large, reject + else { + console.error(`Failed to compress image below ${maxSizeKB}KB. Final size: ${sizeKB.toFixed(1)}KB`); + reject(new Error(`Unable to compress image below ${maxSizeKB}KB. Please try a different image.`)); + return; + } } // Create new file with compressed data @@ -79,6 +104,8 @@ export async function compressImage( lastModified: Date.now() }); + console.log(`Compression successful: ${sizeKB.toFixed(1)}KB (${((blob.size / file.size) * 100).toFixed(1)}% of original)`); + resolve({ file: compressedFile, originalSize: file.size, @@ -91,7 +118,7 @@ export async function compressImage( ); }; - tryCompress(quality); + tryCompress(quality, width, height); } catch (error) { reject(error); } @@ -132,29 +159,42 @@ export function isImageFile(file: File): boolean { export function getCompressionSettings(file: File): CompressionOptions { const sizeMB = file.size / (1024 * 1024); + let settings: CompressionOptions; + if (sizeMB > 5) { - // Very large files - aggressive compression - return { + // Very large files - moderate compression (food photos need detail) + settings = { maxWidth: 1200, - maxHeight: 800, - quality: 0.6, + maxHeight: 900, + quality: 0.7, maxSizeKB: 400 }; } else if (sizeMB > 2) { - // Large files - moderate compression - return { - maxWidth: 1600, - maxHeight: 1000, - quality: 0.7, + // Large files - light compression + settings = { + maxWidth: 1400, + maxHeight: 1050, + quality: 0.75, maxSizeKB: 450 }; - } else { - // Smaller files - light compression - return { - maxWidth: 1920, - maxHeight: 1080, + } else if (sizeMB > 1) { + // Medium files - minimal compression + settings = { + maxWidth: 1600, + maxHeight: 1200, quality: 0.8, + maxSizeKB: 480 + }; + } else { + // Smaller files - very light compression + settings = { + maxWidth: 1800, + maxHeight: 1350, + quality: 0.85, maxSizeKB: 500 }; } + + console.log(`Compression settings for ${sizeMB.toFixed(1)}MB file:`, settings); + return settings; } diff --git a/src/routes/recipe/[id]/edit/+page.svelte b/src/routes/recipe/[id]/edit/+page.svelte index c755ca7..738f0b1 100644 --- a/src/routes/recipe/[id]/edit/+page.svelte +++ b/src/routes/recipe/[id]/edit/+page.svelte @@ -383,11 +383,21 @@ formData.set('description', descriptionText); formData.set('instructions', instructionsText); + // Remove the original photo from FormData (if it exists) + formData.delete('photo'); + // Add parsed ingredients as JSON formData.append('parsedIngredients', JSON.stringify(parsedIngredients)); - // Add photo if selected + // Add compressed photo if selected if (selectedPhoto) { + console.log('Uploading compressed photo:', { + name: selectedPhoto.file.name, + size: selectedPhoto.file.size, + type: selectedPhoto.file.type, + originalSize: selectedPhoto.originalSize, + compressedSize: selectedPhoto.compressedSize + }); formData.append('photo', selectedPhoto.file); } @@ -459,7 +469,7 @@ method="POST" action="?/update" {onsubmit} - class="card relative grid gap-4 border border-base-200 bg-base-100 p-3 shadow-xl sm:p-6" + class="card relative grid gap-4 overflow-hidden border border-base-200 bg-base-100 p-3 shadow-xl sm:p-6" > {#if pending}
-