Class: FormatParser::BMPParser

Inherits:
Object
  • Object
show all
Includes:
IOUtils
Defined in:
lib/parsers/bmp_parser.rb

Overview

Constant Summary collapse

VALID_BMP =
'BM'
PERMISSIBLE_PIXEL_ARRAY_LOCATIONS =
40..512

Instance Method Summary collapse

Methods included from IOUtils

#safe_read, #safe_skip

Instance Method Details

#call(io) ⇒ Object



9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
# File 'lib/parsers/bmp_parser.rb', line 9

def call(io)
  io = FormatParser::IOConstraint.new(io)

  magic_number, _file_size, _reserved1, _reserved2, pix_array_location = safe_read(io, 14).unpack('A2Vv2V')
  return unless VALID_BMP == magic_number

  # The number that gets unpacked can be fairly large, but in practice this offset cannot be too big -
  # the DIB image header won't be that big anyway/
  return unless PERMISSIBLE_PIXEL_ARRAY_LOCATIONS.cover?(pix_array_location)

  dib_header = safe_read(io, 40)

  _header_size, width, height, _planes, _bits_per_pixel,
  _compression_method, _image_size, horizontal_res,
  vertical_res, _n_colors, _i_colors = dib_header.unpack('Vl<2v2V2l<2V2')

  # There are cases where the height might by negative indicating the data
  # is ordered from top to bottom instead of bottom to top
  # http://www.dragonwins.com/domains/getteched/bmp/bmpfileformat.htm#The%20Image%20Header
  data_order = height < 0 ? :inverse : :normal

  FormatParser::Image.new(
    format: :bmp,
    width_px: width,
    height_px: height.abs,
    color_mode: :rgb,
    intrinsics: {
      vertical_resolution: vertical_res,
      horizontal_resolution: horizontal_res,
      data_order: data_order
    }
  )
end