Module: VivlioStarter::Pdf::JpegToPdf::JpegInfo

Defined in:
lib/vivlio_starter/cli/pdf/jpeg_to_pdf.rb

Overview

JPEG の SOF マーカーから PDF 埋め込みに必要な寸法・色空間を読む。

Constant Summary collapse

SOF_MARKERS =
[0xC0, 0xC1, 0xC2, 0xC3, 0xC5, 0xC6, 0xC7, 0xC9, 0xCA, 0xCB, 0xCD, 0xCE, 0xCF].freeze
STANDALONE_MARKERS =
[0x01, *(0xD0..0xD9)].freeze

Class Method Summary collapse

Class Method Details

.color_space_for(components, path:) ⇒ Object



202
203
204
205
206
207
208
209
# File 'lib/vivlio_starter/cli/pdf/jpeg_to_pdf.rb', line 202

def color_space_for(components, path:)
  case components
  when 1 then '/DeviceGray'
  when 3 then '/DeviceRGB'
  else
    raise Error, "対応していないJPEG色空間です: components=#{components} #{path}"
  end
end

.jpeg?(data) ⇒ Boolean

Returns:

  • (Boolean)


171
172
173
# File 'lib/vivlio_starter/cli/pdf/jpeg_to_pdf.rb', line 171

def jpeg?(data)
  data.bytesize >= 4 && data.getbyte(0) == 0xFF && data.getbyte(1) == 0xD8
end

.metadata_from_sof(data, offset, path:) ⇒ Object

Raises:



190
191
192
193
194
195
196
197
198
199
200
# File 'lib/vivlio_starter/cli/pdf/jpeg_to_pdf.rb', line 190

def (data, offset, path:)
  segment_length = read_segment_length(data, offset, path:)
  raise Error, "JPEG SOF セグメントが壊れています: #{path}" if segment_length < 8

  bits = data.getbyte(offset + 2)
  height = data.byteslice(offset + 3, 2).unpack1('n')
  width = data.byteslice(offset + 5, 2).unpack1('n')
  components = data.getbyte(offset + 7)

  JpegMetadata.new(width:, height:, bits_per_component: bits, color_space: color_space_for(components, path:))
end

.next_marker_offset(data, offset) ⇒ Object



175
176
177
178
179
180
181
182
# File 'lib/vivlio_starter/cli/pdf/jpeg_to_pdf.rb', line 175

def next_marker_offset(data, offset)
  index = offset
  index += 1 while index < data.bytesize && data.getbyte(index) != 0xFF
  index += 1 while index < data.bytesize && data.getbyte(index) == 0xFF
  return nil if index >= data.bytesize

  index - 1
end

.read(data, path: nil) ⇒ Object

Raises:



150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
# File 'lib/vivlio_starter/cli/pdf/jpeg_to_pdf.rb', line 150

def read(data, path: nil)
  raise Error, "JPEG ではありません: #{path}" unless jpeg?(data)

  offset = 2
  while offset < data.bytesize
    marker_offset = next_marker_offset(data, offset)
    raise Error, "JPEG の寸法を取得できませんでした: #{path}" unless marker_offset

    marker = data.getbyte(marker_offset + 1)
    offset = marker_offset + 2
    next if STANDALONE_MARKERS.include?(marker)

    segment_length = read_segment_length(data, offset, path:)
    return (data, offset, path:) if SOF_MARKERS.include?(marker)

    offset += segment_length
  end

  raise Error, "JPEG の寸法を取得できませんでした: #{path}"
end

.read_segment_length(data, offset, path:) ⇒ Object

Raises:



184
185
186
187
188
# File 'lib/vivlio_starter/cli/pdf/jpeg_to_pdf.rb', line 184

def read_segment_length(data, offset, path:)
  raise Error, "JPEG セグメントが壊れています: #{path}" if offset + 1 >= data.bytesize

  data.byteslice(offset, 2).unpack1('n')
end