How do I get the best PNG compression with gulp-imagemin + plugins?
Asked Answered
F

1

8

I am trying to get the best setup possible for compressing pngs.

I have found there are some plugins available here for imagemin: https://www.npmjs.com/browse/keyword/imageminplugin

I have tried all the PNG options but the compression rates appear to be pretty bad.

pngquant appears to have the highest compression rate, (obviously the worst quality) similar quality to tinypng, but could still get nearer the tinypng figure.

Essentially I have 3 questions:

Question 1: Changing the options for both advpng & optipng doesn't seem to alter the filesize, here is an example, am I using this correctly? I am guessing that maybe it isn't using my settings at all and falling back to the default settings? If you notice the filesizes of these two are identical!:

.pipe(imagemin(
    imageminOptipng({
        optimizationLevel: 4
    })
))

Question 2: Am I using "pngout" in correctly? Is there a method to use it that I do not know about? The examples from their page seem not to work & neither does this method:

.pipe(imagemin([
    imageminPngout({
        strategy: 1
    })
]))

Question 3: Is there a better method to deal with png compression that I haven't yet found? Ideally I would somehow like to get a method that has the rate of pngquant, but the quality is a bit better.

Fenian answered 6/10, 2016 at 11:34 Comment(0)
B
15

After a long process of trials and errors, I've managed to get the imagemin-pngquant plugin to produce the image of the similarly small size as TinyPNG.com. Still a little bigger, but some parts of the image were looking better than the TinyPNG.com result.

Input image size: 1.1MB
TinyPNG.com: 223kb
imagemin-pngquant: 251kb

I used the next plugin settings:

{
    quality: '70-90', // When used more then 70 the image wasn't saved
    speed: 1, // The lowest speed of optimization with the highest quality
    floyd: 1 // Controls level of dithering (0 = none, 1 = full).
}

Also, it may be a good idea to generate .webp images from .png and serve it to the browsers that support this format with the .png as a backup. More info about .webp image format: Google Developer Section

After generating .webp from the optimized image (with the minimal quality loss) the image size was 62kB. You can use the imagemin-webp plugin with gulp-rename to stream images to the dist folder with the same base name, but different extension. Example gulp task:

const config = require('./src/gulp/config.json');

const gulp = require('gulp');
const plugins = require('gulp-load-plugins')();
const imageminWebp = require('imagemin-webp');

gulp.task('images', function () {
    return gulp.src(config.src.images)
        pipe(plugins.imagemin([imageminWebp({
            method: 6,
        })]))
        .pipe(plugins.rename({ extname: '.webp' }))
        .pipe(gulp.dest(config.dist.images));
});
Buchalter answered 29/3, 2018 at 16:20 Comment(1)
Nice! Good findings! I've set this as best answer (as you've got pretty close to TinyPNG 😄). I've ditched gulp now for my own setups in favour of webpack, but, good suggestion on converting to webp instead. I'll probably look at setting that up myself!Fenian

© 2022 - 2024 — McMap. All rights reserved.