Class: VivlioStarter::CLI::PreProcessCommands::ShowcaseTransformer::ImageTools

Inherits:
Object
  • Object
show all
Defined in:
lib/vivlio_starter/cli/pre_process/showcase_transformer.rb

Overview

外部ツール依存をこのクラスへ隔離する(builder は純関数のまま保つ・§7.1)。

Instance Method Summary collapse

Instance Method Details

#available?Boolean

magick と rsvg-convert が両方揃っているか。

Returns:

  • (Boolean)


285
286
287
288
289
# File 'lib/vivlio_starter/cli/pre_process/showcase_transformer.rb', line 285

def available?
  return @available unless @available.nil?

  @available = tool_ok?('magick', '-version') && tool_ok?('rsvg-convert', '--version')
end

#data_uri(path) ⇒ Object

元画像を PNG の base64 data URI へ。EMBED_MAX_EDGE まで縮小して軽量化する (viewBox は元画像実寸で張るため、縮小しても座標計算には影響しない)。



317
318
319
320
321
322
323
324
325
326
327
# File 'lib/vivlio_starter/cli/pre_process/showcase_transformer.rb', line 317

def data_uri(path)
  png, status = Open3.capture2(
    'magick', path, '-resize', "#{EMBED_MAX_EDGE}x#{EMBED_MAX_EDGE}>", 'png:-', binmode: true
  )
  return nil unless status.success? && !png.empty?

  # base64 は Ruby 3.4+ で default gem 外のため Array#pack('m0')(改行なし base64)で代替
  "data:image/png;base64,#{[png].pack('m0')}"
rescue StandardError
  nil
end

#image_dimensions(path) ⇒ Array(Integer, Integer)?

元画像の実寸(px→パーミル変換・viewBox 計算に使う)。

Returns:

  • (Array(Integer, Integer), nil)


293
294
295
296
297
298
299
300
301
# File 'lib/vivlio_starter/cli/pre_process/showcase_transformer.rb', line 293

def image_dimensions(path)
  out, status = Open3.capture2('magick', 'identify', '-format', '%w %h', path)
  return nil unless status.success?

  width, height = out.split.map(&:to_i)
  (width.to_i.positive? && height.to_i.positive?) ? [width, height] : nil
rescue StandardError
  nil
end

#photographic?(path) ⇒ Boolean

元画像が写真か(=ユニーク色数が多いか)。スクリーンショットは平坦色で色数が 桁違いに少ない(冒頭コメントの実測値)。判定はキャッシュ未ヒット時のみ走り、 実測 0.2〜0.35 秒。

Returns:

  • (Boolean)


306
307
308
309
310
311
312
313
# File 'lib/vivlio_starter/cli/pre_process/showcase_transformer.rb', line 306

def photographic?(path)
  out, status = Open3.capture2('magick', 'identify', '-format', '%k', path)
  return false unless status.success?

  out.strip.to_i > PHOTO_COLOR_THRESHOLD
rescue StandardError
  false
end

#rasterize(svg, width, format: :png) ⇒ Object

合成 SVG をラスター(バイト列)へ変換する。JPEG は透過を持てないため白で フラット化する(リーダーの白ページと馴染ませる。HeadingImageComposer と同じ流儀)。

Parameters:

  • format (Symbol) (defaults to: :png)

    :png(可逆・透過保持)/ :jpg(写真向け)



333
334
335
336
337
338
339
340
341
342
343
344
# File 'lib/vivlio_starter/cli/pre_process/showcase_transformer.rb', line 333

def rasterize(svg, width, format: :png)
  png, status = Open3.capture2('rsvg-convert', '-w', width.to_s, '-f', 'png',
                               stdin_data: svg, binmode: true)
  return nil unless status.success? && !png.empty?
  return png if format == :png

  jpg, jpg_status = Open3.capture2('magick', 'png:-', '-background', 'white', '-flatten',
                                   '-quality', '85', 'jpg:-', stdin_data: png, binmode: true)
  (jpg_status.success? && !jpg.empty?) ? jpg : nil
rescue StandardError
  nil
end