Module: Pdfrb::ImageLoader::JPEG

Defined in:
lib/pdfrb/image_loader/jpeg.rb

Class Method Summary collapse

Class Method Details

.call(document, data, **_opts) ⇒ Object



8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
# File 'lib/pdfrb/image_loader/jpeg.rb', line 8

def call(document, data, **_opts)
  data = data.read if data.is_a?(IO) || data.is_a?(StringIO)
  info = parse_header(data)
  return nil if info.empty?

  image = document.add(
    {
      Type: :XObject,
      Subtype: :Image,
      Width: info[:width],
      Height: info[:height],
      ColorSpace: info[:color_space],
      BitsPerComponent: info[:bits],
      Filter: :DCTDecode,
      Length: data.bytesize,
    },
    type: Pdfrb::Model::Type::XObjectImage
  )
  image.stream = data
  image
end

.parse_header(data) ⇒ Object



30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
# File 'lib/pdfrb/image_loader/jpeg.rb', line 30

def parse_header(data)
  return {} unless data.is_a?(String) && data.bytesize >= 6
  return {} unless data.getbyte(0) == 0xFF && data.getbyte(1) == 0xD8

  i = 2
  while i < data.bytesize - 1
    break unless data.getbyte(i) == 0xFF

    marker = data.getbyte(i + 1)
    i += 2

    next if marker.between?(0xD0, 0xD9)
    next if marker == 0x01

    break if i + 1 >= data.bytesize

    seg_len = (data.getbyte(i) << 8) | data.getbyte(i + 1)

    if marker.between?(0xC0, 0xCF) && marker != 0xC4 && marker != 0xC8 && marker != 0xCC
      return parse_sof(data, i)
    end

    i += seg_len
  end
  {}
end

.parse_sof(data, offset) ⇒ Object



57
58
59
60
61
62
63
64
65
66
67
68
# File 'lib/pdfrb/image_loader/jpeg.rb', line 57

def parse_sof(data, offset)
  {
    bits: data.getbyte(offset + 2),
    height: (data.getbyte(offset + 3) << 8) | data.getbyte(offset + 4),
    width: (data.getbyte(offset + 5) << 8) | data.getbyte(offset + 6),
    color_space: case data.getbyte(offset + 7)
                 when 1 then :DeviceGray
                 when 4 then :DeviceCMYK
                 else :DeviceRGB
                 end,
  }
end