0

I was wondering if there is a blaring reason to use jimp vs. imagemin-mozjpeg for compressing jpegs (I am already using both imagemin and jimp in my project already, imagemin-webp to serve next gen images, and jimp to convert pngs to jpegs in rare cases) So I am more looking for reasoning that is based on the following:

  1. Performance
  2. Reliability (I have noticed that there are some JPEGs mozjpeg has trouble with and fails on. specifically ones that I have used GNU Image Manipulation Program [GIMP] with.)

However, if someone has good reasons that don't align with the two aforementioned I would still like to hear them.

Heres some quick links to the NPM packages mentioned if anyone needs them:
imagemin-mozjpeg
jimp

Daniel
  • 1,392
  • 1
  • 5
  • 16

2 Answers2

2

Performance

imagemin-mozjpeg uses mozjpeg to process images. And mozjpeg itself is made using C language. While jimp uses javascript to process it.

As mention in the main repository jimp:

An image processing library for Node written entirely in JavaScript, with zero native dependencies.

We know the difference in performance between Javascript and C.

Reliability

I do not want much opinion in this section. but we can see directly how the statistics of each repository.

mozjpeg:

  • Star: 4.1k
  • Open Issues: 76
  • Closed Issues: 186

jimp:

  • Star: 10.3k
  • Open Issues: 157
  • Closed Issues: 430

I do not side with either. They all have worked well. I really appreciate the work of the maintainers and contributors of the library library.

Laode Muhammad Al Fatih
  • 3,994
  • 1
  • 18
  • 32
1

Yes, and it goes far beyond the performance of the compression process (ie how long it takes to compress an image, which is also important) or the relative activity of development of the library (which is arguably less important).

I highly recommend reading Is WebP really better than JPEG? (and this discussion), which shows that even among JPEG compression libraries, the implementation can have a significant impact on compression ratio.

In short, MozJPEG produces jpeg files that are 10% smaller than jpeg files produced by the reference JPEG implementation (libjpeg). Even more interesting, for images larger than 500px, MozJPEG actually produces jpeg files that are smaller than WebP.

This leads to an interesting question. It will depend on exactly your use case and priorities, but it might actually make sense to simplify and use MozJPEG for everything, and ditch WebP entirely.

Looking forward, AVIF might make sense as a true next-gen format (delivering 30% smaller images), but browser support is "coming soon". Alternatively, JPEG XL also looks promising, but the standard hasn't been finalized yet. HEIC is problematic and I wouldn't count on wide support.


Warning regarding jimp:

As jimp is implemented in pure JavaScript, all image operations end up blocking the JS thread. This is catastrophic in node.js.

You must use the new Worker Threads API manually to run jimp on a thread.


Finally, a warning regarding selecting image manipulation libraries generally in the node.js world:

From what I've seen, a majority of them end up writing temp files to disk and then invoking a child process to do the actual work, and then read the result back in. (eg something like child_process.exec('imageresizer -in temp/file.jpg -out temp/resized.jpg')).

This is not an ideal way to do this, and it may be especially surprising when the API looks something like var img = await resizeImg(buffer), which does not look like it writes to disk.

imagemin is one such library; I would avoid it where performance matters.

Instead, search for modules that implement bindings to native code on the libuv thread pool. This will usually be the most performant way to work with images, since the operations happen on a thread in your node process and with minimal memory copying — and no disk I/O at all.

I've never used it, but node-mozjpeg looks like a good candidate.

josh3736
  • 139,160
  • 33
  • 216
  • 263
  • In reference to your jimp warning (section 2 above): Does jimp block the thread even when ran as async? e.g. return await jimp.read(`${routeToImage}`) .then(async (picture) => { return picture .quality(100) // set JPEG quality .background(0xFFFFFFFF) .write(`.${routeForImage}`); }) – Daniel Jun 26 '20 at 21:11
  • It mostly does. While IO operations like `jimp.read()` are non-blocking (it [calls `fs.readFile`](https://github.com/oliver-moran/jimp/blob/a29b6686e3084e6d57dc643c351979a83af9352c/packages/core/src/index.js#L94)), once the bytes are read in, jimp does all its CPU-heavy operations on the JS thread, blocking everything else while the image is manipulated. This is why it's critical to run those operations in a thread. There's an [open issue](https://github.com/oliver-moran/jimp/issues/601) for built-in worker thread support in jimp, but it doesn't look like a priority. – josh3736 Jun 26 '20 at 21:29