Class: FileData::ExifStream
- Inherits:
-
Object
- Object
- FileData::ExifStream
- Extended by:
- Forwardable
- Includes:
- BinaryExtensions
- Defined in:
- lib/file_data/formats/exif/exif_stream.rb
Overview
Wraps a stream with exif specific logic
Constant Summary collapse
- MOTOROLLA_BYTES =
'MM'.bytes.to_a.freeze
- INTEL_BYTES =
'II'.bytes.to_a.freeze
- TYPE_BYTE =
1
- TYPE_ASCII =
2
- TYPE_SHORT =
3
- TYPE_LONG =
4
- TYPE_RATIONAL =
5
- TYPE_UNDEFINED =
7
- TYPE_SLONG =
9
- TYPE_SRATIONAL =
10
- HIGH_BIT_MASK =
2**31
- VALUE_OFFSET_SIZE =
4
Instance Method Summary collapse
-
#initialize(stream) ⇒ ExifStream
constructor
A new instance of ExifStream.
- #read_header ⇒ Object
- #read_large_val(type) ⇒ Object
- #read_rational(is_srational) ⇒ Object
- #read_raw_val(size) ⇒ Object
- #read_small_val(type) ⇒ Object
- #read_tag_value ⇒ Object
- #read_text(size) ⇒ Object
- #read_undefined(size) ⇒ Object
- #seek_exif(offset) ⇒ Object
- #seek_to_large_val ⇒ Object
- #to_slong(raw_value) ⇒ Object
Methods included from BinaryExtensions
Constructor Details
#initialize(stream) ⇒ ExifStream
Returns a new instance of ExifStream.
28 29 30 31 |
# File 'lib/file_data/formats/exif/exif_stream.rb', line 28 def initialize(stream) @stream = stream @section_offset = stream.pos end |
Instance Method Details
#read_header ⇒ Object
33 34 35 36 37 38 39 40 41 42 |
# 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) ⇒ Object
77 78 79 80 |
# 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) ⇒ Object
91 92 93 94 95 96 |
# 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) ⇒ Object
72 73 74 75 |
# 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) ⇒ Object
82 83 84 85 |
# 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 ⇒ Object
48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 |
# 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) ⇒ Object
64 65 66 |
# 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) ⇒ Object
68 69 70 |
# 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) ⇒ Object
44 45 46 |
# 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 ⇒ Object
87 88 89 |
# 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) ⇒ Object
98 99 100 |
# 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 |