RoR-e

If you haven't seen The 15 minute E-Commerce Site CLICK HERE


I'm currently looking for Contract jobs, Contact Me if you are interested. Dave.

Optimize your Images David Henner Mar 11

17 comments Latest by Matt

I want to preface this post with a huge thank you to the developers I've had the chance to work with in Belarus (Altoros). Dmitry Ilyashevich and Yury Velikanau wrote the code that ended up in our code base but the whole team in Belarus is great.

Background

A few months ago my boss brought up a service called smush it. Basically this service allows you to upload an image and return an optimized image. Hence making a smaller image that still looks good for its size.

Taking a longer look Yahoo gives you the libraries they use to make smushit work. Take a look at the bottom of the above link(pngcrush && jpegtran). So the thought was that we could simply install these libraries on our server's that we upload pictures to. I wish I had been given this project but Dmitry, Yury and the Altoros team did a great job getting this working.

On to the code. What we did was create a paperclip_postprocess.rb file in config/initializers. Sorry but the code doesn't size well on the blog...

module Paperclip
  class Thumbnail < Processor
    def make
    src = @file
    conv = Tempfile.new([@basename, @format ? ".#{@format}" : ''])
    conv.binmode
    dst = Tempfile.new([@basename, @format ? ".#{@format}" : ''])
    dst.binmode

  begin
    parameters = []
    parameters << source_file_options
    parameters << ":source"
    parameters << transformation_command
    parameters << convert_options
    parameters << ":dest"

    parameters = parameters.flatten.compact.join(" ").strip.squeeze(" ")

    success = Paperclip.run("convert", parameters, :source => "#{File.expand_path(src.path)}[0]", :dest => File.expand_path(conv.path))

    if conv.size > 0
      format = begin
        Paperclip.run("identify", "-format %m :file", :file => "#{File.expand_path(conv.path)}[0]")
      rescue PaperclipCommandLineError
        ""
      end

      case format.strip
      when 'JPEG'
        # Part of libjpeg-progs deb package
        success = Paperclip.run('jpegtran', "-copy none -optimize -perfect :source > :dest", :source => File.expand_path(conv.path), :dest => File.expand_path(dst.path))
      when 'PNG'
        success = Paperclip.run('pngcrush', "-rem alla -reduce -brute :source :dest", :source => File.expand_path(conv.path), :dest => File.expand_path(dst.path))
      else
        dst = conv
      end
    end
  rescue Exception => e
    Rails.logger.error "There was an error processing the thumbnail for #{@basename}. Check imagemagick, jpegtran and pngcrush installed."

    HoptoadNotifier.notify(
      :error_class => "Paperclip - images optimization",
      :error_message => "Paperclip ERROR: #{e.message}"
    )
  end

  dst.size > 0 ? dst : conv
    end
  end
end

At the end of the day This reduced our file sizes dramatically. Some images were reduced in size by about 85%. It is well worth the extra time to get this set up with paperclip.

Check back later as we will try to create our own fork of paperclip and allow this to be a paperclip option. For now install jpegtran and pngcrush on your linux box and start optimizing your images.

17 comments so far

Philip Hallstrom 12 Mar 11

It's been awhile since I looked at paperclips source but I think you can define your own processor that can athen be specified in the has_attachment line either replacing the default or adding to it....

DRH 12 Mar 11

Interesting Philip. I'll take a look. Thanks.

Claudio 12 Mar 11

It sounds a great idea to combine paperclip with Smush.it. I should try your approach on my projects. Thanks.

khelll 13 Mar 11

Good idea, waiting the fork :)

Rodrigo 21 Mar 11

what about gift processing? case format.strip when 'GIF' success = Paperclip.run('gifsicle', "-b -O2 :source", :source => File.expand_path(conv.path)) ...

Rodrigo 21 Mar 11

first of all you need a 'sudo apt-get install imagemagick pngcrush libjpeg-progs gifsicle'

marcus 30 Dec 11

trying to isolate the problem a ran the command directly in the terminal: /opt/local/bin/jpegtran -copy none -optimize -perfect 16_original.jpg > 16_original2.jpg but the new image is generated with the same size...

rong 04 Nov 11

this is exactly what i'm looking for! after applying the code, I'm getting this error: Command 'jpegtran -copy none -optimize -perfect '/tmp/stream20111104-1603-1gfl9j120111104-1603-1m3496z' > '/tmp/stream20111104-1603-1gfl9j120111104-1603-1pmsxai'' returned 1. Expected 0 any ideas? I have jpegtran installed.

marcus 30 Dec 11

hey man, great job but here is not working. Looking through the log i can see that it tries to apply the optimization but image files keep the same size... paperclip] /opt/local/bin/jpegtran -copy none -optimize -perfect '/tmp/stream20111230-5419-em4jrt-020111230-5419-1y8ih3m-0' > '/tmp/stream20111230-5419-em4jrt-020111230-5419-43gto0-0' 2>/dev/null

DRH 01 Dec 11

I had no idea people were still commenting on this... I guess I should be looking at my old blog posts. Rong, Do you have privileges to use jpegtran? I'll post later if I find a solution.

DRH 30 Dec 11

marcus, Your original JGP has probably already been optimized by photoshop. Paperclip will take that photo and make different copies of the photo. Each copy will not be optimized and hence need to be ran through this script.

DRH 30 Dec 11

marcus, Also paperclip might have gotten better since I wrote this. They might be resizing in a better way now.

Andrea Salicetti 10 Feb 12

I have just published my contribution: https://github.com/knightq/paperclip-smusher It is just the gem-ification of your great efforts: hope it may help you all. Any contribution to the gem will be wellcome!

Andrea Salicetti 10 Feb 12

Here is the followable link: https://github.com/knightq/paperclip-smusher

test 16 Feb 12

aw sum, but want more optimization...

umer 16 Feb 12

Want more optimization...

Matt 10 Apr 12

I look at this and ran some test to see the effect jpegtran has on my images as most of user uploaded images seem to be JPEG for me. The results were on average around 10-20% lossless compression, anyone experience anything different? I think this was great and but I was looking for more like a 40-60% gain which I achieve with some loss in image quality using the "-quality: 40" imagemagick compression, to do this add :convert_options => { :all => "-quality 40"} to your options for paperclip or use the new quality option as documented: https://github.com/thoughtbot/paperclip/wiki/Usage - scroll to the bottom. By the way, apparently a quality setting of 75 has minimal loss with the best compression: http://www.imagemagick.org/script/command-line-options.php#quality

Comments are closed