ruby_spriter 0.6.6 → 0.6.7.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +257 -0
- data/README.md +384 -33
- data/lib/ruby_spriter/batch_processor.rb +214 -0
- data/lib/ruby_spriter/cli.rb +355 -8
- data/lib/ruby_spriter/compression_manager.rb +101 -0
- data/lib/ruby_spriter/consolidator.rb +33 -0
- data/lib/ruby_spriter/dependency_checker.rb +65 -15
- data/lib/ruby_spriter/gimp_processor.rb +395 -4
- data/lib/ruby_spriter/platform.rb +56 -1
- data/lib/ruby_spriter/processor.rb +419 -9
- data/lib/ruby_spriter/version.rb +2 -2
- data/lib/ruby_spriter.rb +2 -0
- data/spec/ruby_spriter/batch_processor_spec.rb +200 -0
- data/spec/ruby_spriter/cli_spec.rb +387 -0
- data/spec/ruby_spriter/compression_manager_spec.rb +157 -0
- data/spec/ruby_spriter/consolidator_spec.rb +163 -0
- data/spec/ruby_spriter/platform_spec.rb +11 -1
- data/spec/ruby_spriter/processor_spec.rb +350 -0
- metadata +6 -2
|
@@ -0,0 +1,214 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'fileutils'
|
|
4
|
+
|
|
5
|
+
module RubySpriter
|
|
6
|
+
# Processes multiple videos in batch mode
|
|
7
|
+
class BatchProcessor
|
|
8
|
+
attr_reader :options
|
|
9
|
+
|
|
10
|
+
def initialize(options = {})
|
|
11
|
+
@options = options
|
|
12
|
+
validate_directory!
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
# Find all MP4 files in the directory
|
|
16
|
+
# @return [Array<String>] List of MP4 file paths
|
|
17
|
+
def find_videos
|
|
18
|
+
pattern = File.join(options[:dir], '*.mp4')
|
|
19
|
+
videos = Dir.glob(pattern)
|
|
20
|
+
|
|
21
|
+
if videos.empty?
|
|
22
|
+
raise ValidationError, "No MP4 files found in directory: #{options[:dir]}"
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
if options[:debug]
|
|
26
|
+
Utils::OutputFormatter.note("Found #{videos.length} video(s) to process")
|
|
27
|
+
videos.each { |v| Utils::OutputFormatter.indent(File.basename(v)) }
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
videos
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
# Process all videos in the directory
|
|
34
|
+
# @return [Hash] Processing results with outputs and errors
|
|
35
|
+
def process
|
|
36
|
+
videos = find_videos
|
|
37
|
+
output_dir = determine_output_directory
|
|
38
|
+
ensure_output_directory_exists(output_dir)
|
|
39
|
+
|
|
40
|
+
results = {
|
|
41
|
+
processed_count: 0,
|
|
42
|
+
outputs: [],
|
|
43
|
+
errors: []
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
Utils::OutputFormatter.header("Batch Processing: #{videos.length} video(s)")
|
|
47
|
+
|
|
48
|
+
videos.each_with_index do |video, index|
|
|
49
|
+
begin
|
|
50
|
+
puts "\nProcessing [#{index + 1}/#{videos.length}]: #{File.basename(video)}"
|
|
51
|
+
|
|
52
|
+
output_file = determine_output_file(video, output_dir)
|
|
53
|
+
output_file = Utils::FileHelper.ensure_unique_output(output_file, overwrite: options[:overwrite])
|
|
54
|
+
|
|
55
|
+
# Process video
|
|
56
|
+
video_result = process_video(video, output_file)
|
|
57
|
+
|
|
58
|
+
# Apply max compression if requested
|
|
59
|
+
if options[:max_compress] && video_result[:output_file]
|
|
60
|
+
video_result[:output_file] = apply_compression(video_result[:output_file])
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
results[:outputs] << video_result[:output_file]
|
|
64
|
+
results[:processed_count] += 1
|
|
65
|
+
|
|
66
|
+
Utils::OutputFormatter.success("Output: #{File.basename(video_result[:output_file])}")
|
|
67
|
+
rescue StandardError => e
|
|
68
|
+
error_msg = "#{File.basename(video)}: #{e.message}"
|
|
69
|
+
results[:errors] << error_msg
|
|
70
|
+
Utils::OutputFormatter.error(error_msg)
|
|
71
|
+
end
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
# Consolidate if requested
|
|
75
|
+
if options[:batch_consolidate] && results[:outputs].any?
|
|
76
|
+
consolidated = consolidate_results(results[:outputs])
|
|
77
|
+
results[:consolidated] = consolidated if consolidated
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
display_summary(results)
|
|
81
|
+
|
|
82
|
+
results
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
# Consolidate all resulting spritesheets
|
|
86
|
+
# @param outputs [Array<String>] List of spritesheet file paths
|
|
87
|
+
# @return [Hash, nil] Consolidation result or nil if not requested
|
|
88
|
+
def consolidate_results(outputs)
|
|
89
|
+
return nil unless options[:batch_consolidate]
|
|
90
|
+
return nil if outputs.empty?
|
|
91
|
+
|
|
92
|
+
Utils::OutputFormatter.header("Consolidating #{outputs.length} spritesheets")
|
|
93
|
+
|
|
94
|
+
output_dir = options[:outputdir] || options[:dir]
|
|
95
|
+
consolidated_file = File.join(output_dir, 'batch_consolidated_spritesheet.png')
|
|
96
|
+
consolidated_file = Utils::FileHelper.ensure_unique_output(consolidated_file, overwrite: options[:overwrite])
|
|
97
|
+
|
|
98
|
+
consolidator = Consolidator.new(options)
|
|
99
|
+
result = consolidator.consolidate(outputs, consolidated_file)
|
|
100
|
+
|
|
101
|
+
Utils::OutputFormatter.success("Consolidated output: #{File.basename(consolidated_file)}")
|
|
102
|
+
|
|
103
|
+
result
|
|
104
|
+
end
|
|
105
|
+
|
|
106
|
+
private
|
|
107
|
+
|
|
108
|
+
def validate_directory!
|
|
109
|
+
dir = options[:dir]
|
|
110
|
+
|
|
111
|
+
raise ValidationError, "Must specify --dir for batch processing" unless dir
|
|
112
|
+
raise ValidationError, "Directory not found: #{dir}" unless File.directory?(dir)
|
|
113
|
+
end
|
|
114
|
+
|
|
115
|
+
def determine_output_directory
|
|
116
|
+
options[:outputdir] || options[:dir]
|
|
117
|
+
end
|
|
118
|
+
|
|
119
|
+
def ensure_output_directory_exists(dir)
|
|
120
|
+
return if File.directory?(dir)
|
|
121
|
+
|
|
122
|
+
if options[:debug]
|
|
123
|
+
Utils::OutputFormatter.note("Creating output directory: #{dir}")
|
|
124
|
+
end
|
|
125
|
+
|
|
126
|
+
FileUtils.mkdir_p(dir)
|
|
127
|
+
end
|
|
128
|
+
|
|
129
|
+
def determine_output_file(video_file, output_dir)
|
|
130
|
+
basename = File.basename(video_file, '.*')
|
|
131
|
+
File.join(output_dir, "#{basename}_spritesheet.png")
|
|
132
|
+
end
|
|
133
|
+
|
|
134
|
+
def process_video(video_file, output_file)
|
|
135
|
+
video_processor = VideoProcessor.new(options)
|
|
136
|
+
result = video_processor.create_spritesheet(video_file, output_file)
|
|
137
|
+
|
|
138
|
+
working_file = result[:output_file]
|
|
139
|
+
|
|
140
|
+
# Apply GIMP processing if requested
|
|
141
|
+
if needs_gimp_processing?
|
|
142
|
+
working_file = process_with_gimp(working_file, result)
|
|
143
|
+
end
|
|
144
|
+
|
|
145
|
+
# Update result with final file
|
|
146
|
+
result[:output_file] = working_file
|
|
147
|
+
result
|
|
148
|
+
end
|
|
149
|
+
|
|
150
|
+
def needs_gimp_processing?
|
|
151
|
+
options[:scale_percent] || options[:remove_bg] || options[:sharpen]
|
|
152
|
+
end
|
|
153
|
+
|
|
154
|
+
def process_with_gimp(input_file, video_result)
|
|
155
|
+
# Get GIMP path and version from dependency checker
|
|
156
|
+
checker = DependencyChecker.new(verbose: false)
|
|
157
|
+
results = checker.check_all
|
|
158
|
+
gimp_path = checker.gimp_path
|
|
159
|
+
gimp_version = checker.gimp_version
|
|
160
|
+
|
|
161
|
+
unless gimp_path
|
|
162
|
+
raise DependencyError, "GIMP not found but required for processing"
|
|
163
|
+
end
|
|
164
|
+
|
|
165
|
+
gimp_options = options.merge(gimp_version: gimp_version)
|
|
166
|
+
gimp_processor = GimpProcessor.new(gimp_path, gimp_options)
|
|
167
|
+
output_file = gimp_processor.process(input_file)
|
|
168
|
+
|
|
169
|
+
# Clean up intermediate file if different
|
|
170
|
+
if output_file != input_file && File.exist?(input_file)
|
|
171
|
+
File.delete(input_file) unless options[:keep_temp]
|
|
172
|
+
end
|
|
173
|
+
|
|
174
|
+
output_file
|
|
175
|
+
end
|
|
176
|
+
|
|
177
|
+
def apply_compression(file)
|
|
178
|
+
Utils::OutputFormatter.indent("Applying maximum compression...")
|
|
179
|
+
|
|
180
|
+
temp_file = file.gsub('.png', '_temp.png')
|
|
181
|
+
CompressionManager.compress_with_metadata(file, temp_file)
|
|
182
|
+
|
|
183
|
+
# Show compression stats
|
|
184
|
+
if options[:debug]
|
|
185
|
+
stats = CompressionManager.compression_stats(file, temp_file)
|
|
186
|
+
Utils::OutputFormatter.indent("Saved #{Utils::FileHelper.format_size(stats[:saved_bytes])} (#{stats[:reduction_percent].round(1)}% reduction)")
|
|
187
|
+
end
|
|
188
|
+
|
|
189
|
+
# Replace original with compressed
|
|
190
|
+
FileUtils.mv(temp_file, file)
|
|
191
|
+
|
|
192
|
+
file
|
|
193
|
+
end
|
|
194
|
+
|
|
195
|
+
def display_summary(results)
|
|
196
|
+
Utils::OutputFormatter.header("Batch Processing Summary")
|
|
197
|
+
|
|
198
|
+
puts "Total videos: #{results[:processed_count] + results[:errors].length}"
|
|
199
|
+
Utils::OutputFormatter.success("Successfully processed: #{results[:processed_count]}")
|
|
200
|
+
|
|
201
|
+
if results[:errors].any?
|
|
202
|
+
Utils::OutputFormatter.error("Failed: #{results[:errors].length}")
|
|
203
|
+
results[:errors].each do |error|
|
|
204
|
+
Utils::OutputFormatter.indent("- #{error}")
|
|
205
|
+
end
|
|
206
|
+
end
|
|
207
|
+
|
|
208
|
+
if results[:consolidated]
|
|
209
|
+
puts "\nConsolidated spritesheet:"
|
|
210
|
+
Utils::OutputFormatter.indent(results[:consolidated][:output_file])
|
|
211
|
+
end
|
|
212
|
+
end
|
|
213
|
+
end
|
|
214
|
+
end
|
data/lib/ruby_spriter/cli.rb
CHANGED
|
@@ -18,6 +18,12 @@ module RubySpriter
|
|
|
18
18
|
|
|
19
19
|
def parse_and_run(args)
|
|
20
20
|
options = {}
|
|
21
|
+
|
|
22
|
+
# Handle context-sensitive help before validation
|
|
23
|
+
if args.include?('--help') || args.include?('-h')
|
|
24
|
+
handle_context_sensitive_help(args)
|
|
25
|
+
end
|
|
26
|
+
|
|
21
27
|
parser = build_option_parser(options)
|
|
22
28
|
|
|
23
29
|
parser.parse!(args)
|
|
@@ -29,6 +35,16 @@ module RubySpriter
|
|
|
29
35
|
exit(checker.all_satisfied? ? 0 : 1)
|
|
30
36
|
end
|
|
31
37
|
|
|
38
|
+
# Validate mutually exclusive options
|
|
39
|
+
if options[:extract] && options[:split]
|
|
40
|
+
raise ValidationError, "--extract and --split are mutually exclusive"
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
# Validate --add-meta cannot be combined with processing options
|
|
44
|
+
if options[:add_meta] && (options[:scale_percent] || options[:remove_bg] || options[:sharpen])
|
|
45
|
+
raise ValidationError, "--add-meta cannot be combined with processing options (--scale, --remove-bg, --sharpen)"
|
|
46
|
+
end
|
|
47
|
+
|
|
32
48
|
# Run processor
|
|
33
49
|
processor = Processor.new(options)
|
|
34
50
|
processor.run
|
|
@@ -57,14 +73,21 @@ module RubySpriter
|
|
|
57
73
|
|
|
58
74
|
def add_header(opts)
|
|
59
75
|
opts.separator ""
|
|
60
|
-
opts.separator "Ruby Spriter v#{VERSION} - MP4 to Spritesheet
|
|
76
|
+
opts.separator "Ruby Spriter v#{VERSION} - Professional MP4 to Spritesheet Converter with Advanced Image Processing"
|
|
61
77
|
opts.separator "Platform: #{Platform.current.to_s.capitalize}"
|
|
62
78
|
opts.separator ""
|
|
79
|
+
opts.separator "Get mode-specific help:"
|
|
80
|
+
opts.separator " ruby_spriter --video --help"
|
|
81
|
+
opts.separator " ruby_spriter --image --help"
|
|
82
|
+
opts.separator " ruby_spriter --consolidate --help"
|
|
83
|
+
opts.separator " ruby_spriter --batch --help"
|
|
84
|
+
opts.separator " ruby_spriter --split --help"
|
|
85
|
+
opts.separator ""
|
|
63
86
|
end
|
|
64
87
|
|
|
65
88
|
def add_input_options(opts, options)
|
|
66
89
|
opts.separator "Input Options:"
|
|
67
|
-
|
|
90
|
+
|
|
68
91
|
opts.on("-v", "--video FILE", "Input video file (MP4)") do |v|
|
|
69
92
|
options[:video] = v
|
|
70
93
|
end
|
|
@@ -73,8 +96,25 @@ module RubySpriter
|
|
|
73
96
|
options[:image] = i
|
|
74
97
|
end
|
|
75
98
|
|
|
76
|
-
opts.on("--
|
|
77
|
-
options[:
|
|
99
|
+
opts.on("--batch", "Batch process all MP4 files in directory") do
|
|
100
|
+
options[:batch] = true
|
|
101
|
+
end
|
|
102
|
+
|
|
103
|
+
opts.on("--dir DIRECTORY", "Directory for batch processing") do |d|
|
|
104
|
+
options[:dir] = d
|
|
105
|
+
end
|
|
106
|
+
|
|
107
|
+
opts.on("--outputdir DIRECTORY", "Output directory for batch processing") do |d|
|
|
108
|
+
options[:outputdir] = d
|
|
109
|
+
end
|
|
110
|
+
|
|
111
|
+
opts.on("--batch-consolidate", "Consolidate all spritesheets after batch processing") do
|
|
112
|
+
options[:batch_consolidate] = true
|
|
113
|
+
end
|
|
114
|
+
|
|
115
|
+
opts.on("--consolidate [FILES]", Array, "Consolidate spritesheets (comma-separated files or use with --dir)") do |c|
|
|
116
|
+
options[:consolidate_mode] = true
|
|
117
|
+
options[:consolidate] = c if c && !c.empty?
|
|
78
118
|
end
|
|
79
119
|
|
|
80
120
|
opts.on("--verify FILE", "Verify spritesheet metadata") do |v|
|
|
@@ -89,6 +129,22 @@ module RubySpriter
|
|
|
89
129
|
options[:override_md] = true
|
|
90
130
|
end
|
|
91
131
|
|
|
132
|
+
opts.on("--extract FRAMES", "Extract specific frames by number (comma-separated, e.g., 1,2,4,5,8)") do |e|
|
|
133
|
+
options[:extract] = e
|
|
134
|
+
end
|
|
135
|
+
|
|
136
|
+
opts.on("--columns NUM", Integer, "Number of columns for extracted spritesheet (default: 4)") do |c|
|
|
137
|
+
options[:columns] = c
|
|
138
|
+
end
|
|
139
|
+
|
|
140
|
+
opts.on("--add-meta R:C", "Add spritesheet metadata to image (rows:columns, e.g., 4:4)") do |m|
|
|
141
|
+
options[:add_meta] = m
|
|
142
|
+
end
|
|
143
|
+
|
|
144
|
+
opts.on("--overwrite-meta", "Overwrite existing metadata when using --add-meta") do
|
|
145
|
+
options[:overwrite_meta] = true
|
|
146
|
+
end
|
|
147
|
+
|
|
92
148
|
opts.separator ""
|
|
93
149
|
end
|
|
94
150
|
|
|
@@ -115,7 +171,7 @@ module RubySpriter
|
|
|
115
171
|
options[:bg_color] = b
|
|
116
172
|
end
|
|
117
173
|
|
|
118
|
-
opts.on("--save-frames", "Save individual frames to disk (video
|
|
174
|
+
opts.on("--save-frames", "Save individual frames to disk (for --video or --extract)") do
|
|
119
175
|
options[:save_frames] = true
|
|
120
176
|
end
|
|
121
177
|
|
|
@@ -123,7 +179,7 @@ module RubySpriter
|
|
|
123
179
|
end
|
|
124
180
|
|
|
125
181
|
def add_gimp_options(opts, options)
|
|
126
|
-
opts.separator "
|
|
182
|
+
opts.separator "Processing Options:"
|
|
127
183
|
|
|
128
184
|
opts.on("-s", "--scale PERCENT", Integer, "Scale image by percentage") do |s|
|
|
129
185
|
options[:scale_percent] = s
|
|
@@ -150,11 +206,11 @@ module RubySpriter
|
|
|
150
206
|
options[:sharpen_threshold] = t
|
|
151
207
|
end
|
|
152
208
|
|
|
153
|
-
opts.on("-r", "--remove-bg", "Remove background from spritesheet
|
|
209
|
+
opts.on("-r", "--remove-bg", "Remove background from spritesheet") do
|
|
154
210
|
options[:remove_bg] = true
|
|
155
211
|
end
|
|
156
212
|
|
|
157
|
-
opts.on("-t", "--threshold VALUE", Float, "
|
|
213
|
+
opts.on("-t", "--threshold VALUE", Float, "Background color tolerance % (default: 15.0, range: 0-100)") do |t|
|
|
158
214
|
options[:bg_threshold] = t
|
|
159
215
|
end
|
|
160
216
|
|
|
@@ -220,6 +276,10 @@ module RubySpriter
|
|
|
220
276
|
def add_other_options(opts, options)
|
|
221
277
|
opts.separator "Other Options:"
|
|
222
278
|
|
|
279
|
+
opts.on("--max-compress", "Apply maximum PNG compression to output") do
|
|
280
|
+
options[:max_compress] = true
|
|
281
|
+
end
|
|
282
|
+
|
|
223
283
|
opts.on("--overwrite", "Overwrite existing output files (default: create unique filenames)") do
|
|
224
284
|
options[:overwrite] = true
|
|
225
285
|
end
|
|
@@ -255,11 +315,298 @@ module RubySpriter
|
|
|
255
315
|
opts.separator " ruby_spriter --video input.mp4"
|
|
256
316
|
opts.separator " ruby_spriter --video input.mp4 --remove-bg --scale 50"
|
|
257
317
|
opts.separator " ruby_spriter --video input.mp4 --scale 50 --interpolation nohalo --sharpen"
|
|
318
|
+
opts.separator " ruby_spriter --video input.mp4 --max-compress"
|
|
258
319
|
opts.separator " ruby_spriter --image sprite.png --scale 50 --sharpen --sharpen-gain 1.5"
|
|
259
320
|
opts.separator " ruby_spriter --image sprite.png --remove-bg --fuzzy"
|
|
321
|
+
opts.separator " ruby_spriter --batch --dir videos/"
|
|
322
|
+
opts.separator " ruby_spriter --batch --dir videos/ --outputdir output/"
|
|
323
|
+
opts.separator " ruby_spriter --batch --dir videos/ --batch-consolidate --max-compress"
|
|
260
324
|
opts.separator " ruby_spriter --consolidate file1.png,file2.png,file3.png"
|
|
325
|
+
opts.separator " ruby_spriter --consolidate --dir spritesheets/"
|
|
326
|
+
opts.separator " ruby_spriter --consolidate --dir spritesheets/ --outputdir output/ --max-compress"
|
|
261
327
|
opts.separator " ruby_spriter --verify spritesheet.png"
|
|
262
328
|
opts.separator ""
|
|
263
329
|
end
|
|
330
|
+
|
|
331
|
+
def handle_context_sensitive_help(args)
|
|
332
|
+
if args.include?('--video') || args.include?('-v')
|
|
333
|
+
show_video_mode_help
|
|
334
|
+
elsif args.include?('--image') || args.include?('-i')
|
|
335
|
+
show_image_mode_help
|
|
336
|
+
elsif args.include?('--consolidate')
|
|
337
|
+
show_consolidate_mode_help
|
|
338
|
+
elsif args.include?('--batch')
|
|
339
|
+
show_batch_mode_help
|
|
340
|
+
elsif args.include?('--split')
|
|
341
|
+
show_split_mode_help
|
|
342
|
+
else
|
|
343
|
+
# Default help - let OptionParser handle it
|
|
344
|
+
return
|
|
345
|
+
end
|
|
346
|
+
end
|
|
347
|
+
|
|
348
|
+
def show_video_mode_help
|
|
349
|
+
puts ""
|
|
350
|
+
puts "Video Mode"
|
|
351
|
+
puts "=" * 60
|
|
352
|
+
puts ""
|
|
353
|
+
puts "Convert MP4 videos to spritesheets with advanced image processing."
|
|
354
|
+
puts ""
|
|
355
|
+
puts "Basic Usage:"
|
|
356
|
+
puts " ruby_spriter --video FILE [options]"
|
|
357
|
+
puts ""
|
|
358
|
+
puts "Required:"
|
|
359
|
+
puts " -v, --video FILE Input video file (MP4)"
|
|
360
|
+
puts ""
|
|
361
|
+
puts "Spritesheet Options:"
|
|
362
|
+
puts " -o, --output FILE Output file path"
|
|
363
|
+
puts " -f, --frames COUNT Number of frames to extract (default: 16)"
|
|
364
|
+
puts " -c, --columns COUNT Grid columns (default: 4)"
|
|
365
|
+
puts " -w, --width PIXELS Max frame width (default: 320)"
|
|
366
|
+
puts " -b, --background COLOR Tile background: black, white (default: black)"
|
|
367
|
+
puts " --save-frames Save individual frames to disk"
|
|
368
|
+
puts ""
|
|
369
|
+
puts "Image Processing:"
|
|
370
|
+
puts " -s, --scale PERCENT Scale image by percentage"
|
|
371
|
+
puts " --interpolation METHOD └─ Interpolation: none, linear, cubic, nohalo, lohalo (default: nohalo)"
|
|
372
|
+
puts ""
|
|
373
|
+
puts " --sharpen Apply unsharp mask for edge enhancement"
|
|
374
|
+
puts " --sharpen-radius VALUE └─ Sharpen radius in pixels (default: 2.0)"
|
|
375
|
+
puts " --sharpen-gain VALUE └─ Sharpen gain/strength (default: 0.5)"
|
|
376
|
+
puts " --sharpen-threshold VALUE └─ Sharpen threshold (default: 0.03)"
|
|
377
|
+
puts ""
|
|
378
|
+
puts " -r, --remove-bg Remove background"
|
|
379
|
+
puts " --fuzzy └─ Use fuzzy select (contiguous regions) - DEFAULT"
|
|
380
|
+
puts " --no-fuzzy └─ Use global color select (all matching pixels)"
|
|
381
|
+
puts " -t, --threshold VALUE └─ Feather radius (default: 0.0)"
|
|
382
|
+
puts " -g, --grow PIXELS └─ Grow selection pixels (default: 1)"
|
|
383
|
+
puts ""
|
|
384
|
+
puts " --order ORDER Operation order when using BOTH --scale AND --remove-bg:"
|
|
385
|
+
puts " scale_first or bg_first (default: scale_first)"
|
|
386
|
+
puts ""
|
|
387
|
+
puts "Output Options:"
|
|
388
|
+
puts " --max-compress Apply maximum PNG compression"
|
|
389
|
+
puts " --overwrite Overwrite existing files"
|
|
390
|
+
puts " --keep-temp Keep temporary files"
|
|
391
|
+
puts " --debug Enable debug mode"
|
|
392
|
+
puts ""
|
|
393
|
+
puts "Examples:"
|
|
394
|
+
puts " ruby_spriter --video input.mp4"
|
|
395
|
+
puts " ruby_spriter --video input.mp4 --scale 50 --interpolation nohalo"
|
|
396
|
+
puts " ruby_spriter --video input.mp4 --remove-bg --fuzzy --threshold 0.5"
|
|
397
|
+
puts " ruby_spriter --video input.mp4 --scale 50 --sharpen --max-compress"
|
|
398
|
+
puts ""
|
|
399
|
+
exit
|
|
400
|
+
end
|
|
401
|
+
|
|
402
|
+
def show_image_mode_help
|
|
403
|
+
puts ""
|
|
404
|
+
puts "Image Mode"
|
|
405
|
+
puts "=" * 60
|
|
406
|
+
puts ""
|
|
407
|
+
puts "Process PNG spritesheets with advanced image operations."
|
|
408
|
+
puts ""
|
|
409
|
+
puts "Basic Usage:"
|
|
410
|
+
puts " ruby_spriter --image FILE [options]"
|
|
411
|
+
puts ""
|
|
412
|
+
puts "Required:"
|
|
413
|
+
puts " -i, --image FILE Input image file (PNG)"
|
|
414
|
+
puts ""
|
|
415
|
+
puts "Image Processing:"
|
|
416
|
+
puts " -s, --scale PERCENT Scale image by percentage"
|
|
417
|
+
puts " --interpolation METHOD └─ Interpolation: none, linear, cubic, nohalo, lohalo (default: nohalo)"
|
|
418
|
+
puts ""
|
|
419
|
+
puts " --sharpen Apply unsharp mask for edge enhancement"
|
|
420
|
+
puts " --sharpen-radius VALUE └─ Sharpen radius in pixels (default: 2.0)"
|
|
421
|
+
puts " --sharpen-gain VALUE └─ Sharpen gain/strength (default: 0.5)"
|
|
422
|
+
puts " --sharpen-threshold VALUE └─ Sharpen threshold (default: 0.03)"
|
|
423
|
+
puts ""
|
|
424
|
+
puts " -r, --remove-bg Remove background"
|
|
425
|
+
puts " --fuzzy └─ Use fuzzy select (contiguous regions) - DEFAULT"
|
|
426
|
+
puts " --no-fuzzy └─ Use global color select (all matching pixels)"
|
|
427
|
+
puts " -t, --threshold VALUE └─ Feather radius (default: 0.0)"
|
|
428
|
+
puts " -g, --grow PIXELS └─ Grow selection pixels (default: 1)"
|
|
429
|
+
puts ""
|
|
430
|
+
puts " --order ORDER Operation order when using BOTH --scale AND --remove-bg:"
|
|
431
|
+
puts " scale_first or bg_first (default: scale_first)"
|
|
432
|
+
puts ""
|
|
433
|
+
puts "Frame Extraction & Reassembly:"
|
|
434
|
+
puts " --split R:C Split spritesheet into all individual frames (rows:columns)"
|
|
435
|
+
puts " --override-md └─ Override embedded metadata"
|
|
436
|
+
puts ""
|
|
437
|
+
puts " --extract FRAMES Extract specific frames and create new spritesheet (e.g., 1,2,4,5,8)"
|
|
438
|
+
puts " --columns NUM └─ Output grid columns (default: 4)"
|
|
439
|
+
puts " --save-frames └─ Keep individual extracted frames on disk"
|
|
440
|
+
puts ""
|
|
441
|
+
puts "Metadata Management:"
|
|
442
|
+
puts " --add-meta R:C Add spritesheet metadata (rows:columns, e.g., 4:4)"
|
|
443
|
+
puts " --overwrite-meta └─ Replace existing metadata"
|
|
444
|
+
puts " -f, --frames COUNT └─ Custom frame count for partial grids"
|
|
445
|
+
puts ""
|
|
446
|
+
puts "Output Options:"
|
|
447
|
+
puts " -o, --output FILE Output file path"
|
|
448
|
+
puts " --max-compress Apply maximum PNG compression"
|
|
449
|
+
puts " --overwrite Overwrite existing files"
|
|
450
|
+
puts " --keep-temp Keep temporary files"
|
|
451
|
+
puts " --debug Enable debug mode"
|
|
452
|
+
puts ""
|
|
453
|
+
puts "Examples:"
|
|
454
|
+
puts " ruby_spriter --image sprite.png --scale 50 --interpolation nohalo"
|
|
455
|
+
puts " ruby_spriter --image sprite.png --remove-bg --fuzzy --threshold 1.0"
|
|
456
|
+
puts " ruby_spriter --image sprite.png --scale 50 --sharpen --sharpen-gain 1.5"
|
|
457
|
+
puts " ruby_spriter --image sprite.png --split 4:4 --override-md"
|
|
458
|
+
puts " ruby_spriter --image sprite.png --extract 1,2,4,5,8 --columns 3"
|
|
459
|
+
puts " ruby_spriter --image sprite.png --extract 1,1,2,2,3,3 --save-frames"
|
|
460
|
+
puts " ruby_spriter --image sprite.png --add-meta 4:4"
|
|
461
|
+
puts " ruby_spriter --image sprite.png --add-meta 4:4 --frames 14 --output sprite_meta.png"
|
|
462
|
+
puts ""
|
|
463
|
+
exit
|
|
464
|
+
end
|
|
465
|
+
|
|
466
|
+
def show_consolidate_mode_help
|
|
467
|
+
puts ""
|
|
468
|
+
puts "Consolidate Mode"
|
|
469
|
+
puts "=" * 60
|
|
470
|
+
puts ""
|
|
471
|
+
puts "Combine multiple spritesheets into a single consolidated spritesheet."
|
|
472
|
+
puts ""
|
|
473
|
+
puts "Basic Usage:"
|
|
474
|
+
puts " ruby_spriter --consolidate FILE1,FILE2,FILE3 [options]"
|
|
475
|
+
puts " ruby_spriter --consolidate --dir DIRECTORY [options]"
|
|
476
|
+
puts ""
|
|
477
|
+
puts "Input Methods:"
|
|
478
|
+
puts " --consolidate [FILES] Comma-separated list of PNG files"
|
|
479
|
+
puts " --consolidate --dir DIRECTORY Process all spritesheets in directory"
|
|
480
|
+
puts " --[no-]validate-columns └─ Abort if column counts don't match (default: true)"
|
|
481
|
+
puts ""
|
|
482
|
+
puts "Output Options:"
|
|
483
|
+
puts " -o, --output FILE Output file path"
|
|
484
|
+
puts " --outputdir DIRECTORY Output directory (when using --dir)"
|
|
485
|
+
puts " --max-compress Apply maximum PNG compression"
|
|
486
|
+
puts " --overwrite Overwrite existing files"
|
|
487
|
+
puts " --keep-temp Keep temporary files"
|
|
488
|
+
puts " --debug Enable debug mode"
|
|
489
|
+
puts ""
|
|
490
|
+
puts "Requirements:"
|
|
491
|
+
puts " - All input files must be PNG spritesheets with embedded metadata"
|
|
492
|
+
puts " - Column counts must match across all spritesheets (unless --no-validate-columns)"
|
|
493
|
+
puts " - Minimum 2 spritesheets required"
|
|
494
|
+
puts ""
|
|
495
|
+
puts "Examples:"
|
|
496
|
+
puts " ruby_spriter --consolidate file1.png,file2.png,file3.png"
|
|
497
|
+
puts " ruby_spriter --consolidate --dir spritesheets/"
|
|
498
|
+
puts " ruby_spriter --consolidate --dir spritesheets/ --outputdir output/"
|
|
499
|
+
puts " ruby_spriter --consolidate --dir spritesheets/ --no-validate-columns"
|
|
500
|
+
puts ""
|
|
501
|
+
exit
|
|
502
|
+
end
|
|
503
|
+
|
|
504
|
+
def show_batch_mode_help
|
|
505
|
+
puts ""
|
|
506
|
+
puts "Batch Mode"
|
|
507
|
+
puts "=" * 60
|
|
508
|
+
puts ""
|
|
509
|
+
puts "Process multiple MP4 videos in a directory with consistent options."
|
|
510
|
+
puts ""
|
|
511
|
+
puts "Basic Usage:"
|
|
512
|
+
puts " ruby_spriter --batch --dir DIRECTORY [options]"
|
|
513
|
+
puts ""
|
|
514
|
+
puts "Required:"
|
|
515
|
+
puts " --batch Enable batch processing mode"
|
|
516
|
+
puts " --dir DIRECTORY Directory containing MP4 files"
|
|
517
|
+
puts ""
|
|
518
|
+
puts "Batch Options:"
|
|
519
|
+
puts " --outputdir DIRECTORY Output directory (default: same as input dir)"
|
|
520
|
+
puts " --batch-consolidate Consolidate all results into single spritesheet"
|
|
521
|
+
puts ""
|
|
522
|
+
puts "Spritesheet Options (applied to all videos):"
|
|
523
|
+
puts " -f, --frames COUNT Number of frames to extract (default: 16)"
|
|
524
|
+
puts " -c, --columns COUNT Grid columns (default: 4)"
|
|
525
|
+
puts " -w, --width PIXELS Max frame width (default: 320)"
|
|
526
|
+
puts " -b, --background COLOR Tile background: black, white (default: black)"
|
|
527
|
+
puts " --save-frames Save individual frames to disk"
|
|
528
|
+
puts ""
|
|
529
|
+
puts "Image Processing (applied to all videos):"
|
|
530
|
+
puts " -s, --scale PERCENT Scale images by percentage"
|
|
531
|
+
puts " --interpolation METHOD └─ Interpolation: none, linear, cubic, nohalo, lohalo (default: nohalo)"
|
|
532
|
+
puts ""
|
|
533
|
+
puts " --sharpen Apply unsharp mask for edge enhancement"
|
|
534
|
+
puts " --sharpen-radius VALUE └─ Sharpen radius (default: 2.0)"
|
|
535
|
+
puts " --sharpen-gain VALUE └─ Sharpen gain (default: 0.5)"
|
|
536
|
+
puts " --sharpen-threshold VALUE └─ Sharpen threshold (default: 0.03)"
|
|
537
|
+
puts ""
|
|
538
|
+
puts " -r, --remove-bg Remove background"
|
|
539
|
+
puts " --fuzzy └─ Use fuzzy select (DEFAULT)"
|
|
540
|
+
puts " --no-fuzzy └─ Use global color select"
|
|
541
|
+
puts " -t, --threshold VALUE └─ Feather radius (default: 0.0)"
|
|
542
|
+
puts " -g, --grow PIXELS └─ Grow selection (default: 1)"
|
|
543
|
+
puts ""
|
|
544
|
+
puts " --order ORDER Operation order when using BOTH --scale AND --remove-bg:"
|
|
545
|
+
puts " scale_first or bg_first (default: scale_first)"
|
|
546
|
+
puts ""
|
|
547
|
+
puts "Output Options:"
|
|
548
|
+
puts " --max-compress Apply maximum PNG compression"
|
|
549
|
+
puts " --overwrite Overwrite existing files"
|
|
550
|
+
puts " --keep-temp Keep temporary files"
|
|
551
|
+
puts " --debug Enable debug mode"
|
|
552
|
+
puts ""
|
|
553
|
+
puts "Behavior:"
|
|
554
|
+
puts " - Processes all MP4 files in the specified directory"
|
|
555
|
+
puts " - Enforces unique filenames unless --overwrite is specified"
|
|
556
|
+
puts " - Continues processing remaining videos if one fails"
|
|
557
|
+
puts " - Provides summary of successes and failures"
|
|
558
|
+
puts ""
|
|
559
|
+
puts "Examples:"
|
|
560
|
+
puts " ruby_spriter --batch --dir videos/"
|
|
561
|
+
puts " ruby_spriter --batch --dir videos/ --outputdir output/"
|
|
562
|
+
puts " ruby_spriter --batch --dir videos/ --scale 50 --sharpen"
|
|
563
|
+
puts " ruby_spriter --batch --dir videos/ --batch-consolidate --max-compress"
|
|
564
|
+
puts ""
|
|
565
|
+
exit
|
|
566
|
+
end
|
|
567
|
+
|
|
568
|
+
def show_split_mode_help
|
|
569
|
+
puts ""
|
|
570
|
+
puts "Split Mode"
|
|
571
|
+
puts "=" * 60
|
|
572
|
+
puts ""
|
|
573
|
+
puts "Extract individual frames from a spritesheet (requires --image)."
|
|
574
|
+
puts ""
|
|
575
|
+
puts "Basic Usage:"
|
|
576
|
+
puts " ruby_spriter --image FILE --split R:C [options]"
|
|
577
|
+
puts ""
|
|
578
|
+
puts "Required:"
|
|
579
|
+
puts " -i, --image FILE Input spritesheet file (PNG)"
|
|
580
|
+
puts " --split R:C Split format: rows:columns (e.g., 4:4)"
|
|
581
|
+
puts " --override-md └─ Override embedded metadata"
|
|
582
|
+
puts ""
|
|
583
|
+
puts "Format Requirements:"
|
|
584
|
+
puts " - Rows and columns must be 1-99"
|
|
585
|
+
puts " - Total frames (R × C) must be < 1000"
|
|
586
|
+
puts " - Image dimensions must divide evenly by rows and columns"
|
|
587
|
+
puts ""
|
|
588
|
+
puts "Metadata Behavior:"
|
|
589
|
+
puts " - If spritesheet has embedded metadata, it will be used automatically"
|
|
590
|
+
puts " - Use --override-md to ignore embedded metadata and use --split value"
|
|
591
|
+
puts " - If no metadata exists, --split value is required"
|
|
592
|
+
puts ""
|
|
593
|
+
puts "Output Options:"
|
|
594
|
+
puts " -o, --output FILE Output directory (default: filename_frames/)"
|
|
595
|
+
puts " --overwrite Overwrite existing files"
|
|
596
|
+
puts " --keep-temp Keep temporary files"
|
|
597
|
+
puts " --debug Enable debug mode"
|
|
598
|
+
puts ""
|
|
599
|
+
puts "Output:"
|
|
600
|
+
puts " - Frames are saved as: FR001_filename.png, FR002_filename.png, etc."
|
|
601
|
+
puts " - Frame naming uses 3-digit zero-padded format (FR001-FR999)"
|
|
602
|
+
puts " - Output directory: filename_frames/ (unless --output specified)"
|
|
603
|
+
puts ""
|
|
604
|
+
puts "Examples:"
|
|
605
|
+
puts " ruby_spriter --image sprite.png --split 4:4"
|
|
606
|
+
puts " ruby_spriter --image sprite.png --split 8:8 --override-md"
|
|
607
|
+
puts " ruby_spriter --image sprite.png --split 2:5 --output frames/"
|
|
608
|
+
puts ""
|
|
609
|
+
exit
|
|
610
|
+
end
|
|
264
611
|
end
|
|
265
612
|
end
|