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
data/CHANGELOG.md CHANGED
@@ -1,524 +1,1035 @@
1
-
2
- ---
3
-
4
- ### **CHANGELOG.md**
5
- ```markdown
6
- # Changelog
7
-
8
- All notable changes to Ruby Spriter will be documented in this file.
9
-
10
- The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
11
- and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
12
-
13
- ---
14
-
15
- ## [0.6.7.1] - 2025-10-24
16
-
17
- ### ๐Ÿง Linux Support Enhancement Release
18
-
19
- #### Added
20
- - **Linux GIMP 3.x Support**: Full support for GIMP 3.x on Linux via Flatpak
21
- - Automatic detection of Flatpak GIMP installation (`flatpak:org.gimp.GIMP`)
22
- - Automatic Xvfb integration for completely headless GIMP operation
23
- - Virtual display provided by Xvfb eliminates display connection requirement
24
- - Flatpak socket isolation (`--nosocket=x11 --nosocket=wayland`) prevents GUI from appearing
25
- - Python-fu batch mode works correctly with `python-fu-eval` interpreter
26
- - Background removal, scaling, and all GIMP features fully functional
27
- - Perfect for desktop use (no GUI distraction) and server environments (CI/CD, Docker, SSH)
28
- - **GIMP Version Detection**: Detect and report GIMP version (2.x or 3.x)
29
- - `Platform.detect_gimp_version(version_output)` - Parse version from `--version` output
30
- - `Platform.get_gimp_version(gimp_path)` - Get version from executable or Flatpak
31
- - Works with both regular executables and Flatpak installations
32
- - **Xvfb Dependency Checking**: Added Xvfb to dependency checker (Linux only)
33
- - Marked as required on Linux, optional on Windows/macOS
34
- - Provides clear installation instructions if missing
35
- - Validates availability before GIMP operations
36
- - **DependencyChecker Version Tracking**: Store and report detected GIMP version
37
- - **Xvfb Integration**: Transparent Xvfb usage when GIMP Flatpak detected
38
- - Command format: `xvfb-run --auto-servernum --server-args='-screen 0 1024x768x24' flatpak run --nosocket=x11 --nosocket=wayland org.gimp.GIMP --no-splash --quit --batch-interpreter=python-fu-eval`
39
- - No user configuration required - works automatically
40
- - Completely headless - no GUI windows appear on screen
41
-
42
- #### Changed
43
- - **Platform Detection**: Enhanced to detect Flatpak GIMP alongside traditional installations
44
- - **GimpProcessor**: Updated to support both GIMP 2.x and 3.x APIs (version-aware)
45
- - **Unix GIMP Execution**: Automatically uses Xvfb with socket isolation for Flatpak installations
46
- - **Alternative GIMP Paths**: Added `flatpak:org.gimp.GIMP` to Linux search paths
47
- - **Warning Filters**: Enhanced to filter Xvfb, Wayland, and Flatpak cosmetic warnings
48
- - **DependencyChecker**: Now supports platform-specific optional dependencies
49
-
50
- #### Technical Details
51
- - **GIMP Flatpak Detection**: Uses `flatpak list --app | grep` to verify installation
52
- - **Version Parsing**: Regex-based parsing of `GIMP version X.Y.Z` output
53
- - **Python Interpreter**: Correct name is `python-fu-eval` (not `python-eval`)
54
- - **Xvfb Flags**:
55
- - `--auto-servernum` - Automatically finds free display number
56
- - `--server-args='-screen 0 1024x768x24'` - Configures virtual display
57
- - **Flatpak Socket Isolation**:
58
- - `--nosocket=x11` - Prevents access to host X11 display socket
59
- - `--nosocket=wayland` - Prevents access to host Wayland display socket
60
- - Ensures GIMP runs only in Xvfb virtual display
61
- - **Platform Module**: New methods for version detection and Flatpak handling
62
- - **Warning Filtering**: Filters Gdk-WARNING, LibGimp-WARNING, Gimp-Core-WARNING, X11 socket messages
63
-
64
- #### Installation Requirements (Linux)
65
- ```bash
66
- # Ubuntu/Debian
67
- sudo apt install flatpak xvfb -y
68
- flatpak remote-add --if-not-exists flathub https://flathub.org/repo/flathub.flatpakrepo
69
- flatpak install flathub org.gimp.GIMP -y
70
-
71
- # Fedora/RHEL
72
- sudo dnf install flatpak xorg-x11-server-Xvfb -y
73
- flatpak remote-add --if-not-exists flathub https://flathub.org/repo/flathub.flatpakrepo
74
- flatpak install flathub org.gimp.GIMP -y
75
- ```
76
-
77
- #### Example Output
78
- ```bash
79
- $ ruby_spriter --check-dependencies
80
- ============================================================
81
- Dependency Check
82
- ============================================================
83
-
84
- โœ… FFMPEG
85
- Found: 6.1.1
86
-
87
- โœ… FFPROBE
88
- Found: 6.1.1
89
-
90
- โœ… IMAGEMAGICK
91
- Found: Version: ImageMagick 6.9.12-98 Q16 x86_64
92
-
93
- โœ… XVFB
94
- Found: Usage: xvfb-run [OPTION ...] COMMAND
95
-
96
- โœ… GIMP
97
- Found: flatpak:org.gimp.GIMP
98
- Version: GIMP 3.0.6
99
-
100
- ============================================================
101
-
102
- $ ruby_spriter --image sprite.png --remove-bg
103
- ============================================================
104
- GIMP Processing
105
- ============================================================
106
- ๐Ÿ“ Using GIMP via Xvfb (virtual display)
107
- Removing background (fuzzy select)...
108
- === GIMP Messages ===
109
- Loading image...
110
- Image size: 1280x748
111
- Added alpha channel
112
- Sampling 4 corners...
113
- Using FUZZY SELECT (contiguous regions only)
114
- Corner 1 at (0, 0)
115
- Corner 2 at (1279, 0)
116
- Corner 3 at (0, 747)
117
- Corner 4 at (1279, 747)
118
- Selection complete
119
- Growing selection by 1 pixels...
120
- Selection grown
121
- Removing background...
122
- Background removed
123
- Deselecting...
124
- Exporting...
125
- SUCCESS - Background removed!
126
- ====================
127
- โœ… Background Removal complete (142.15 KB)
128
- ```
129
-
130
- **Note**: No GIMP GUI window appears on screen - completely headless operation!
131
-
132
- ---
133
-
134
- ## [0.6.7] - 2025-10-24
135
-
136
- ### ๐Ÿš€ Batch Processing, Compression, Directory Consolidation & Frame Extraction Release
137
-
138
- #### Added
139
- - **Batch Processing Mode** (`--batch`): Process multiple MP4 files in a directory (Issue #16)
140
- - `--dir DIRECTORY`: Specify directory containing MP4 files to process
141
- - `--outputdir DIRECTORY`: Optional output directory (defaults to input directory)
142
- - `--batch-consolidate`: Automatically consolidate all resulting spritesheets
143
- - Supports all existing processing options: `--scale`, `--remove-bg`, `--sharpen`, `--interpolation`, etc.
144
- - Enforces unique filenames unless `--overwrite` is specified
145
- - Continues processing remaining videos if one fails
146
- - Provides detailed summary of successes and failures
147
- - **Maximum Compression** (`--max-compress`): Apply maximum PNG compression (Issue #14)
148
- - Uses ImageMagick with optimal compression settings (level 9, filter 5, strategy 1, quality 95)
149
- - Preserves embedded metadata through compression
150
- - Works with all processing modes: `--video`, `--image`, `--batch`, `--consolidate`
151
- - Displays compression statistics (original size, compressed size, savings, reduction percentage)
152
- - **Directory-Based Consolidation**: `--consolidate` now supports `--dir` option to automatically consolidate all spritesheets in a directory
153
- - Scans directory for PNG files with embedded spritesheet metadata
154
- - Automatically filters out non-spritesheet PNG files
155
- - Sorts files alphabetically by filename before consolidation
156
- - Requires at least 2 valid spritesheets in directory
157
- - Works with all existing consolidation options: `--output`, `--outputdir`, `--overwrite`, `--max-compress`, `--no-validate-columns`
158
- - Mutual exclusivity validation: Cannot use both comma-separated file list and `--dir` with `--consolidate`
159
- - **Enhanced Context-Sensitive Help System**: Mode-specific help displays only relevant options
160
- - `ruby_spriter --video --help`: Shows video mode options (spritesheet generation, processing, output)
161
- - `ruby_spriter --image --help`: Shows image mode options (processing, frame extraction, output)
162
- - `ruby_spriter --consolidate --help`: Shows consolidation options (input methods, validation, output)
163
- - `ruby_spriter --batch --help`: Shows batch processing options (directory processing, applied options)
164
- - `ruby_spriter --split --help`: Shows frame extraction options (split format, metadata behavior, output)
165
- - General `--help`: Shows mode-specific help hints and directs users to detailed help
166
- - **Parent-Child Option Hierarchy**: Visual hierarchy (โ””โ”€) shows modifier options grouped under parent options
167
- - `--interpolation`, `--sharpen*` modifiers shown under `--scale`
168
- - `--fuzzy`, `--threshold`, `--grow` modifiers shown under `--remove-bg`
169
- - `--override-md` modifier shown under `--split`
170
- - `--validate-columns` modifier shown under `--consolidate --dir`
171
- - Organized by function (Image Processing, Output Options) instead of by tool (GIMP Processing Options)
172
- - **Frame Extraction** (`--extract`): Extract specific frames and create new spritesheet
173
- - `--extract FRAMES`: Comma-separated frame numbers (e.g., `1,2,4,5,8`)
174
- - `--columns NUM`: Specify output grid columns (default: 4)
175
- - Supports duplicate frame numbers for animation sequences
176
- - 1-indexed frame numbering (left-to-right, top-to-bottom)
177
- - Requires spritesheet metadata (works with `--verify` output)
178
- - Works with all `--image` processing options: `--scale`, `--remove-bg`, `--sharpen`, `--max-compress`
179
- - Automatic output naming with `_extracted` suffix or custom via `--output`
180
- - Temporary frames deleted after reassembly unless `--save-frames` specified
181
- - Minimum 2 frames required
182
- - Out-of-bounds validation against spritesheet metadata
183
- - Mutual exclusivity with `--split`
184
- - **Metadata Management** (`--add-meta`): Add spritesheet metadata to images without metadata
185
- - `--add-meta R:C`: Specify grid layout (rows:columns, e.g., `4:4`)
186
- - `--overwrite-meta`: Replace existing metadata
187
- - `--frames COUNT`: Custom frame count for partial grids (fewer frames than grid size)
188
- - In-place modification by default (respects `--overwrite` flag)
189
- - Optional `--output` for copying to new file
190
- - Dimension validation: Image dimensions must divide evenly by grid
191
- - Enables `--extract`, `--consolidate`, `--verify`, `--split` on external spritesheets
192
- - Standalone mode: Cannot combine with `--scale`, `--remove-bg`, `--sharpen`
193
- - **Enhanced `--save-frames`**: Now works with both `--video` and `--extract`
194
- - **New Modules**:
195
- - `BatchProcessor` (lib/ruby_spriter/batch_processor.rb): Orchestrates batch video processing
196
- - `CompressionManager` (lib/ruby_spriter/compression_manager.rb): Handles PNG compression with metadata preservation
197
- - **New Public Method**: `Consolidator#find_spritesheets_in_directory(directory)` for directory scanning
198
- - **Comprehensive Test Coverage**: 68 new tests (13 for BatchProcessor, 11 for CompressionManager, 15 for directory consolidation, 7 for context-sensitive help, 22 for frame extraction and metadata management)
199
-
200
- #### Changed
201
- - **CLI**: Updated `--consolidate` description to mention `--dir` option
202
- - **CLI**: Renamed "GIMP Processing Options" to "Processing Options" for tool-agnostic organization
203
- - **CLI**: Updated image mode help with Frame Extraction & Reassembly section
204
- - **CLI**: Added Metadata Management section to image mode help
205
- - **Processor**: Refactored consolidation workflow to support both file list and directory modes
206
- - **Test Suite**: Increased from 274 to 365 examples (all passing), 75.8% line coverage
207
- - **CLI**: Added parent-child visual hierarchy to all context-sensitive help displays
208
- - **CLI**: Corrected `--sharpen` to show as standalone option (not under `--scale`)
209
-
210
- #### Examples
211
- ```bash
212
- # Get context-sensitive help for specific modes
213
- ruby_spriter --video --help
214
- ruby_spriter --image --help
215
- ruby_spriter --consolidate --help
216
- ruby_spriter --batch --help
217
- ruby_spriter --split --help
218
-
219
- # Process all videos in directory
220
- ruby_spriter --batch --dir "videos/"
221
-
222
- # Process with output to different directory
223
- ruby_spriter --batch --dir "videos/" --outputdir "output/"
224
-
225
- # Process and consolidate all results
226
- ruby_spriter --batch --dir "videos/" --batch-consolidate
227
-
228
- # Process with scaling and compression
229
- ruby_spriter --batch --dir "videos/" --scale 50 --max-compress
230
-
231
- # Compress video output
232
- ruby_spriter --video "input.mp4" --max-compress
233
-
234
- # Compress image processing output
235
- ruby_spriter --image "sprite.png" --scale 50 --max-compress
236
-
237
- # Directory-based consolidation
238
- ruby_spriter --consolidate --dir "spritesheets/"
239
- ruby_spriter --consolidate --dir "spritesheets/" --outputdir "output/"
240
- ruby_spriter --consolidate --dir "spritesheets/" --max-compress
241
-
242
- # File list consolidation still works
243
- ruby_spriter --consolidate file1.png,file2.png,file3.png
244
-
245
- # Extract specific frames and create new spritesheet
246
- ruby_spriter --image sprite.png --extract 1,2,4,5,8 --columns 3
247
-
248
- # Extract with duplicates for animation loops
249
- ruby_spriter --image sprite.png --extract 1,1,2,2,3,3 --save-frames
250
-
251
- # Extract and process
252
- ruby_spriter --image sprite.png --extract 1,3,5,7 --scale 50 --sharpen
253
-
254
- # Add metadata to external spritesheet
255
- ruby_spriter --image sprite.png --add-meta 4:4
256
-
257
- # Add metadata with partial grid
258
- ruby_spriter --image sprite.png --add-meta 4:4 --frames 14 --output sprite_meta.png
259
-
260
- # Replace existing metadata
261
- ruby_spriter --image existing.png --add-meta 8:8 --overwrite-meta
262
-
263
- # Workflow: Add metadata, then extract frames
264
- ruby_spriter --image external.png --add-meta 4:4
265
- ruby_spriter --image external.png --extract 1,5,9,13 --columns 2
266
- ```
267
-
268
- Closes #14, #16
269
-
270
- ---
271
-
272
- ## [0.6.6] - 2025-10-23
273
-
274
- ### ๐Ÿ”’ File Protection & Frame Extraction Release
275
-
276
- #### Added
277
- - **Automatic Unique Filenames**: By default, generates timestamped filenames to prevent accidental overwrites
278
- - Format: `filename_YYYYMMDD_HHMMSS_mmm.ext` (includes milliseconds)
279
- - Applies to all output modes: `--video`, `--image`, `--consolidate`
280
- - Works with both auto-generated and `--output` specified filenames
281
- - **`--overwrite` Flag**: Optional flag to explicitly allow overwriting existing files
282
- - **`--split R:C` Option**: Split spritesheets into individual frames for `--image` workflow
283
- - Format: `--split 4:4` (rows:columns, e.g., 4 rows ร— 4 columns)
284
- - Validation: Rows and columns must be 1-99, total frames < 1000
285
- - Frame naming: `FRddd_filename.png` (3-digit zero-padded format: FR001, FR002, ..., FR999)
286
- - Output directory: `filename_frames/`
287
- - Metadata priority: Uses embedded metadata if available, unless `--override-md` flag is provided
288
- - Dimension validation: Image dimensions must divide evenly by specified rows and columns
289
- - **`--override-md` Flag**: Override embedded metadata when using `--split` with images that have metadata
290
- - **Intermediate File Cleanup**: Fixed cleanup of intermediate files from GIMP processing
291
- - Now correctly removes files with dash separator (e.g., `file-nobg-fuzzy.png`, `file-scaled-40pct.png`)
292
- - Added Windows-compatible path normalization for file comparison
293
- - **Frame Extraction Tests**: 17 new comprehensive tests for split functionality
294
- - CLI option tests for `--split` and `--override-md`
295
- - Format and range validation tests (10 tests)
296
- - Metadata priority logic tests (5 tests)
297
- - Updated SpritesheetSplitter tests for FR%03d format
298
-
299
- #### Changed
300
- - **Default Behavior**: Changed from overwriting to creating unique files (breaking change, but safer)
301
- - **GimpProcessor**: Now respects `--overwrite` flag for scaled and background-removed images
302
- - **Consolidate Workflow**: Default filename changed from `consolidated_spritesheet_TIMESTAMP.png` to `consolidated_spritesheet.png` (uniqueness handled by flag)
303
- - **Frame Naming Format**: Changed from FR%02d (2 digits) to FR%03d (3 digits) to support up to 999 frames
304
- - **Intermediate File Pattern**: Fixed glob pattern from underscore to dash separator for GIMP output files
305
-
306
- #### Technical Details
307
- - New utility methods in `Utils::FileHelper`:
308
- - `unique_filename(path)` - Generates timestamped filename if file exists
309
- - `ensure_unique_output(path, overwrite:)` - Applies overwrite logic
310
- - New methods in `Processor`:
311
- - `validate_split_option!` - Validates split format and ranges during initialization
312
- - `determine_split_parameters(image_file)` - Implements metadata priority logic
313
- - `validate_image_dimensions(image_file, rows, columns)` - Validates even division
314
- - Processor workflows updated to use `ensure_unique_output` for all output paths
315
- - `SpritesheetSplitter` updated to use 3-digit frame format (FR%03d)
316
- - Test coverage increased to 72.27% (688/952 lines)
317
-
318
- Closes #17, #19, #30
319
-
320
- ---
321
-
322
- ## [0.6.5] - 2025-10-23
323
-
324
- ### ๐Ÿ“ฆ Distribution & Packaging Release
325
-
326
- **Note**: Version 0.6.5 is functionally identical to 0.6.4, which was yanked from RubyGems due to RubyGems policy preventing re-publication of yanked versions.
327
-
328
- #### Added
329
- - **GitHub Actions CI/CD Pipeline**: Automated testing across Ruby 2.7-3.3 on Ubuntu, macOS, and Windows
330
- - **Automated RubyGems Publishing**: Auto-publish gem to RubyGems.org on version tag push
331
- - **Release Automation Workflow**: Multi-platform gem builds with artifact uploads to GitHub Releases
332
- - **Code Coverage Reporting**: SimpleCov integration in CI with PR summaries
333
-
334
- #### Changed
335
- - **Installation Options**: Two installation methods (RubyGems for all platforms, from source)
336
- - **README Structure**: Simplified installation section focusing on gem distribution
337
- - **Gemspec Author Info**: Updated from placeholders to actual author details
338
-
339
- #### Distribution
340
- - **RubyGems**: Published gem with all runtime files (works on Windows, macOS, Linux)
341
- - **Source Install**: Git clone with local gem build option
342
-
343
- #### Deferred
344
- - **Windows Standalone Executable**: Deferred due to OCRA incompatibility with Ruby 3.x
345
- - OCRA 1.3.11 (last version, 2019) fails with Ruby 3.2+ due to internal fiber changes
346
- - Windows users can use `gem install ruby_spriter` after installing Ruby
347
- - Will revisit when better Windows packaging tools become available
348
-
349
- Closes #18
350
-
351
- ---
352
-
353
- ## [0.6.4] - 2025-10-23 [YANKED]
354
-
355
- Version yanked from RubyGems. Use 0.6.5 instead.
356
-
357
- ### ๐Ÿ“ฆ Distribution & Packaging Release
358
-
359
- #### Added
360
- - **GitHub Actions CI/CD Pipeline**: Automated testing across Ruby 2.7-3.3 on Ubuntu, macOS, and Windows
361
- - **Automated RubyGems Publishing**: Auto-publish gem to RubyGems.org on version tag push
362
- - **Release Automation Workflow**: Multi-platform gem builds with artifact uploads to GitHub Releases
363
- - **Code Coverage Reporting**: SimpleCov integration in CI with PR summaries
364
-
365
- #### Changed
366
- - **Installation Options**: Two installation methods (RubyGems for all platforms, from source)
367
- - **README Structure**: Simplified installation section focusing on gem distribution
368
- - **Gemspec Author Info**: Updated from placeholders to actual author details
369
-
370
- #### Distribution
371
- - **RubyGems**: Published gem with all runtime files (works on Windows, macOS, Linux)
372
- - **Source Install**: Git clone with local gem build option
373
-
374
- #### Deferred
375
- - **Windows Standalone Executable**: Deferred due to OCRA incompatibility with Ruby 3.x
376
- - OCRA 1.3.11 (last version, 2019) fails with Ruby 3.2+ due to internal fiber changes
377
- - Windows users can use `gem install ruby_spriter` after installing Ruby
378
- - Will revisit when better Windows packaging tools become available
379
-
380
- Closes #18
381
-
382
- ---
383
-
384
- ## [0.6.3] - 2025-10-23
385
-
386
- ### ๐Ÿงช Testing & Quality Assurance Release
387
-
388
- #### Added
389
- - **155 New RSpec Tests**: Comprehensive test coverage for CLI, GimpProcessor, Consolidator, PathHelper
390
- - **Test Fixtures**: Real spritesheet fixtures (4x2, 6x2, 4x4), PNG images, MP4 video
391
- - **Code Coverage Reporting**: SimpleCov tracking showing 57.09% coverage
392
-
393
- #### Fixed
394
- - **CLI Preset Bug**: Fixed OptionParser limitation preventing all 4 presets from working
395
- - **PathHelper Quote Escaping**: Fixed single quote escaping in Unix paths (needed 4 backslashes)
396
- - **Spec Helper Bug**: Changed instance variable to global variable for cross-context access
397
- - **PathHelper Tests**: Made drive letter detection flexible for E: drive compatibility
398
-
399
- #### Testing
400
- - **CLI Tests (97)**: --help, --version, --check-dependencies, --image, --video, --consolidate, --verify
401
- - **GimpProcessor Tests (48)**: Initialization, operations, interpolation, output filtering, script generation
402
- - **Consolidator Tests (33)**: File validation, metadata, column validation, consolidation logic
403
- - **PathHelper Tests (7)**: Quote paths, normalize for Python, native format conversion
404
- - **Coverage**: Increased from 22.52% to 57.09% (+34.57 percentage points)
405
-
406
- Closes #5
407
-
408
- ---
409
-
410
- ## [0.6.2] - 2025-10-22
411
-
412
- ### โœจ Quality Enhancement & Tooling Release
413
-
414
- #### Added
415
- - **Interpolation Options**: 5 interpolation methods for scaling (none, linear, cubic, nohalo, lohalo)
416
- - **Sharpening Support**: Unsharp mask with configurable radius, gain, and threshold
417
- - **`--version` Flag**: Display version, platform, and date information
418
- - **`--check-dependencies` Flag**: Verify all external tools are installed with platform-specific guidance
419
- - **File Extension Validation**: Runtime validation for MP4 (video) and PNG (images)
420
- - **GIMP Investigation Documentation**: Comprehensive documentation of GIMP sharpen attempts and solutions
421
-
422
- #### Changed
423
- - **Automatic Operation Order**: Auto-optimize to remove background before scaling for better quality
424
- - **Sharpening via ImageMagick**: Use ImageMagick instead of GIMP for reliable cross-platform sharpening
425
- - **Alpha Channel Preservation**: Use merge instead of flatten to preserve transparency
426
- - **Conservative Sharpen Defaults**: radius: 2.0, gain: 0.5, threshold: 0.03 to minimize halo artifacts
427
- - **Parameter Terminology**: Changed "amount" to "gain" to match ImageMagick documentation
428
-
429
- #### Fixed
430
- - **Gem Build Error**: Removed .rb extension from `bin/ruby_spriter` executable
431
- - **Clear Error Messages**: File extension validation provides helpful feedback
432
-
433
- #### Documentation
434
- - **README.md**: Added interpolation and sharpening documentation, file format requirements
435
- - **CLAUDE.md**: Updated with new features and validation details
436
- - **GIMP_SHARPEN_INVESTIGATION.md**: Documents 8 failed GIMP attempts and architectural decisions
437
-
438
- ---
439
-
440
- ## [0.6.1] - 2025-10-22
441
-
442
- ### ๐ŸŽ‰ Major Refactoring Release
443
-
444
- #### Added
445
- - **Modular Architecture**: Split monolithic script into organized modules
446
- - **RSpec Testing Framework**: Comprehensive unit test coverage
447
- - **Dependency Checking**: Automatic validation of external tools
448
- - **Better Error Handling**: Custom exception classes
449
- - **Code Documentation**: Inline comments and YARD-compatible docs
450
- - **SimpleCov Integration**: Code coverage reporting
451
- - **RuboCop Support**: Code style enforcement
452
-
453
- #### Changed
454
- - **Project Structure**: Reorganized into `lib/`, `spec/`, and `bin/` directories
455
- - **Class Organization**:
456
- - `Platform` - Platform detection and configuration
457
- - `DependencyChecker` - External tool validation
458
- - `VideoProcessor` - FFmpeg operations
459
- - `GimpProcessor` - GIMP operations
460
- - `MetadataManager` - PNG metadata handling
461
- - `Consolidator` - Spritesheet consolidation
462
- - `Processor` - Main orchestration
463
- - `CLI` - Command-line interface
464
- - Utilities: `PathHelper`, `FileHelper`, `OutputFormatter`
465
-
466
- #### Fixed
467
- - Path handling edge cases on Windows
468
- - Improved error messages with actionable guidance
469
- - Better temp file cleanup
470
-
471
- #### Developer Experience
472
- - Gemfile for dependency management
473
- - RSpec test suite with fixtures
474
- - Comprehensive README with examples
475
- - Troubleshooting guide
476
- - Contributing guidelines
477
-
478
- ---
479
-
480
- ## [0.6.0] - 2024-XX-XX
481
-
482
- ### Added
483
- - Metadata embedding in PNG files
484
- - Spritesheet consolidation feature
485
- - Metadata verification command (`--verify`)
486
- - Debug mode for troubleshooting
487
-
488
- ### Changed
489
- - Improved GIMP script generation
490
- - Better cross-platform path handling
491
-
492
- ---
493
-
494
- ## [0.5.0] - 2024-XX-XX
495
-
496
- ### Added
497
- - Background removal with GIMP
498
- - Fuzzy select and global color select options
499
- - Image scaling support
500
- - Configurable operation order
501
-
502
- ---
503
-
504
- ## [0.4.0] - 2024-XX-XX
505
-
506
- ### Added
507
- - Video to spritesheet conversion
508
- - FFmpeg integration
509
- - Customizable grid layouts
510
-
511
- ---
512
-
513
- ## [0.1.0] - 2024-XX-XX
514
-
515
- ### Added
516
- - Initial release
517
- - Basic video processing
518
- - Cross-platform support
519
-
520
- ---
521
-
522
- [0.6.2]: https://github.com/scooter-indie/ruby-spriter/compare/v0.6.1...v0.6.2
523
- [0.6.1]: https://github.com/scooter-indie/ruby-spriter/compare/v0.6.0...v0.6.1
524
- [0.6.0]: https://github.com/scooter-indie/ruby-spriter/releases/tag/v0.6.0
1
+ ---
2
+
3
+ ### **CHANGELOG.md**
4
+ ```markdown
5
+ ## [0.7.0.1] - 2025-11-07 to 2025-11-11
6
+ ### ๐Ÿ”ง Code Quality & Performance Release (Nov 8-11, 2025)
7
+
8
+ ### ๐ŸŽจ Cell-Based Background Cleanup (EXPERIMENTAL - Nov 10-11, 2025)
9
+
10
+ #### Added
11
+ - **Cell-Based Background Cleanup** (`--cleanup-cells`): Post-process residual backgrounds from finished spritesheets
12
+ - Analyzes each cell independently for dominant background colors exceeding threshold
13
+ - Uses GIMP to remove detected dominant colors from individual cells
14
+ - Configurable threshold via `--cell-cleanup-threshold` (default: 15.0%, range: 1.0-50.0)
15
+ - Requires `--remove-bg` flag (validates usage)
16
+ - Cannot be combined with `--by-frame` (redundant - by-frame already handles per-frame cleanup)
17
+ - Works with both `--video` and `--batch` modes
18
+ - Progress reporting shows cells processed/cleaned/skipped counts
19
+ - โš ๏ธ **Experimental**: Feature is technically complete and all tests pass, but background removal is not yet effective in practice. Requires algorithm optimization. Not recommended for production use.
20
+
21
+ #### New Classes
22
+ - **CellCleanupProcessor** (`lib/ruby_spriter/cell_cleanup_processor.rb`)
23
+ - Orchestrates cell-by-cell analysis and cleanup
24
+ - Methods: `cleanup_cells`, `extract_cell`, `analyze_cell_colors`, `remove_dominant_colors`, `reassemble_spritesheet`
25
+ - Integrates with GimpProcessor for color selection
26
+ - Returns statistics: `{ processed: N, cleaned: N, skipped: N, colors_removed: N }`
27
+
28
+ - **CellCleanupConfig** (`lib/ruby_spriter/cell_cleanup_config.rb`)
29
+ - Configuration validation for cleanup parameters
30
+ - Validates threshold range (1.0-50.0)
31
+
32
+ - **CellCleanupGimpScript** (`lib/ruby_spriter/cell_cleanup_gimp_script.rb`)
33
+ - Generates GIMP 3.x Python-fu scripts for cell cleanup
34
+ - Handles path normalization for Windows
35
+ - Uses exact color matching with Gegl.Color API
36
+ - Proper garbage collection to prevent memory leaks
37
+
38
+ #### Integration
39
+ - **Processor**: Updated `apply_cell_cleanup` method with proper parameter passing
40
+ - **VideoProcessor**: Added cell cleanup step after standard background removal in pipeline
41
+ - **BatchProcessor**: Cell cleanup automatically applies to all videos when flag set
42
+ - **Execution Order**: Standard BG removal โ†’ Cell-based cleanup โ†’ Scaling/Sharpening/Compression
43
+
44
+ #### Test Coverage
45
+ - **21 New Tests Added**: CellCleanupProcessor (13), CellCleanupConfig (4), CellCleanupGimpScript (4)
46
+ - **CLI Validation**: 6 tests for flag combination validation
47
+ - **Integration Tests**: 2 VideoProcessor integration tests
48
+ - **Total**: 512 examples, 0 failures
49
+ - **Code Coverage**: 72.58% (1844 / 2544 lines)
50
+
51
+ #### Technical Details
52
+ - Uses ImageMagick `histogram:info` for dominant color detection
53
+ - Skips transparent pixels in histogram analysis
54
+ - Uses GIMP `gimp-image-select-color` with REPLACE (first color) and ADD (subsequent colors) operations
55
+ - Clears selection with `gimp-drawable-edit-clear` to make colors transparent
56
+ - Reassembles cells using ImageMagick `montage` with no gaps/borders
57
+
58
+ #### Known Issues (Deferred to v0.7.0.2)
59
+ 1. **Ineffective Background Removal** (AC-35, AC-48)
60
+ - Feature executes without errors but doesn't effectively remove backgrounds
61
+ - GIMP color selection may need explicit threshold parameter
62
+ - Requires algorithm investigation and refinement
63
+
64
+ 2. **Performance Exceeds Target** (AC-41)
65
+ - Adds more than 30% overhead to total processing time
66
+ - Each cell invokes separate GIMP process (16 invocations for 16-cell spritesheet)
67
+ - Requires parallel processing optimization
68
+
69
+ 3. **Missing PNG Metadata** (AC-39)
70
+ - Cell cleanup statistics not embedded in PNG metadata
71
+ - Low priority - informational only
72
+
73
+ #### Fixes
74
+ - **Division by Zero in Cell Cleanup**: Fixed parameter passing through pipeline (frames/columns not passed to cleanup_cells)
75
+ - **GIMP Script Generation**: Corrected path normalization, Gegl.Color API, removed non-existent threshold property
76
+ - **Module Loading**: Added missing require for CellCleanupGimpScript in CellCleanupProcessor
77
+
78
+ #### Documentation
79
+ - Updated requirements document (Revision #11)
80
+ - Added 49 acceptance criteria tracking table
81
+ - Marked feature as "Implemented but requires optimization"
82
+ - Added comprehensive known issues section with root cause analysis
83
+
84
+ ---
85
+
86
+ ### ๐Ÿ› Bug Fixes (Nov 8, 2025)
87
+
88
+ #### Fixed
89
+ - **Missing `--by-frame` Flag in Help Text**: Added `--by-frame` to context-sensitive help
90
+ - Now appears in `--video --help` output under "Background Removal Options"
91
+ - Now appears in `--batch --help` output under "Background Removal Options"
92
+ - Now appears in `--image --help` output under "Background Removal Options"
93
+ - Description: "Remove background from each frame individually (slower, better quality)"
94
+ - Proper indentation with tree character (โ””โ”€) showing hierarchy under `--remove-bg`
95
+
96
+ - **Runtime Error with `--by-frame` Flag**: Fixed `NoMethodError: undefined method 'extract_frames'`
97
+ - **Root Causes Identified**:
98
+ 1. `extract_frames` method didn't exist in VideoProcessor
99
+ 2. `assemble_spritesheet_from_frames` method didn't exist in VideoProcessor
100
+ 3. `temp_dir` not passed in options hash to assembly method
101
+ 4. Pattern detection missing for `_nobg` suffix in frame filenames
102
+ 5. Metadata embedding using incorrect API (single argument instead of two)
103
+
104
+ - **Fixes Implemented**:
105
+ 1. โœ… Implemented `VideoProcessor#extract_frames(video_path, temp_dir, options)`
106
+ - Extracts individual frames from video using FFmpeg
107
+ - Calculates FPS based on video duration and frame count
108
+ - Returns array of frame filenames (basenames only)
109
+ - Proper error handling with ProcessingError
110
+
111
+ 2. โœ… Implemented `VideoProcessor#assemble_spritesheet_from_frames(frame_files, output_path, options)`
112
+ - Assembles frames into spritesheet using FFmpeg tile filter
113
+ - Automatic row calculation with ceiling division
114
+ - Pattern detection for `_nobg` suffix (handles both regular and processed frames)
115
+ - Validates output file exists after assembly
116
+
117
+ 3. โœ… Fixed `temp_dir` passing in options
118
+ - `process_with_background_removal` now merges `temp_dir` into options
119
+ - Both by-frame and standard paths correctly pass temp directory
120
+
121
+ 4. โœ… Added pattern detection for `_nobg` suffix
122
+ - Detects suffix from first filename in array
123
+ - Constructs correct FFmpeg input pattern: `frame_%03d.png` or `frame_%03d_nobg.png`
124
+ - Handles frame-by-frame processed files correctly
125
+
126
+ 5. โœ… Fixed metadata embedding API
127
+ - Changed from single-argument hash to two-argument form with keywords
128
+ - Uses temp file pattern: create temp โ†’ embed metadata โ†’ cleanup
129
+ - Matches `create_spritesheet` implementation pattern
130
+ - Properly calculates rows for metadata
131
+
132
+ #### Test Coverage
133
+ - **11 New Tests Added** (470 โ†’ 481 examples, all passing)
134
+ - CLI help text: 2 tests (video mode, batch mode)
135
+ - `extract_frames`: 3 tests (FFmpeg command, return value, error handling)
136
+ - `assemble_spritesheet_from_frames`: 6 tests (assembly, row calculation, ceiling division, _nobg suffix, error handling, file validation)
137
+ - **Code Coverage**: Increased to 19.23% (457 / 2377 lines)
138
+ - **No Regressions**: All existing tests continue to pass
139
+
140
+ #### Real-World Testing
141
+ - โœ… Tested with actual video file processing
142
+ - โœ… Frame-by-frame processing completes successfully
143
+ - โœ… All frames extracted and processed individually
144
+ - โœ… Spritesheet assembled correctly from processed frames
145
+ - โœ… Metadata embedded properly
146
+ - โœ… Output file created successfully
147
+
148
+ #### Files Modified
149
+ - `lib/ruby_spriter/cli.rb` - Added `--by-frame` to help text (3 locations)
150
+ - `lib/ruby_spriter/video_processor.rb` - Implemented missing methods, fixed bugs
151
+ - `spec/ruby_spriter/cli_spec.rb` - Added 2 help text tests
152
+ - `spec/ruby_spriter/video_processor_spec.rb` - Added 9 method tests
153
+ - `requirements/Ruby Spriter v0.7.0.1 Bug Fixes.md` - Updated to Revision 2
154
+
155
+
156
+
157
+ #### Refactored
158
+ - **BatchProcessor Architecture**: Eliminated code duplication and improved performance
159
+ - **Eager Dependency Checking**: Dependencies now checked once during initialization (not per video)
160
+ - **Cached Instance Variables**: `@gimp_path` and `@gimp_version` stored and reused
161
+ - **Helper Methods Extracted**:
162
+ - `using_frame_by_frame_background_removal?` - Checks both `--by-frame` and `--remove-bg` flags
163
+ - `normalize_video_result_format` - Standardizes result hash format
164
+ - `needs_dependency_setup?` - Determines if GIMP operations required
165
+ - `setup_dependencies` - Caches dependency check results
166
+ - **Refactored Methods**:
167
+ - `process_video` - Uses cached dependencies, eliminates redundant VideoProcessor instantiation
168
+ - `process_with_gimp` - Uses cached dependencies directly
169
+ - **Performance Impact**: 20ร— reduction in dependency checks (2 per video โ†’ 1 total during initialization)
170
+ - **Architectural Consistency**: BatchProcessor now follows same pattern as Processor class
171
+ - **Test Coverage**: Added 14 new tests (15 โ†’ 29 examples, all passing)
172
+ - **Code Quality**: Eliminated 5 duplication issues identified in code review
173
+
174
+ #### Performance
175
+ - **Before**: 2 `DependencyChecker` instantiations per video (shell commands executed repeatedly)
176
+ - **After**: 1 `DependencyChecker` instantiation during initialization (results cached)
177
+ - **Batch Processing**: For 10 videos, reduced from 20 dependency checks to 1 (20ร— improvement)
178
+ - **Shell Command Reduction**: Eliminated redundant `where gimp`, `gimp --version` calls
179
+
180
+ #### Technical Details
181
+ - **Files Modified**:
182
+ - `lib/ruby_spriter/batch_processor.rb` - Refactored implementation (+287 lines net)
183
+ - `spec/ruby_spriter/batch_processor_spec.rb` - Added comprehensive test coverage
184
+ - `requirements/Ruby Spriter v0.7.0.1 Requirements.md` - Updated to Revision 10
185
+ - **Test Results**: 474 examples, 0 failures, 0 regressions
186
+ - **Commit**: 1a0f5f3
187
+
188
+ ### ๐ŸŽž๏ธ Frame-by-Frame Background Removal Release
189
+
190
+ #### Added
191
+ - **Frame-by-Frame Processing** (`--by-frame`): Process each video frame individually before assembling spritesheet
192
+ - Perfect for videos with varying backgrounds (lighting changes, environment changes, camera movement)
193
+ - Processes each frame with background removal before assembly
194
+ - Progress indicator: "Processing frame X/Y..."
195
+ - Adds `processing_mode: by-frame` to PNG metadata
196
+ - Works with all background removal modes: `--fuzzy`, `--threshold`, `--threshold-stepping`
197
+ - Compatible with `--scale`, `--sharpen`, `--max-compress`
198
+ - Supports both `--video` and `--batch` modes
199
+ - **CLI Validation**: `--by-frame` requires both `--video` or `--batch` AND `--remove-bg`
200
+ - **VideoProcessor Enhancement**: New `process_with_background_removal` method for frame-by-frame workflow
201
+ - **Processor Integration**: Automatic routing to frame-by-frame processing when flag is set
202
+ - **BatchProcessor Integration**: Full support for batch processing with frame-by-frame mode
203
+
204
+ #### Changed
205
+ - **Processing Workflow**: When `--by-frame` is used, workflow changes from "Extract โ†’ Assemble โ†’ Remove BG" to "Extract โ†’ Remove BG (each) โ†’ Assemble"
206
+ - **Performance Trade-off**: Frame-by-frame processing is ~16ร— slower than standard mode (e.g., 16 frames: ~120s vs ~7.5s) but produces superior results for varying backgrounds
207
+
208
+ #### Technical Details
209
+ - **New Methods**:
210
+ - `VideoProcessor#process_with_background_removal(video_path, output_path, options)` - Main frame-by-frame processing
211
+ - `VideoProcessor#process_frames_individually(frame_files, temp_dir, options)` - Per-frame background removal
212
+ - `VideoProcessor#process_image_with_gimp(input_path, output_path, options)` - Helper for GIMP processing
213
+ - `VideoProcessor#no_background_filename(filename)` - Generate _nobg filenames
214
+ - `Processor#using_frame_by_frame_background_removal?` - Check if frame-by-frame mode active
215
+ - `Processor#normalize_video_result_format(result)` - Normalize result format
216
+ - `BatchProcessor#process_video` - Updated to support frame-by-frame mode
217
+ - **Constants**: `VideoProcessor::NO_BACKGROUND_SUFFIX = '_nobg'`
218
+ - **Test Coverage**: 12 new tests (5 CLI validation, 3 VideoProcessor, 2 Processor integration, 2 BatchProcessor)
219
+ - **Total Tests**: 455 examples, 0 failures
220
+
221
+ #### Examples
222
+ ```bash
223
+ # Basic frame-by-frame processing
224
+ ruby_spriter --video input.mp4 --remove-bg --by-frame
225
+
226
+ # With custom grid and scaling
227
+ ruby_spriter --video input.mp4 --remove-bg --by-frame \
228
+ --frames 32 --columns 8 \
229
+ --scale 50 --sharpen
230
+
231
+ # Batch processing with frame-by-frame
232
+ ruby_spriter --batch --dir "videos/" --remove-bg --by-frame
233
+
234
+ # Combine with threshold stepping for maximum quality
235
+ ruby_spriter --video explosion.mp4 \
236
+ --remove-bg --by-frame --threshold-stepping \
237
+ --frames 32 --columns 8
238
+ ```
239
+
240
+ #### When to Use `--by-frame`
241
+ - โœ… Video has changing backgrounds between frames
242
+ - โœ… Character moves through different environments
243
+ - โœ… Lighting conditions vary throughout video
244
+ - โœ… Camera pans or moves during recording
245
+ - โœ… Quality is more important than processing speed
246
+
247
+ #### Performance Characteristics
248
+ - **Standard Mode**: ~7.5 seconds for 16 frames (1ร— background removal)
249
+ - **Frame-by-Frame Mode**: ~120 seconds for 16 frames (16ร— background removal)
250
+ - **Trade-off**: Significantly longer processing time for superior quality with varying backgrounds
251
+
252
+ #### Backward Compatibility
253
+ - Fully backward compatible - all existing workflows continue to work unchanged
254
+ - `--by-frame` is opt-in and disabled by default
255
+ - No breaking changes to existing features or APIs
256
+
257
+ Closes #XX (Frame-by-Frame Background Removal)
258
+
259
+ ---
260
+
261
+ ## [0.7.0.1] - 2025-11-06
262
+
263
+ ### Added
264
+ - BackgroundSampler class for intelligent background color sampling
265
+ - Two-pass background removal: outer (single-point) + inner (sampled colors)
266
+ - CLI options: --bg-sample-offset (default: 5), --bg-sample-count (default: 10)
267
+ - Pixel cache optimization for 65x performance improvement in sampling
268
+
269
+ ### Changed
270
+ - **BREAKING**: --no-fuzzy is now the DEFAULT for --remove-bg
271
+ - --fuzzy flag now required for contiguous-only selection
272
+ - Single-point selection at (5,5) instead of 4-corner selection
273
+ - GIMP threshold behavior now matches GUI (fixed over-removal at high thresholds)
274
+
275
+ ### Removed
276
+ - --try-inner flag (functionality now in --no-fuzzy default)
277
+ - --threshold-stepping flag (superseded by BackgroundSampler)
278
+ - --inner-min-area, --adaptive-min-area, --multi-pass flags
279
+ - --edge-sample-depth, --edge-sample-pattern flags
280
+ - --color-space, --remove-smoke, --bg-fuzz, --ghost-threshold flags
281
+ - EdgeSampler, InnerBackgroundProcessor, InnerBgConfig classes
282
+
283
+ ### Fixed
284
+ - GIMP threshold parameter now works correctly at all values (0-100)
285
+ - Single-point selection eliminates threshold compounding issue
286
+ - Background removal no longer removes more pixels than GIMP GUI
287
+
288
+
289
+ All notable changes to Ruby Spriter will be documented in this file.
290
+
291
+ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
292
+ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
293
+
294
+ ---
295
+
296
+ ## [0.7.0] - 2025-10-30
297
+
298
+ ### ๐ŸŽจ Inner Background Removal Release
299
+
300
+ Major feature release introducing advanced background removal capabilities with multi-stage processing pipeline for superior sprite edge quality.
301
+
302
+ #### Added
303
+
304
+ ##### Inner Background Removal System (`--try-inner`)
305
+ - **Flood Fill-Based Background Removal**: Targets interior transparent regions missed by edge-based methods
306
+ - Detects fully transparent pixels (alpha = 0)
307
+ - Samples pixel colors from surrounding opaque regions
308
+ - Uses flood fill to remove matching colors from transparent areas
309
+ - Preserves sprite edges and anti-aliasing
310
+ - Configurable tolerance and opacity thresholds
311
+ - **Edge Sampling Algorithm**: Intelligent color detection from sprite boundaries
312
+ - Scans 8-directional neighbors (N, S, E, W, NE, NW, SE, SW)
313
+ - Configurable search radius (default: 10 pixels, up to 50)
314
+ - Returns most common color from opaque edge pixels
315
+ - Handles cases with no opaque neighbors gracefully
316
+ - **Configuration Options**:
317
+ - `--inner-tolerance VALUE`: Flood fill color matching tolerance (0.0-100.0%, default: 10.0%)
318
+ - `--inner-opacity VALUE`: Minimum opacity threshold for edge sampling (0.0-1.0, default: 0.9)
319
+ - `--inner-radius VALUE`: Edge sampling search radius in pixels (1-50, default: 10)
320
+
321
+ ##### Threshold Stepping (`--threshold-stepping`)
322
+ - **Multi-Threshold Processing**: Applies background removal with multiple fuzzy select thresholds
323
+ - Default thresholds: [0.0, 0.5, 1.0, 3.0, 5.0, 10.0]
324
+ - Processes image separately with each threshold
325
+ - Combines results using ImageMagick DstOver composite
326
+ - Improves edge detection compared to single threshold
327
+ - **Automatic Result Combination**: Layers threshold results from highest to lowest
328
+ - **Configurable Thresholds**: Can override defaults via InnerBgConfig
329
+
330
+ ##### Ghost Edge Prevention (`--multi-pass`)
331
+ - **Multi-Pass Alpha Cleanup**: Removes semi-transparent "ghost" pixels from edges
332
+ - Iterative processing (up to 3 passes)
333
+ - Detects pixels with alpha below threshold (default: 30/255 = ~12%)
334
+ - Sets low-alpha pixels to fully transparent
335
+ - Converges when no more ghost pixels detected
336
+ - **Convergence Detection**: Stops early when cleanup complete
337
+ - **Configuration**:
338
+ - `--ghost-threshold VALUE`: Alpha threshold for ghost detection (0-255, default: 30)
339
+
340
+ ##### Smoke Detection and Removal (`--remove-smoke`)
341
+ - **Transparency Gradient Detection**: Identifies smoke-like semi-transparent regions
342
+ - Detects alpha values between 20-80% (MIN_ALPHA to MAX_ALPHA)
343
+ - Filters by minimum contiguous area (50 pixels)
344
+ - Grid-based sampling for performance (20-pixel steps)
345
+ - Reports region coordinates, areas, and alpha ranges
346
+ - **Optional Removal**: Remove detected smoke effects with `--remove-smoke`
347
+ - **Detection Reports**: Always reports smoke regions when background removal active
348
+
349
+ ##### Enhanced Color Space Support
350
+ - **RGBA Enforcement**: All modules force RGBA color space with `-define png:color-type=6`
351
+ - Handles grayscale input images correctly
352
+ - Ensures alpha channel availability for all operations
353
+ - Prevents colorspace-related processing failures
354
+
355
+ ##### Comprehensive Reporting
356
+ - **Detailed Processing Reports**: Each module provides timing and statistics
357
+ - ThresholdStepper: Lists processed thresholds and timing
358
+ - InnerBackgroundProcessor: Reports pixels removed, regions processed, edge sampling stats
359
+ - GhostEdgeCleaner: Reports passes performed, ghost pixels detected/removed
360
+ - SmokeDetector: Reports smoke regions detected, removal status, processing time
361
+ - **Pipeline Visibility**: Clear output formatting for each processing stage
362
+
363
+ #### Changed
364
+
365
+ ##### Processing Pipeline Order
366
+ 1. **Threshold Stepping** (if `--threshold-stepping` and `--remove-bg`)
367
+ 2. **GIMP Edge-Based Removal** (if `--remove-bg` or `--scale`)
368
+ 3. **Inner Background Removal** (if `--try-inner` and `--remove-bg`)
369
+ 4. **Ghost Edge Cleaning** (if `--multi-pass` and `--remove-bg`)
370
+ 5. **Smoke Detection** (always active when `--remove-bg`)
371
+
372
+ ##### GIMP Version Requirement
373
+ - **Requires GIMP 3.x**: GIMP 2.x is NOT supported
374
+ - **Ubuntu 25.04+**: Native GIMP 3.x package available
375
+ - **Older distributions**: Use Flatpak for GIMP 3.x installation
376
+
377
+ #### Performance
378
+
379
+ ##### Benchmark Results (Windows 11, i7-12700K)
380
+ - **Edge Sampling**: ~0.015s per transparent pixel
381
+ - **Inner Background Removal**: ~2-5s for typical sprite (depends on transparent regions)
382
+ - **Threshold Stepping**: ~10-15s (6 thresholds ร— ~2s per threshold)
383
+ - **Ghost Edge Cleaning**: ~1-2s per pass (typically 1-2 passes)
384
+ - **Smoke Detection**: ~5-10s for typical sprite (grid sampling)
385
+
386
+ ##### Total Pipeline Time
387
+ - **Basic Pipeline** (edge removal only): ~5-10s
388
+ - **Full Pipeline** (all features): ~25-40s
389
+ - **Recommended**: Enable only features needed for your sprites to optimize performance
390
+
391
+ #### Backward Compatibility
392
+
393
+ ##### Fully Backward Compatible
394
+ - All existing CLI flags and workflows continue to work unchanged
395
+ - Default behavior (without new flags) identical to v0.6.7.1
396
+ - Existing spritesheets and metadata formats fully supported
397
+ - No breaking changes to public APIs or file formats
398
+
399
+ ##### Opt-In Features
400
+ - All v0.7.0 features disabled by default
401
+ - Must explicitly enable with command-line flags
402
+ - Safe to upgrade without workflow changes
403
+
404
+ #### Testing
405
+
406
+ ##### Test Coverage
407
+ - **102 Unit Tests**: All passing (35 new tests added)
408
+ - 12 tests for ThresholdStepper
409
+ - 16 tests for GhostEdgeCleaner
410
+ - 20 tests for SmokeDetector
411
+ - 14 tests for EdgeSampler
412
+ - 17 tests for InnerBackgroundProcessor
413
+ - 4 tests for InnerBgConfig
414
+ - **3 Feature Tests**: Integration tests for complete workflows
415
+ - **471 Total Examples**: Comprehensive coverage across entire codebase
416
+ - **Test Duration**: ~3 minutes 8 seconds for full suite
417
+
418
+ ##### Test Quality
419
+ - TDD methodology (RED-GREEN-REFACTOR) used throughout
420
+ - ImageMagick command mocking for unit tests
421
+ - Real image processing in feature tests
422
+ - Performance tests ensure reasonable processing times
423
+
424
+ #### Documentation
425
+
426
+ ##### Updated Documentation
427
+ - **README.md**: Added comprehensive v0.7.0 features section
428
+ - 11 new command-line flags documented
429
+ - 3 usage examples (basic, full pipeline, advanced)
430
+ - Processing order diagram
431
+ - Performance considerations
432
+ - **CHANGELOG.md**: This comprehensive release documentation
433
+ - **Code Comments**: Extensive inline documentation in all new modules
434
+
435
+ #### Technical Details
436
+
437
+ ##### New Modules
438
+ - `lib/ruby_spriter/inner_bg_config.rb` (134 lines)
439
+ - `lib/ruby_spriter/edge_sampler.rb` (141 lines)
440
+ - `lib/ruby_spriter/inner_background_processor.rb` (256 lines)
441
+ - `lib/ruby_spriter/threshold_stepper.rb` (133 lines)
442
+ - `lib/ruby_spriter/ghost_edge_cleaner.rb` (153 lines)
443
+ - `lib/ruby_spriter/smoke_detector.rb` (224 lines)
444
+
445
+ ##### New Test Files
446
+ - `spec/unit/inner_bg_config_spec.rb` (61 lines, 4 tests)
447
+ - `spec/unit/edge_sampler_spec.rb` (137 lines, 14 tests)
448
+ - `spec/unit/inner_background_processor_spec.rb` (188 lines, 17 tests)
449
+ - `spec/unit/threshold_stepper_spec.rb` (164 lines, 12 tests)
450
+ - `spec/unit/ghost_edge_cleaner_spec.rb` (217 lines, 16 tests)
451
+ - `spec/unit/smoke_detector_spec.rb` (246 lines, 20 tests)
452
+ - `spec/features/inner_background_removal_spec.rb` (139 lines, 3 tests)
453
+
454
+ ##### Modified Files
455
+ - `lib/ruby_spriter/processor.rb`: Added 5-stage pipeline integration (3 new methods)
456
+ - `lib/ruby_spriter/cli.rb`: Added 11 new command-line options
457
+ - `lib/ruby_spriter.rb`: Added requires for new modules
458
+
459
+ #### Known Issues
460
+
461
+ ##### Performance Considerations
462
+ - Full pipeline (all features enabled) takes 25-40s for typical sprites
463
+ - Smoke detection uses grid sampling - may miss very small smoke regions
464
+ - Inner background removal performance depends on transparent region size
465
+
466
+ ##### Recommended Usage
467
+ - Enable `--try-inner` for sprites with complex interior backgrounds
468
+ - Use `--threshold-stepping` for sprites with subtle edge colors
469
+ - Enable `--multi-pass` for sprites with noticeable ghost edges
470
+ - Use `--remove-smoke` only if smoke effects detected in report
471
+ - For best performance, enable only features you need
472
+
473
+ #### Migration Guide
474
+
475
+ ##### Upgrading from v0.6.7.1
476
+
477
+ **No Changes Required**
478
+ ```bash
479
+ # Existing workflows continue to work unchanged
480
+ ruby_spriter --video input.mp4 --remove-bg --scale 50%
481
+ ```
482
+
483
+ **Opt-In to New Features**
484
+ ```bash
485
+ # Basic inner background removal
486
+ ruby_spriter --video input.mp4 --remove-bg --try-inner
487
+
488
+ # Full pipeline with all features
489
+ ruby_spriter --video input.mp4 --remove-bg \
490
+ --threshold-stepping \
491
+ --try-inner \
492
+ --multi-pass \
493
+ --remove-smoke
494
+
495
+ # Advanced configuration
496
+ ruby_spriter --video input.mp4 --remove-bg \
497
+ --try-inner \
498
+ --inner-tolerance 15.0 \
499
+ --inner-opacity 0.85 \
500
+ --inner-radius 15 \
501
+ --ghost-threshold 40
502
+ ```
503
+
504
+ **Performance Optimization**
505
+ ```bash
506
+ # For simple sprites: edge removal only (fastest)
507
+ ruby_spriter --video input.mp4 --remove-bg
508
+
509
+ # For sprites with interior backgrounds: add --try-inner (moderate)
510
+ ruby_spriter --video input.mp4 --remove-bg --try-inner
511
+
512
+ # For complex sprites: full pipeline (slowest but highest quality)
513
+ ruby_spriter --video input.mp4 --remove-bg --threshold-stepping --try-inner --multi-pass
514
+ ```
515
+
516
+ ---
517
+
518
+ ## [0.6.7.1] - 2025-10-24
519
+
520
+ ### ๐Ÿง Linux Support Enhancement Release
521
+
522
+ #### Added
523
+ - **Linux GIMP 3.x Support**: Full support for GIMP 3.x on Linux via Flatpak
524
+ - Automatic detection of Flatpak GIMP installation (`flatpak:org.gimp.GIMP`)
525
+ - Automatic Xvfb integration for completely headless GIMP operation
526
+ - Virtual display provided by Xvfb eliminates display connection requirement
527
+ - Flatpak socket isolation (`--nosocket=x11 --nosocket=wayland`) prevents GUI from appearing
528
+ - Python-fu batch mode works correctly with `python-fu-eval` interpreter
529
+ - Background removal, scaling, and all GIMP features fully functional
530
+ - Perfect for desktop use (no GUI distraction) and server environments (CI/CD, Docker, SSH)
531
+ - **GIMP Version Detection**: Detect and report GIMP version (2.x or 3.x)
532
+ - `Platform.detect_gimp_version(version_output)` - Parse version from `--version` output
533
+ - `Platform.get_gimp_version(gimp_path)` - Get version from executable or Flatpak
534
+ - Works with both regular executables and Flatpak installations
535
+ - **Xvfb Dependency Checking**: Added Xvfb to dependency checker (Linux only)
536
+ - Marked as required on Linux, optional on Windows/macOS
537
+ - Provides clear installation instructions if missing
538
+ - Validates availability before GIMP operations
539
+ - **DependencyChecker Version Tracking**: Store and report detected GIMP version
540
+ - **Xvfb Integration**: Transparent Xvfb usage when GIMP Flatpak detected
541
+ - Command format: `xvfb-run --auto-servernum --server-args='-screen 0 1024x768x24' flatpak run --nosocket=x11 --nosocket=wayland org.gimp.GIMP --no-splash --quit --batch-interpreter=python-fu-eval`
542
+ - No user configuration required - works automatically
543
+ - Completely headless - no GUI windows appear on screen
544
+
545
+ #### Changed
546
+ - **Platform Detection**: Enhanced to detect Flatpak GIMP alongside traditional installations
547
+ - **GimpProcessor**: Updated to support both GIMP 2.x and 3.x APIs (version-aware)
548
+ - **Unix GIMP Execution**: Automatically uses Xvfb with socket isolation for Flatpak installations
549
+ - **Alternative GIMP Paths**: Added `flatpak:org.gimp.GIMP` to Linux search paths
550
+ - **Warning Filters**: Enhanced to filter Xvfb, Wayland, and Flatpak cosmetic warnings
551
+ - **DependencyChecker**: Now supports platform-specific optional dependencies
552
+
553
+ #### Technical Details
554
+ - **GIMP Flatpak Detection**: Uses `flatpak list --app | grep` to verify installation
555
+ - **Version Parsing**: Regex-based parsing of `GIMP version X.Y.Z` output
556
+ - **Python Interpreter**: Correct name is `python-fu-eval` (not `python-eval`)
557
+ - **Xvfb Flags**:
558
+ - `--auto-servernum` - Automatically finds free display number
559
+ - `--server-args='-screen 0 1024x768x24'` - Configures virtual display
560
+ - **Flatpak Socket Isolation**:
561
+ - `--nosocket=x11` - Prevents access to host X11 display socket
562
+ - `--nosocket=wayland` - Prevents access to host Wayland display socket
563
+ - Ensures GIMP runs only in Xvfb virtual display
564
+ - **Platform Module**: New methods for version detection and Flatpak handling
565
+ - **Warning Filtering**: Filters Gdk-WARNING, LibGimp-WARNING, Gimp-Core-WARNING, X11 socket messages
566
+
567
+ #### Installation Requirements (Linux)
568
+ ```bash
569
+ # Ubuntu/Debian
570
+ sudo apt install flatpak xvfb -y
571
+ flatpak remote-add --if-not-exists flathub https://flathub.org/repo/flathub.flatpakrepo
572
+ flatpak install flathub org.gimp.GIMP -y
573
+
574
+ # Fedora/RHEL
575
+ sudo dnf install flatpak xorg-x11-server-Xvfb -y
576
+ flatpak remote-add --if-not-exists flathub https://flathub.org/repo/flathub.flatpakrepo
577
+ flatpak install flathub org.gimp.GIMP -y
578
+ ```
579
+
580
+ #### Example Output
581
+ ```bash
582
+ $ ruby_spriter --check-dependencies
583
+ ============================================================
584
+ Dependency Check
585
+ ============================================================
586
+
587
+ โœ… FFMPEG
588
+ Found: 6.1.1
589
+
590
+ โœ… FFPROBE
591
+ Found: 6.1.1
592
+
593
+ โœ… IMAGEMAGICK
594
+ Found: Version: ImageMagick 6.9.12-98 Q16 x86_64
595
+
596
+ โœ… XVFB
597
+ Found: Usage: xvfb-run [OPTION ...] COMMAND
598
+
599
+ โœ… GIMP
600
+ Found: flatpak:org.gimp.GIMP
601
+ Version: GIMP 3.0.6
602
+
603
+ ============================================================
604
+
605
+ $ ruby_spriter --image sprite.png --remove-bg
606
+ ============================================================
607
+ GIMP Processing
608
+ ============================================================
609
+ ๐Ÿ“ Using GIMP via Xvfb (virtual display)
610
+ Removing background (fuzzy select)...
611
+ === GIMP Messages ===
612
+ Loading image...
613
+ Image size: 1280x748
614
+ Added alpha channel
615
+ Sampling 4 corners...
616
+ Using FUZZY SELECT (contiguous regions only)
617
+ Corner 1 at (0, 0)
618
+ Corner 2 at (1279, 0)
619
+ Corner 3 at (0, 747)
620
+ Corner 4 at (1279, 747)
621
+ Selection complete
622
+ Growing selection by 1 pixels...
623
+ Selection grown
624
+ Removing background...
625
+ Background removed
626
+ Deselecting...
627
+ Exporting...
628
+ SUCCESS - Background removed!
629
+ ====================
630
+ โœ… Background Removal complete (142.15 KB)
631
+ ```
632
+
633
+ **Note**: No GIMP GUI window appears on screen - completely headless operation!
634
+
635
+ ---
636
+
637
+ ## [0.6.7] - 2025-10-24
638
+
639
+ ### ๐Ÿš€ Batch Processing, Compression, Directory Consolidation & Frame Extraction Release
640
+
641
+ #### Added
642
+ - **Batch Processing Mode** (`--batch`): Process multiple MP4 files in a directory (Issue #16)
643
+ - `--dir DIRECTORY`: Specify directory containing MP4 files to process
644
+ - `--outputdir DIRECTORY`: Optional output directory (defaults to input directory)
645
+ - `--batch-consolidate`: Automatically consolidate all resulting spritesheets
646
+ - Supports all existing processing options: `--scale`, `--remove-bg`, `--sharpen`, `--interpolation`, etc.
647
+ - Enforces unique filenames unless `--overwrite` is specified
648
+ - Continues processing remaining videos if one fails
649
+ - Provides detailed summary of successes and failures
650
+ - **Maximum Compression** (`--max-compress`): Apply maximum PNG compression (Issue #14)
651
+ - Uses ImageMagick with optimal compression settings (level 9, filter 5, strategy 1, quality 95)
652
+ - Preserves embedded metadata through compression
653
+ - Works with all processing modes: `--video`, `--image`, `--batch`, `--consolidate`
654
+ - Displays compression statistics (original size, compressed size, savings, reduction percentage)
655
+ - **Directory-Based Consolidation**: `--consolidate` now supports `--dir` option to automatically consolidate all spritesheets in a directory
656
+ - Scans directory for PNG files with embedded spritesheet metadata
657
+ - Automatically filters out non-spritesheet PNG files
658
+ - Sorts files alphabetically by filename before consolidation
659
+ - Requires at least 2 valid spritesheets in directory
660
+ - Works with all existing consolidation options: `--output`, `--outputdir`, `--overwrite`, `--max-compress`, `--no-validate-columns`
661
+ - Mutual exclusivity validation: Cannot use both comma-separated file list and `--dir` with `--consolidate`
662
+ - **Enhanced Context-Sensitive Help System**: Mode-specific help displays only relevant options
663
+ - `ruby_spriter --video --help`: Shows video mode options (spritesheet generation, processing, output)
664
+ - `ruby_spriter --image --help`: Shows image mode options (processing, frame extraction, output)
665
+ - `ruby_spriter --consolidate --help`: Shows consolidation options (input methods, validation, output)
666
+ - `ruby_spriter --batch --help`: Shows batch processing options (directory processing, applied options)
667
+ - `ruby_spriter --split --help`: Shows frame extraction options (split format, metadata behavior, output)
668
+ - General `--help`: Shows mode-specific help hints and directs users to detailed help
669
+ - **Parent-Child Option Hierarchy**: Visual hierarchy (โ””โ”€) shows modifier options grouped under parent options
670
+ - `--interpolation`, `--sharpen*` modifiers shown under `--scale`
671
+ - `--fuzzy`, `--threshold`, `--grow` modifiers shown under `--remove-bg`
672
+ - `--override-md` modifier shown under `--split`
673
+ - `--validate-columns` modifier shown under `--consolidate --dir`
674
+ - Organized by function (Image Processing, Output Options) instead of by tool (GIMP Processing Options)
675
+ - **Frame Extraction** (`--extract`): Extract specific frames and create new spritesheet
676
+ - `--extract FRAMES`: Comma-separated frame numbers (e.g., `1,2,4,5,8`)
677
+ - `--columns NUM`: Specify output grid columns (default: 4)
678
+ - Supports duplicate frame numbers for animation sequences
679
+ - 1-indexed frame numbering (left-to-right, top-to-bottom)
680
+ - Requires spritesheet metadata (works with `--verify` output)
681
+ - Works with all `--image` processing options: `--scale`, `--remove-bg`, `--sharpen`, `--max-compress`
682
+ - Automatic output naming with `_extracted` suffix or custom via `--output`
683
+ - Temporary frames deleted after reassembly unless `--save-frames` specified
684
+ - Minimum 2 frames required
685
+ - Out-of-bounds validation against spritesheet metadata
686
+ - Mutual exclusivity with `--split`
687
+ - **Metadata Management** (`--add-meta`): Add spritesheet metadata to images without metadata
688
+ - `--add-meta R:C`: Specify grid layout (rows:columns, e.g., `4:4`)
689
+ - `--overwrite-meta`: Replace existing metadata
690
+ - `--frames COUNT`: Custom frame count for partial grids (fewer frames than grid size)
691
+ - In-place modification by default (respects `--overwrite` flag)
692
+ - Optional `--output` for copying to new file
693
+ - Dimension validation: Image dimensions must divide evenly by grid
694
+ - Enables `--extract`, `--consolidate`, `--verify`, `--split` on external spritesheets
695
+ - Standalone mode: Cannot combine with `--scale`, `--remove-bg`, `--sharpen`
696
+ - **Enhanced `--save-frames`**: Now works with both `--video` and `--extract`
697
+ - **New Modules**:
698
+ - `BatchProcessor` (lib/ruby_spriter/batch_processor.rb): Orchestrates batch video processing
699
+ - `CompressionManager` (lib/ruby_spriter/compression_manager.rb): Handles PNG compression with metadata preservation
700
+ - **New Public Method**: `Consolidator#find_spritesheets_in_directory(directory)` for directory scanning
701
+ - **Comprehensive Test Coverage**: 68 new tests (13 for BatchProcessor, 11 for CompressionManager, 15 for directory consolidation, 7 for context-sensitive help, 22 for frame extraction and metadata management)
702
+
703
+ #### Changed
704
+ - **CLI**: Updated `--consolidate` description to mention `--dir` option
705
+ - **CLI**: Renamed "GIMP Processing Options" to "Processing Options" for tool-agnostic organization
706
+ - **CLI**: Updated image mode help with Frame Extraction & Reassembly section
707
+ - **CLI**: Added Metadata Management section to image mode help
708
+ - **Processor**: Refactored consolidation workflow to support both file list and directory modes
709
+ - **Test Suite**: Increased from 274 to 365 examples (all passing), 75.8% line coverage
710
+ - **CLI**: Added parent-child visual hierarchy to all context-sensitive help displays
711
+ - **CLI**: Corrected `--sharpen` to show as standalone option (not under `--scale`)
712
+
713
+ #### Examples
714
+ ```bash
715
+ # Get context-sensitive help for specific modes
716
+ ruby_spriter --video --help
717
+ ruby_spriter --image --help
718
+ ruby_spriter --consolidate --help
719
+ ruby_spriter --batch --help
720
+ ruby_spriter --split --help
721
+
722
+ # Process all videos in directory
723
+ ruby_spriter --batch --dir "videos/"
724
+
725
+ # Process with output to different directory
726
+ ruby_spriter --batch --dir "videos/" --outputdir "output/"
727
+
728
+ # Process and consolidate all results
729
+ ruby_spriter --batch --dir "videos/" --batch-consolidate
730
+
731
+ # Process with scaling and compression
732
+ ruby_spriter --batch --dir "videos/" --scale 50 --max-compress
733
+
734
+ # Compress video output
735
+ ruby_spriter --video "input.mp4" --max-compress
736
+
737
+ # Compress image processing output
738
+ ruby_spriter --image "sprite.png" --scale 50 --max-compress
739
+
740
+ # Directory-based consolidation
741
+ ruby_spriter --consolidate --dir "spritesheets/"
742
+ ruby_spriter --consolidate --dir "spritesheets/" --outputdir "output/"
743
+ ruby_spriter --consolidate --dir "spritesheets/" --max-compress
744
+
745
+ # File list consolidation still works
746
+ ruby_spriter --consolidate file1.png,file2.png,file3.png
747
+
748
+ # Extract specific frames and create new spritesheet
749
+ ruby_spriter --image sprite.png --extract 1,2,4,5,8 --columns 3
750
+
751
+ # Extract with duplicates for animation loops
752
+ ruby_spriter --image sprite.png --extract 1,1,2,2,3,3 --save-frames
753
+
754
+ # Extract and process
755
+ ruby_spriter --image sprite.png --extract 1,3,5,7 --scale 50 --sharpen
756
+
757
+ # Add metadata to external spritesheet
758
+ ruby_spriter --image sprite.png --add-meta 4:4
759
+
760
+ # Add metadata with partial grid
761
+ ruby_spriter --image sprite.png --add-meta 4:4 --frames 14 --output sprite_meta.png
762
+
763
+ # Replace existing metadata
764
+ ruby_spriter --image existing.png --add-meta 8:8 --overwrite-meta
765
+
766
+ # Workflow: Add metadata, then extract frames
767
+ ruby_spriter --image external.png --add-meta 4:4
768
+ ruby_spriter --image external.png --extract 1,5,9,13 --columns 2
769
+ ```
770
+
771
+ Closes #14, #16
772
+
773
+ ---
774
+
775
+ ## [0.6.6] - 2025-10-23
776
+
777
+ ### ๐Ÿ”’ File Protection & Frame Extraction Release
778
+
779
+ #### Added
780
+ - **Automatic Unique Filenames**: By default, generates timestamped filenames to prevent accidental overwrites
781
+ - Format: `filename_YYYYMMDD_HHMMSS_mmm.ext` (includes milliseconds)
782
+ - Applies to all output modes: `--video`, `--image`, `--consolidate`
783
+ - Works with both auto-generated and `--output` specified filenames
784
+ - **`--overwrite` Flag**: Optional flag to explicitly allow overwriting existing files
785
+ - **`--split R:C` Option**: Split spritesheets into individual frames for `--image` workflow
786
+ - Format: `--split 4:4` (rows:columns, e.g., 4 rows ร— 4 columns)
787
+ - Validation: Rows and columns must be 1-99, total frames < 1000
788
+ - Frame naming: `FRddd_filename.png` (3-digit zero-padded format: FR001, FR002, ..., FR999)
789
+ - Output directory: `filename_frames/`
790
+ - Metadata priority: Uses embedded metadata if available, unless `--override-md` flag is provided
791
+ - Dimension validation: Image dimensions must divide evenly by specified rows and columns
792
+ - **`--override-md` Flag**: Override embedded metadata when using `--split` with images that have metadata
793
+ - **Intermediate File Cleanup**: Fixed cleanup of intermediate files from GIMP processing
794
+ - Now correctly removes files with dash separator (e.g., `file-nobg-fuzzy.png`, `file-scaled-40pct.png`)
795
+ - Added Windows-compatible path normalization for file comparison
796
+ - **Frame Extraction Tests**: 17 new comprehensive tests for split functionality
797
+ - CLI option tests for `--split` and `--override-md`
798
+ - Format and range validation tests (10 tests)
799
+ - Metadata priority logic tests (5 tests)
800
+ - Updated SpritesheetSplitter tests for FR%03d format
801
+
802
+ #### Changed
803
+ - **Default Behavior**: Changed from overwriting to creating unique files (breaking change, but safer)
804
+ - **GimpProcessor**: Now respects `--overwrite` flag for scaled and background-removed images
805
+ - **Consolidate Workflow**: Default filename changed from `consolidated_spritesheet_TIMESTAMP.png` to `consolidated_spritesheet.png` (uniqueness handled by flag)
806
+ - **Frame Naming Format**: Changed from FR%02d (2 digits) to FR%03d (3 digits) to support up to 999 frames
807
+ - **Intermediate File Pattern**: Fixed glob pattern from underscore to dash separator for GIMP output files
808
+
809
+ #### Technical Details
810
+ - New utility methods in `Utils::FileHelper`:
811
+ - `unique_filename(path)` - Generates timestamped filename if file exists
812
+ - `ensure_unique_output(path, overwrite:)` - Applies overwrite logic
813
+ - New methods in `Processor`:
814
+ - `validate_split_option!` - Validates split format and ranges during initialization
815
+ - `determine_split_parameters(image_file)` - Implements metadata priority logic
816
+ - `validate_image_dimensions(image_file, rows, columns)` - Validates even division
817
+ - Processor workflows updated to use `ensure_unique_output` for all output paths
818
+ - `SpritesheetSplitter` updated to use 3-digit frame format (FR%03d)
819
+ - Test coverage increased to 72.27% (688/952 lines)
820
+
821
+ Closes #17, #19, #30
822
+
823
+ ---
824
+
825
+ ## [0.6.5] - 2025-10-23
826
+
827
+ ### ๐Ÿ“ฆ Distribution & Packaging Release
828
+
829
+ **Note**: Version 0.6.5 is functionally identical to 0.6.4, which was yanked from RubyGems due to RubyGems policy preventing re-publication of yanked versions.
830
+
831
+ #### Added
832
+ - **GitHub Actions CI/CD Pipeline**: Automated testing across Ruby 2.7-3.3 on Ubuntu, macOS, and Windows
833
+ - **Automated RubyGems Publishing**: Auto-publish gem to RubyGems.org on version tag push
834
+ - **Release Automation Workflow**: Multi-platform gem builds with artifact uploads to GitHub Releases
835
+ - **Code Coverage Reporting**: SimpleCov integration in CI with PR summaries
836
+
837
+ #### Changed
838
+ - **Installation Options**: Two installation methods (RubyGems for all platforms, from source)
839
+ - **README Structure**: Simplified installation section focusing on gem distribution
840
+ - **Gemspec Author Info**: Updated from placeholders to actual author details
841
+
842
+ #### Distribution
843
+ - **RubyGems**: Published gem with all runtime files (works on Windows, macOS, Linux)
844
+ - **Source Install**: Git clone with local gem build option
845
+
846
+ #### Deferred
847
+ - **Windows Standalone Executable**: Deferred due to OCRA incompatibility with Ruby 3.x
848
+ - OCRA 1.3.11 (last version, 2019) fails with Ruby 3.2+ due to internal fiber changes
849
+ - Windows users can use `gem install ruby_spriter` after installing Ruby
850
+ - Will revisit when better Windows packaging tools become available
851
+
852
+ Closes #18
853
+
854
+ ---
855
+
856
+ ## [0.6.4] - 2025-10-23 [YANKED]
857
+
858
+ Version yanked from RubyGems. Use 0.6.5 instead.
859
+
860
+ ### ๐Ÿ“ฆ Distribution & Packaging Release
861
+
862
+ #### Added
863
+ - **GitHub Actions CI/CD Pipeline**: Automated testing across Ruby 2.7-3.3 on Ubuntu, macOS, and Windows
864
+ - **Automated RubyGems Publishing**: Auto-publish gem to RubyGems.org on version tag push
865
+ - **Release Automation Workflow**: Multi-platform gem builds with artifact uploads to GitHub Releases
866
+ - **Code Coverage Reporting**: SimpleCov integration in CI with PR summaries
867
+
868
+ #### Changed
869
+ - **Installation Options**: Two installation methods (RubyGems for all platforms, from source)
870
+ - **README Structure**: Simplified installation section focusing on gem distribution
871
+ - **Gemspec Author Info**: Updated from placeholders to actual author details
872
+
873
+ #### Distribution
874
+ - **RubyGems**: Published gem with all runtime files (works on Windows, macOS, Linux)
875
+ - **Source Install**: Git clone with local gem build option
876
+
877
+ #### Deferred
878
+ - **Windows Standalone Executable**: Deferred due to OCRA incompatibility with Ruby 3.x
879
+ - OCRA 1.3.11 (last version, 2019) fails with Ruby 3.2+ due to internal fiber changes
880
+ - Windows users can use `gem install ruby_spriter` after installing Ruby
881
+ - Will revisit when better Windows packaging tools become available
882
+
883
+ Closes #18
884
+
885
+ ---
886
+
887
+ ## [0.6.3] - 2025-10-23
888
+
889
+ ### ๐Ÿงช Testing & Quality Assurance Release
890
+
891
+ #### Added
892
+ - **155 New RSpec Tests**: Comprehensive test coverage for CLI, GimpProcessor, Consolidator, PathHelper
893
+ - **Test Fixtures**: Real spritesheet fixtures (4x2, 6x2, 4x4), PNG images, MP4 video
894
+ - **Code Coverage Reporting**: SimpleCov tracking showing 57.09% coverage
895
+
896
+ #### Fixed
897
+ - **CLI Preset Bug**: Fixed OptionParser limitation preventing all 4 presets from working
898
+ - **PathHelper Quote Escaping**: Fixed single quote escaping in Unix paths (needed 4 backslashes)
899
+ - **Spec Helper Bug**: Changed instance variable to global variable for cross-context access
900
+ - **PathHelper Tests**: Made drive letter detection flexible for E: drive compatibility
901
+
902
+ #### Testing
903
+ - **CLI Tests (97)**: --help, --version, --check-dependencies, --image, --video, --consolidate, --verify
904
+ - **GimpProcessor Tests (48)**: Initialization, operations, interpolation, output filtering, script generation
905
+ - **Consolidator Tests (33)**: File validation, metadata, column validation, consolidation logic
906
+ - **PathHelper Tests (7)**: Quote paths, normalize for Python, native format conversion
907
+ - **Coverage**: Increased from 22.52% to 57.09% (+34.57 percentage points)
908
+
909
+ Closes #5
910
+
911
+ ---
912
+
913
+ ## [0.6.2] - 2025-10-22
914
+
915
+ ### โœจ Quality Enhancement & Tooling Release
916
+
917
+ #### Added
918
+ - **Interpolation Options**: 5 interpolation methods for scaling (none, linear, cubic, nohalo, lohalo)
919
+ - **Sharpening Support**: Unsharp mask with configurable radius, gain, and threshold
920
+ - **`--version` Flag**: Display version, platform, and date information
921
+ - **`--check-dependencies` Flag**: Verify all external tools are installed with platform-specific guidance
922
+ - **File Extension Validation**: Runtime validation for MP4 (video) and PNG (images)
923
+ - **GIMP Investigation Documentation**: Comprehensive documentation of GIMP sharpen attempts and solutions
924
+
925
+ #### Changed
926
+ - **Automatic Operation Order**: Auto-optimize to remove background before scaling for better quality
927
+ - **Sharpening via ImageMagick**: Use ImageMagick instead of GIMP for reliable cross-platform sharpening
928
+ - **Alpha Channel Preservation**: Use merge instead of flatten to preserve transparency
929
+ - **Conservative Sharpen Defaults**: radius: 2.0, gain: 0.5, threshold: 0.03 to minimize halo artifacts
930
+ - **Parameter Terminology**: Changed "amount" to "gain" to match ImageMagick documentation
931
+
932
+ #### Fixed
933
+ - **Gem Build Error**: Removed .rb extension from `bin/ruby_spriter` executable
934
+ - **Clear Error Messages**: File extension validation provides helpful feedback
935
+
936
+ #### Documentation
937
+ - **README.md**: Added interpolation and sharpening documentation, file format requirements
938
+ - **CLAUDE.md**: Updated with new features and validation details
939
+ - **GIMP_SHARPEN_INVESTIGATION.md**: Documents 8 failed GIMP attempts and architectural decisions
940
+
941
+ ---
942
+
943
+ ## [0.6.1] - 2025-10-22
944
+
945
+ ### ๐ŸŽ‰ Major Refactoring Release
946
+
947
+ #### Added
948
+ - **Modular Architecture**: Split monolithic script into organized modules
949
+ - **RSpec Testing Framework**: Comprehensive unit test coverage
950
+ - **Dependency Checking**: Automatic validation of external tools
951
+ - **Better Error Handling**: Custom exception classes
952
+ - **Code Documentation**: Inline comments and YARD-compatible docs
953
+ - **SimpleCov Integration**: Code coverage reporting
954
+ - **RuboCop Support**: Code style enforcement
955
+
956
+ #### Changed
957
+ - **Project Structure**: Reorganized into `lib/`, `spec/`, and `bin/` directories
958
+ - **Class Organization**:
959
+ - `Platform` - Platform detection and configuration
960
+ - `DependencyChecker` - External tool validation
961
+ - `VideoProcessor` - FFmpeg operations
962
+ - `GimpProcessor` - GIMP operations
963
+ - `MetadataManager` - PNG metadata handling
964
+ - `Consolidator` - Spritesheet consolidation
965
+ - `Processor` - Main orchestration
966
+ - `CLI` - Command-line interface
967
+ - Utilities: `PathHelper`, `FileHelper`, `OutputFormatter`
968
+
969
+ #### Fixed
970
+ - Path handling edge cases on Windows
971
+ - Improved error messages with actionable guidance
972
+ - Better temp file cleanup
973
+
974
+ #### Developer Experience
975
+ - Gemfile for dependency management
976
+ - RSpec test suite with fixtures
977
+ - Comprehensive README with examples
978
+ - Troubleshooting guide
979
+ - Contributing guidelines
980
+
981
+ ---
982
+
983
+ ## [0.6.0] - 2024-XX-XX
984
+
985
+ ### Added
986
+ - Metadata embedding in PNG files
987
+ - Spritesheet consolidation feature
988
+ - Metadata verification command (`--verify`)
989
+ - Debug mode for troubleshooting
990
+
991
+ ### Changed
992
+ - Improved GIMP script generation
993
+ - Better cross-platform path handling
994
+
995
+ ---
996
+
997
+ ## [0.5.0] - 2024-XX-XX
998
+
999
+ ### Added
1000
+ - Background removal with GIMP
1001
+ - Fuzzy select and global color select options
1002
+ - Image scaling support
1003
+ - Configurable operation order
1004
+
1005
+ ---
1006
+
1007
+ ## [0.4.0] - 2024-XX-XX
1008
+
1009
+ ### Added
1010
+ - Video to spritesheet conversion
1011
+ - FFmpeg integration
1012
+ - Customizable grid layouts
1013
+
1014
+ ---
1015
+
1016
+ ## [0.1.0] - 2024-XX-XX
1017
+
1018
+ ### Added
1019
+ - Initial release
1020
+ - Basic video processing
1021
+ - Cross-platform support
1022
+
1023
+ ---
1024
+
1025
+ [0.7.0.1]: https://github.com/scooter-indie/ruby-spriter/compare/v0.7.0...v0.7.0.1
1026
+ [0.7.0]: https://github.com/scooter-indie/ruby-spriter/compare/v0.6.7.1...v0.7.0
1027
+ [0.6.7.1]: https://github.com/scooter-indie/ruby-spriter/compare/v0.6.7...v0.6.7.1
1028
+ [0.6.7]: https://github.com/scooter-indie/ruby-spriter/compare/v0.6.6...v0.6.7
1029
+ [0.6.6]: https://github.com/scooter-indie/ruby-spriter/compare/v0.6.5...v0.6.6
1030
+ [0.6.5]: https://github.com/scooter-indie/ruby-spriter/compare/v0.6.4...v0.6.5
1031
+ [0.6.4]: https://github.com/scooter-indie/ruby-spriter/releases/tag/v0.6.4
1032
+ [0.6.3]: https://github.com/scooter-indie/ruby-spriter/compare/v0.6.2...v0.6.3
1033
+ [0.6.2]: https://github.com/scooter-indie/ruby-spriter/compare/v0.6.1...v0.6.2
1034
+ [0.6.1]: https://github.com/scooter-indie/ruby-spriter/compare/v0.6.0...v0.6.1
1035
+ [0.6.0]: https://github.com/scooter-indie/ruby-spriter/releases/tag/v0.6.0