Class: Dimensions::JpegScanner

Inherits:
Scanner
  • Object
show all
Defined in:
lib/dimensions/jpeg_scanner.rb

Constant Summary collapse

SOF_MARKERS =
[0xC0..0xC3, 0xC5..0xC7, 0xC9..0xCB, 0xCD..0xCF]
EOI_MARKER =

end of image

0xD9
SOS_MARKER =

start of stream

0xDA
APP1_MARKER =

maybe EXIF

0xE1

Instance Attribute Summary collapse

Attributes inherited from Scanner

#pos

Instance Method Summary collapse

Methods inherited from Scanner

#advance, #big!, #little!, #raise_scan_error, #read, #read_char, #read_data, #read_long, #read_short, #skip_to

Constructor Details

#initialize(data) ⇒ JpegScanner

Returns a new instance of JpegScanner.



12
13
14
15
16
17
# File 'lib/dimensions/jpeg_scanner.rb', line 12

def initialize(data)
  @width  = nil
  @height = nil
  @angle  = 0
  super
end

Instance Attribute Details

#angleObject (readonly)

Returns the value of attribute angle.



10
11
12
# File 'lib/dimensions/jpeg_scanner.rb', line 10

def angle
  @angle
end

#heightObject (readonly)

Returns the value of attribute height.



10
11
12
# File 'lib/dimensions/jpeg_scanner.rb', line 10

def height
  @height
end

#widthObject (readonly)

Returns the value of attribute width.



10
11
12
# File 'lib/dimensions/jpeg_scanner.rb', line 10

def width
  @width
end

Instance Method Details

#read_frameObject



76
77
78
79
# File 'lib/dimensions/jpeg_scanner.rb', line 76

def read_frame
  length = read_short - 2
  read_data(length)
end

#read_next_markerObject



38
39
40
41
42
# File 'lib/dimensions/jpeg_scanner.rb', line 38

def read_next_marker
  c = read_char while c != 0xFF
  c = read_char while c == 0xFF
  c
end

#scanObject



19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
# File 'lib/dimensions/jpeg_scanner.rb', line 19

def scan
  advance(2)

  while marker = read_next_marker
    case marker
    when *SOF_MARKERS
      scan_start_of_frame
    when EOI_MARKER, SOS_MARKER
      break
    when APP1_MARKER
      scan_app1_frame
    else
      skip_frame
    end
  end

  width && height
end

#scan_app1_frameObject



58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
# File 'lib/dimensions/jpeg_scanner.rb', line 58

def scan_app1_frame
  frame = read_frame
  if frame[0..5] == "Exif\000\000"
    scanner = ExifScanner.new(frame[6..-1])
    if scanner.scan
      case scanner.orientation
      when :bottom_right
        @angle = 180
      when :left_top, :right_top
        @angle = 90
      when :right_bottom, :left_bottom
        @angle = 270
      end
    end
  end
rescue ExifScanner::ScanError
end

#scan_start_of_frameObject



44
45
46
47
48
49
50
51
52
53
54
55
56
# File 'lib/dimensions/jpeg_scanner.rb', line 44

def scan_start_of_frame
  length = read_short
  read_char # depth, unused
  height = read_short
  width  = read_short
  size   = read_char

  if length == (size * 3) + 8
    @width, @height = width, height
  else
    raise_scan_error
  end
end

#skip_frameObject



81
82
83
84
# File 'lib/dimensions/jpeg_scanner.rb', line 81

def skip_frame
  length = read_short - 2
  advance(length)
end