toy / image_optim

Optimize images using multiple utilities
https://github.com/toy/image_optim
MIT License
1.52k stars 109 forks source link

Optimization silently fails #153

Closed razola closed 6 years ago

razola commented 6 years ago

Hi,

I've installed image_optim and image_optim_pack by adding the below to my Gemfile:

gem 'image_optim'
gem 'image_optim_pack'

I then optimize a jpeg with the below code:

image_optim = ImageOptim.new({
  verbose: true,
  pngout: false,
  svgo: false,
})
image_optim.optimize_image(file)

The last command returns nil indicating that the optimization has failed, but looking at the output below all everything seems ok. Am I missing something here?

config:
  verbose: true
  pngout: false
  svgo: false
nice: 10
threads: 2
pack: true
skip_missing_workers: true
allow_lossy: false
cache_dir:
cache_worker_digests: false
image_optim_pack: all bins from /usr/local/bundle/gems/image_optim_pack-0.5.0.20171101-x86_64-linux/vendor/linux-x86_64 worked
Resolved pngcrush 1.8.13 at /usr/local/bundle/gems/image_optim_pack-0.5.0.20171101-x86_64-linux/vendor/linux-x86_64/pngcrush
Resolved advpng 2.0 at /usr/local/bundle/gems/image_optim_pack-0.5.0.20171101-x86_64-linux/vendor/linux-x86_64/advpng
Resolved optipng 0.7.6 at /usr/local/bundle/gems/image_optim_pack-0.5.0.20171101-x86_64-linux/vendor/linux-x86_64/optipng
Resolved pngquant 2.11.0 at /usr/local/bundle/gems/image_optim_pack-0.5.0.20171101-x86_64-linux/vendor/linux-x86_64/pngquant
Resolved jhead 3.00 at /usr/local/bundle/gems/image_optim_pack-0.5.0.20171101-x86_64-linux/vendor/linux-x86_64/jhead
Resolved jpegtran 9b at /usr/local/bundle/gems/image_optim_pack-0.5.0.20171101-x86_64-linux/vendor/linux-x86_64/jpegtran
Resolved jpegoptim 1.4.4 at /usr/local/bundle/gems/image_optim_pack-0.5.0.20171101-x86_64-linux/vendor/linux-x86_64/jpegoptim
Resolved gifsicle 1.90 at /usr/local/bundle/gems/image_optim_pack-0.5.0.20171101-x86_64-linux/vendor/linux-x86_64/gifsicle
Workers by format:
jpeg:
  jhead:
  jpegoptim:
    allow_lossy: false
    strip: ["all"]
    max_quality: 100
  jpegtran:
    copy_chunks: false
    progressive: true
    jpegrescan: false
png:
  pngcrush:
    chunks: ["alla"]
    fix: false
    brute: false
    blacken: true
  optipng:
    level: 6
    interlace: false
    strip: true
  pngquant:
    allow_lossy: false
    max_colors: 256
    quality: 100..100
    speed: 3
  advpng:
    level: 4
gif:
  gifsicle:
    interlace: false
    level: 3
    careful: false
  gifsicle:
    interlace: true
    level: 3
    careful: false
✓ 0.0316017s jpegoptim --strip-all --quiet -- /tmp/1510164294-697468377820171108-393-1q9it55.jpeg
✓ 0.1136343s jpegtran -progressive -copy none -optimize -outfile /tmp/1510164294-697468377820171108-393-1q9it55.jpeg /tmp/1510164294-6974683778.jpeg
toy commented 6 years ago

Hi Sebastian, You are right, returned nil indicates that the image was not optimized and verbose output shows no problems. It needs to be confirmed, but I assume that even if both commands succeeded, they did not optimize the image (the size did not decrease). It may be good to introduce showing size change in verbose output of every command.

razola commented 6 years ago

Yep. Confirmed. The filesize doesn’t change. Any idea on where to begin digging to identify the issue?

toy commented 6 years ago

May it be that it is already optimized? So it can't be optimized further. If you already verified that both tools don'r change the size, than it most probably is the case. If you really want to reduce the size you can allow lossy optimisations.

razola commented 6 years ago

I've tried with lossy optimizations and that didn't do anything to the filesize either..

razola commented 6 years ago

Oops, I've tried a few other images and it actually seems to work now. Sorry, that should have been the first thing I tried.

This is the image that was causing me trouble. I guess it is somehow corrupt. Although it does actually work if I use the ImageOptim.app..

razola commented 6 years ago

Hmm, also is it expected that this gem doesn't shrink the filesize as much as the ImageOptim.app?

For example this image:

132 994 bytes (original)
132 988 bytes (gem)
130 711 bytes (ImageOptim.app)

I use the default settings for the gem and only enable the workers used with the gem in the ImageOptim.app.

config:
  verbose: true
  pngout: false
  svgo: false
nice: 10
threads: 2
pack: true
skip_missing_workers: true
allow_lossy: false
cache_dir:
cache_worker_digests: false
image_optim_pack: all bins from /usr/local/bundle/gems/image_optim_pack-0.5.0.20171101-x86_64-linux/vendor/linux-x86_64 worked
Resolved pngcrush 1.8.13 at /usr/local/bundle/gems/image_optim_pack-0.5.0.20171101-x86_64-linux/vendor/linux-x86_64/pngcrush
Resolved advpng 2.0 at /usr/local/bundle/gems/image_optim_pack-0.5.0.20171101-x86_64-linux/vendor/linux-x86_64/advpng
Resolved optipng 0.7.6 at /usr/local/bundle/gems/image_optim_pack-0.5.0.20171101-x86_64-linux/vendor/linux-x86_64/optipng
Resolved pngquant 2.11.0 at /usr/local/bundle/gems/image_optim_pack-0.5.0.20171101-x86_64-linux/vendor/linux-x86_64/pngquant
Resolved jhead 3.00 at /usr/local/bundle/gems/image_optim_pack-0.5.0.20171101-x86_64-linux/vendor/linux-x86_64/jhead
Resolved jpegtran 9b at /usr/local/bundle/gems/image_optim_pack-0.5.0.20171101-x86_64-linux/vendor/linux-x86_64/jpegtran
Resolved jpegoptim 1.4.4 at /usr/local/bundle/gems/image_optim_pack-0.5.0.20171101-x86_64-linux/vendor/linux-x86_64/jpegoptim
Resolved gifsicle 1.90 at /usr/local/bundle/gems/image_optim_pack-0.5.0.20171101-x86_64-linux/vendor/linux-x86_64/gifsicle
Workers by format:
jpeg:
  jhead:
  jpegoptim:
    allow_lossy: false
    strip: ["all"]
    max_quality: 100
  jpegtran:
    copy_chunks: false
    progressive: true
    jpegrescan: false
png:
  pngcrush:
    chunks: ["alla"]
    fix: false
    brute: false
    blacken: true
  optipng:
    level: 6
    interlace: false
    strip: true
  pngquant:
    allow_lossy: false
    max_colors: 256
    quality: 100..100
    speed: 3
  advpng:
    level: 4
gif:
  gifsicle:
    interlace: false
    level: 3
    careful: false
  gifsicle:
    interlace: true
    level: 3
    careful: false
✓ 0.055505929s jpegoptim --strip-all --quiet -- /tmp/1510231329-347225575320171109-159-1ps7q4g.jpeg
✓ 0.133377156s jpegtran -progressive -copy none -optimize -outfile /tmp/1510231329-347225575320171109-159-1cz8856.jpeg /tmp/1510231329-347225575320171109-159-1ps7q4g.jpeg
before: 132 994 bytes
 after: 132 988 bytes

1 2 3

toy commented 6 years ago

Seems I've found the reason, jpegrescan is not on by default for the gem, so if you use image_opitm --jpegtran-jpegrescan=t or same option through config, then 6.95% are removed from the image.

razola commented 6 years ago

Hmm, like this right?

image_optim = ImageOptim.new({
  verbose: true,
  pngout: false,
  svgo: false,
  jpegtran: {
    jpegrescan: true
  }
})

For some reason the jpegrescan operation isn't applied for me. I assume that's what the in the output indicates. I've tried five different jpeg and get the same results. The below output is for the image I linked to in my previous comment.

config:
  verbose: true
  pngout: false
  svgo: false
  jpegtran:
    jpegrescan: true
nice: 10
threads: 2
pack: true
skip_missing_workers: true
allow_lossy: false
cache_dir:
cache_worker_digests: false
image_optim_pack: all bins from /usr/local/bundle/gems/image_optim_pack-0.5.0.20171101-x86_64-linux/vendor/linux-x86_64 worked
Resolved pngcrush 1.8.13 at /usr/local/bundle/gems/image_optim_pack-0.5.0.20171101-x86_64-linux/vendor/linux-x86_64/pngcrush
Resolved advpng 2.0 at /usr/local/bundle/gems/image_optim_pack-0.5.0.20171101-x86_64-linux/vendor/linux-x86_64/advpng
Resolved optipng 0.7.6 at /usr/local/bundle/gems/image_optim_pack-0.5.0.20171101-x86_64-linux/vendor/linux-x86_64/optipng
Resolved pngquant 2.11.0 at /usr/local/bundle/gems/image_optim_pack-0.5.0.20171101-x86_64-linux/vendor/linux-x86_64/pngquant
Resolved jhead 3.00 at /usr/local/bundle/gems/image_optim_pack-0.5.0.20171101-x86_64-linux/vendor/linux-x86_64/jhead
Resolved jpegtran 9b at /usr/local/bundle/gems/image_optim_pack-0.5.0.20171101-x86_64-linux/vendor/linux-x86_64/jpegtran
Resolved jpegoptim 1.4.4 at /usr/local/bundle/gems/image_optim_pack-0.5.0.20171101-x86_64-linux/vendor/linux-x86_64/jpegoptim
Resolved jpegrescan e5395bb5 at /usr/local/bundle/gems/image_optim-0.25.0/vendor/jpegrescan
Resolved gifsicle 1.90 at /usr/local/bundle/gems/image_optim_pack-0.5.0.20171101-x86_64-linux/vendor/linux-x86_64/gifsicle
Workers by format:
jpeg:
  jhead:
  jpegoptim:
    allow_lossy: false
    strip: ["all"]
    max_quality: 100
  jpegtran:
    copy_chunks: false
    progressive: true
    jpegrescan: true
png:
  pngcrush:
    chunks: ["alla"]
    fix: false
    brute: false
    blacken: true
  optipng:
    level: 6
    interlace: false
    strip: true
  pngquant:
    allow_lossy: false
    max_colors: 256
    quality: 100..100
    speed: 3
  advpng:
    level: 4
gif:
  gifsicle:
    interlace: false
    level: 3
    careful: false
  gifsicle:
    interlace: true
    level: 3
    careful: false
✓ 0.04791775s jpegoptim --strip-all --quiet -- /tmp/1510303412-218846347220171110-25-xd51ch.jpeg
✗ 0.010895873s jpegrescan -s /tmp/1510303412-218846347220171110-25-xd51ch.jpeg /tmp/1510303412-218846347220171110-25-194cknt.jpeg
before: 132 994 bytes
 after: 132 988 bytes
toy commented 6 years ago

Can you check if PATH="$(dirname $(gem which image_optim))/../vendor:$PATH" jpegrescan outputs help info? I think jpegrescan was not turned on by default because it requires not only perl, but also some cpan modules. Can be resolved by either removing those dependencies, rewriting it somehow else or using other version of jpegtran including those modifications.

razola commented 6 years ago

Yep. That was the issue. Running apt-get install libfile-slurp-perl solved both problems.

Now all test images are optimized properly and the size saved matches ImageOptim.app.

Thanks for a great gem and for helping out with this! ❤️

toy commented 6 years ago

Glad I could help! I'll try to think how to improve jpegrescan handling.

toy commented 6 years ago

@razola Could you please check if jpegrescan branch works for you (it doesn't require file-slurp module to be installed)

razola commented 6 years ago

Yep, it works! \o/

toy commented 6 years ago

Thanks for checking! I'll release new version and think how to handle mozjpeg which should give even better optimisation than jpegrescan