Class: VivlioStarter::CLI::PreProcessCommands::ShowcaseTransformer::ImageTools
- Inherits:
-
Object
- Object
- VivlioStarter::CLI::PreProcessCommands::ShowcaseTransformer::ImageTools
- Defined in:
- lib/vivlio_starter/cli/pre_process/showcase_transformer.rb
Overview
外部ツール依存をこのクラスへ隔離する(builder は純関数のまま保つ・§7.1)。
Instance Method Summary collapse
-
#available? ⇒ Boolean
magick と rsvg-convert が両方揃っているか。.
-
#data_uri(path) ⇒ Object
元画像を PNG の base64 data URI へ。EMBED_MAX_EDGE まで縮小して軽量化する (viewBox は元画像実寸で張るため、縮小しても座標計算には影響しない)。.
-
#image_dimensions(path) ⇒ Array(Integer, Integer)?
元画像の実寸(px→パーミル変換・viewBox 計算に使う)。.
-
#photographic?(path) ⇒ Boolean
元画像が写真か(=ユニーク色数が多いか)。スクリーンショットは平坦色で色数が 桁違いに少ない(冒頭コメントの実測値)。判定はキャッシュ未ヒット時のみ走り、 実測 0.2〜0.35 秒。.
-
#rasterize(svg, width, format: :png) ⇒ Object
合成 SVG をラスター(バイト列)へ変換する。JPEG は透過を持てないため白で フラット化する(リーダーの白ページと馴染ませる。HeadingImageComposer と同じ流儀)。.
Instance Method Details
#available? ⇒ Boolean
magick と rsvg-convert が両方揃っているか。
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 計算に使う)。
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 秒。
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 と同じ流儀)。
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 |