Find jpeg dimensions fast in pure Ruby, no image library needed

It so happens that in our application we need to find the dimensions of many images that 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 system.Fortunately we know all these files are jpegs, and if you check the jpeg documentation you can see that the dimensions of an image are normally contained near the start, which is ideal.  We will just fetch enough of the image to get the dimensions, and no more.How can we do that?  The get method from Net::HTTP will do the trick – given a block it will yield each packet of data from the remote server as it arrives. And fetching over http makes this method very general – we can size any jpeg from anywhere using this code.Parsing the returned data for the dimensions requires a simple state machine which will break from the http get block once the dimensions are located.So I ended up with a small class to encapsulate the dimension information from the jpeg, JpegDimensions. Here’s how to use it:

jpg_info ="")jpg_info.height  # is the heightjpg_info.width  # is the width??

And the best thing is that only a small part of the image will be fetched, saving time and bandwith.Here’s the code

require 'net/http'class JpegDimensions  attr_reader :width, :height  def initialize(image_path)    @uri_split = URI.split(image_path)    find_jpeg_size  end  def find_jpeg_size    begin      http =[2], @uri_split[3])      state = 0      http.get(@uri_split[5]) do |str|  # this yields strings as each packet arrives        str.each_byte do |b|          state = case state          when 0            b == 0xFF ? 1 : 0          when 1            b >= 0xC0 && b <= 0xC3 ? 2 : 0          when 2            3          when 3            4          when 4            5          when 5            @height = b * 256            6          when 6            @height += b            7          when 7            @width = b * 256            8          when 8            @width += b            break          end        end        break if state == 8  # don't need to fetch any more of the image      end    rescue Exception=>e      # I do nothing here, but you can do something more useful with the exception if required    end  endend

3 thoughts on “Find jpeg dimensions fast in pure Ruby, no image library needed

  1. […] just released a gem to find image dimensions and type information fast. I have previously done some work in this area, but this is a much more comprehensive solution, and fixes problems with certain […]

Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s