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.
Files changed (85) hide show
  1. checksums.yaml +4 -4
  2. data/.rspec +3 -3
  3. data/CHANGELOG.md +1035 -524
  4. data/Gemfile +17 -17
  5. data/LICENSE +21 -21
  6. data/README.md +183 -950
  7. data/bin/ruby_spriter +20 -20
  8. data/lib/ruby_spriter/background_sampler.rb +140 -0
  9. data/lib/ruby_spriter/batch_processor.rb +268 -214
  10. data/lib/ruby_spriter/cell_cleanup_config.rb +21 -0
  11. data/lib/ruby_spriter/cell_cleanup_gimp_script.rb +123 -0
  12. data/lib/ruby_spriter/cell_cleanup_processor.rb +230 -0
  13. data/lib/ruby_spriter/cli.rb +676 -612
  14. data/lib/ruby_spriter/compression_manager.rb +101 -101
  15. data/lib/ruby_spriter/consolidator.rb +179 -179
  16. data/lib/ruby_spriter/dependency_checker.rb +224 -224
  17. data/lib/ruby_spriter/ghost_edge_cleaner.rb +164 -0
  18. data/lib/ruby_spriter/gimp_processor.rb +1188 -1058
  19. data/lib/ruby_spriter/metadata_manager.rb +117 -116
  20. data/lib/ruby_spriter/platform.rb +137 -137
  21. data/lib/ruby_spriter/processor.rb +1230 -891
  22. data/lib/ruby_spriter/smoke_detector.rb +223 -0
  23. data/lib/ruby_spriter/threshold_stepper.rb +227 -0
  24. data/lib/ruby_spriter/utils/file_helper.rb +82 -82
  25. data/lib/ruby_spriter/utils/image_helper.rb +16 -0
  26. data/lib/ruby_spriter/utils/output_formatter.rb +65 -65
  27. data/lib/ruby_spriter/utils/path_helper.rb +59 -59
  28. data/lib/ruby_spriter/utils/spritesheet_splitter.rb +86 -86
  29. data/lib/ruby_spriter/version.rb +6 -7
  30. data/lib/ruby_spriter/video_processor.rb +357 -139
  31. data/lib/ruby_spriter.rb +38 -34
  32. data/ruby_spriter.gemspec +44 -42
  33. data/spec/fixtures/centered_sprite_with_inner_bg.png +0 -0
  34. data/spec/fixtures/centered_sprite_with_inner_bg_inner_removed.png +0 -0
  35. data/spec/fixtures/centered_sprite_with_inner_bg_threshold_stepped.png +0 -0
  36. data/spec/fixtures/complex_background_sprite.png +0 -0
  37. data/spec/fixtures/death - bloodborne rekconing.mp4 +0 -0
  38. data/spec/fixtures/death - bloodborne rekconing_spritesheet-nobg-global.png +0 -0
  39. data/spec/fixtures/death - bloodborne rekconing_spritesheet.png +0 -0
  40. data/spec/fixtures/death - bloodborne rekconing_spritesheet_20251110_185027_431-nobg-global.png +0 -0
  41. data/spec/fixtures/death - bloodborne rekconing_spritesheet_20251110_185027_431.png +0 -0
  42. data/spec/fixtures/death - bloodborne rekconing_spritesheet_20251110_185125_738-nobg-global.png +0 -0
  43. data/spec/fixtures/death - bloodborne rekconing_spritesheet_20251110_185125_738.png +0 -0
  44. data/spec/fixtures/has_inner_bg.png +0 -0
  45. data/spec/fixtures/has_small_inner_bg.png +0 -0
  46. data/spec/fixtures/smoke_effect_sprite.png +0 -0
  47. data/spec/fixtures/spritesheet_with_metadata.png +0 -0
  48. data/spec/fixtures/test_sprite.png +0 -0
  49. data/spec/fixtures/test_sprite_smoke_processed.png +0 -0
  50. data/spec/fixtures/test_video_spritesheet.png +0 -0
  51. data/spec/fixtures/transparent_bg_sprite.png +0 -0
  52. data/spec/fixtures/walk_north_sprite-sheet.png +0 -0
  53. data/spec/integration/no_fuzzy_mode_spec.rb +100 -0
  54. data/spec/ruby_spriter/batch_processor_spec.rb +509 -200
  55. data/spec/ruby_spriter/cli_spec.rb +2026 -1892
  56. data/spec/ruby_spriter/compression_manager_spec.rb +157 -157
  57. data/spec/ruby_spriter/consolidator_spec.rb +538 -538
  58. data/spec/ruby_spriter/gimp_processor_spec.rb +523 -425
  59. data/spec/ruby_spriter/platform_spec.rb +92 -92
  60. data/spec/ruby_spriter/processor_spec.rb +911 -735
  61. data/spec/ruby_spriter/utils/file_helper_spec.rb +150 -150
  62. data/spec/ruby_spriter/utils/path_helper_spec.rb +78 -78
  63. data/spec/ruby_spriter/utils/spritesheet_splitter_spec.rb +104 -104
  64. data/spec/ruby_spriter/video_processor_spec.rb +346 -29
  65. data/spec/spec_helper.rb +41 -41
  66. data/spec/tmp/cli_test_output.png +0 -0
  67. data/spec/tmp/cli_test_output_20251105_114647_395.png +0 -0
  68. data/spec/tmp/combined_test.png +0 -0
  69. data/spec/tmp/compat_test.png +0 -0
  70. data/spec/tmp/compat_test_20251030_174233_361.png +0 -0
  71. data/spec/tmp/final_all_features.png +0 -0
  72. data/spec/tmp/final_test_all_features.png +0 -0
  73. data/spec/tmp/full_pipeline_test.png +0 -0
  74. data/spec/tmp/inner_test.png +0 -0
  75. data/spec/tmp/integration_test.png +0 -0
  76. data/spec/tmp/validation_test.png +0 -0
  77. data/spec/unit/background_sampler_spec.rb +132 -0
  78. data/spec/unit/cell_cleanup_config_spec.rb +32 -0
  79. data/spec/unit/cell_cleanup_gimp_script_spec.rb +59 -0
  80. data/spec/unit/cell_cleanup_processor_spec.rb +261 -0
  81. data/spec/unit/ghost_edge_cleaner_spec.rb +223 -0
  82. data/spec/unit/gimp_processor_single_point_selection_spec.rb +81 -0
  83. data/spec/unit/smoke_detector_spec.rb +246 -0
  84. data/spec/unit/threshold_stepper_spec.rb +195 -0
  85. metadata +56 -10
@@ -0,0 +1,246 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'spec_helper'
4
+
5
+ RSpec.describe RubySpriter::SmokeDetector do
6
+ let(:config) do
7
+ double('InnerBgConfig',
8
+ remove_smoke: false)
9
+ end
10
+
11
+ let(:input_image) { 'spec/fixtures/test_sprite.png' }
12
+ let(:output_image) { 'spec/tmp/smoke_processed.png' }
13
+
14
+ before do
15
+ FileUtils.mkdir_p('spec/tmp')
16
+ end
17
+
18
+ after do
19
+ FileUtils.rm_f(output_image) if File.exist?(output_image)
20
+ end
21
+
22
+ describe '#initialize' do
23
+ it 'accepts input image, output image, and config' do
24
+ detector = described_class.new(input_image, output_image, config)
25
+ expect(detector).to be_a(RubySpriter::SmokeDetector)
26
+ end
27
+ end
28
+
29
+ describe '#detect' do
30
+ subject { described_class.new(input_image, output_image, config) }
31
+
32
+ it 'identifies smoke-like transparency gradients' do
33
+ smoke_regions = subject.detect
34
+
35
+ expect(smoke_regions).to be_an(Array)
36
+ # May or may not find smoke depending on fixture
37
+ end
38
+
39
+ it 'detects pixels with alpha between 20-80%' do
40
+ smoke_regions = subject.detect
41
+
42
+ # Each region should have alpha characteristics
43
+ smoke_regions.each do |region|
44
+ expect(region).to have_key(:alpha_range)
45
+ expect(region).to have_key(:area)
46
+ end
47
+ end
48
+
49
+ it 'filters regions by minimum area (50 pixels)' do
50
+ smoke_regions = subject.detect
51
+
52
+ smoke_regions.each do |region|
53
+ expect(region[:area]).to be >= 50
54
+ end
55
+ end
56
+ end
57
+
58
+ describe '#process' do
59
+ context 'when remove_smoke is false' do
60
+ subject { described_class.new(input_image, output_image, config) }
61
+
62
+ it 'detects but does not remove smoke effects' do
63
+ subject.process
64
+ report = subject.report
65
+
66
+ expect(report[:smoke_detected]).to be_a(Integer)
67
+ expect(report[:smoke_removed]).to eq(false)
68
+ end
69
+
70
+ it 'copies input to output unchanged' do
71
+ subject.process
72
+
73
+ expect(File.exist?(output_image)).to be true
74
+
75
+ # Files should be identical
76
+ expect(FileUtils.compare_file(input_image, output_image)).to be true
77
+ end
78
+ end
79
+
80
+ context 'when remove_smoke is true' do
81
+ let(:config) do
82
+ double('InnerBgConfig',
83
+ remove_smoke: true)
84
+ end
85
+
86
+ subject { described_class.new(input_image, output_image, config) }
87
+
88
+ it 'detects and removes smoke effects' do
89
+ subject.process
90
+ report = subject.report
91
+
92
+ expect(report[:smoke_detected]).to be_a(Integer)
93
+ expect(report[:smoke_removed]).to eq(true)
94
+ end
95
+
96
+ it 'creates an output image file' do
97
+ subject.process
98
+ expect(File.exist?(output_image)).to be true
99
+ end
100
+
101
+ it 'removes semi-transparent gradient regions' do
102
+ subject.process
103
+
104
+ # Output should exist and be valid
105
+ expect(File.exist?(output_image)).to be true
106
+
107
+ # Check file size is reasonable
108
+ file_size = File.size(output_image)
109
+ expect(file_size).to be > 100
110
+ end
111
+ end
112
+ end
113
+
114
+ describe '#remove_smoke_regions' do
115
+ let(:config) do
116
+ double('InnerBgConfig',
117
+ remove_smoke: true)
118
+ end
119
+
120
+ subject { described_class.new(input_image, output_image, config) }
121
+
122
+ it 'removes detected smoke regions' do
123
+ smoke_regions = [
124
+ { x: 50, y: 50, area: 100, alpha_range: [0.2, 0.8] }
125
+ ]
126
+
127
+ FileUtils.cp(input_image, output_image)
128
+ result = subject.remove_smoke_regions(smoke_regions)
129
+
130
+ expect(result).to be true
131
+ end
132
+ end
133
+
134
+ describe '#is_smoke_like?' do
135
+ subject { described_class.new(input_image, output_image, config) }
136
+
137
+ it 'returns true for alpha values between 20-80%' do
138
+ expect(subject.is_smoke_like?(0.5)).to be true
139
+ expect(subject.is_smoke_like?(0.3)).to be true
140
+ expect(subject.is_smoke_like?(0.7)).to be true
141
+ end
142
+
143
+ it 'returns false for fully transparent pixels' do
144
+ expect(subject.is_smoke_like?(0.0)).to be false
145
+ expect(subject.is_smoke_like?(0.1)).to be false
146
+ end
147
+
148
+ it 'returns false for fully opaque pixels' do
149
+ expect(subject.is_smoke_like?(1.0)).to be false
150
+ expect(subject.is_smoke_like?(0.9)).to be false
151
+ end
152
+ end
153
+
154
+ describe '#report' do
155
+ subject { described_class.new(input_image, output_image, config) }
156
+
157
+ it 'generates a detection report' do
158
+ subject.process
159
+ report = subject.report
160
+
161
+ expect(report).to be_a(Hash)
162
+ expect(report).to have_key(:smoke_detected)
163
+ expect(report).to have_key(:smoke_removed)
164
+ expect(report).to have_key(:smoke_regions)
165
+ expect(report).to have_key(:processing_time)
166
+ end
167
+
168
+ it 'includes region details when smoke is detected' do
169
+ subject.process
170
+ report = subject.report
171
+
172
+ expect(report[:smoke_regions]).to be_an(Array)
173
+ end
174
+ end
175
+
176
+ describe 'alpha range detection' do
177
+ subject { described_class.new(input_image, output_image, config) }
178
+
179
+ it 'identifies the alpha range of detected regions' do
180
+ smoke_regions = subject.detect
181
+
182
+ smoke_regions.each do |region|
183
+ alpha_range = region[:alpha_range]
184
+ expect(alpha_range).to be_an(Array)
185
+ expect(alpha_range.length).to eq(2)
186
+ expect(alpha_range[0]).to be >= 0.2
187
+ expect(alpha_range[1]).to be <= 0.8
188
+ end
189
+ end
190
+ end
191
+
192
+ describe 'minimum area threshold' do
193
+ subject { described_class.new(input_image, output_image, config) }
194
+
195
+ it 'uses 50 pixels as minimum area' do
196
+ smoke_regions = subject.detect
197
+
198
+ # All detected regions should meet minimum
199
+ smoke_regions.each do |region|
200
+ expect(region[:area]).to be >= 50
201
+ end
202
+ end
203
+ end
204
+
205
+ describe 'performance' do
206
+ subject { described_class.new(input_image, output_image, config) }
207
+
208
+ it 'completes detection in reasonable time' do
209
+ start_time = Time.now
210
+ subject.detect
211
+ elapsed = Time.now - start_time
212
+
213
+ # Should complete in under 15 seconds for small test image
214
+ expect(elapsed).to be < 15
215
+ end
216
+ end
217
+
218
+ describe 'integration scenarios' do
219
+ context 'with image containing no smoke effects' do
220
+ let(:input_image) { 'spec/fixtures/test_sprite.png' }
221
+
222
+ subject { described_class.new(input_image, output_image, config) }
223
+
224
+ it 'reports zero smoke regions detected' do
225
+ subject.process
226
+ report = subject.report
227
+
228
+ expect(report[:smoke_detected]).to eq(0)
229
+ end
230
+ end
231
+
232
+ context 'with grayscale image' do
233
+ let(:input_image) { 'spec/fixtures/test_sprite.png' }
234
+
235
+ subject { described_class.new(input_image, output_image, config) }
236
+
237
+ it 'handles grayscale images correctly' do
238
+ subject.process
239
+ report = subject.report
240
+
241
+ # Should complete without errors
242
+ expect(report[:smoke_detected]).to be >= 0
243
+ end
244
+ end
245
+ end
246
+ end
@@ -0,0 +1,195 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'spec_helper'
4
+ require 'ruby_spriter/threshold_stepper'
5
+ require 'ruby_spriter/gimp_processor'
6
+ require 'tempfile'
7
+
8
+ RSpec.describe RubySpriter::ThresholdStepper do
9
+ let(:input_file) { Tempfile.new(['input', '.png']) }
10
+ let(:output_file) { Tempfile.new(['output', '.png']) }
11
+ let(:background_palette) do
12
+ [
13
+ { r: 255, g: 255, b: 255 },
14
+ { r: 250, g: 250, b: 250 },
15
+ { r: 245, g: 245, b: 245 }
16
+ ]
17
+ end
18
+ let(:gimp_processor) { instance_double(RubySpriter::GimpProcessor) }
19
+ let(:options) { { debug: false } }
20
+ let(:stepper) do
21
+ described_class.new(
22
+ input_file.path,
23
+ output_file.path,
24
+ background_palette,
25
+ gimp_processor,
26
+ options
27
+ )
28
+ end
29
+
30
+ after do
31
+ input_file.close
32
+ input_file.unlink
33
+ output_file.close
34
+ output_file.unlink
35
+ end
36
+
37
+ describe '#initialize' do
38
+ it 'accepts background palette parameter' do
39
+ expect(stepper.instance_variable_get(:@background_palette)).to eq(background_palette)
40
+ end
41
+
42
+ it 'accepts gimp_processor instance' do
43
+ expect(stepper.instance_variable_get(:@gimp_processor)).to eq(gimp_processor)
44
+ end
45
+
46
+ it 'uses default threshold values' do
47
+ thresholds = stepper.instance_variable_get(:@threshold_values)
48
+ expect(thresholds).to eq([0.0, 0.5, 1.0, 3.0, 5.0, 10.0])
49
+ end
50
+
51
+ it 'accepts custom threshold values' do
52
+ custom_stepper = described_class.new(
53
+ input_file.path,
54
+ output_file.path,
55
+ background_palette,
56
+ gimp_processor,
57
+ { threshold_values: [1.0, 5.0, 10.0] }
58
+ )
59
+
60
+ thresholds = custom_stepper.instance_variable_get(:@threshold_values)
61
+ expect(thresholds).to eq([1.0, 5.0, 10.0])
62
+ end
63
+ end
64
+
65
+ describe '#process' do
66
+ it 'generates GIMP script for each threshold value' do
67
+ # Mock GIMP processor to track script executions
68
+ script_calls = []
69
+ allow(gimp_processor).to receive(:execute_python_script) do |script, temp_output|
70
+ script_calls << { script: script, output: temp_output }
71
+ true
72
+ end
73
+
74
+ # Mock ImageMagick compositing
75
+ allow(Open3).to receive(:capture3).and_return(['', '', double(success?: true)])
76
+
77
+ stepper.process
78
+
79
+ # Should generate 6 scripts (one per default threshold)
80
+ expect(script_calls.length).to eq(6)
81
+ end
82
+
83
+ it 'includes background palette colors in GIMP script' do
84
+ generated_script = nil
85
+ allow(gimp_processor).to receive(:execute_python_script) do |script, _|
86
+ generated_script = script
87
+ true
88
+ end
89
+
90
+ allow(Open3).to receive(:capture3).and_return(['', '', double(success?: true)])
91
+
92
+ stepper.process
93
+
94
+ # Script should reference the background colors (normalized to 0.0-1.0)
95
+ # Background palette has: {r: 255, g: 255, b: 255}, {r: 250, g: 250, b: 250}, {r: 245, g: 245, b: 245}
96
+ # These become: rgb(1.0, 1.0, 1.0), rgb(0.98..., 0.98..., 0.98...), rgb(0.96..., 0.96..., 0.96...)
97
+ expect(generated_script).to include('Gegl.Color.new') # Uses Gegl.Color
98
+ expect(generated_script).to include('rgb(') # RGB format
99
+ expect(generated_script).to match(/rgb\(1\.0, 1\.0, 1\.0\)/) # First color (255,255,255)
100
+ end
101
+
102
+ it 'uses gimp-image-select-color in generated script' do
103
+ generated_script = nil
104
+ allow(gimp_processor).to receive(:execute_python_script) do |script, _|
105
+ generated_script = script
106
+ true
107
+ end
108
+
109
+ allow(Open3).to receive(:capture3).and_return(['', '', double(success?: true)])
110
+
111
+ stepper.process
112
+
113
+ # Script should use the correct GIMP procedure
114
+ expect(generated_script).to include('gimp-image-select-color')
115
+ end
116
+
117
+ it 'applies threshold parameter in GIMP script' do
118
+ generated_scripts = []
119
+ allow(gimp_processor).to receive(:execute_python_script) do |script, _|
120
+ generated_scripts << script
121
+ true
122
+ end
123
+
124
+ allow(Open3).to receive(:capture3).and_return(['', '', double(success?: true)])
125
+
126
+ stepper.process
127
+
128
+ # Each script should have a different threshold value
129
+ expect(generated_scripts[0]).to include('threshold')
130
+ expect(generated_scripts[1]).to include('threshold')
131
+ end
132
+
133
+ it 'composites threshold results with ImageMagick' do
134
+ allow(gimp_processor).to receive(:execute_python_script).and_return(true)
135
+
136
+ composite_calls = []
137
+ allow(Open3).to receive(:capture3) do |cmd|
138
+ composite_calls << cmd if cmd.include?('magick')
139
+ ['', '', double(success?: true)]
140
+ end
141
+
142
+ stepper.process
143
+
144
+ # Should composite the results
145
+ expect(composite_calls.length).to be > 0
146
+ end
147
+ end
148
+
149
+ describe 'timeout handling' do
150
+ it 'skips threshold on per-threshold timeout' do
151
+ call_count = 0
152
+ allow(gimp_processor).to receive(:execute_python_script) do
153
+ call_count += 1
154
+ if call_count == 2
155
+ # Simulate timeout on second threshold
156
+ sleep 0.1
157
+ raise Timeout::Error, 'Threshold processing timeout'
158
+ end
159
+ true
160
+ end
161
+
162
+ allow(Open3).to receive(:capture3).and_return(['', '', double(success?: true)])
163
+
164
+ # Should not raise error, just skip the threshold
165
+ expect { stepper.process }.not_to raise_error
166
+ end
167
+
168
+ it 'reports skipped thresholds' do
169
+ allow(gimp_processor).to receive(:execute_python_script) do
170
+ raise Timeout::Error, 'Threshold processing timeout'
171
+ end
172
+
173
+ allow(Open3).to receive(:capture3).and_return(['', '', double(success?: true)])
174
+
175
+ stepper.process
176
+ report = stepper.report
177
+
178
+ expect(report[:skipped_thresholds]).to be > 0
179
+ end
180
+ end
181
+
182
+ describe '#report' do
183
+ it 'includes processing statistics' do
184
+ allow(gimp_processor).to receive(:execute_python_script).and_return(true)
185
+ allow(Open3).to receive(:capture3).and_return(['', '', double(success?: true)])
186
+
187
+ stepper.process
188
+ report = stepper.report
189
+
190
+ expect(report).to have_key(:thresholds_processed)
191
+ expect(report).to have_key(:skipped_thresholds)
192
+ expect(report).to have_key(:total_time)
193
+ end
194
+ end
195
+ end
metadata CHANGED
@@ -1,19 +1,20 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ruby_spriter
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.6.7.1
4
+ version: 0.7.0.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - scooter-indie
8
- autorequire:
9
8
  bindir: bin
10
9
  cert_chain: []
11
- date: 2025-10-25 00:00:00.000000000 Z
10
+ date: 1980-01-02 00:00:00.000000000 Z
12
11
  dependencies: []
13
12
  description: |
14
- Ruby Spriter is a cross-platform tool for creating spritesheets from video files
15
- and processing them with GIMP. Features include background removal, scaling,
16
- consolidation, and metadata management.
13
+ Ruby Spriter is a cross-platform tool for creating professional spritesheets from video files
14
+ with advanced GIMP image processing. Features include edge-based and inner background removal,
15
+ multi-threshold processing, ghost edge prevention, smoke detection, scaling with multiple
16
+ interpolation methods, sharpening, batch processing, spritesheet consolidation, frame extraction,
17
+ and comprehensive metadata management. Designed for game development workflows with Godot Engine.
17
18
  email:
18
19
  - scooter-indie@users.noreply.github.com
19
20
  executables:
@@ -28,28 +29,56 @@ files:
28
29
  - README.md
29
30
  - bin/ruby_spriter
30
31
  - lib/ruby_spriter.rb
32
+ - lib/ruby_spriter/background_sampler.rb
31
33
  - lib/ruby_spriter/batch_processor.rb
34
+ - lib/ruby_spriter/cell_cleanup_config.rb
35
+ - lib/ruby_spriter/cell_cleanup_gimp_script.rb
36
+ - lib/ruby_spriter/cell_cleanup_processor.rb
32
37
  - lib/ruby_spriter/cli.rb
33
38
  - lib/ruby_spriter/compression_manager.rb
34
39
  - lib/ruby_spriter/consolidator.rb
35
40
  - lib/ruby_spriter/dependency_checker.rb
41
+ - lib/ruby_spriter/ghost_edge_cleaner.rb
36
42
  - lib/ruby_spriter/gimp_processor.rb
37
43
  - lib/ruby_spriter/metadata_manager.rb
38
44
  - lib/ruby_spriter/platform.rb
39
45
  - lib/ruby_spriter/processor.rb
46
+ - lib/ruby_spriter/smoke_detector.rb
47
+ - lib/ruby_spriter/threshold_stepper.rb
40
48
  - lib/ruby_spriter/utils/file_helper.rb
49
+ - lib/ruby_spriter/utils/image_helper.rb
41
50
  - lib/ruby_spriter/utils/output_formatter.rb
42
51
  - lib/ruby_spriter/utils/path_helper.rb
43
52
  - lib/ruby_spriter/utils/spritesheet_splitter.rb
44
53
  - lib/ruby_spriter/version.rb
45
54
  - lib/ruby_spriter/video_processor.rb
46
55
  - ruby_spriter.gemspec
56
+ - spec/fixtures/centered_sprite_with_inner_bg.png
57
+ - spec/fixtures/centered_sprite_with_inner_bg_inner_removed.png
58
+ - spec/fixtures/centered_sprite_with_inner_bg_threshold_stepped.png
59
+ - spec/fixtures/complex_background_sprite.png
60
+ - spec/fixtures/death - bloodborne rekconing.mp4
61
+ - spec/fixtures/death - bloodborne rekconing_spritesheet-nobg-global.png
62
+ - spec/fixtures/death - bloodborne rekconing_spritesheet.png
63
+ - spec/fixtures/death - bloodborne rekconing_spritesheet_20251110_185027_431-nobg-global.png
64
+ - spec/fixtures/death - bloodborne rekconing_spritesheet_20251110_185027_431.png
65
+ - spec/fixtures/death - bloodborne rekconing_spritesheet_20251110_185125_738-nobg-global.png
66
+ - spec/fixtures/death - bloodborne rekconing_spritesheet_20251110_185125_738.png
67
+ - spec/fixtures/has_inner_bg.png
68
+ - spec/fixtures/has_small_inner_bg.png
47
69
  - spec/fixtures/image_without_metadata.png
70
+ - spec/fixtures/smoke_effect_sprite.png
48
71
  - spec/fixtures/spritesheet_4x2.png
49
72
  - spec/fixtures/spritesheet_4x4.png
50
73
  - spec/fixtures/spritesheet_6x2.png
51
74
  - spec/fixtures/spritesheet_with_metadata.png
75
+ - spec/fixtures/test_sprite.png
76
+ - spec/fixtures/test_sprite_smoke_processed.png
52
77
  - spec/fixtures/test_video.mp4
78
+ - spec/fixtures/test_video_spritesheet.png
79
+ - spec/fixtures/transparent_bg_sprite.png
80
+ - spec/fixtures/walk_north_sprite-sheet.png
81
+ - spec/integration/no_fuzzy_mode_spec.rb
53
82
  - spec/ruby_spriter/batch_processor_spec.rb
54
83
  - spec/ruby_spriter/cli_spec.rb
55
84
  - spec/ruby_spriter/compression_manager_spec.rb
@@ -65,6 +94,25 @@ files:
65
94
  - spec/ruby_spriter/utils/spritesheet_splitter_spec.rb
66
95
  - spec/ruby_spriter/video_processor_spec.rb
67
96
  - spec/spec_helper.rb
97
+ - spec/tmp/cli_test_output.png
98
+ - spec/tmp/cli_test_output_20251105_114647_395.png
99
+ - spec/tmp/combined_test.png
100
+ - spec/tmp/compat_test.png
101
+ - spec/tmp/compat_test_20251030_174233_361.png
102
+ - spec/tmp/final_all_features.png
103
+ - spec/tmp/final_test_all_features.png
104
+ - spec/tmp/full_pipeline_test.png
105
+ - spec/tmp/inner_test.png
106
+ - spec/tmp/integration_test.png
107
+ - spec/tmp/validation_test.png
108
+ - spec/unit/background_sampler_spec.rb
109
+ - spec/unit/cell_cleanup_config_spec.rb
110
+ - spec/unit/cell_cleanup_gimp_script_spec.rb
111
+ - spec/unit/cell_cleanup_processor_spec.rb
112
+ - spec/unit/ghost_edge_cleaner_spec.rb
113
+ - spec/unit/gimp_processor_single_point_selection_spec.rb
114
+ - spec/unit/smoke_detector_spec.rb
115
+ - spec/unit/threshold_stepper_spec.rb
68
116
  homepage: https://github.com/scooter-indie/ruby-spriter
69
117
  licenses:
70
118
  - MIT
@@ -72,7 +120,6 @@ metadata:
72
120
  homepage_uri: https://github.com/scooter-indie/ruby-spriter
73
121
  source_code_uri: https://github.com/scooter-indie/ruby-spriter
74
122
  changelog_uri: https://github.com/scooter-indie/ruby-spriter/blob/main/CHANGELOG.md
75
- post_install_message:
76
123
  rdoc_options: []
77
124
  require_paths:
78
125
  - lib
@@ -87,8 +134,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
87
134
  - !ruby/object:Gem::Version
88
135
  version: '0'
89
136
  requirements: []
90
- rubygems_version: 3.5.22
91
- signing_key:
137
+ rubygems_version: 3.7.2
92
138
  specification_version: 4
93
- summary: MP4 to Spritesheet converter with GIMP image processing
139
+ summary: Professional MP4 to Spritesheet converter with advanced GIMP image processing
94
140
  test_files: []