mojo_magick 0.5.7 → 0.6.5

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.
data/lib/mojo_magick.rb CHANGED
@@ -1,15 +1,12 @@
1
- cwd = File.dirname(__FILE__)
2
- require 'open3'
3
- initializers_dir = File.expand_path(File.join(cwd, 'initializers'))
4
- Dir.glob(File.join(initializers_dir, '*.rb')).each { |f| require f }
5
- require File.join(cwd, 'mojo_magick/util/parser')
6
- require File.join(cwd, 'mojo_magick/errors')
7
- require File.join(cwd, 'mojo_magick/command_status')
8
- require File.join(cwd, 'image_magick/resource_limits')
9
- require File.join(cwd, 'image_magick/fonts')
10
- require File.join(cwd, 'mojo_magick/opt_builder')
11
- require File.join(cwd, 'mojo_magick/font')
12
- require 'tempfile'
1
+ require "tempfile"
2
+ require "open3"
3
+ require_relative "./mojo_magick/util/font_parser"
4
+ require_relative "./mojo_magick/errors"
5
+ require_relative "./mojo_magick/command_status"
6
+ require_relative "./mojo_magick/commands"
7
+ require_relative "./image_magick/fonts"
8
+ require_relative "./mojo_magick/opt_builder"
9
+ require_relative "./mojo_magick/font"
13
10
 
14
11
  # MojoMagick is a stateless set of module methods which present a convient interface
15
12
  # for accessing common tasks for ImageMagick command line library.
@@ -35,7 +32,8 @@ require 'tempfile'
35
32
  #
36
33
  # Equivalent to:
37
34
  #
38
- # MojoMagick::raw_command('convert', 'source.jpg -crop 250x250+0+0 +repage -strip -set comment "my favorite file" dest.jpg')
35
+ # MojoMagick::Commands.raw_command('convert', 'source.jpg -crop 250x250+0+0\
36
+ # +repage -strip -set comment "my favorite file" dest.jpg')
39
37
  #
40
38
  # Example #mogrify usage:
41
39
  #
@@ -43,7 +41,7 @@ require 'tempfile'
43
41
  #
44
42
  # Equivalent to:
45
43
  #
46
- # MojoMagick::raw_command('mogrify', '-shave 10x10 image.jpg')
44
+ # MojoMagick::Commands.raw_command('mogrify', '-shave 10x10 image.jpg')
47
45
  #
48
46
  # Example showing some additional options:
49
47
  #
@@ -60,39 +58,40 @@ require 'tempfile'
60
58
  # bang (!) can be appended to command names to use the '+' versions
61
59
  # instead of '-' versions.
62
60
  #
63
- module MojoMagick
64
- # enable resource limiting functionality
65
- extend ImageMagick::ResourceLimits
66
- extend ImageMagick::Fonts
67
61
 
68
- def self.windows?
69
- !(RUBY_PLATFORM =~ /win32/).nil?
62
+ module MojoMagickDeprecations
63
+ # rubocop:disable Naming/AccessorMethodName
64
+ def get_fonts
65
+ warn "DEPRECATION WARNING: #{__method__} is deprecated and will be removed with the next minor version release."\
66
+ " Please use `available_fonts` instead"
67
+ MojoMagick.available_fonts
70
68
  end
71
69
 
72
- def self.execute(command, args, _options = {})
73
- # this suppress error messages to the console
74
- # err_pipe = windows? ? "2>nul" : "2>/dev/null"
70
+ # rubocop:enable Naming/AccessorMethodName
71
+ ### Moved to `Commands`
72
+ def execute!(*args)
73
+ warn "DEPRECATION WARNING: #{__method__} is deprecated and will be removed with the next minor version release."\
74
+ " Please use `MojoMagick::Commands.execute!` instead"
75
+ MojoMagick::Commands.send(:execute!, *args)
76
+ end
75
77
 
76
- execute = "#{command} #{get_limits_as_params} #{args}"
77
- out, outerr, status = Open3.capture3(execute)
78
- CommandStatus.new execute, out, outerr, status
79
- rescue Exception => e
80
- raise MojoError, "#{e.class}: #{e.message}"
78
+ def execute(*args)
79
+ warn "DEPRECATION WARNING: #{__method__} is deprecated and will be removed with the next minor version release."\
80
+ " Please use `MojoMagick::Commands.execute!` instead"
81
+ MojoMagick::Commands.send(:execute, *args)
81
82
  end
82
83
 
83
- def self.execute!(command, args, options = {})
84
- # this suppress error messages to the console
85
- # err_pipe = windows? ? "2>nul" : "2>/dev/null"
86
- status = execute(command, args, options)
87
- unless status.success?
88
- err_msg = options[:err_msg] || "MojoMagick command failed: #{command}."
89
- raise(MojoFailed, "#{err_msg} (Exit status: #{status.exit_code})\n Command: #{status.command}\n Error: #{status.error}")
90
- end
91
- status.return_value
84
+ def raw_command(*args)
85
+ warn "DEPRECATION WARNING: #{__method__} is deprecated and will be removed with the next minor version release."\
86
+ " Please use `MojoMagick::Commands.execute!` instead"
87
+ MojoMagick::Commands.raw_command(*args)
92
88
  end
89
+ end
93
90
 
94
- def self.raw_command(*args)
95
- execute!(*args)
91
+ module MojoMagick
92
+ extend MojoMagickDeprecations
93
+ def self.windows?
94
+ !RUBY_PLATFORM.include(win32)
96
95
  end
97
96
 
98
97
  def self.shrink(source_file, dest_file, options)
@@ -110,46 +109,56 @@ module MojoMagick
110
109
  # resizes an image and returns the filename written to
111
110
  # options:
112
111
  # :width / :height => scale to these dimensions
113
- # :scale => pass scale options such as ">" to force shrink scaling only or "!" to force absolute width/height scaling (do not preserve aspect ratio)
112
+ # :scale => pass scale options such as ">" to force shrink scaling only or
113
+ # "!" to force absolute width/height scaling (do not preserve aspect ratio)
114
114
  # :percent => scale image to this percentage (do not specify :width/:height in this case)
115
115
  def self.resize(source_file, dest_file, options)
116
- scale_options = []
117
- scale_options << '>' unless options[:shrink_only].nil?
118
- scale_options << '<' unless options[:expand_only].nil?
119
- scale_options << '!' unless options[:absolute_aspect].nil?
120
- scale_options << '^' unless options[:fill].nil?
121
- scale_options = scale_options.join
122
-
116
+ scale_options = extract_scale_options(options)
117
+ geometry = extract_geometry_options(options)
123
118
  extras = []
124
- if !options[:width].nil? && !options[:height].nil?
125
- geometry = "#{options[:width]}X#{options[:height]}"
126
- elsif !options[:percent].nil?
127
- geometry = "#{options[:percent]}%"
128
- else
129
- raise MojoMagickError, "Unknown options for method resize: #{options.inspect}"
130
- end
131
119
  if !options[:fill].nil? && !options[:crop].nil?
132
- extras << '-gravity Center'
133
- extras << "-extent #{geometry}"
120
+ extras << "-gravity"
121
+ extras << "Center"
122
+ extras << "-extent"
123
+ extras << geometry.to_s
134
124
  end
135
- raw_command('convert', "\"#{source_file}\" -resize \"#{geometry}#{scale_options}\" #{extras.join(' ')} \"#{dest_file}\"")
125
+ Commands.raw_command("convert",
126
+ source_file,
127
+ "-resize", "#{geometry}#{scale_options}",
128
+ *extras, dest_file)
136
129
  dest_file
137
130
  end
138
131
 
132
+ def self.convert(source = nil, dest = nil)
133
+ opts = OptBuilder.new
134
+ opts.file source if source
135
+ yield opts
136
+ opts.file dest if dest
137
+
138
+ Commands.raw_command("convert", *opts.to_a)
139
+ end
140
+
141
+ def self.mogrify(dest = nil)
142
+ opts = OptBuilder.new
143
+ yield opts
144
+ opts.file dest if dest
145
+ Commands.raw_command("mogrify", *opts.to_a)
146
+ end
147
+
139
148
  def self.available_fonts
140
149
  # returns width, height of image if available, nil if not
141
150
  Font.all
142
151
  end
143
152
 
144
153
  def self.get_format(source_file, format_string)
145
- raw_command('identify', "-format \"#{format_string}\" \"#{source_file}\"")
154
+ Commands.raw_command("identify", "-format", format_string, source_file)
146
155
  end
147
156
 
148
157
  # returns an empty hash or a hash with :width and :height set (e.g. {:width => INT, :height => INT})
149
158
  # raises MojoFailed when results are indeterminate (width and height could not be determined)
150
159
  def self.get_image_size(source_file)
151
160
  # returns width, height of image if available, nil if not
152
- retval = get_format(source_file, 'w:%w h:%h')
161
+ retval = get_format(source_file, "w:%w h:%h")
153
162
  return {} unless retval
154
163
 
155
164
  width = retval.match(/w:([0-9]+) /)
@@ -161,30 +170,38 @@ module MojoMagick
161
170
  { width: width, height: height }
162
171
  end
163
172
 
164
- def self.convert(source = nil, dest = nil)
165
- opts = OptBuilder.new
166
- opts.file source if source
167
- yield opts
168
- opts.file dest if dest
169
- raw_command('convert', opts.to_s)
170
- end
171
-
172
- def self.mogrify(dest = nil)
173
- opts = OptBuilder.new
174
- yield opts
175
- opts.file dest if dest
176
- raw_command('mogrify', opts.to_s)
177
- end
178
-
179
173
  def self.tempfile(*opts)
180
174
  data = opts[0]
181
175
  rest = opts[1]
182
176
  ext = rest && rest[:format]
183
- file = Tempfile.new(['mojo', ext ? '.' + ext.to_s : ''])
177
+ file = Tempfile.new(["mojo", ext ? ".#{ext}" : ""])
184
178
  file.binmode
185
179
  file.write(data)
186
180
  file.path
187
181
  ensure
188
182
  file.close
189
183
  end
190
- end # MojoMagick
184
+
185
+ class << self
186
+ private
187
+
188
+ def extract_geometry_options(options)
189
+ if !options[:width].nil? && !options[:height].nil?
190
+ "#{options[:width]}X#{options[:height]}"
191
+ elsif !options[:percent].nil?
192
+ "#{options[:percent]}%"
193
+ else
194
+ raise MojoMagickError, "Resize requires width and height or percentage: #{options.inspect}"
195
+ end
196
+ end
197
+
198
+ def extract_scale_options(options)
199
+ [].tap { |scale_options|
200
+ scale_options << ">" unless options[:shrink_only].nil?
201
+ scale_options << "<" unless options[:expand_only].nil?
202
+ scale_options << "!" unless options[:absolute_aspect].nil?
203
+ scale_options << "^" unless options[:fill].nil?
204
+ }.join
205
+ end
206
+ end
207
+ end
@@ -5,7 +5,7 @@ module MojoMagick
5
5
  end
6
6
 
7
7
  def exit_code
8
- system_status.exitstatus || 'unknown'
8
+ system_status.exitstatus || "unknown"
9
9
  end
10
10
  end
11
11
  end
@@ -0,0 +1,32 @@
1
+ require_relative "opt_builder"
2
+
3
+ module MojoMagick
4
+ class Commands
5
+ def self.raw_command(*args)
6
+ execute!(*args)
7
+ end
8
+
9
+ class << self
10
+ private
11
+
12
+ def execute(command, *args)
13
+ execute = "#{command} #{args}"
14
+ out, outerr, status = Open3.capture3(command, *args.map(&:to_s))
15
+ CommandStatus.new execute, out, outerr, status
16
+ rescue StandardError => e
17
+ raise MojoError, "#{e.class}: #{e.message}"
18
+ end
19
+
20
+ def execute!(command, *args)
21
+ status = execute(command, *args)
22
+ unless status.success?
23
+ err_msg = "MojoMagick command failed: #{command}."
24
+ raise(MojoFailed, "#{err_msg} (Exit status: #{status.exit_code})\n" \
25
+ " Command: #{status.command}\n" \
26
+ " Error: #{status.error}")
27
+ end
28
+ status.return_value
29
+ end
30
+ end
31
+ end
32
+ end
@@ -1,5 +1,7 @@
1
1
  module MojoMagick
2
2
  class MojoMagickException < StandardError; end
3
+
3
4
  class MojoError < MojoMagickException; end
5
+
4
6
  class MojoFailed < MojoMagickException; end
5
7
  end
@@ -7,7 +7,6 @@ module MojoMagick
7
7
  end
8
8
 
9
9
  def initialize(property_hash = {})
10
- property_hash.symbolize_keys!
11
10
  %i[name family style stretch weight glyphs].each do |f|
12
11
  setter = "#{f}="
13
12
  send(setter, property_hash[f])
@@ -15,7 +14,7 @@ module MojoMagick
15
14
  end
16
15
 
17
16
  def self.all
18
- ImageMagick::Font.all.map { |font_info| Font.new(font_info) }
17
+ ImageMagick::Fonts.all
19
18
  end
20
19
  end
21
20
  end
@@ -17,9 +17,7 @@ module MojoMagick
17
17
 
18
18
  # Add files to command line, formatted if necessary
19
19
  def file(*args)
20
- args.each do |arg|
21
- add_formatted arg
22
- end
20
+ @opts << args
23
21
  self
24
22
  end
25
23
  alias files file
@@ -29,21 +27,17 @@ module MojoMagick
29
27
  end
30
28
 
31
29
  # annotate takes non-standard args
32
- def annotate(*args)
33
- @opts << '-annotate'
34
- arguments = args.join.split
35
- arguments.unshift '0' if arguments.length == 1
36
- arguments.each do |arg|
37
- add_formatted arg
38
- end
30
+ def annotate(*args, geometry: 0)
31
+ @opts << "-annotate"
32
+ arguments = [args.join]
33
+ arguments.unshift geometry.to_s
34
+ @opts << arguments
39
35
  end
40
36
 
41
37
  # Create a temporary file for the given image and add to command line
42
38
  def format(*args)
43
- @opts << '-format'
44
- args.each do |arg|
45
- add_formatted arg
46
- end
39
+ @opts << "-format"
40
+ @opts << args
47
41
  end
48
42
 
49
43
  def blob(*args)
@@ -64,33 +58,28 @@ module MojoMagick
64
58
  end
65
59
 
66
60
  # Generic commands. Arguments will be formatted if necessary
61
+ # rubocop:disable Style/MissingRespondToMissing
67
62
  def method_missing(command, *args)
68
- @opts << if command.to_s[-1, 1] == '!'
63
+ @opts << if command.to_s[-1, 1] == "!"
69
64
  "+#{command.to_s.chop}"
70
65
  else
71
66
  "-#{command}"
72
67
  end
73
- args.each do |arg|
74
- add_formatted arg
75
- end
68
+ @opts << args
76
69
  self
77
70
  end
78
71
 
79
- def to_s
80
- @opts.join ' '
72
+ # rubocop:enable Style/MissingRespondToMissing
73
+ def to_a
74
+ @opts.flatten
81
75
  end
82
76
 
83
77
  protected
84
78
 
85
- def add_formatted(arg)
86
- # Quote anything that would cause problems on *nix or windows
87
- @opts << quoted_arg(arg)
88
- end
89
-
90
79
  def quoted_arg(arg)
91
- return arg unless arg =~ /[#'<>^|&();` ]/
80
+ return arg unless /[#'<>^|&();` ]/.match?(arg)
92
81
 
93
- ['"', arg.gsub('"', '\"').gsub("'", "\'"), '"'].join
82
+ ['"', arg.gsub('"', '\"').tr("'", "\'"), '"'].join
94
83
  end
95
84
  end
96
85
  end
@@ -0,0 +1,43 @@
1
+ # rubocop:disable Lint/AssignmentInCondition
2
+ module MojoMagick
3
+ module Util
4
+ class FontParser
5
+ attr_reader :raw_fonts
6
+
7
+ def initialize(raw_fonts)
8
+ @raw_fonts = raw_fonts
9
+ end
10
+
11
+ def parse
12
+ fonts = {}
13
+ enumerator = raw_fonts.split("\n").each
14
+ name = nil
15
+ while begin; line = enumerator.next; rescue StopIteration; line = nil; end
16
+ line.chomp!
17
+ line = enumerator.next if line_is_empty(line)
18
+ m = /^\s*Font:\s+(.*)$/.match(line)
19
+ if m
20
+ name = m[1].strip
21
+ fonts[name] = { name: name }
22
+ else
23
+ k, v = extract_key_value(line)
24
+ fonts[name][k] = v if k && name
25
+ end
26
+ end
27
+ fonts.values.map { |f| MojoMagick::Font.new f }
28
+ end
29
+
30
+ private
31
+
32
+ def extract_key_value(line)
33
+ key_val = line.split(":").map(&:strip)
34
+ [key_val[0].downcase.to_sym, key_val[1]]
35
+ end
36
+
37
+ def line_is_empty(line)
38
+ line.nil? || line.empty? || (/^\s+$/ =~ line)
39
+ end
40
+ end
41
+ end
42
+ end
43
+ # rubocop:enable Lint/AssignmentInCondition
@@ -1,65 +1,20 @@
1
+ require_relative "./font_parser"
1
2
  module MojoMagick
2
3
  module Util
3
4
  class Parser
4
- # handle parsing outputs from ImageMagick commands
5
+ attr_reader :raw_fonts
5
6
 
6
- def parse_fonts(raw_fonts)
7
- fonts = {}
8
- enumerator = raw_fonts.split(/\n/).each
9
- name = nil
10
- while begin; line = enumerator.next; rescue StopIteration; line = nil; end
11
- line.chomp!
12
- line = enumerator.next if line.nil? || line.empty? || (/^\s+$/ =~ line)
13
- if m = /^\s*Font:\s+(.*)$/.match(line)
14
- name = m[1].strip
15
- fonts[name] = {name: name}
16
- else
17
- key_val = line.split(/:/).map(&:strip)
18
- k = key_val[0].downcase.to_sym
19
- v = key_val[1]
20
- fonts[name][k] = v if k && name
21
- end
22
- end
23
- fonts.values.map { |f| MojoMagick::Font.new f}
7
+ def initialize
8
+ warn "DEPRECATION WARNING: This class has been deprecated and will be removed with"\
9
+ " the next minor version release."\
10
+ " Please use `MojoMagick::Util::FontParser` instead"
24
11
  end
25
12
 
26
- def parse_limits(raw_limits)
27
- row_limits = raw_limits.split("\n")
28
- header = row_limits[0].chomp
29
- data = row_limits[2].chomp
30
- resources = header.strip.split
31
- limits = data.strip.split
32
-
33
- actual_values = {}
34
- readable_values = {}
35
-
36
- resources.each_index do |i|
37
- resource = resources[i].downcase.to_sym
38
- scale = limits[i].match(/[a-z]+$/) || []
39
- value = limits[i].match(/^[0-9]+/)
40
- unscaled_value = value ? value[0].to_i : -1
41
- scaled_value = case scale[0]
42
- when 'eb'
43
- unscaled_value * (2**60)
44
- when 'pb'
45
- unscaled_value * (2**50)
46
- when 'tb'
47
- unscaled_value * (2**40)
48
- when 'gb'
49
- unscaled_value * (2**30)
50
- when 'mb'
51
- unscaled_value * (2**20)
52
- when 'kb'
53
- unscaled_value * (2**10)
54
- when 'b'
55
- unscaled_value
56
- else
57
- unscaled_value
58
- end
59
- actual_values[resource] = scaled_value
60
- readable_values[resource] = limits[i]
61
- end
62
- [actual_values, readable_values]
13
+ def parse_fonts(fonts)
14
+ warn "DEPRECATION WARNING: #{__method__} has been deprecated and will be removed with"\
15
+ " the next minor version release."\
16
+ " Please use `MojoMagick::Util::FontParser#parse` instead"
17
+ FontParser.new(fonts).parse
63
18
  end
64
19
  end
65
20
  end