TIFF file dimensions in Ruby

Using Ruby, I wanted to get the dimensions of image files without using a full-on image library. I found handy code for PNG, BMP, GIF and JPEG and adapted the JPEG code for TIFF. Saved as gist 431893.
# TIFF.rb # by Paul Schreiber <paulschreiber at gmail.com> # 09 June 2010 # # Based on JPEG.rb by Remco van’t Veer and imagesize by Keisuke Minami <keisuke at rccn.com> # http://snippets.dzone.com/posts/show/805 # http://blog.remvee.net/2005/12/02/hoogte_en_breedte_van_een_JPEG (JPEG # http://rubyforge.org/projects/imagesize/ class TIFF attr_reader :width, :height def initialize(file) if file.kind_of? IO examine(file) else File.open(file, ‘rb’) { |io| examine(io) } end end private def def_read_o(io) io.seek(0, 0) # define Singleton-method definition to IO (byte, offset) def io.read_o(length = 1, offset = nil) self.seek(offset, 0) if offset ret = self.read(length) raise “cannot read!!” unless ret ret end io end def examine(io) img_top = io.read(1024) if not (img_top[0, 4] == “MM\x00\x2a” or img_top[0, 4] == “II\x2a\x00”) raise ‘malformed TIFF’ end img_io = def_read_o(io) endian = if (img_io.read_o(4) =~ /II\x2a\x00/o) then ‘v’ else ‘n’ end # ‘v’ little-endian ‘n’ default to big-endian packspec = [ nil, # nothing (shouldn’t happen) ‘C’, # BYTE (8-bit unsigned integer) nil, # ASCII endian, # SHORT (16-bit unsigned integer) endian.upcase, # LONG (32-bit unsigned integer) nil, # RATIONAL ‘c’, # SBYTE (8-bit signed integer) nil, # UNDEFINED endian, # SSHORT (16-bit unsigned integer) endian.upcase, # SLONG (32-bit unsigned integer) ] offset = img_io.read_o(4).unpack(endian.upcase)[0] # Get offset to IFD ifd = img_io.read_o(2, offset) num_dirent = ifd.unpack(endian)[0] # Make it useful offset += 2 num_dirent = offset + (num_dirent * 12); # Calc. maximum offset of IFD ifd = width = height = nil while(width.nil? || height.nil?) ifd = img_io.read_o(12, offset) # Get first directory entry break if (ifd.nil? || (offset > num_dirent)) offset += 12 tag = ifd.unpack(endian)[0] # …and decode its tag type = ifd[2, 2].unpack(endian)[0] # …and the data type # Check the type for sanity. next if (type > packspec.size + 0) || (packspec[type].nil?) if tag == 0x0100 # Decode the value @width = ifd[8, 4].unpack(packspec[type])[0] elsif tag == 0x0101 # Decode the value @height = ifd[8, 4].unpack(packspec[type])[0] end end raise ‘malformed TIFF’ if @width.nil? || @height.nil? end # examine end # class

Getting to Consistency

I just found slides from the SXSW Interactive Panel I moderated back in 2007.

Making software predictable and consistent makes it much easier to use. This session will explain UI consistency and point out examples of failures and their consequences. We’ll discuss when it’s appropriate to break consistency, and how to build tools and process to ensure applications are consistent with human interface guidelines and real-world practices.

Moderator: Paul Schreiber Screen Real Estate Agent, Apple
Jennifer Fraser Lead User Experience Designer, Corel
Alex Graveley Senior Engineer, VMware
Steve Johnson Senior User Experience Mgr, Adobe