jsscheller / imagemagick-wasm

imagemagick compiled to WASM
Apache License 2.0
2 stars 2 forks source link

Generating GIFs is very slow #2

Open av01d opened 6 months ago

av01d commented 6 months ago

First of all: thanks for a great library!

Would it be possible to add support for GIF image format? Or would this have a significant impact on the size of the .wasm file? What's the reason GIF support is currently not included?

jsscheller commented 6 months ago

Looking at the configure script for imagemagick (https://imagemagick.org/script/advanced-linux-installation.php), I don't see a flag for GIF support specifically so maybe GIF support is builtin. Have you tried reading/writing a GIF image with this library?

jsscheller commented 6 months ago

Just realized there is a test for writing GIFs: https://github.com/jsscheller/imagemagick-wasm/blob/master/tests/index.js#L57. There isn't one for reading but I assume it works as well.

av01d commented 6 months ago

Thanks for your responses. I've done some more testing and I can indeed confirm that converting to GIF works. But it is incredibly slow. Converting a JPG image of 1024x768px to PNG or WebP takes 0.6 seconds on my Mac (in Chrome), converting it to GIF takes over 55 seconds. On Firefox it's less than 1 second vs 40 seconds.

If the source image gets larger, the differences get even bigger.

Here is my test: http://2img.webgear.nl/gif.html

worker.js file:

import createModule from "https://unpkg.com/@jspawn/imagemagick-wasm/magick.mjs";

const getTime = () => {
   return new Date().getTime()/1000;
}

(async () => {
   let buf, blob, startTime;

   const magick = await createModule({
      // Tell Emscripten where the WASM file is located.
      locateFile: () => "https://unpkg.com/@jspawn/imagemagick-wasm/magick.wasm",
   });

   magick.FS.createLazyFile('/', 'koala.jpg', '/pics/koala.jpg', true, false);

   //
   // Convert a JPG image to PNG (fast)
   //
   console.log('convert koala.jpg -resize 50% -colorspace gray out.png');
   startTime = getTime();

   magick.callMain(['koala.jpg', '-resize', '50%', '-colorspace', 'gray', 'out.png']);

   buf = magick.FS.readFile('out.png');
   blob = new Blob([buf], { type: 'image/png' });
   postMessage({text:'PNG (' + (getTime() - startTime).toFixed(2) + 's)', blob:blob});
   console.log('Done JPG -> PNG!');

   //
   // Convert a JPG image to GIF (very slow)
   //
   console.log('convert koala.jpg -resize 50% -colorspace gray out.gif');
   startTime = getTime();
   magick.callMain(['koala.jpg', '-resize', '50%', '-colorspace', 'gray', 'out.gif']);

   buf = magick.FS.readFile('out.gif');
   blob = new Blob([buf], { type: 'image/gif' });
   postMessage({text:'GIF (' + (getTime() - startTime).toFixed(2) + 's)', blob:blob});
   console.log('Done JPG -> GIF!');
})();

Why is converting to GIF so slow?

jsscheller commented 6 months ago

Interesting. What happens when you just do the JPG to GIF conversion (or do that conversion first)? Some WASM engines will try to optimize the WASM if it is used more than once - wondering if that is the issue here.

If that isn't the issue I would guess the GIF encoder is just slow. Perhaps there is some command line argument which makes it faster?