ruby_spriter 0.6.7.1 → 0.7.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.rspec +3 -3
- data/CHANGELOG.md +1035 -524
- data/Gemfile +17 -17
- data/LICENSE +21 -21
- data/README.md +183 -950
- data/bin/ruby_spriter +20 -20
- data/lib/ruby_spriter/background_sampler.rb +140 -0
- data/lib/ruby_spriter/batch_processor.rb +268 -214
- data/lib/ruby_spriter/cell_cleanup_config.rb +21 -0
- data/lib/ruby_spriter/cell_cleanup_gimp_script.rb +123 -0
- data/lib/ruby_spriter/cell_cleanup_processor.rb +230 -0
- data/lib/ruby_spriter/cli.rb +676 -612
- data/lib/ruby_spriter/compression_manager.rb +101 -101
- data/lib/ruby_spriter/consolidator.rb +179 -179
- data/lib/ruby_spriter/dependency_checker.rb +224 -224
- data/lib/ruby_spriter/ghost_edge_cleaner.rb +164 -0
- data/lib/ruby_spriter/gimp_processor.rb +1188 -1058
- data/lib/ruby_spriter/metadata_manager.rb +117 -116
- data/lib/ruby_spriter/platform.rb +137 -137
- data/lib/ruby_spriter/processor.rb +1230 -891
- data/lib/ruby_spriter/smoke_detector.rb +223 -0
- data/lib/ruby_spriter/threshold_stepper.rb +227 -0
- data/lib/ruby_spriter/utils/file_helper.rb +82 -82
- data/lib/ruby_spriter/utils/image_helper.rb +16 -0
- data/lib/ruby_spriter/utils/output_formatter.rb +65 -65
- data/lib/ruby_spriter/utils/path_helper.rb +59 -59
- data/lib/ruby_spriter/utils/spritesheet_splitter.rb +86 -86
- data/lib/ruby_spriter/version.rb +6 -7
- data/lib/ruby_spriter/video_processor.rb +357 -139
- data/lib/ruby_spriter.rb +38 -34
- data/ruby_spriter.gemspec +44 -42
- data/spec/fixtures/centered_sprite_with_inner_bg.png +0 -0
- data/spec/fixtures/centered_sprite_with_inner_bg_inner_removed.png +0 -0
- data/spec/fixtures/centered_sprite_with_inner_bg_threshold_stepped.png +0 -0
- data/spec/fixtures/complex_background_sprite.png +0 -0
- data/spec/fixtures/death - bloodborne rekconing.mp4 +0 -0
- data/spec/fixtures/death - bloodborne rekconing_spritesheet-nobg-global.png +0 -0
- data/spec/fixtures/death - bloodborne rekconing_spritesheet.png +0 -0
- data/spec/fixtures/death - bloodborne rekconing_spritesheet_20251110_185027_431-nobg-global.png +0 -0
- data/spec/fixtures/death - bloodborne rekconing_spritesheet_20251110_185027_431.png +0 -0
- data/spec/fixtures/death - bloodborne rekconing_spritesheet_20251110_185125_738-nobg-global.png +0 -0
- data/spec/fixtures/death - bloodborne rekconing_spritesheet_20251110_185125_738.png +0 -0
- data/spec/fixtures/has_inner_bg.png +0 -0
- data/spec/fixtures/has_small_inner_bg.png +0 -0
- data/spec/fixtures/smoke_effect_sprite.png +0 -0
- data/spec/fixtures/spritesheet_with_metadata.png +0 -0
- data/spec/fixtures/test_sprite.png +0 -0
- data/spec/fixtures/test_sprite_smoke_processed.png +0 -0
- data/spec/fixtures/test_video_spritesheet.png +0 -0
- data/spec/fixtures/transparent_bg_sprite.png +0 -0
- data/spec/fixtures/walk_north_sprite-sheet.png +0 -0
- data/spec/integration/no_fuzzy_mode_spec.rb +100 -0
- data/spec/ruby_spriter/batch_processor_spec.rb +509 -200
- data/spec/ruby_spriter/cli_spec.rb +2026 -1892
- data/spec/ruby_spriter/compression_manager_spec.rb +157 -157
- data/spec/ruby_spriter/consolidator_spec.rb +538 -538
- data/spec/ruby_spriter/gimp_processor_spec.rb +523 -425
- data/spec/ruby_spriter/platform_spec.rb +92 -92
- data/spec/ruby_spriter/processor_spec.rb +911 -735
- data/spec/ruby_spriter/utils/file_helper_spec.rb +150 -150
- data/spec/ruby_spriter/utils/path_helper_spec.rb +78 -78
- data/spec/ruby_spriter/utils/spritesheet_splitter_spec.rb +104 -104
- data/spec/ruby_spriter/video_processor_spec.rb +346 -29
- data/spec/spec_helper.rb +41 -41
- data/spec/tmp/cli_test_output.png +0 -0
- data/spec/tmp/cli_test_output_20251105_114647_395.png +0 -0
- data/spec/tmp/combined_test.png +0 -0
- data/spec/tmp/compat_test.png +0 -0
- data/spec/tmp/compat_test_20251030_174233_361.png +0 -0
- data/spec/tmp/final_all_features.png +0 -0
- data/spec/tmp/final_test_all_features.png +0 -0
- data/spec/tmp/full_pipeline_test.png +0 -0
- data/spec/tmp/inner_test.png +0 -0
- data/spec/tmp/integration_test.png +0 -0
- data/spec/tmp/validation_test.png +0 -0
- data/spec/unit/background_sampler_spec.rb +132 -0
- data/spec/unit/cell_cleanup_config_spec.rb +32 -0
- data/spec/unit/cell_cleanup_gimp_script_spec.rb +59 -0
- data/spec/unit/cell_cleanup_processor_spec.rb +261 -0
- data/spec/unit/ghost_edge_cleaner_spec.rb +223 -0
- data/spec/unit/gimp_processor_single_point_selection_spec.rb +81 -0
- data/spec/unit/smoke_detector_spec.rb +246 -0
- data/spec/unit/threshold_stepper_spec.rb +195 -0
- metadata +56 -10
|
@@ -1,116 +1,117 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
require 'open3'
|
|
4
|
-
|
|
5
|
-
module RubySpriter
|
|
6
|
-
# Manages PNG metadata for spritesheets
|
|
7
|
-
class MetadataManager
|
|
8
|
-
METADATA_PREFIX = 'SPRITESHEET'
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
#
|
|
12
|
-
# @param
|
|
13
|
-
# @param
|
|
14
|
-
# @param
|
|
15
|
-
# @param
|
|
16
|
-
# @param
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
#
|
|
39
|
-
# @
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
#
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
puts "
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
Utils::OutputFormatter.indent("
|
|
66
|
-
Utils::OutputFormatter.indent("
|
|
67
|
-
Utils::OutputFormatter.indent("
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
puts "
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
Utils::PathHelper.
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
Utils::PathHelper.
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
end
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'open3'
|
|
4
|
+
|
|
5
|
+
module RubySpriter
|
|
6
|
+
# Manages PNG metadata for spritesheets
|
|
7
|
+
class MetadataManager
|
|
8
|
+
METADATA_PREFIX = 'SPRITESHEET'
|
|
9
|
+
METADATA_VERSION = RubySpriter::VERSION
|
|
10
|
+
|
|
11
|
+
# Embed metadata into PNG file
|
|
12
|
+
# @param input_file [String] Source PNG file
|
|
13
|
+
# @param output_file [String] Destination PNG file with metadata
|
|
14
|
+
# @param columns [Integer] Number of columns in grid
|
|
15
|
+
# @param rows [Integer] Number of rows in grid
|
|
16
|
+
# @param frames [Integer] Total number of frames
|
|
17
|
+
# @param debug [Boolean] Enable debug output
|
|
18
|
+
def self.embed(input_file, output_file, columns:, rows:, frames:, debug: false)
|
|
19
|
+
Utils::FileHelper.validate_readable!(input_file)
|
|
20
|
+
|
|
21
|
+
metadata_str = build_metadata_string(columns, rows, frames)
|
|
22
|
+
|
|
23
|
+
cmd = build_embed_command(input_file, output_file, metadata_str)
|
|
24
|
+
|
|
25
|
+
if debug
|
|
26
|
+
Utils::OutputFormatter.indent("DEBUG: Metadata command: #{cmd}")
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
stdout, stderr, status = Open3.capture3(cmd)
|
|
30
|
+
|
|
31
|
+
unless status.success?
|
|
32
|
+
raise ProcessingError, "Failed to embed metadata: #{stderr}"
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
Utils::FileHelper.validate_exists!(output_file)
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
# Read metadata from PNG file
|
|
39
|
+
# @param file [String] PNG file path
|
|
40
|
+
# @return [Hash, nil] Metadata hash or nil if not found
|
|
41
|
+
def self.read(file)
|
|
42
|
+
Utils::FileHelper.validate_readable!(file)
|
|
43
|
+
|
|
44
|
+
cmd = build_read_command(file)
|
|
45
|
+
stdout, stderr, status = Open3.capture3(cmd)
|
|
46
|
+
|
|
47
|
+
return nil unless status.success?
|
|
48
|
+
|
|
49
|
+
parse_metadata(stdout)
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
# Verify and print metadata from file
|
|
53
|
+
# @param file [String] PNG file path
|
|
54
|
+
def self.verify(file)
|
|
55
|
+
Utils::OutputFormatter.header("Spritesheet Metadata Verification")
|
|
56
|
+
|
|
57
|
+
puts "File: #{file}"
|
|
58
|
+
puts "Size: #{Utils::FileHelper.format_size(File.size(file))}\n\n"
|
|
59
|
+
|
|
60
|
+
metadata = read(file)
|
|
61
|
+
|
|
62
|
+
if metadata
|
|
63
|
+
Utils::OutputFormatter.success("Metadata Found")
|
|
64
|
+
puts "\n Grid Layout:"
|
|
65
|
+
Utils::OutputFormatter.indent("Columns: #{metadata[:columns]}")
|
|
66
|
+
Utils::OutputFormatter.indent("Rows: #{metadata[:rows]}")
|
|
67
|
+
Utils::OutputFormatter.indent("Total Frames: #{metadata[:frames]}")
|
|
68
|
+
Utils::OutputFormatter.indent("Metadata Version: #{metadata[:version]}")
|
|
69
|
+
else
|
|
70
|
+
Utils::OutputFormatter.warning("No spritesheet metadata found in this file")
|
|
71
|
+
puts "\nThis file may not have been created by Ruby Spriter,"
|
|
72
|
+
puts "or the metadata was stripped during processing."
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
puts "\n" + "=" * 60 + "\n"
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
private_class_method def self.build_metadata_string(columns, rows, frames)
|
|
79
|
+
"#{METADATA_PREFIX}|columns=#{columns}|rows=#{rows}|frames=#{frames}|version=#{METADATA_VERSION}"
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
private_class_method def self.build_embed_command(input_file, output_file, metadata_str)
|
|
83
|
+
magick_cmd = Platform.imagemagick_convert_cmd
|
|
84
|
+
|
|
85
|
+
[
|
|
86
|
+
magick_cmd,
|
|
87
|
+
Utils::PathHelper.quote_path(input_file),
|
|
88
|
+
'-set', 'comment', Utils::PathHelper.quote_arg(metadata_str),
|
|
89
|
+
Utils::PathHelper.quote_path(output_file)
|
|
90
|
+
].join(' ')
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
private_class_method def self.build_read_command(file)
|
|
94
|
+
magick_cmd = Platform.imagemagick_identify_cmd
|
|
95
|
+
|
|
96
|
+
[
|
|
97
|
+
magick_cmd,
|
|
98
|
+
'-format', Utils::PathHelper.quote_arg('%c'),
|
|
99
|
+
Utils::PathHelper.quote_path(file)
|
|
100
|
+
].join(' ')
|
|
101
|
+
end
|
|
102
|
+
|
|
103
|
+
private_class_method def self.parse_metadata(output)
|
|
104
|
+
# Look for SPRITESHEET metadata pattern
|
|
105
|
+
match = output.match(/#{METADATA_PREFIX}\|columns=(\d+)\|rows=(\d+)\|frames=(\d+)\|version=([\d.]+)/)
|
|
106
|
+
|
|
107
|
+
return nil unless match
|
|
108
|
+
|
|
109
|
+
{
|
|
110
|
+
columns: match[1].to_i,
|
|
111
|
+
rows: match[2].to_i,
|
|
112
|
+
frames: match[3].to_i,
|
|
113
|
+
version: match[4]
|
|
114
|
+
}
|
|
115
|
+
end
|
|
116
|
+
end
|
|
117
|
+
end
|
|
@@ -1,137 +1,137 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
module RubySpriter
|
|
4
|
-
# Platform detection and configuration
|
|
5
|
-
class Platform
|
|
6
|
-
PLATFORM_TYPE = case RUBY_PLATFORM
|
|
7
|
-
when /mingw|mswin|windows/i then :windows
|
|
8
|
-
when /linux/i then :linux
|
|
9
|
-
when /darwin/i then :macos
|
|
10
|
-
else :unknown
|
|
11
|
-
end
|
|
12
|
-
|
|
13
|
-
# GIMP executable paths by platform
|
|
14
|
-
GIMP_DEFAULT_PATHS = {
|
|
15
|
-
windows: 'C:\\Program Files\\GIMP 3\\bin\\gimp-console-3.0.exe',
|
|
16
|
-
linux: '/usr/bin/gimp',
|
|
17
|
-
macos: '/Applications/GIMP.app/Contents/MacOS/gimp'
|
|
18
|
-
}.freeze
|
|
19
|
-
|
|
20
|
-
# Alternative GIMP paths to search
|
|
21
|
-
GIMP_ALTERNATIVE_PATHS = {
|
|
22
|
-
windows: [
|
|
23
|
-
'C:\\Program Files\\GIMP 3\\bin\\gimp-console-3.0.exe',
|
|
24
|
-
'C:\\Program Files (x86)\\GIMP 3\\bin\\gimp-console-3.0.exe',
|
|
25
|
-
'C:\\Program Files\\GIMP 2\\bin\\gimp-console-2.10.exe',
|
|
26
|
-
'C:\\Program Files (x86)\\GIMP 2\\bin\\gimp-console-2.10.exe'
|
|
27
|
-
].freeze,
|
|
28
|
-
linux: [
|
|
29
|
-
'/usr/bin/gimp',
|
|
30
|
-
'/usr/local/bin/gimp',
|
|
31
|
-
'/snap/bin/gimp',
|
|
32
|
-
'/opt/gimp/bin/gimp',
|
|
33
|
-
'flatpak:org.gimp.GIMP' # Flatpak GIMP
|
|
34
|
-
].freeze,
|
|
35
|
-
macos: [
|
|
36
|
-
'/Applications/GIMP.app/Contents/MacOS/gimp',
|
|
37
|
-
'/Applications/GIMP-2.99.app/Contents/MacOS/gimp', # GIMP 3.x dev
|
|
38
|
-
'/Applications/GIMP-3.0.app/Contents/MacOS/gimp', # GIMP 3.x release
|
|
39
|
-
'/Applications/GIMP-2.10.app/Contents/MacOS/gimp'
|
|
40
|
-
].freeze
|
|
41
|
-
}.freeze
|
|
42
|
-
|
|
43
|
-
class << self
|
|
44
|
-
# Get the current platform type
|
|
45
|
-
def current
|
|
46
|
-
PLATFORM_TYPE
|
|
47
|
-
end
|
|
48
|
-
|
|
49
|
-
# Check if running on Windows
|
|
50
|
-
def windows?
|
|
51
|
-
PLATFORM_TYPE == :windows
|
|
52
|
-
end
|
|
53
|
-
|
|
54
|
-
# Check if running on Linux
|
|
55
|
-
def linux?
|
|
56
|
-
PLATFORM_TYPE == :linux
|
|
57
|
-
end
|
|
58
|
-
|
|
59
|
-
# Check if running on macOS
|
|
60
|
-
def macos?
|
|
61
|
-
PLATFORM_TYPE == :macos
|
|
62
|
-
end
|
|
63
|
-
|
|
64
|
-
# Get default GIMP path for current platform
|
|
65
|
-
def default_gimp_path
|
|
66
|
-
GIMP_DEFAULT_PATHS[PLATFORM_TYPE]
|
|
67
|
-
end
|
|
68
|
-
|
|
69
|
-
# Get alternative GIMP paths for current platform
|
|
70
|
-
def alternative_gimp_paths
|
|
71
|
-
GIMP_ALTERNATIVE_PATHS[PLATFORM_TYPE] || []
|
|
72
|
-
end
|
|
73
|
-
|
|
74
|
-
# Get ImageMagick convert command name
|
|
75
|
-
def imagemagick_convert_cmd
|
|
76
|
-
windows? ? 'magick convert' : 'convert'
|
|
77
|
-
end
|
|
78
|
-
|
|
79
|
-
# Get ImageMagick identify command name
|
|
80
|
-
def imagemagick_identify_cmd
|
|
81
|
-
windows? ? 'magick identify' : 'identify'
|
|
82
|
-
end
|
|
83
|
-
|
|
84
|
-
# Detect GIMP version from version string output
|
|
85
|
-
# @param version_output [String] Output from gimp --version command
|
|
86
|
-
# @return [Hash] Version information with :major, :minor, :patch, :full keys, or nil if parse fails
|
|
87
|
-
def detect_gimp_version(version_output)
|
|
88
|
-
return nil if version_output.nil? || version_output.empty?
|
|
89
|
-
|
|
90
|
-
# Match version pattern: "version X.Y.Z" or "version X.Y"
|
|
91
|
-
match = version_output.match(/version\s+(\d+)\.(\d+)(?:\.(\d+))?/i)
|
|
92
|
-
return nil unless match
|
|
93
|
-
|
|
94
|
-
{
|
|
95
|
-
major: match[1].to_i,
|
|
96
|
-
minor: match[2].to_i,
|
|
97
|
-
patch: match[3]&.to_i || 0,
|
|
98
|
-
full: match[1..3].compact.join('.')
|
|
99
|
-
}
|
|
100
|
-
end
|
|
101
|
-
|
|
102
|
-
# Get GIMP version from executable path
|
|
103
|
-
# @param gimp_path [String] Path to GIMP executable or flatpak:app.id
|
|
104
|
-
# @return [Hash] Version information, or nil if detection fails
|
|
105
|
-
def get_gimp_version(gimp_path)
|
|
106
|
-
return nil if gimp_path.nil? || gimp_path.empty?
|
|
107
|
-
|
|
108
|
-
require 'open3'
|
|
109
|
-
|
|
110
|
-
# Handle Flatpak GIMP
|
|
111
|
-
if gimp_path.start_with?('flatpak:')
|
|
112
|
-
flatpak_app = gimp_path.sub('flatpak:', '')
|
|
113
|
-
stdout, stderr, status = Open3.capture3("flatpak run #{flatpak_app} --version")
|
|
114
|
-
return nil unless status.success?
|
|
115
|
-
return detect_gimp_version(stdout + stderr)
|
|
116
|
-
end
|
|
117
|
-
|
|
118
|
-
return nil unless File.exist?(gimp_path)
|
|
119
|
-
|
|
120
|
-
stdout, stderr, status = Open3.capture3("#{quote_path_simple(gimp_path)} --version")
|
|
121
|
-
return nil unless status.success?
|
|
122
|
-
|
|
123
|
-
detect_gimp_version(stdout + stderr)
|
|
124
|
-
rescue StandardError
|
|
125
|
-
nil
|
|
126
|
-
end
|
|
127
|
-
|
|
128
|
-
private
|
|
129
|
-
|
|
130
|
-
# Simple path quoting helper for Platform module
|
|
131
|
-
def quote_path_simple(path)
|
|
132
|
-
return path unless path.include?(' ')
|
|
133
|
-
windows? ? "\"#{path}\"" : "'#{path}'"
|
|
134
|
-
end
|
|
135
|
-
end
|
|
136
|
-
end
|
|
137
|
-
end
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module RubySpriter
|
|
4
|
+
# Platform detection and configuration
|
|
5
|
+
class Platform
|
|
6
|
+
PLATFORM_TYPE = case RUBY_PLATFORM
|
|
7
|
+
when /mingw|mswin|windows/i then :windows
|
|
8
|
+
when /linux/i then :linux
|
|
9
|
+
when /darwin/i then :macos
|
|
10
|
+
else :unknown
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
# GIMP executable paths by platform
|
|
14
|
+
GIMP_DEFAULT_PATHS = {
|
|
15
|
+
windows: 'C:\\Program Files\\GIMP 3\\bin\\gimp-console-3.0.exe',
|
|
16
|
+
linux: '/usr/bin/gimp',
|
|
17
|
+
macos: '/Applications/GIMP.app/Contents/MacOS/gimp'
|
|
18
|
+
}.freeze
|
|
19
|
+
|
|
20
|
+
# Alternative GIMP paths to search
|
|
21
|
+
GIMP_ALTERNATIVE_PATHS = {
|
|
22
|
+
windows: [
|
|
23
|
+
'C:\\Program Files\\GIMP 3\\bin\\gimp-console-3.0.exe',
|
|
24
|
+
'C:\\Program Files (x86)\\GIMP 3\\bin\\gimp-console-3.0.exe',
|
|
25
|
+
'C:\\Program Files\\GIMP 2\\bin\\gimp-console-2.10.exe',
|
|
26
|
+
'C:\\Program Files (x86)\\GIMP 2\\bin\\gimp-console-2.10.exe'
|
|
27
|
+
].freeze,
|
|
28
|
+
linux: [
|
|
29
|
+
'/usr/bin/gimp',
|
|
30
|
+
'/usr/local/bin/gimp',
|
|
31
|
+
'/snap/bin/gimp',
|
|
32
|
+
'/opt/gimp/bin/gimp',
|
|
33
|
+
'flatpak:org.gimp.GIMP' # Flatpak GIMP
|
|
34
|
+
].freeze,
|
|
35
|
+
macos: [
|
|
36
|
+
'/Applications/GIMP.app/Contents/MacOS/gimp',
|
|
37
|
+
'/Applications/GIMP-2.99.app/Contents/MacOS/gimp', # GIMP 3.x dev
|
|
38
|
+
'/Applications/GIMP-3.0.app/Contents/MacOS/gimp', # GIMP 3.x release
|
|
39
|
+
'/Applications/GIMP-2.10.app/Contents/MacOS/gimp'
|
|
40
|
+
].freeze
|
|
41
|
+
}.freeze
|
|
42
|
+
|
|
43
|
+
class << self
|
|
44
|
+
# Get the current platform type
|
|
45
|
+
def current
|
|
46
|
+
PLATFORM_TYPE
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
# Check if running on Windows
|
|
50
|
+
def windows?
|
|
51
|
+
PLATFORM_TYPE == :windows
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
# Check if running on Linux
|
|
55
|
+
def linux?
|
|
56
|
+
PLATFORM_TYPE == :linux
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
# Check if running on macOS
|
|
60
|
+
def macos?
|
|
61
|
+
PLATFORM_TYPE == :macos
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
# Get default GIMP path for current platform
|
|
65
|
+
def default_gimp_path
|
|
66
|
+
GIMP_DEFAULT_PATHS[PLATFORM_TYPE]
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
# Get alternative GIMP paths for current platform
|
|
70
|
+
def alternative_gimp_paths
|
|
71
|
+
GIMP_ALTERNATIVE_PATHS[PLATFORM_TYPE] || []
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
# Get ImageMagick convert command name
|
|
75
|
+
def imagemagick_convert_cmd
|
|
76
|
+
windows? ? 'magick convert' : 'convert'
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
# Get ImageMagick identify command name
|
|
80
|
+
def imagemagick_identify_cmd
|
|
81
|
+
windows? ? 'magick identify' : 'identify'
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
# Detect GIMP version from version string output
|
|
85
|
+
# @param version_output [String] Output from gimp --version command
|
|
86
|
+
# @return [Hash] Version information with :major, :minor, :patch, :full keys, or nil if parse fails
|
|
87
|
+
def detect_gimp_version(version_output)
|
|
88
|
+
return nil if version_output.nil? || version_output.empty?
|
|
89
|
+
|
|
90
|
+
# Match version pattern: "version X.Y.Z" or "version X.Y"
|
|
91
|
+
match = version_output.match(/version\s+(\d+)\.(\d+)(?:\.(\d+))?/i)
|
|
92
|
+
return nil unless match
|
|
93
|
+
|
|
94
|
+
{
|
|
95
|
+
major: match[1].to_i,
|
|
96
|
+
minor: match[2].to_i,
|
|
97
|
+
patch: match[3]&.to_i || 0,
|
|
98
|
+
full: match[1..3].compact.join('.')
|
|
99
|
+
}
|
|
100
|
+
end
|
|
101
|
+
|
|
102
|
+
# Get GIMP version from executable path
|
|
103
|
+
# @param gimp_path [String] Path to GIMP executable or flatpak:app.id
|
|
104
|
+
# @return [Hash] Version information, or nil if detection fails
|
|
105
|
+
def get_gimp_version(gimp_path)
|
|
106
|
+
return nil if gimp_path.nil? || gimp_path.empty?
|
|
107
|
+
|
|
108
|
+
require 'open3'
|
|
109
|
+
|
|
110
|
+
# Handle Flatpak GIMP
|
|
111
|
+
if gimp_path.start_with?('flatpak:')
|
|
112
|
+
flatpak_app = gimp_path.sub('flatpak:', '')
|
|
113
|
+
stdout, stderr, status = Open3.capture3("flatpak run #{flatpak_app} --version")
|
|
114
|
+
return nil unless status.success?
|
|
115
|
+
return detect_gimp_version(stdout + stderr)
|
|
116
|
+
end
|
|
117
|
+
|
|
118
|
+
return nil unless File.exist?(gimp_path)
|
|
119
|
+
|
|
120
|
+
stdout, stderr, status = Open3.capture3("#{quote_path_simple(gimp_path)} --version")
|
|
121
|
+
return nil unless status.success?
|
|
122
|
+
|
|
123
|
+
detect_gimp_version(stdout + stderr)
|
|
124
|
+
rescue StandardError
|
|
125
|
+
nil
|
|
126
|
+
end
|
|
127
|
+
|
|
128
|
+
private
|
|
129
|
+
|
|
130
|
+
# Simple path quoting helper for Platform module
|
|
131
|
+
def quote_path_simple(path)
|
|
132
|
+
return path unless path.include?(' ')
|
|
133
|
+
windows? ? "\"#{path}\"" : "'#{path}'"
|
|
134
|
+
end
|
|
135
|
+
end
|
|
136
|
+
end
|
|
137
|
+
end
|