How to find image sizes in rails without image science

We have a nice new server which runs 64 bit fedora linux. It’s quick and good. But alas FreeImage won’t compile on this architecture. So bang goes any chance of using Image science.

But really I am only interested in finding the dimensions of my images. And it shouldn’t be hard. I found this post about using the gd library to resize images. Well I don’t need to resize images, but I thought it was a good approach, so I hacked it to do what I wanted.

Here is my code (credit to Damien Tanner for the original code). Very short and simple, and you just need the gd library installed together with the header files. On my system ‘yum install gd-devel’ did the trick.

if !ENV['HOME']
  ENV['INLINEDIR'] = RAILS_ROOT + "/tmp"
end

require 'inline'

class ImageInfo
  SUPPORTED_FORMATS = %w(jpg jpeg png gif)

  def initialize(filename, type=nil)
    @filename = filename
    @type = SUPPORTED_FORMATS.index(type || @filename[/[^\.]*$/].downcase)
  end

  def height
    unless @height
      image_size
    end
    @height
  end

  def width
    unless @width
      image_size
    end
    @width
  end

  def fetch_image_size(filename, image_type); end

  def image_size
    if @type
      fetch_image_size(@filename, @type)
    else
      raise "Unknown type of image"
    end
  end

  inline do |builder|
    builder.include '"gd.h"'
    builder.add_link_flags "-lgd"

    builder.c <<-"END"
    void fetch_image_size(char *filename, int image_type) {
      gdImagePtr im_in;
      FILE *in;

      in = fopen(filename, "rb");
      /* Support diff image types: jpg jpeg png gif */
      switch(image_type) {
        case 0:
        case 1: im_in = gdImageCreateFromJpeg(in);
            break;
        case 2: im_in = gdImageCreateFromPng(in);
            break;
        case 3: im_in = gdImageCreateFromGif(in);
            break;
      }
      fclose(in);
      if (im_in) {
        rb_iv_set(self, "@width", INT2FIX(im_in->sx));
        rb_iv_set(self, "@height", INT2FIX(im_in->sy));
      }
    }
    END
  end
end

To use it, do something like this:

begin
  iinfo = ImageInfo.new(filepath)
  my_image_width = iinfo.width
  my_image_height = iinfo.height
rescue Exception=>e
  # check errors
end

5 comments for this post.

  1. Comment from Mike | 27 December 2007 | 12:41 am :

    Wow I have never realized you can use C code inside Ruby!
    I wonder, what about the performance of ImageInfo? Does it needs to get compiled every time a new instance is created, or it is compiled once and then can be used without performance decrease for compilation?

  2. Comment from Stephen Sykes | 27 December 2007 | 8:50 am :

    Mike – rubyinline is smart – it compiles once and caches the compiled code. It usually does this into a directory called .ruby_inline in your home, although it’s configurable (look at the ENV['INLINEDIR'] setting at the top of this code).

    I have had good results with performance by using inline C code – maybe 10 times faster that the same ruby. But the above example was not done for performance – I used gd for compatibility with my architecture (better than image science) and in order not to have to use a large package like RMagick for such a small task.

  3. Comment from Damien Tanner | 14 January 2008 | 6:04 pm :

    Superb!

  4. Pingback from Pennysmalls | 19 August 2008 | 8:05 am :

    [...] do not reside on our rails application server.  I have previously written about how to use the GD library to find image sizes, but this requires fetching the whole file and having it available in the local file [...]

  5. Comment from photoshop restoration and retouching | 11 August 2009 | 6:14 am :

    This is absolutely great! Thanks!!

Leave your comment...

Powered by WP Hashcash

Blog Archives

Navigation


About this blog

A blog about Ruby, Rails and other tech. Mostly.


Find Something?