Created
June 9, 2010 18:12
-
-
Save paulschreiber/431893 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# 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@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 |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment