Self-hosted image compression tool without losing quality

Image compression is a big concern for websites or mobile applications where the main visual element are images.

Loading time can be impacted by image size big time! Most likely, you have used online tools like GTmetrix or Pingdom to analyze your website’s speed and one red flag was to serve scaled images.

 

While working on a project with lots of images, I have found a self-hosted image compression solution that decreases the size of JPG images up to 90% and PNG images up to at least 50%!

The big plus of this solution is that you don’t lose the image quality. Of course, if you’re a perfectionist you’ll observe the differences, but for a normal user the images are in high quality.

 

What you need:

  • Server: any Linux distribution with Node.js support (haven’t tested it, but Mac and Windows should be fine too)
  • Time: ~10 minutes

 

package.json dependencies:

{
    "dependencies": {
        "imagemin": "~5.2.2",
        "imagemin-pngquant": "~5.0.0",
        "imagemin-mozjpeg": "~6.0.0"
    }
}

As you can see, all we need is imagemin and two of its plugins.

Here’s how to use them to get the best results:

'use strict';
const imagemin = require('imagemin');
const pngquant = require('imagemin-pngquant');
const mozjpeg = require('imagemin-mozjpeg');

const input = 'uploads_dir';
const output = `${input}/compressed`;

const imageCompressorRun = (input, output, plugins) => {
    return imagemin(input, output, { plugins });
}

const imageCompressorPNG = () => {
    const pngPlugins = [
        pngquant({ speed: 3, quality: '90' })
    ];

    return imageCompressorRun([`${input}/*.png`], output, pngPlugins);
}

const imageCompressorJPG = () => {
    const jpgPlugins = [
        mozjpeg()
    ];

    return imageCompressorRun([`${input}/*.{jpg,jpeg}`], output, jpgPlugins);
}

imageCompressorPNG().then(() => console.info('PNG compression success!'));
imageCompressorJPG().then(() => console.info('JPG compression success!'));

 

Initially, I wanted to write a Node.js package using this code, but I thought that it doesn’t worth the time and doesn’t make sense to make a wrapper over imagemin as it can be used as it is. The separation of JPG and PNG compression was made because of the initial thought, but you can compress multiple image types in one go:

const compressorPlugins = [
    mozjpeg(),
    pngquant({ speed: 3, quality: '90' })
];

imageCompressorRun([`${input}/*.{jpg,jpeg,png}`], output, compressorPlugins);

 

That’s all you need. A simple & fast self-hosted image compression tool.

 

The results

I’ll show you the results based on two large (1-2MB) images in comparison with 6 best free online image compression tools from 2016 according to this article.

 Tools JPG image (1.8MB) PNG image (1.7MB)
Compressor.io 325.98 kB 802.97 kB
Kraken.io 474.12 kb 855.43 kB
GiftOfSpeed 426.4 kB 923.1 kB
Tinypng 285.6 kB 827.4 kB
OptimiZilla 414 kB 935 kB
ImageRecycle 306.29 kB 833.69 kB
Self-hosted Node.js script 260.1 kB 822.4 kB

* Click on linked text to see original & compressed images.

 

As you can see, the results are the best (excepting PNG image, where compressor.io wins with 20 kB); only Tinypng has similar results to this self-hosted Node.js image compression script.

For kraken.io I had to create a PRO account (because the free web interface has a limit of 1MB) and I was very surprised by the results considering that you pay for it!

 

Happy image optimization!

7 Comments

  • fishingBakersfield

    January 8, 2018

    How difficult would this be to implement with multer? Like if a user uploaded an image then have this compress it?

    Reply
    • Tanase Butcaru

      March 25, 2018

      This script should be easy to integrate with everything.
      I’ve never used multer, but I guess there is a onSuccess event or something similar that gives you the path of the uploaded file. From there, take that path and pass it to this compression script and that should be all.

      Reply
  • Amin Diary

    February 4, 2018

    Thanks for useful code, I’m looking for something to optimize my images on shared hosting that does NOT supports node.js
    is there an option like this but maybe in PHP or something more common?

    Reply
    • Tanase Butcaru

      March 25, 2018

      I don’t know anything like that for PHP. It might exist, but I haven’t coded in PHP for some years.
      One thing you can do is to port my code to PHP. That would work only if your host could install those PHP libraries on the server (imagemin for PHP: https://github.com/itgalaxy/imagemin-php).

      Reply
  • Carlos Echeverria

    April 28, 2018

    Hi Tanase , in the directory i have 39 images but only compress 18, Do you know why ?

    Reply
    • Tanase Butcaru

      May 10, 2018

      Hi Carlos,

      Do you have all 39 images in the root of uploads_dir or you have some of them in other subdirectories?
      Haven’t tried so far to compress so many images at once.

      Reply
  • Leith

    May 31, 2018

    Could someone please help an absolute noob to get this running on a VPS?

    Reply

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.