ruby_spriter 0.6.7.1 → 0.7.0.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/.rspec +3 -3
- data/CHANGELOG.md +1035 -524
- data/Gemfile +17 -17
- data/LICENSE +21 -21
- data/README.md +183 -950
- data/bin/ruby_spriter +20 -20
- data/lib/ruby_spriter/background_sampler.rb +140 -0
- data/lib/ruby_spriter/batch_processor.rb +268 -214
- data/lib/ruby_spriter/cell_cleanup_config.rb +21 -0
- data/lib/ruby_spriter/cell_cleanup_gimp_script.rb +123 -0
- data/lib/ruby_spriter/cell_cleanup_processor.rb +230 -0
- data/lib/ruby_spriter/cli.rb +676 -612
- data/lib/ruby_spriter/compression_manager.rb +101 -101
- data/lib/ruby_spriter/consolidator.rb +179 -179
- data/lib/ruby_spriter/dependency_checker.rb +224 -224
- data/lib/ruby_spriter/ghost_edge_cleaner.rb +164 -0
- data/lib/ruby_spriter/gimp_processor.rb +1188 -1058
- data/lib/ruby_spriter/metadata_manager.rb +117 -116
- data/lib/ruby_spriter/platform.rb +137 -137
- data/lib/ruby_spriter/processor.rb +1230 -891
- data/lib/ruby_spriter/smoke_detector.rb +223 -0
- data/lib/ruby_spriter/threshold_stepper.rb +227 -0
- data/lib/ruby_spriter/utils/file_helper.rb +82 -82
- data/lib/ruby_spriter/utils/image_helper.rb +16 -0
- data/lib/ruby_spriter/utils/output_formatter.rb +65 -65
- data/lib/ruby_spriter/utils/path_helper.rb +59 -59
- data/lib/ruby_spriter/utils/spritesheet_splitter.rb +86 -86
- data/lib/ruby_spriter/version.rb +6 -7
- data/lib/ruby_spriter/video_processor.rb +357 -139
- data/lib/ruby_spriter.rb +38 -34
- data/ruby_spriter.gemspec +44 -42
- data/spec/fixtures/centered_sprite_with_inner_bg.png +0 -0
- data/spec/fixtures/centered_sprite_with_inner_bg_inner_removed.png +0 -0
- data/spec/fixtures/centered_sprite_with_inner_bg_threshold_stepped.png +0 -0
- data/spec/fixtures/complex_background_sprite.png +0 -0
- data/spec/fixtures/death - bloodborne rekconing.mp4 +0 -0
- data/spec/fixtures/death - bloodborne rekconing_spritesheet-nobg-global.png +0 -0
- data/spec/fixtures/death - bloodborne rekconing_spritesheet.png +0 -0
- data/spec/fixtures/death - bloodborne rekconing_spritesheet_20251110_185027_431-nobg-global.png +0 -0
- data/spec/fixtures/death - bloodborne rekconing_spritesheet_20251110_185027_431.png +0 -0
- data/spec/fixtures/death - bloodborne rekconing_spritesheet_20251110_185125_738-nobg-global.png +0 -0
- data/spec/fixtures/death - bloodborne rekconing_spritesheet_20251110_185125_738.png +0 -0
- data/spec/fixtures/has_inner_bg.png +0 -0
- data/spec/fixtures/has_small_inner_bg.png +0 -0
- data/spec/fixtures/smoke_effect_sprite.png +0 -0
- data/spec/fixtures/spritesheet_with_metadata.png +0 -0
- data/spec/fixtures/test_sprite.png +0 -0
- data/spec/fixtures/test_sprite_smoke_processed.png +0 -0
- data/spec/fixtures/test_video_spritesheet.png +0 -0
- data/spec/fixtures/transparent_bg_sprite.png +0 -0
- data/spec/fixtures/walk_north_sprite-sheet.png +0 -0
- data/spec/integration/no_fuzzy_mode_spec.rb +100 -0
- data/spec/ruby_spriter/batch_processor_spec.rb +509 -200
- data/spec/ruby_spriter/cli_spec.rb +2026 -1892
- data/spec/ruby_spriter/compression_manager_spec.rb +157 -157
- data/spec/ruby_spriter/consolidator_spec.rb +538 -538
- data/spec/ruby_spriter/gimp_processor_spec.rb +523 -425
- data/spec/ruby_spriter/platform_spec.rb +92 -92
- data/spec/ruby_spriter/processor_spec.rb +911 -735
- data/spec/ruby_spriter/utils/file_helper_spec.rb +150 -150
- data/spec/ruby_spriter/utils/path_helper_spec.rb +78 -78
- data/spec/ruby_spriter/utils/spritesheet_splitter_spec.rb +104 -104
- data/spec/ruby_spriter/video_processor_spec.rb +346 -29
- data/spec/spec_helper.rb +41 -41
- data/spec/tmp/cli_test_output.png +0 -0
- data/spec/tmp/cli_test_output_20251105_114647_395.png +0 -0
- data/spec/tmp/combined_test.png +0 -0
- data/spec/tmp/compat_test.png +0 -0
- data/spec/tmp/compat_test_20251030_174233_361.png +0 -0
- data/spec/tmp/final_all_features.png +0 -0
- data/spec/tmp/final_test_all_features.png +0 -0
- data/spec/tmp/full_pipeline_test.png +0 -0
- data/spec/tmp/inner_test.png +0 -0
- data/spec/tmp/integration_test.png +0 -0
- data/spec/tmp/validation_test.png +0 -0
- data/spec/unit/background_sampler_spec.rb +132 -0
- data/spec/unit/cell_cleanup_config_spec.rb +32 -0
- data/spec/unit/cell_cleanup_gimp_script_spec.rb +59 -0
- data/spec/unit/cell_cleanup_processor_spec.rb +261 -0
- data/spec/unit/ghost_edge_cleaner_spec.rb +223 -0
- data/spec/unit/gimp_processor_single_point_selection_spec.rb +81 -0
- data/spec/unit/smoke_detector_spec.rb +246 -0
- data/spec/unit/threshold_stepper_spec.rb +195 -0
- metadata +56 -10
data/lib/ruby_spriter/cli.rb
CHANGED
|
@@ -1,612 +1,676 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
require 'optparse'
|
|
4
|
-
|
|
5
|
-
module RubySpriter
|
|
6
|
-
# Command-line interface
|
|
7
|
-
class CLI
|
|
8
|
-
PRESETS = {
|
|
9
|
-
thumbnail: { columns: 3, frame_count: 9, max_width: 240 },
|
|
10
|
-
preview: { columns: 4, frame_count: 16, max_width: 400 },
|
|
11
|
-
detailed: { columns: 10, frame_count: 50, max_width: 320 },
|
|
12
|
-
contact: { columns: 8, frame_count: 64, max_width: 160 }
|
|
13
|
-
}.freeze
|
|
14
|
-
|
|
15
|
-
def self.start(args)
|
|
16
|
-
new.parse_and_run(args)
|
|
17
|
-
end
|
|
18
|
-
|
|
19
|
-
def parse_and_run(args)
|
|
20
|
-
options = {}
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
checker.
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
options
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
opts.
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
opts.
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
opts.on("--
|
|
125
|
-
options[:
|
|
126
|
-
end
|
|
127
|
-
|
|
128
|
-
opts.on("
|
|
129
|
-
options[:
|
|
130
|
-
end
|
|
131
|
-
|
|
132
|
-
opts.on("--
|
|
133
|
-
options[:
|
|
134
|
-
end
|
|
135
|
-
|
|
136
|
-
opts.on("--
|
|
137
|
-
options[:
|
|
138
|
-
end
|
|
139
|
-
|
|
140
|
-
opts.on("--
|
|
141
|
-
options[:
|
|
142
|
-
end
|
|
143
|
-
|
|
144
|
-
opts.on("--
|
|
145
|
-
options[:
|
|
146
|
-
end
|
|
147
|
-
|
|
148
|
-
opts.
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
opts.on("-
|
|
218
|
-
options[:
|
|
219
|
-
end
|
|
220
|
-
|
|
221
|
-
opts.
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
opts.on("--
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
options[:
|
|
294
|
-
end
|
|
295
|
-
|
|
296
|
-
opts.
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
opts.
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
opts.separator "
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
opts.separator "
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
opts.
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
puts "
|
|
411
|
-
puts ""
|
|
412
|
-
puts "
|
|
413
|
-
puts "
|
|
414
|
-
puts ""
|
|
415
|
-
puts "
|
|
416
|
-
puts "
|
|
417
|
-
puts "
|
|
418
|
-
puts ""
|
|
419
|
-
puts "
|
|
420
|
-
puts "
|
|
421
|
-
puts "
|
|
422
|
-
puts "
|
|
423
|
-
puts ""
|
|
424
|
-
puts " -
|
|
425
|
-
puts "
|
|
426
|
-
puts "
|
|
427
|
-
puts "
|
|
428
|
-
puts "
|
|
429
|
-
puts ""
|
|
430
|
-
puts "
|
|
431
|
-
puts "
|
|
432
|
-
puts ""
|
|
433
|
-
puts "
|
|
434
|
-
puts " --
|
|
435
|
-
puts " --
|
|
436
|
-
puts ""
|
|
437
|
-
puts "
|
|
438
|
-
puts "
|
|
439
|
-
puts "
|
|
440
|
-
puts ""
|
|
441
|
-
puts "
|
|
442
|
-
puts "
|
|
443
|
-
puts " --
|
|
444
|
-
puts " -
|
|
445
|
-
puts ""
|
|
446
|
-
puts "
|
|
447
|
-
puts "
|
|
448
|
-
puts "
|
|
449
|
-
puts "
|
|
450
|
-
puts " --
|
|
451
|
-
puts " --
|
|
452
|
-
puts ""
|
|
453
|
-
puts "
|
|
454
|
-
puts "
|
|
455
|
-
puts "
|
|
456
|
-
puts " ruby_spriter --
|
|
457
|
-
puts " ruby_spriter --
|
|
458
|
-
puts " ruby_spriter --
|
|
459
|
-
puts " ruby_spriter --
|
|
460
|
-
puts "
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
puts ""
|
|
468
|
-
puts "
|
|
469
|
-
puts "
|
|
470
|
-
puts ""
|
|
471
|
-
puts "
|
|
472
|
-
puts ""
|
|
473
|
-
puts "
|
|
474
|
-
puts "
|
|
475
|
-
puts "
|
|
476
|
-
puts ""
|
|
477
|
-
puts "
|
|
478
|
-
puts " --
|
|
479
|
-
puts "
|
|
480
|
-
puts "
|
|
481
|
-
puts ""
|
|
482
|
-
puts "
|
|
483
|
-
puts "
|
|
484
|
-
puts "
|
|
485
|
-
puts "
|
|
486
|
-
puts " --
|
|
487
|
-
puts "
|
|
488
|
-
puts "
|
|
489
|
-
puts ""
|
|
490
|
-
puts "
|
|
491
|
-
puts "
|
|
492
|
-
puts "
|
|
493
|
-
puts "
|
|
494
|
-
puts ""
|
|
495
|
-
puts "
|
|
496
|
-
puts "
|
|
497
|
-
puts "
|
|
498
|
-
puts "
|
|
499
|
-
puts "
|
|
500
|
-
puts ""
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
puts ""
|
|
506
|
-
puts "
|
|
507
|
-
puts "
|
|
508
|
-
puts ""
|
|
509
|
-
puts "
|
|
510
|
-
puts ""
|
|
511
|
-
puts "
|
|
512
|
-
puts "
|
|
513
|
-
puts ""
|
|
514
|
-
puts "
|
|
515
|
-
puts "
|
|
516
|
-
puts "
|
|
517
|
-
puts ""
|
|
518
|
-
puts "
|
|
519
|
-
puts " --
|
|
520
|
-
puts " --
|
|
521
|
-
puts ""
|
|
522
|
-
puts "
|
|
523
|
-
puts "
|
|
524
|
-
puts "
|
|
525
|
-
puts "
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
puts "
|
|
531
|
-
puts "
|
|
532
|
-
puts ""
|
|
533
|
-
puts "
|
|
534
|
-
puts "
|
|
535
|
-
puts "
|
|
536
|
-
puts "
|
|
537
|
-
puts ""
|
|
538
|
-
puts "
|
|
539
|
-
puts "
|
|
540
|
-
puts "
|
|
541
|
-
puts "
|
|
542
|
-
puts "
|
|
543
|
-
puts ""
|
|
544
|
-
puts "
|
|
545
|
-
puts "
|
|
546
|
-
puts ""
|
|
547
|
-
puts "Output
|
|
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 "
|
|
554
|
-
puts " -
|
|
555
|
-
puts " -
|
|
556
|
-
puts " -
|
|
557
|
-
puts "
|
|
558
|
-
puts ""
|
|
559
|
-
puts "
|
|
560
|
-
puts " ruby_spriter --
|
|
561
|
-
puts " ruby_spriter --
|
|
562
|
-
puts " ruby_spriter --
|
|
563
|
-
puts "
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
puts ""
|
|
570
|
-
puts "
|
|
571
|
-
puts "
|
|
572
|
-
puts ""
|
|
573
|
-
puts "
|
|
574
|
-
puts ""
|
|
575
|
-
puts "
|
|
576
|
-
puts "
|
|
577
|
-
puts ""
|
|
578
|
-
puts "
|
|
579
|
-
puts "
|
|
580
|
-
puts "
|
|
581
|
-
puts "
|
|
582
|
-
puts ""
|
|
583
|
-
puts "
|
|
584
|
-
puts "
|
|
585
|
-
puts "
|
|
586
|
-
puts " -
|
|
587
|
-
puts ""
|
|
588
|
-
puts "
|
|
589
|
-
puts " -
|
|
590
|
-
puts " -
|
|
591
|
-
puts "
|
|
592
|
-
puts ""
|
|
593
|
-
puts "
|
|
594
|
-
puts "
|
|
595
|
-
puts "
|
|
596
|
-
puts " --
|
|
597
|
-
puts "
|
|
598
|
-
puts ""
|
|
599
|
-
puts "
|
|
600
|
-
puts "
|
|
601
|
-
puts " -
|
|
602
|
-
puts "
|
|
603
|
-
puts ""
|
|
604
|
-
puts "
|
|
605
|
-
puts "
|
|
606
|
-
puts "
|
|
607
|
-
puts "
|
|
608
|
-
puts ""
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'optparse'
|
|
4
|
+
|
|
5
|
+
module RubySpriter
|
|
6
|
+
# Command-line interface
|
|
7
|
+
class CLI
|
|
8
|
+
PRESETS = {
|
|
9
|
+
thumbnail: { columns: 3, frame_count: 9, max_width: 240 },
|
|
10
|
+
preview: { columns: 4, frame_count: 16, max_width: 400 },
|
|
11
|
+
detailed: { columns: 10, frame_count: 50, max_width: 320 },
|
|
12
|
+
contact: { columns: 8, frame_count: 64, max_width: 160 }
|
|
13
|
+
}.freeze
|
|
14
|
+
|
|
15
|
+
def self.start(args)
|
|
16
|
+
new.parse_and_run(args)
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def parse_and_run(args)
|
|
20
|
+
options = {}
|
|
21
|
+
options[:fuzzy_select] = false # Default to --no-fuzzy (global color select)
|
|
22
|
+
|
|
23
|
+
# Handle context-sensitive help before validation
|
|
24
|
+
if args.include?('--help') || args.include?('-h')
|
|
25
|
+
handle_context_sensitive_help(args)
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
parser = build_option_parser(options)
|
|
29
|
+
|
|
30
|
+
parser.parse!(args)
|
|
31
|
+
|
|
32
|
+
# Handle special commands that don't need full processing
|
|
33
|
+
if options[:check_dependencies]
|
|
34
|
+
checker = DependencyChecker.new(verbose: true)
|
|
35
|
+
checker.print_report
|
|
36
|
+
exit(checker.all_satisfied? ? 0 : 1)
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
# Validate mutually exclusive options
|
|
40
|
+
if options[:extract] && options[:split]
|
|
41
|
+
raise ValidationError, "--extract and --split are mutually exclusive"
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
# Validate --add-meta cannot be combined with processing options
|
|
45
|
+
if options[:add_meta] && (options[:scale_percent] || options[:remove_bg] || options[:sharpen])
|
|
46
|
+
raise ValidationError, "--add-meta cannot be combined with processing options (--scale, --remove-bg, --sharpen)"
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
# Validate --by-frame flag requirements
|
|
50
|
+
if options[:by_frame]
|
|
51
|
+
unless options[:remove_bg]
|
|
52
|
+
raise ValidationError, "--by-frame requires --remove-bg"
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
unless options[:video] || options[:batch]
|
|
56
|
+
raise ValidationError, "--by-frame requires --video or --batch"
|
|
57
|
+
end
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
# Validate --cleanup-cells flag requirements
|
|
61
|
+
if options[:cleanup_cells]
|
|
62
|
+
unless options[:remove_bg]
|
|
63
|
+
raise ValidationError, "--cleanup-cells requires --remove-bg flag"
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
if options[:by_frame]
|
|
67
|
+
raise ValidationError, "--cleanup-cells cannot be used with --by-frame (redundant)"
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
unless options[:video] || options[:batch]
|
|
71
|
+
raise ValidationError, "--cleanup-cells requires --video or --batch mode"
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
if options[:cell_cleanup_threshold]
|
|
75
|
+
unless options[:cell_cleanup_threshold].between?(1.0, 50.0)
|
|
76
|
+
raise ValidationError, "--cell-cleanup-threshold must be between 1.0 and 50.0"
|
|
77
|
+
end
|
|
78
|
+
end
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
# Run processor
|
|
82
|
+
processor = Processor.new(options)
|
|
83
|
+
processor.run
|
|
84
|
+
rescue OptionParser::InvalidOption, OptionParser::MissingArgument => e
|
|
85
|
+
puts "Error: #{e.message}"
|
|
86
|
+
puts "\nUse --help for usage information"
|
|
87
|
+
exit 1
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
private
|
|
91
|
+
|
|
92
|
+
def build_option_parser(options)
|
|
93
|
+
OptionParser.new do |opts|
|
|
94
|
+
opts.banner = "Usage: ruby_spriter [options]"
|
|
95
|
+
|
|
96
|
+
add_header(opts)
|
|
97
|
+
add_input_options(opts, options)
|
|
98
|
+
add_spritesheet_options(opts, options)
|
|
99
|
+
add_gimp_options(opts, options)
|
|
100
|
+
add_bg_removal_options(opts, options)
|
|
101
|
+
add_consolidation_options(opts, options)
|
|
102
|
+
add_preset_options(opts, options)
|
|
103
|
+
add_other_options(opts, options)
|
|
104
|
+
end
|
|
105
|
+
end
|
|
106
|
+
|
|
107
|
+
def add_header(opts)
|
|
108
|
+
opts.separator ""
|
|
109
|
+
opts.separator "Ruby Spriter v#{VERSION} - Professional MP4 to Spritesheet Converter with Advanced Image Processing"
|
|
110
|
+
opts.separator "Platform: #{Platform.current.to_s.capitalize}"
|
|
111
|
+
opts.separator ""
|
|
112
|
+
opts.separator "Get mode-specific help:"
|
|
113
|
+
opts.separator " ruby_spriter --video --help"
|
|
114
|
+
opts.separator " ruby_spriter --image --help"
|
|
115
|
+
opts.separator " ruby_spriter --consolidate --help"
|
|
116
|
+
opts.separator " ruby_spriter --batch --help"
|
|
117
|
+
opts.separator " ruby_spriter --split --help"
|
|
118
|
+
opts.separator ""
|
|
119
|
+
end
|
|
120
|
+
|
|
121
|
+
def add_input_options(opts, options)
|
|
122
|
+
opts.separator "Input Options:"
|
|
123
|
+
|
|
124
|
+
opts.on("-v", "--video FILE", "Input video file (MP4)") do |v|
|
|
125
|
+
options[:video] = v
|
|
126
|
+
end
|
|
127
|
+
|
|
128
|
+
opts.on("-i", "--image FILE", "Input image file (PNG) for direct processing") do |i|
|
|
129
|
+
options[:image] = i
|
|
130
|
+
end
|
|
131
|
+
|
|
132
|
+
opts.on("--batch", "Batch process all MP4 files in directory") do
|
|
133
|
+
options[:batch] = true
|
|
134
|
+
end
|
|
135
|
+
|
|
136
|
+
opts.on("--dir DIRECTORY", "Directory for batch processing") do |d|
|
|
137
|
+
options[:dir] = d
|
|
138
|
+
end
|
|
139
|
+
|
|
140
|
+
opts.on("--outputdir DIRECTORY", "Output directory for batch processing") do |d|
|
|
141
|
+
options[:outputdir] = d
|
|
142
|
+
end
|
|
143
|
+
|
|
144
|
+
opts.on("--batch-consolidate", "Consolidate all spritesheets after batch processing") do
|
|
145
|
+
options[:batch_consolidate] = true
|
|
146
|
+
end
|
|
147
|
+
|
|
148
|
+
opts.on("--consolidate [FILES]", Array, "Consolidate spritesheets (comma-separated files or use with --dir)") do |c|
|
|
149
|
+
options[:consolidate_mode] = true
|
|
150
|
+
options[:consolidate] = c if c && !c.empty?
|
|
151
|
+
end
|
|
152
|
+
|
|
153
|
+
opts.on("--verify FILE", "Verify spritesheet metadata") do |v|
|
|
154
|
+
options[:verify] = v
|
|
155
|
+
end
|
|
156
|
+
|
|
157
|
+
opts.on("--split R:C", "Split image into frames (rows:columns, e.g., 4:4)") do |s|
|
|
158
|
+
options[:split] = s
|
|
159
|
+
end
|
|
160
|
+
|
|
161
|
+
opts.on("--override-md", "Override embedded metadata when using --split") do
|
|
162
|
+
options[:override_md] = true
|
|
163
|
+
end
|
|
164
|
+
|
|
165
|
+
opts.on("--extract FRAMES", "Extract specific frames by number (comma-separated, e.g., 1,2,4,5,8)") do |e|
|
|
166
|
+
options[:extract] = e
|
|
167
|
+
end
|
|
168
|
+
|
|
169
|
+
opts.on("--columns NUM", Integer, "Number of columns for extracted spritesheet (default: 4)") do |c|
|
|
170
|
+
options[:columns] = c
|
|
171
|
+
end
|
|
172
|
+
|
|
173
|
+
opts.on("--add-meta R:C", "Add spritesheet metadata to image (rows:columns, e.g., 4:4)") do |m|
|
|
174
|
+
options[:add_meta] = m
|
|
175
|
+
end
|
|
176
|
+
|
|
177
|
+
opts.on("--overwrite-meta", "Overwrite existing metadata when using --add-meta") do
|
|
178
|
+
options[:overwrite_meta] = true
|
|
179
|
+
end
|
|
180
|
+
|
|
181
|
+
opts.separator ""
|
|
182
|
+
end
|
|
183
|
+
|
|
184
|
+
def add_spritesheet_options(opts, options)
|
|
185
|
+
opts.separator "Spritesheet Options:"
|
|
186
|
+
|
|
187
|
+
opts.on("-o", "--output FILE", "Output file path") do |o|
|
|
188
|
+
options[:output] = o
|
|
189
|
+
end
|
|
190
|
+
|
|
191
|
+
opts.on("-f", "--frames COUNT", Integer, "Number of frames to extract (default: 16)") do |f|
|
|
192
|
+
options[:frame_count] = f
|
|
193
|
+
end
|
|
194
|
+
|
|
195
|
+
opts.on("-c", "--columns COUNT", Integer, "Grid columns (default: 4)") do |c|
|
|
196
|
+
options[:columns] = c
|
|
197
|
+
end
|
|
198
|
+
|
|
199
|
+
opts.on("-w", "--width PIXELS", Integer, "Max frame width (default: 320)") do |w|
|
|
200
|
+
options[:max_width] = w
|
|
201
|
+
end
|
|
202
|
+
|
|
203
|
+
opts.on("-b", "--background COLOR", "Tile background: black, white (default: black)") do |b|
|
|
204
|
+
options[:bg_color] = b
|
|
205
|
+
end
|
|
206
|
+
|
|
207
|
+
opts.on("--save-frames", "Save individual frames to disk (for --video or --extract)") do
|
|
208
|
+
options[:save_frames] = true
|
|
209
|
+
end
|
|
210
|
+
|
|
211
|
+
opts.separator ""
|
|
212
|
+
end
|
|
213
|
+
|
|
214
|
+
def add_gimp_options(opts, options)
|
|
215
|
+
opts.separator "Processing Options:"
|
|
216
|
+
|
|
217
|
+
opts.on("-s", "--scale PERCENT", Integer, "Scale image by percentage") do |s|
|
|
218
|
+
options[:scale_percent] = s
|
|
219
|
+
end
|
|
220
|
+
|
|
221
|
+
opts.on("--interpolation METHOD", [:none, :linear, :cubic, :nohalo, :lohalo],
|
|
222
|
+
"Interpolation method: none, linear, cubic, nohalo, lohalo (default: nohalo)") do |i|
|
|
223
|
+
options[:scale_interpolation] = i.to_s
|
|
224
|
+
end
|
|
225
|
+
|
|
226
|
+
opts.on("--sharpen", "Apply unsharp mask after scaling (enhances edges)") do
|
|
227
|
+
options[:sharpen] = true
|
|
228
|
+
end
|
|
229
|
+
|
|
230
|
+
opts.on("--sharpen-radius VALUE", Float, "Sharpen radius in pixels (default: 2.0)") do |r|
|
|
231
|
+
options[:sharpen_radius] = r
|
|
232
|
+
end
|
|
233
|
+
|
|
234
|
+
opts.on("--sharpen-gain VALUE", Float, "Sharpen gain/strength (default: 0.5, range: 0.0-2.0+)") do |g|
|
|
235
|
+
options[:sharpen_gain] = g
|
|
236
|
+
end
|
|
237
|
+
|
|
238
|
+
opts.on("--sharpen-threshold VALUE", Float, "Sharpen threshold as fraction (default: 0.03, range: 0.0-1.0)") do |t|
|
|
239
|
+
options[:sharpen_threshold] = t
|
|
240
|
+
end
|
|
241
|
+
|
|
242
|
+
opts.on("-r", "--remove-bg", "Remove background from spritesheet") do
|
|
243
|
+
options[:remove_bg] = true
|
|
244
|
+
end
|
|
245
|
+
|
|
246
|
+
opts.on("-t", "--threshold VALUE", Float, "Background color tolerance % (default: 15.0, range: 0-100)") do |t|
|
|
247
|
+
options[:bg_threshold] = t
|
|
248
|
+
end
|
|
249
|
+
|
|
250
|
+
opts.on("-g", "--grow PIXELS", Integer, "Pixels to grow selection (default: 1)") do |g|
|
|
251
|
+
options[:grow_selection] = g
|
|
252
|
+
end
|
|
253
|
+
|
|
254
|
+
opts.on("-f", "--feather PIXELS", Float, "Feather selection edges in pixels (default: 0.0, softer edges)") do |f|
|
|
255
|
+
options[:feather_radius] = f
|
|
256
|
+
end
|
|
257
|
+
|
|
258
|
+
opts.separator ""
|
|
259
|
+
end
|
|
260
|
+
|
|
261
|
+
def add_bg_removal_options(opts, options)
|
|
262
|
+
opts.separator "Background Removal Method:"
|
|
263
|
+
|
|
264
|
+
opts.on("--fuzzy", "Use fuzzy select (contiguous regions only)") do
|
|
265
|
+
options[:fuzzy_select] = true
|
|
266
|
+
end
|
|
267
|
+
|
|
268
|
+
opts.on("--no-fuzzy", "Use global color select (all matching pixels) - DEFAULT") do
|
|
269
|
+
options[:fuzzy_select] = false
|
|
270
|
+
end
|
|
271
|
+
|
|
272
|
+
opts.on('--by-frame', 'Remove background from each frame individually (video/batch mode only)') do
|
|
273
|
+
options[:by_frame] = true
|
|
274
|
+
end
|
|
275
|
+
|
|
276
|
+
opts.on('--cleanup-cells', 'Apply cell-based background cleanup (requires --remove-bg, cannot use with --by-frame)') do
|
|
277
|
+
options[:cleanup_cells] = true
|
|
278
|
+
end
|
|
279
|
+
|
|
280
|
+
opts.on('--cell-cleanup-threshold N', Float,
|
|
281
|
+
'Minimum percentage for dominant color detection (default: 15.0, range: 1.0-50.0)') do |n|
|
|
282
|
+
options[:cell_cleanup_threshold] = n
|
|
283
|
+
end
|
|
284
|
+
|
|
285
|
+
opts.separator ""
|
|
286
|
+
opts.separator "Background Color Sampling (for --no-fuzzy mode):"
|
|
287
|
+
|
|
288
|
+
opts.on("--bg-sample-offset N", Integer, "Distance from edge to start sampling background colors (default: 5)") do |n|
|
|
289
|
+
options[:bg_sample_offset] = n
|
|
290
|
+
end
|
|
291
|
+
|
|
292
|
+
opts.on("--bg-sample-count N", Integer, "Number of unique background colors to collect (default: 10)") do |n|
|
|
293
|
+
options[:bg_sample_count] = n
|
|
294
|
+
end
|
|
295
|
+
|
|
296
|
+
opts.separator ""
|
|
297
|
+
opts.separator "Operation Order:"
|
|
298
|
+
|
|
299
|
+
opts.on("--order ORDER", [:scale_first, :bg_first],
|
|
300
|
+
"Operation order: scale_first or bg_first (default: scale_first)") do |order|
|
|
301
|
+
options[:operation_order] = order == :scale_first ? :scale_then_remove_bg : :remove_bg_then_scale
|
|
302
|
+
end
|
|
303
|
+
|
|
304
|
+
opts.separator ""
|
|
305
|
+
end
|
|
306
|
+
|
|
307
|
+
def add_consolidation_options(opts, options)
|
|
308
|
+
opts.separator "Consolidation Options:"
|
|
309
|
+
|
|
310
|
+
opts.on("--[no-]validate-columns", "Abort if column counts don't match (default: true)") do |v|
|
|
311
|
+
options[:validate_columns] = v
|
|
312
|
+
end
|
|
313
|
+
|
|
314
|
+
opts.separator ""
|
|
315
|
+
end
|
|
316
|
+
|
|
317
|
+
def add_preset_options(opts, options)
|
|
318
|
+
opts.separator "Preset Configurations:"
|
|
319
|
+
|
|
320
|
+
preset_descriptions = PRESETS.map do |name, config|
|
|
321
|
+
" #{name}: #{config[:columns]}×? grid, #{config[:frame_count]} frames, #{config[:max_width]}px wide"
|
|
322
|
+
end.join("\n")
|
|
323
|
+
|
|
324
|
+
opts.on("--preset NAME", String, "Apply preset configuration:",
|
|
325
|
+
*preset_descriptions.split("\n")) do |preset_name|
|
|
326
|
+
preset_key = preset_name.to_sym
|
|
327
|
+
unless PRESETS.key?(preset_key)
|
|
328
|
+
valid_presets = PRESETS.keys.join(', ')
|
|
329
|
+
raise OptionParser::InvalidArgument, "Unknown preset: #{preset_name}. Valid options: #{valid_presets}"
|
|
330
|
+
end
|
|
331
|
+
options.merge!(PRESETS[preset_key])
|
|
332
|
+
end
|
|
333
|
+
|
|
334
|
+
opts.separator ""
|
|
335
|
+
end
|
|
336
|
+
|
|
337
|
+
def add_other_options(opts, options)
|
|
338
|
+
opts.separator "Other Options:"
|
|
339
|
+
|
|
340
|
+
opts.on("--max-compress", "Apply maximum PNG compression to output") do
|
|
341
|
+
options[:max_compress] = true
|
|
342
|
+
end
|
|
343
|
+
|
|
344
|
+
opts.on("--overwrite", "Overwrite existing output files (default: create unique filenames)") do
|
|
345
|
+
options[:overwrite] = true
|
|
346
|
+
end
|
|
347
|
+
|
|
348
|
+
opts.on("--keep-temp", "Keep temporary files for debugging") do
|
|
349
|
+
options[:keep_temp] = true
|
|
350
|
+
end
|
|
351
|
+
|
|
352
|
+
opts.on("--debug", "Enable debug mode (verbose output + keep temp files)") do
|
|
353
|
+
options[:debug] = true
|
|
354
|
+
options[:keep_temp] = true
|
|
355
|
+
end
|
|
356
|
+
|
|
357
|
+
opts.on("-h", "--help", "Show this help message") do
|
|
358
|
+
puts opts
|
|
359
|
+
exit
|
|
360
|
+
end
|
|
361
|
+
|
|
362
|
+
opts.on("--version", "Show version information") do
|
|
363
|
+
puts "Ruby Spriter v#{VERSION}"
|
|
364
|
+
puts "Platform: #{Platform.current.to_s.capitalize}"
|
|
365
|
+
puts "Date: #{VERSION_DATE}"
|
|
366
|
+
exit
|
|
367
|
+
end
|
|
368
|
+
|
|
369
|
+
opts.on("--check-dependencies", "Check if all required external tools are installed") do
|
|
370
|
+
options[:check_dependencies] = true
|
|
371
|
+
end
|
|
372
|
+
|
|
373
|
+
opts.separator ""
|
|
374
|
+
opts.separator "Examples:"
|
|
375
|
+
opts.separator " ruby_spriter --check-dependencies"
|
|
376
|
+
opts.separator " ruby_spriter --video input.mp4"
|
|
377
|
+
opts.separator " ruby_spriter --video input.mp4 --remove-bg --scale 50"
|
|
378
|
+
opts.separator " ruby_spriter --video input.mp4 --scale 50 --interpolation nohalo --sharpen"
|
|
379
|
+
opts.separator " ruby_spriter --video input.mp4 --max-compress"
|
|
380
|
+
opts.separator " ruby_spriter --image sprite.png --scale 50 --sharpen --sharpen-gain 1.5"
|
|
381
|
+
opts.separator " ruby_spriter --image sprite.png --remove-bg"
|
|
382
|
+
opts.separator " ruby_spriter --batch --dir videos/"
|
|
383
|
+
opts.separator " ruby_spriter --batch --dir videos/ --outputdir output/"
|
|
384
|
+
opts.separator " ruby_spriter --batch --dir videos/ --batch-consolidate --max-compress"
|
|
385
|
+
opts.separator " ruby_spriter --consolidate file1.png,file2.png,file3.png"
|
|
386
|
+
opts.separator " ruby_spriter --consolidate --dir spritesheets/"
|
|
387
|
+
opts.separator " ruby_spriter --consolidate --dir spritesheets/ --outputdir output/ --max-compress"
|
|
388
|
+
opts.separator " ruby_spriter --verify spritesheet.png"
|
|
389
|
+
opts.separator ""
|
|
390
|
+
end
|
|
391
|
+
|
|
392
|
+
def handle_context_sensitive_help(args)
|
|
393
|
+
if args.include?('--video') || args.include?('-v')
|
|
394
|
+
show_video_mode_help
|
|
395
|
+
elsif args.include?('--image') || args.include?('-i')
|
|
396
|
+
show_image_mode_help
|
|
397
|
+
elsif args.include?('--consolidate')
|
|
398
|
+
show_consolidate_mode_help
|
|
399
|
+
elsif args.include?('--batch')
|
|
400
|
+
show_batch_mode_help
|
|
401
|
+
elsif args.include?('--split')
|
|
402
|
+
show_split_mode_help
|
|
403
|
+
else
|
|
404
|
+
# Default help - let OptionParser handle it
|
|
405
|
+
return
|
|
406
|
+
end
|
|
407
|
+
end
|
|
408
|
+
|
|
409
|
+
def show_video_mode_help
|
|
410
|
+
puts ""
|
|
411
|
+
puts "Video Mode"
|
|
412
|
+
puts "=" * 60
|
|
413
|
+
puts ""
|
|
414
|
+
puts "Convert MP4 videos to spritesheets with advanced image processing."
|
|
415
|
+
puts ""
|
|
416
|
+
puts "Basic Usage:"
|
|
417
|
+
puts " ruby_spriter --video FILE [options]"
|
|
418
|
+
puts ""
|
|
419
|
+
puts "Required:"
|
|
420
|
+
puts " -v, --video FILE Input video file (MP4)"
|
|
421
|
+
puts ""
|
|
422
|
+
puts "Spritesheet Options:"
|
|
423
|
+
puts " -o, --output FILE Output file path"
|
|
424
|
+
puts " -f, --frames COUNT Number of frames to extract (default: 16)"
|
|
425
|
+
puts " -c, --columns COUNT Grid columns (default: 4)"
|
|
426
|
+
puts " -w, --width PIXELS Max frame width (default: 320)"
|
|
427
|
+
puts " -b, --background COLOR Tile background: black, white (default: black)"
|
|
428
|
+
puts " --save-frames Save individual frames to disk"
|
|
429
|
+
puts ""
|
|
430
|
+
puts "Image Processing:"
|
|
431
|
+
puts " -s, --scale PERCENT Scale image by percentage"
|
|
432
|
+
puts " --interpolation METHOD └─ Interpolation: none, linear, cubic, nohalo, lohalo (default: nohalo)"
|
|
433
|
+
puts ""
|
|
434
|
+
puts " --sharpen Apply unsharp mask for edge enhancement"
|
|
435
|
+
puts " --sharpen-radius VALUE └─ Sharpen radius in pixels (default: 2.0)"
|
|
436
|
+
puts " --sharpen-gain VALUE └─ Sharpen gain/strength (default: 0.5)"
|
|
437
|
+
puts " --sharpen-threshold VALUE └─ Sharpen threshold (default: 0.03)"
|
|
438
|
+
puts ""
|
|
439
|
+
puts " -r, --remove-bg Remove background"
|
|
440
|
+
puts " --no-fuzzy └─ Use global color select (all matching pixels) - DEFAULT"
|
|
441
|
+
puts " --fuzzy └─ Use fuzzy select (contiguous regions only)"
|
|
442
|
+
puts " --by-frame └─ Remove background from each frame individually (slower, better quality)"
|
|
443
|
+
puts " -t, --threshold VALUE └─ Feather radius (default: 0.0)"
|
|
444
|
+
puts " -g, --grow PIXELS └─ Grow selection pixels (default: 1)"
|
|
445
|
+
puts ""
|
|
446
|
+
puts " --order ORDER Operation order when using BOTH --scale AND --remove-bg:"
|
|
447
|
+
puts " scale_first or bg_first (default: scale_first)"
|
|
448
|
+
puts ""
|
|
449
|
+
puts "Output Options:"
|
|
450
|
+
puts " --max-compress Apply maximum PNG compression"
|
|
451
|
+
puts " --overwrite Overwrite existing files"
|
|
452
|
+
puts " --keep-temp Keep temporary files"
|
|
453
|
+
puts " --debug Enable debug mode"
|
|
454
|
+
puts ""
|
|
455
|
+
puts "Examples:"
|
|
456
|
+
puts " ruby_spriter --video input.mp4"
|
|
457
|
+
puts " ruby_spriter --video input.mp4 --scale 50 --interpolation nohalo"
|
|
458
|
+
puts " ruby_spriter --video input.mp4 --remove-bg --threshold 0.5"
|
|
459
|
+
puts " ruby_spriter --video input.mp4 --scale 50 --sharpen --max-compress"
|
|
460
|
+
puts ""
|
|
461
|
+
exit
|
|
462
|
+
end
|
|
463
|
+
|
|
464
|
+
def show_image_mode_help
|
|
465
|
+
puts ""
|
|
466
|
+
puts "Image Mode"
|
|
467
|
+
puts "=" * 60
|
|
468
|
+
puts ""
|
|
469
|
+
puts "Process PNG spritesheets with advanced image operations."
|
|
470
|
+
puts ""
|
|
471
|
+
puts "Basic Usage:"
|
|
472
|
+
puts " ruby_spriter --image FILE [options]"
|
|
473
|
+
puts ""
|
|
474
|
+
puts "Required:"
|
|
475
|
+
puts " -i, --image FILE Input image file (PNG)"
|
|
476
|
+
puts ""
|
|
477
|
+
puts "Image Processing:"
|
|
478
|
+
puts " -s, --scale PERCENT Scale image by percentage"
|
|
479
|
+
puts " --interpolation METHOD └─ Interpolation: none, linear, cubic, nohalo, lohalo (default: nohalo)"
|
|
480
|
+
puts ""
|
|
481
|
+
puts " --sharpen Apply unsharp mask for edge enhancement"
|
|
482
|
+
puts " --sharpen-radius VALUE └─ Sharpen radius in pixels (default: 2.0)"
|
|
483
|
+
puts " --sharpen-gain VALUE └─ Sharpen gain/strength (default: 0.5)"
|
|
484
|
+
puts " --sharpen-threshold VALUE └─ Sharpen threshold (default: 0.03)"
|
|
485
|
+
puts ""
|
|
486
|
+
puts " -r, --remove-bg Remove background"
|
|
487
|
+
puts " --no-fuzzy └─ Use global color select (all matching pixels) - DEFAULT"
|
|
488
|
+
puts " --fuzzy └─ Use fuzzy select (contiguous regions only)"
|
|
489
|
+
puts " --by-frame └─ Remove background from each frame individually (slower, better quality)"
|
|
490
|
+
puts " -t, --threshold VALUE └─ Feather radius (default: 0.0)"
|
|
491
|
+
puts " -g, --grow PIXELS └─ Grow selection pixels (default: 1)"
|
|
492
|
+
puts ""
|
|
493
|
+
puts " --order ORDER Operation order when using BOTH --scale AND --remove-bg:"
|
|
494
|
+
puts " scale_first or bg_first (default: scale_first)"
|
|
495
|
+
puts ""
|
|
496
|
+
puts "Frame Extraction & Reassembly:"
|
|
497
|
+
puts " --split R:C Split spritesheet into all individual frames (rows:columns)"
|
|
498
|
+
puts " --override-md └─ Override embedded metadata"
|
|
499
|
+
puts ""
|
|
500
|
+
puts " --extract FRAMES Extract specific frames and create new spritesheet (e.g., 1,2,4,5,8)"
|
|
501
|
+
puts " --columns NUM └─ Output grid columns (default: 4)"
|
|
502
|
+
puts " --save-frames └─ Keep individual extracted frames on disk"
|
|
503
|
+
puts ""
|
|
504
|
+
puts "Metadata Management:"
|
|
505
|
+
puts " --add-meta R:C Add spritesheet metadata (rows:columns, e.g., 4:4)"
|
|
506
|
+
puts " --overwrite-meta └─ Replace existing metadata"
|
|
507
|
+
puts " -f, --frames COUNT └─ Custom frame count for partial grids"
|
|
508
|
+
puts ""
|
|
509
|
+
puts "Output Options:"
|
|
510
|
+
puts " -o, --output FILE Output file path"
|
|
511
|
+
puts " --max-compress Apply maximum PNG compression"
|
|
512
|
+
puts " --overwrite Overwrite existing files"
|
|
513
|
+
puts " --keep-temp Keep temporary files"
|
|
514
|
+
puts " --debug Enable debug mode"
|
|
515
|
+
puts ""
|
|
516
|
+
puts "Examples:"
|
|
517
|
+
puts " ruby_spriter --image sprite.png --scale 50 --interpolation nohalo"
|
|
518
|
+
puts " ruby_spriter --image sprite.png --remove-bg --threshold 1.0"
|
|
519
|
+
puts " ruby_spriter --image sprite.png --scale 50 --sharpen --sharpen-gain 1.5"
|
|
520
|
+
puts " ruby_spriter --image sprite.png --split 4:4 --override-md"
|
|
521
|
+
puts " ruby_spriter --image sprite.png --extract 1,2,4,5,8 --columns 3"
|
|
522
|
+
puts " ruby_spriter --image sprite.png --extract 1,1,2,2,3,3 --save-frames"
|
|
523
|
+
puts " ruby_spriter --image sprite.png --add-meta 4:4"
|
|
524
|
+
puts " ruby_spriter --image sprite.png --add-meta 4:4 --frames 14 --output sprite_meta.png"
|
|
525
|
+
puts ""
|
|
526
|
+
exit
|
|
527
|
+
end
|
|
528
|
+
|
|
529
|
+
def show_consolidate_mode_help
|
|
530
|
+
puts ""
|
|
531
|
+
puts "Consolidate Mode"
|
|
532
|
+
puts "=" * 60
|
|
533
|
+
puts ""
|
|
534
|
+
puts "Combine multiple spritesheets into a single consolidated spritesheet."
|
|
535
|
+
puts ""
|
|
536
|
+
puts "Basic Usage:"
|
|
537
|
+
puts " ruby_spriter --consolidate FILE1,FILE2,FILE3 [options]"
|
|
538
|
+
puts " ruby_spriter --consolidate --dir DIRECTORY [options]"
|
|
539
|
+
puts ""
|
|
540
|
+
puts "Input Methods:"
|
|
541
|
+
puts " --consolidate [FILES] Comma-separated list of PNG files"
|
|
542
|
+
puts " --consolidate --dir DIRECTORY Process all spritesheets in directory"
|
|
543
|
+
puts " --[no-]validate-columns └─ Abort if column counts don't match (default: true)"
|
|
544
|
+
puts ""
|
|
545
|
+
puts "Output Options:"
|
|
546
|
+
puts " -o, --output FILE Output file path"
|
|
547
|
+
puts " --outputdir DIRECTORY Output directory (when using --dir)"
|
|
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 "Requirements:"
|
|
554
|
+
puts " - All input files must be PNG spritesheets with embedded metadata"
|
|
555
|
+
puts " - Column counts must match across all spritesheets (unless --no-validate-columns)"
|
|
556
|
+
puts " - Minimum 2 spritesheets required"
|
|
557
|
+
puts ""
|
|
558
|
+
puts "Examples:"
|
|
559
|
+
puts " ruby_spriter --consolidate file1.png,file2.png,file3.png"
|
|
560
|
+
puts " ruby_spriter --consolidate --dir spritesheets/"
|
|
561
|
+
puts " ruby_spriter --consolidate --dir spritesheets/ --outputdir output/"
|
|
562
|
+
puts " ruby_spriter --consolidate --dir spritesheets/ --no-validate-columns"
|
|
563
|
+
puts ""
|
|
564
|
+
exit
|
|
565
|
+
end
|
|
566
|
+
|
|
567
|
+
def show_batch_mode_help
|
|
568
|
+
puts ""
|
|
569
|
+
puts "Batch Mode"
|
|
570
|
+
puts "=" * 60
|
|
571
|
+
puts ""
|
|
572
|
+
puts "Process multiple MP4 videos in a directory with consistent options."
|
|
573
|
+
puts ""
|
|
574
|
+
puts "Basic Usage:"
|
|
575
|
+
puts " ruby_spriter --batch --dir DIRECTORY [options]"
|
|
576
|
+
puts ""
|
|
577
|
+
puts "Required:"
|
|
578
|
+
puts " --batch Enable batch processing mode"
|
|
579
|
+
puts " --dir DIRECTORY Directory containing MP4 files"
|
|
580
|
+
puts ""
|
|
581
|
+
puts "Batch Options:"
|
|
582
|
+
puts " --outputdir DIRECTORY Output directory (default: same as input dir)"
|
|
583
|
+
puts " --batch-consolidate Consolidate all results into single spritesheet"
|
|
584
|
+
puts ""
|
|
585
|
+
puts "Spritesheet Options (applied to all videos):"
|
|
586
|
+
puts " -f, --frames COUNT Number of frames to extract (default: 16)"
|
|
587
|
+
puts " -c, --columns COUNT Grid columns (default: 4)"
|
|
588
|
+
puts " -w, --width PIXELS Max frame width (default: 320)"
|
|
589
|
+
puts " -b, --background COLOR Tile background: black, white (default: black)"
|
|
590
|
+
puts " --save-frames Save individual frames to disk"
|
|
591
|
+
puts ""
|
|
592
|
+
puts "Image Processing (applied to all videos):"
|
|
593
|
+
puts " -s, --scale PERCENT Scale images by percentage"
|
|
594
|
+
puts " --interpolation METHOD └─ Interpolation: none, linear, cubic, nohalo, lohalo (default: nohalo)"
|
|
595
|
+
puts ""
|
|
596
|
+
puts " --sharpen Apply unsharp mask for edge enhancement"
|
|
597
|
+
puts " --sharpen-radius VALUE └─ Sharpen radius (default: 2.0)"
|
|
598
|
+
puts " --sharpen-gain VALUE └─ Sharpen gain (default: 0.5)"
|
|
599
|
+
puts " --sharpen-threshold VALUE └─ Sharpen threshold (default: 0.03)"
|
|
600
|
+
puts ""
|
|
601
|
+
puts " -r, --remove-bg Remove background"
|
|
602
|
+
puts " --no-fuzzy └─ Use global color select - DEFAULT"
|
|
603
|
+
puts " --fuzzy └─ Use fuzzy select (contiguous only)"
|
|
604
|
+
puts " --by-frame └─ Remove background from each frame individually (slower, better quality)"
|
|
605
|
+
puts " -t, --threshold VALUE └─ Feather radius (default: 0.0)"
|
|
606
|
+
puts " -g, --grow PIXELS └─ Grow selection (default: 1)"
|
|
607
|
+
puts ""
|
|
608
|
+
puts " --order ORDER Operation order when using BOTH --scale AND --remove-bg:"
|
|
609
|
+
puts " scale_first or bg_first (default: scale_first)"
|
|
610
|
+
puts ""
|
|
611
|
+
puts "Output Options:"
|
|
612
|
+
puts " --max-compress Apply maximum PNG compression"
|
|
613
|
+
puts " --overwrite Overwrite existing files"
|
|
614
|
+
puts " --keep-temp Keep temporary files"
|
|
615
|
+
puts " --debug Enable debug mode"
|
|
616
|
+
puts ""
|
|
617
|
+
puts "Behavior:"
|
|
618
|
+
puts " - Processes all MP4 files in the specified directory"
|
|
619
|
+
puts " - Enforces unique filenames unless --overwrite is specified"
|
|
620
|
+
puts " - Continues processing remaining videos if one fails"
|
|
621
|
+
puts " - Provides summary of successes and failures"
|
|
622
|
+
puts ""
|
|
623
|
+
puts "Examples:"
|
|
624
|
+
puts " ruby_spriter --batch --dir videos/"
|
|
625
|
+
puts " ruby_spriter --batch --dir videos/ --outputdir output/"
|
|
626
|
+
puts " ruby_spriter --batch --dir videos/ --scale 50 --sharpen"
|
|
627
|
+
puts " ruby_spriter --batch --dir videos/ --batch-consolidate --max-compress"
|
|
628
|
+
puts ""
|
|
629
|
+
exit
|
|
630
|
+
end
|
|
631
|
+
|
|
632
|
+
def show_split_mode_help
|
|
633
|
+
puts ""
|
|
634
|
+
puts "Split Mode"
|
|
635
|
+
puts "=" * 60
|
|
636
|
+
puts ""
|
|
637
|
+
puts "Extract individual frames from a spritesheet (requires --image)."
|
|
638
|
+
puts ""
|
|
639
|
+
puts "Basic Usage:"
|
|
640
|
+
puts " ruby_spriter --image FILE --split R:C [options]"
|
|
641
|
+
puts ""
|
|
642
|
+
puts "Required:"
|
|
643
|
+
puts " -i, --image FILE Input spritesheet file (PNG)"
|
|
644
|
+
puts " --split R:C Split format: rows:columns (e.g., 4:4)"
|
|
645
|
+
puts " --override-md └─ Override embedded metadata"
|
|
646
|
+
puts ""
|
|
647
|
+
puts "Format Requirements:"
|
|
648
|
+
puts " - Rows and columns must be 1-99"
|
|
649
|
+
puts " - Total frames (R × C) must be < 1000"
|
|
650
|
+
puts " - Image dimensions must divide evenly by rows and columns"
|
|
651
|
+
puts ""
|
|
652
|
+
puts "Metadata Behavior:"
|
|
653
|
+
puts " - If spritesheet has embedded metadata, it will be used automatically"
|
|
654
|
+
puts " - Use --override-md to ignore embedded metadata and use --split value"
|
|
655
|
+
puts " - If no metadata exists, --split value is required"
|
|
656
|
+
puts ""
|
|
657
|
+
puts "Output Options:"
|
|
658
|
+
puts " -o, --output FILE Output directory (default: filename_frames/)"
|
|
659
|
+
puts " --overwrite Overwrite existing files"
|
|
660
|
+
puts " --keep-temp Keep temporary files"
|
|
661
|
+
puts " --debug Enable debug mode"
|
|
662
|
+
puts ""
|
|
663
|
+
puts "Output:"
|
|
664
|
+
puts " - Frames are saved as: FR001_filename.png, FR002_filename.png, etc."
|
|
665
|
+
puts " - Frame naming uses 3-digit zero-padded format (FR001-FR999)"
|
|
666
|
+
puts " - Output directory: filename_frames/ (unless --output specified)"
|
|
667
|
+
puts ""
|
|
668
|
+
puts "Examples:"
|
|
669
|
+
puts " ruby_spriter --image sprite.png --split 4:4"
|
|
670
|
+
puts " ruby_spriter --image sprite.png --split 8:8 --override-md"
|
|
671
|
+
puts " ruby_spriter --image sprite.png --split 2:5 --output frames/"
|
|
672
|
+
puts ""
|
|
673
|
+
exit
|
|
674
|
+
end
|
|
675
|
+
end
|
|
676
|
+
end
|