lib/tiff.rb in exifr-1.0.0 vs lib/tiff.rb in exifr-1.0.1

- old
+ new

@@ -457,48 +457,70 @@ def initialize(data, pos) @tag, count, @offset = data.readshort(pos), data.readlong(pos + 4), data.readlong(pos + 8) @type = data.readshort(pos + 2) case @type - when 1, 6 # byte, signed byte - # TODO handle signed bytes + when 1 # byte len, pack = count, proc { |d| d } + when 6 # signed byte + len, pack = count, proc { |d| sign_byte(d) } when 2 # ascii len, pack = count, proc { |d| d.unpack("A*") } - when 3, 8 # short, signed short - # TODO handle signed + when 3 # short len, pack = count * 2, proc { |d| d.unpack(data.short + '*') } - when 4, 9 # long, signed long - # TODO handle signed + when 8 # signed short + len, pack = count * 2, proc { |d| d.unpack(data.short + '*').map{|n| sign_short(n)} } + when 4 # long len, pack = count * 4, proc { |d| d.unpack(data.long + '*') } + when 9 # signed long + len, pack = count * 4, proc { |d| d.unpack(data.long + '*').map{|n| sign_long(n)} } when 7 # undefined # UserComment if @tag == 0x9286 len, pack = count, proc { |d| d.strip } len -= 8 # reduce to account for first 8 bytes start = len > 4 ? @offset + 8 : (pos + 8) # UserComment first 8-bytes is char code @value = [pack[data[start..(start + len - 1)]]].flatten end - when 5, 10 + when 5 # unsigned rational len, pack = count * 8, proc do |d| - r = [] - d.unpack(data.long + '*').each_with_index do |v,i| - i % 2 == 0 ? r << [v] : r.last << v + d.unpack(data.long + '*').each_slice(2).map do |f| + rational(*f) end - r.map do |f| - if f[1] == 0 # allow NaN and Infinity - f[0].to_f.quo(f[1]) - else - Rational.respond_to?(:reduce) ? Rational.reduce(*f) : f[0].quo(f[1]) - end + end + when 10 # signed rational + len, pack = count * 8, proc do |d| + d.unpack(data.long + '*').map{|n| sign_long(n)}.each_slice(2).map do |f| + rational(*f) end end end if len && pack && @type != 7 start = len > 4 ? @offset : (pos + 8) d = data[start..(start + len - 1)] @value = d && [pack[d]].flatten + end + end + + private + def sign_byte(n) + (n & 0x80) != 0 ? n - 0x100 : n + end + + def sign_short(n) + (n & 0x8000) != 0 ? n - 0x10000 : n + end + + def sign_long(n) + (n & 0x80000000) != 0 ? n - 0x100000000 : n + end + + def rational(n, d) + if d == 0 # allow NaN and Infinity + n.to_f.quo(d) + else + Rational.respond_to?(:reduce) ? Rational.reduce(n, d) : n.quo(d) end end end class Data #:nodoc: