From 78394b7e972eb6169a0ad895cf828e23265f0c37 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20Kr=C3=BCger?= Date: Mon, 17 Nov 2025 11:56:54 +0100 Subject: [PATCH] fix: implement actual ImageMagick WASM conversion with quality settings MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Previously, the ImageMagick service was just a placeholder that returned the input data unchanged. This caused PNG to WebP conversions to have the same file size. Changes: - Properly implement ImageMagick.read() with conversion logic - Apply imageQuality option to control compression - Apply imageWidth/imageHeight options with aspect ratio preservation - Use correct MagickFormat enum values for output formats - Fix write() method signature (format comes before callback) - Remove unnecessary initializeImageMagick() call Image conversion now properly applies: - Quality settings (1-100%) - Resolution/resize options - Format-specific compression This fixes the issue where quality settings had no effect on output file size. Users will now see proper file size reduction when using lower quality settings or converting to compressed formats like WebP. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude --- lib/converters/imagemagickService.ts | 77 ++++++++++++++++++++-------- 1 file changed, 56 insertions(+), 21 deletions(-) diff --git a/lib/converters/imagemagickService.ts b/lib/converters/imagemagickService.ts index 653bf7b..fe97d05 100644 --- a/lib/converters/imagemagickService.ts +++ b/lib/converters/imagemagickService.ts @@ -14,7 +14,7 @@ export async function convertWithImageMagick( try { // Load ImageMagick instance - const ImageMagick = await loadImageMagick(); + await loadImageMagick(); // Report initial progress if (onProgress) onProgress(10); @@ -26,21 +26,55 @@ export async function convertWithImageMagick( if (onProgress) onProgress(30); // Import ImageMagick functions - const IM = await import('@imagemagick/magick-wasm'); + const { ImageMagick } = await import('@imagemagick/magick-wasm'); - // Determine output format - const magickFormat = getMagickFormat(outputFormat); + if (onProgress) onProgress(40); + + // Get output format enum + const outputFormatEnum = await getMagickFormatEnum(outputFormat); if (onProgress) onProgress(50); - // Convert image - Note: This is a placeholder implementation - // The actual ImageMagick WASM API may differ - const result = inputData; // Placeholder: just return input for now + // Convert image using ImageMagick + let result: Uint8Array; - if (onProgress) onProgress(90); + await ImageMagick.read(inputData, (image) => { + // Apply quality setting if specified + if (options.imageQuality !== undefined) { + image.quality = options.imageQuality; + } + + // Apply resize if specified + if (options.imageWidth || options.imageHeight) { + const width = options.imageWidth || 0; + const height = options.imageHeight || 0; + + if (width > 0 && height > 0) { + // Both dimensions specified + image.resize(width, height); + } else if (width > 0) { + // Only width specified, maintain aspect ratio + const aspectRatio = image.height / image.width; + image.resize(width, Math.round(width * aspectRatio)); + } else if (height > 0) { + // Only height specified, maintain aspect ratio + const aspectRatio = image.width / image.height; + image.resize(Math.round(height * aspectRatio), height); + } + } + + if (onProgress) onProgress(70); + + // Write to output format + image.write(outputFormatEnum, (data) => { + result = data; + }); + + if (onProgress) onProgress(90); + }); // Create blob from result - const blob = new Blob([result as BlobPart], { type: getMimeType(outputFormat) }); + const blob = new Blob([result! as BlobPart], { type: getMimeType(outputFormat) }); if (onProgress) onProgress(100); @@ -65,20 +99,21 @@ export async function convertWithImageMagick( /** * Get ImageMagick format enum */ -function getMagickFormat(format: string): any { - // This is a placeholder - actual implementation would use MagickFormat enum - const formatMap: Record = { - png: 'Png', - jpg: 'Jpeg', - jpeg: 'Jpeg', - webp: 'WebP', - gif: 'Gif', - bmp: 'Bmp', - tiff: 'Tiff', - svg: 'Svg', +async function getMagickFormatEnum(format: string): Promise { + const { MagickFormat } = await import('@imagemagick/magick-wasm'); + + const formatMap: Record = { + png: MagickFormat.Png, + jpg: MagickFormat.Jpg, + jpeg: MagickFormat.Jpg, + webp: MagickFormat.WebP, + gif: MagickFormat.Gif, + bmp: MagickFormat.Bmp, + tiff: MagickFormat.Tiff, + svg: MagickFormat.Svg, }; - return formatMap[format.toLowerCase()] || format; + return formatMap[format.toLowerCase()] || MagickFormat.Png; } /**