A perfect image optimizer for Ruby

191
27
Ruby

Piet

Build Status

Description

Piet is a gem that optimizes an image stored in a file, and it has
integration with CarrierWave uploaders.

This gem is named after the minimalist Dutch painter Piet Mondrian.

Installation

This gem requires two image optimization utilities: optipng and
jpegoptim, available in various platforms such as Unix or Windows.
You can install them by following the instructions on each authors’
page:

After installing both utils, simply install the gem:

gem install piet

Easy installation of binaries

While install binaries (like optipng, jpegoptim) is not a rocket science, it can be hard (or even impossible) for some people. Thinking on this a gem called piet-binary was created with theses binaries packed.
This is a good approach if you are using Heroku as your host provider, or if you are lazy or impatient 😉

After install piet, just install piet-binary and add to your Gemfile (if you are using Rails):

gem install piet-binary

And in your Gemfile

gem 'piet'
gem 'piet-binary'

PS 1: it’s optional to call piet in your Gemfile, because piet-binary already do this. The same is valid to install the gem via command-line: just install the piet-gem and it will install the piet for you.

PS 2: don’t forget to call ‘bundle install’ if you are using Rails

Usage

You simply require the gem

require 'piet'

and then call the optimize method:

Piet.optimize(path, opts)

Not that this will work not by just using the file extension, but by
MIME type detection, which should be more reliable.

The options are:

  • verbose: Whether you want to get the output of the command or not. It is interpreted as a Boolean value. Default: false.

  • quality: Adjust the output compression for JPEGs. Valid values are any integer between 0 and 100 (100 means no compression and highest quality). Default: 100

  • level: Adjust the optimization level for PNGs. Valid values are any integer between 0 and 7 (7 means highest compression and longest processing time). Default: 7

CarrierWave integration

As stated before, Piet can be integrated into CarrierWave uploaders.
This way, you can optimize the original image or a version.

In order to do that, firstly add piet to your Gemfile:

gem 'piet'

Then go to your CarrierWave uploader and include Piet’s extension:

class ImageUploader < CarrierWave::Uploader::Base
  ...
  include Piet::CarrierWaveExtension
  ...
end

And finally use Piet! For all the images:

class ImageUploader < CarrierWave::Uploader::Base
  ...
  process :optimize
  ...
end

Or only for a version:

class ImageUploader < CarrierWave::Uploader::Base
  ...
  version :normal do
    ...
    process :optimize
  end
  ...
end

To use custom options in the optimization:

class ImageUploader < CarrierWave::Uploader::Base
  ...
  # To pass 1 hash as 1 argument
  # It needs to be put in an array
  # So in this example the actual call will look like:
  # ```
  # optimize({quality: 90, level: 7})
  # ```
  process optimize: [{quality: 90, level: 7}]
  ...
end

Examples

  • Simply Optimizing
Piet.optimize('/my/wonderful/pics/piggy.png')

Piet.optimize('/my/wonderful/pics/pony.jpg')

would optimize those PNG, GIF and JPEG files but output nothing.

  • Optimizing PNG/GIF and getting feedback
Piet.optimize('/my/wonderful/pics/piggy.png', :verbose => true)

would optimize that PNG/GIF file and output something similar to this one:

** Processing: piggy.png
340x340 pixels, 4x8 bits/pixel, RGB+alpha
Input IDAT size = 157369 bytes
Input file size = 157426 bytes

Trying:
  zc = 9  zm = 9  zs = 0  f = 1   IDAT size = 156966
  zc = 9  zm = 8  zs = 0  f = 1   IDAT size = 156932

Selecting parameters:
  zc = 9  zm = 8  zs = 0  f = 1   IDAT size = 156932

Output IDAT size = 156932 bytes (437 bytes decrease)
Output file size = 156989 bytes (437 bytes = 0.28% decrease)
  • Optimizing JPEG and getting feedback
Piet.optimize('/my/wonderful/pics/pony.jpg', :verbose => true)

would optimize that JPEG file and ouput similar to this one:

/my/wonderful/pics/pony.jpg 235x314 24bit JFIF  [OK] 15305 --> 13012 bytes (14.98%), optimized.

Pngquant

You can use Piet to convert 24/32-bit PNG images to paletted (8-bit) PNGs. The conversion reduces file sizes significantly and preserves full alpha transparency.

Simply use Piet like this:

Piet.pngquant('/a/path/where/you/store/the/file/to/convert')

Please note you have to install the binary in order to use the tool. Simply follow the instructions (and read more info about it) in the official site.

Thanks to @rogercampos for providing the awesome png_quantizator gem, which you can find here.

TODO

  • Add SVG optimization
  • Leave testing files out of the bundled gem
  • Binary tool for optimizing a file
  • Add some testing!

Changelog

  • v.0.2.6 Strip metadata for PNGs (same way we do with JPEGs) thanks to @PikachuEXE.
  • v.0.2.5 Improved CI coverage & dropped support for Ruby 1.9
  • v.0.2.4 Fixed Gemfile issues!
  • v.0.2.3 More efficient treatment of open files thanks to @lavrovdv.
  • v.0.2.2 Lighter gem weight (to be improved in the future).
  • v.0.2.1 More reliable file type detection, by not using the extension but the MIME type. Thanks to @jewlofthelotus! Also, the Carrierwave
    extension is now compatible with RMagick thanks to @YoranBrondsema.
  • v.0.2.0 Users of the gem can now use piet-binary gem, and bug with filenames containing spaces, parentheses and some other characters is solved too, thanks to @loureirorg. Requiring png_quantizator when it’s due, thanks to @jayzes. Finally, specifying the gem version due to @jigfox interest.
  • v.0.1.3 Use png_quantizator gem instead of the own implementation.
  • v.0.1.2 Fixed some problems with missing processing, thanks to @lentg.
  • v.0.1.1 Added support for GIFs. Added an extra option to use pngquant (thanks @rogercampos). Solved problems with Carrierwave >= 0.6 (thanks @mllocs and @huacnlee).
  • v.0.1.0 Optimization of PNGs and JPEGs, including an integration with Carrierwave