class FileData::ExifStream

Wraps a stream with exif specific logic

Constants

HIGH_BIT_MASK
INTEL_BYTES
MOTOROLLA_BYTES
TYPE_ASCII
TYPE_BYTE
TYPE_LONG
TYPE_RATIONAL
TYPE_SHORT
TYPE_SLONG
TYPE_SRATIONAL
TYPE_UNDEFINED
VALUE_OFFSET_SIZE

Public Class Methods

new(stream) click to toggle source
# File lib/file_data/formats/exif/exif_stream.rb, line 28
def initialize(stream)
  @stream = stream
  @section_offset = stream.pos
end

Public Instance Methods

read_header() click to toggle source
# File lib/file_data/formats/exif/exif_stream.rb, line 33
def read_header
  @is_little_endian =
    case @stream.each_byte.take(2)
    when INTEL_BYTES then true
    when MOTOROLLA_BYTES then false
    else raise 'the byte order bytes did not match any expected value'
    end

  raise 'the tiff constant 42 is missing' unless read_value(2) == 42
end
read_large_val(type) click to toggle source
# File lib/file_data/formats/exif/exif_stream.rb, line 77
def read_large_val(type)
  seek_to_large_val
  read_rational(type == TYPE_SRATIONAL)
end
read_rational(is_srational) click to toggle source
# File lib/file_data/formats/exif/exif_stream.rb, line 91
def read_rational(is_srational)
  Array.new(2) do
    piece = read_value(4)
    is_srational ? to_slong(piece) : piece
  end.join('/')
end
read_raw_val(size) click to toggle source
# File lib/file_data/formats/exif/exif_stream.rb, line 72
def read_raw_val(size)
  seek_to_large_val if size > VALUE_OFFSET_SIZE
  @stream.each_byte.take([size, VALUE_OFFSET_SIZE].max)
end
read_small_val(type) click to toggle source
# File lib/file_data/formats/exif/exif_stream.rb, line 82
def read_small_val(type)
  value = read_value(4)
  type == TYPE_SLONG ? to_slong(value) : value
end
read_tag_value() click to toggle source
# File lib/file_data/formats/exif/exif_stream.rb, line 48
def read_tag_value
  type = read_value(2)
  size = read_value(4)

  case type
  when TYPE_RATIONAL, TYPE_SRATIONAL
    read_large_val(type)
  when TYPE_BYTE, TYPE_SHORT, TYPE_LONG, TYPE_SLONG
    read_small_val(type)
  when TYPE_ASCII
    read_text(size)
  when TYPE_UNDEFINED
    read_undefined(size)
  end
end
read_text(size) click to toggle source
# File lib/file_data/formats/exif/exif_stream.rb, line 64
def read_text(size)
  read_raw_val(size).pack('c*').chomp("\x00")
end
read_undefined(size) click to toggle source
# File lib/file_data/formats/exif/exif_stream.rb, line 68
def read_undefined(size)
  [read_raw_val(size), @is_little_endian]
end
seek_exif(offset) click to toggle source
# File lib/file_data/formats/exif/exif_stream.rb, line 44
def seek_exif(offset)
  @stream.seek(@section_offset + offset)
end
seek_to_large_val() click to toggle source
# File lib/file_data/formats/exif/exif_stream.rb, line 87
def seek_to_large_val
  seek_exif(read_value(4))
end
to_slong(raw_value) click to toggle source
# File lib/file_data/formats/exif/exif_stream.rb, line 98
def to_slong(raw_value)
  -(raw_value & HIGH_BIT_MASK) + (raw_value & ~HIGH_BIT_MASK)
end