Module: Vivlio::Starter::CLI::Import::ImageProcessor

Defined in:
lib/vivlio/starter/cli/import/image_processor.rb

Overview

画像処理モジュール

Constant Summary collapse

MASTER_WIDTH =
CoverCommands::SIZES[:a4][:width]
MASTER_HEIGHT =
CoverCommands::SIZES[:a4][:height]

Class Method Summary collapse

Class Method Details

.command_in_path?(command) ⇒ Boolean

Returns:

  • (Boolean)


169
170
171
172
173
174
175
176
# File 'lib/vivlio/starter/cli/import/image_processor.rb', line 169

def command_in_path?(command)
  return false if command.to_s.empty?

  ENV.fetch('PATH', '').split(File::PATH_SEPARATOR).any? do |dir|
    path = File.join(dir, command)
    File.executable?(path) && !File.directory?(path)
  end
end

.convert_front_cover_pdf_to_master!(covers_dir, cover_filename) ⇒ Object

Re:VIEW の PDF を Vivlio マスター PNG へ変換する



106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
# File 'lib/vivlio/starter/cli/import/image_processor.rb', line 106

def convert_front_cover_pdf_to_master!(covers_dir, cover_filename)
  pdf_path = File.join(covers_dir, cover_filename)
  unless File.exist?(pdf_path)
    Common.log_warn("  コピー済みの表紙 PDF が見つかりません: #{pdf_path}")
    return false
  end

  convert_cmd = find_imagemagick_convert_command
  unless convert_cmd
    Common.log_warn('  ImageMagick(magick/convert)が見つからないため frontcover_master.png を生成できませんでした')
    return false
  end

  master_path = File.join(covers_dir, CoverCommands::FRONTCOVER_MASTER)
  cmd = convert_cmd + [
    "#{pdf_path}[0]",
    '-density', '350',
    '-resize', "#{MASTER_WIDTH}x#{MASTER_HEIGHT}!",
    '-quality', '100',
    "PNG32:#{master_path}"
  ]

  if run_imagemagick_command(cmd, label: 'frontcover_master.png 生成')
    Common.log_info("  frontcover_master.png を生成しました: #{master_path}")
    true
  else
    FileUtils.rm_f(master_path)
    false
  end
end

.convert_to_webp!(starter_dir) ⇒ void

This method returns an undefined value.

画像を WebP に変換してコピーする

Parameters:

  • starter_dir (String)

    Starter プロジェクトのディレクトリ



41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
# File 'lib/vivlio/starter/cli/import/image_processor.rb', line 41

def convert_to_webp!(starter_dir)
  Common.log_action('[Step 3] 画像を WebP に変換します')

  starter_images = File.join(starter_dir, 'images')
  unless Dir.exist?(starter_images)
    Common.log_warn("  images/ ディレクトリが見つかりません: #{starter_images}")
    return
  end

  files = copy_images_to_local(starter_images)
  return if files.empty?

  Common.log_info("  #{files.size} 個の画像をコピーしました")

  # ResizeCommands で WebP 変換
  ResizeCommands.execute_resize_medium('images')
  remove_original_files!
end

.copy_front_cover!(starter_dir, cover_filename) ⇒ Boolean

表紙 PDF をコピーし、frontcover_master.png を生成する

Parameters:

  • starter_dir (String)

    Starter プロジェクトのディレクトリ

  • cover_filename (String)

    表紙ファイル名(例: hyoshi.pdf)

Returns:

  • (Boolean)

    成功時 true



85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
# File 'lib/vivlio/starter/cli/import/image_processor.rb', line 85

def copy_front_cover!(starter_dir, cover_filename)
  return false unless cover_filename
  return false unless cover_filename.downcase.end_with?('.pdf')

  src = File.join(starter_dir, 'images', cover_filename)
  unless File.exist?(src)
    Common.log_warn("  表紙 PDF が見つかりません: #{src}")
    return false
  end

  dest_dir = 'covers'
  FileUtils.mkdir_p(dest_dir)

  dest = File.join(dest_dir, cover_filename)
  FileUtils.cp(src, dest)
  Common.log_info("  表紙 PDF をコピーしました: #{cover_filename} → covers/")

  convert_front_cover_pdf_to_master!(dest_dir, cover_filename)
end

.copy_images_to_local(starter_images) ⇒ Array<String>

画像ファイルをローカルにコピーする

Parameters:

  • starter_images (String)

    Starter の images ディレクトリパス

Returns:

  • (Array<String>)

    コピーしたファイルのリスト



143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
# File 'lib/vivlio/starter/cli/import/image_processor.rb', line 143

def copy_images_to_local(starter_images)
  patterns = %w[png jpg jpeg gif PNG JPG JPEG GIF]
  files = patterns.flat_map { |ext| Dir.glob(File.join(starter_images, "**/*.#{ext}")) }

  if files.empty?
    Common.log_info('  変換対象の画像がありません')
    return []
  end

  files.each do |src|
    relative = src.sub("#{starter_images}/", '')
    dest_dir = File.join('images', File.dirname(relative))
    FileUtils.mkdir_p(dest_dir)
    FileUtils.cp(src, File.join(dest_dir, File.basename(src)))
  end

  files
end

.find_imagemagick_convert_commandObject



162
163
164
165
166
167
# File 'lib/vivlio/starter/cli/import/image_processor.rb', line 162

def find_imagemagick_convert_command
  return %w[magick convert] if command_in_path?('magick')
  return ['convert'] if command_in_path?('convert')

  nil
end

.remove_original_files!void

This method returns an undefined value.

元画像(png/jpg/gif)を削除する



63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
# File 'lib/vivlio/starter/cli/import/image_processor.rb', line 63

def remove_original_files!
  removed = 0
  Dir.glob(File.join('images', '**', '*')).each do |path|
    next unless File.file?(path)
    next unless path.match?(/\.(png|jpe?g|gif)$/i)

    FileUtils.rm_f(path)
    removed += 1
  end

  if removed.positive?
    Common.log_info("  旧画像 (png/jpg/gif) を #{removed} 個削除しました")
  else
    Common.log_info('  削除対象の旧画像はありませんでした')
  end
end

.run_imagemagick_command(cmd, label:) ⇒ Object



178
179
180
181
182
183
# File 'lib/vivlio/starter/cli/import/image_processor.rb', line 178

def run_imagemagick_command(cmd, label:)
  Common.log_action("  $ #{Shellwords.join(cmd.map(&:to_s))}")
  success = system(*cmd, out: File::NULL, err: File::NULL)
  Common.log_error("  #{label} に失敗しました") unless success
  success
end