mini_magick 3.8.1 → 4.9.4

Sign up to get free protection for your applications and to get access to all the features.
Files changed (42) hide show
  1. checksums.yaml +5 -5
  2. data/lib/mini_gmagick.rb +1 -0
  3. data/lib/mini_magick/configuration.rb +198 -0
  4. data/lib/mini_magick/image/info.rb +192 -0
  5. data/lib/mini_magick/image.rb +456 -341
  6. data/lib/mini_magick/shell.rb +81 -0
  7. data/lib/mini_magick/tool/animate.rb +14 -0
  8. data/lib/mini_magick/tool/compare.rb +14 -0
  9. data/lib/mini_magick/tool/composite.rb +14 -0
  10. data/lib/mini_magick/tool/conjure.rb +14 -0
  11. data/lib/mini_magick/tool/convert.rb +14 -0
  12. data/lib/mini_magick/tool/display.rb +14 -0
  13. data/lib/mini_magick/tool/identify.rb +14 -0
  14. data/lib/mini_magick/tool/import.rb +14 -0
  15. data/lib/mini_magick/tool/magick.rb +14 -0
  16. data/lib/mini_magick/tool/mogrify.rb +14 -0
  17. data/lib/mini_magick/tool/mogrify_restricted.rb +15 -0
  18. data/lib/mini_magick/tool/montage.rb +14 -0
  19. data/lib/mini_magick/tool/stream.rb +14 -0
  20. data/lib/mini_magick/tool.rb +297 -0
  21. data/lib/mini_magick/utilities.rb +23 -50
  22. data/lib/mini_magick/version.rb +5 -5
  23. data/lib/mini_magick.rb +54 -65
  24. metadata +49 -51
  25. data/lib/mini_magick/command_builder.rb +0 -94
  26. data/lib/mini_magick/errors.rb +0 -4
  27. data/spec/files/actually_a_gif.jpg +0 -0
  28. data/spec/files/animation.gif +0 -0
  29. data/spec/files/composited.jpg +0 -0
  30. data/spec/files/erroneous.jpg +0 -0
  31. data/spec/files/layers.psd +0 -0
  32. data/spec/files/leaves (spaced).tiff +0 -0
  33. data/spec/files/not_an_image.php +0 -1
  34. data/spec/files/png.png +0 -0
  35. data/spec/files/simple-minus.gif +0 -0
  36. data/spec/files/simple.gif +0 -0
  37. data/spec/files/trogdor.jpg +0 -0
  38. data/spec/files/trogdor_capitalized.JPG +0 -0
  39. data/spec/lib/mini_magick/command_builder_spec.rb +0 -153
  40. data/spec/lib/mini_magick/image_spec.rb +0 -499
  41. data/spec/lib/mini_magick_spec.rb +0 -63
  42. data/spec/spec_helper.rb +0 -29
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: 4f4ae6b4f7d224af6275ad37b108c978f3fd8817
4
- data.tar.gz: 69d6e3f3b1289af2dd54a0309166e71fce1e2f45
2
+ SHA256:
3
+ metadata.gz: 3ab4ce03957b9a0f941f9bd2c34a5dcab63faffac5143eb6e7c90d7d860b57c5
4
+ data.tar.gz: 7bd78f0c862f1ca72b34e3c6fc4d14297adfa9dd6bc36218a35ef68c235320b5
5
5
  SHA512:
6
- metadata.gz: 248c08f2af654156c2a422bb3bb3e48a9b97087bab6dacace044bbc2175465c9a2e5de09eac05cb4110cc4efcc8a47f25424f03f6effa6df2cbb2fda85524557
7
- data.tar.gz: 3c000c0861b8e66312d875b8858cdc3fe0b32c842332b70c979675acbf9b4fc62fcb4732c5c49db96240e0bf400974a90ee01e90a34b1c3d817eaf60444030fb
6
+ metadata.gz: 16c4bfa3744a2bea117bff0118afcbf89fac2f3d9e92c5c8af2b095f6c1381c1d000bede5086ccffd72ecca8152845cde11a5ff762186bd90793ee5d83e03a77
7
+ data.tar.gz: fe593ad2a7bfd4b6f2d9892533fd5347046e7dfb6cfd8e3bc6049cb1ae7686f5af60c23f33254175bca4728a58bdeeab2b9bfb873ebd94c46f14e68e086f002f
data/lib/mini_gmagick.rb CHANGED
@@ -1,2 +1,3 @@
1
1
  require 'mini_magick'
2
+
2
3
  MiniMagick.processor = :gm
@@ -0,0 +1,198 @@
1
+ require 'mini_magick/utilities'
2
+ require 'logger'
3
+
4
+ module MiniMagick
5
+ module Configuration
6
+
7
+ ##
8
+ # Set whether you want to use [ImageMagick](http://www.imagemagick.org) or
9
+ # [GraphicsMagick](http://www.graphicsmagick.org).
10
+ #
11
+ # @return [Symbol] `:imagemagick`, `:imagemagick7`, or `:graphicsmagick`
12
+ #
13
+ attr_accessor :cli
14
+
15
+ ##
16
+ # If you don't have the CLI tools in your PATH, you can set the path to the
17
+ # executables.
18
+ #
19
+ attr_writer :cli_path
20
+ # @private (for backwards compatibility)
21
+ attr_accessor :processor_path
22
+
23
+ ##
24
+ # Adds a prefix to the CLI command.
25
+ # For example, you could use `firejail` to run all commands in a sandbox.
26
+ # Can be a string, or an array of strings.
27
+ # e.g. 'firejail', or ['firejail', '--force']
28
+ #
29
+ # @return [String]
30
+ # @return [Array<String>]
31
+ #
32
+ attr_accessor :cli_prefix
33
+
34
+ ##
35
+ # If you don't want commands to take too long, you can set a timeout (in
36
+ # seconds).
37
+ #
38
+ # @return [Integer]
39
+ #
40
+ attr_accessor :timeout
41
+ ##
42
+ # When get to `true`, it outputs each command to STDOUT in their shell
43
+ # version.
44
+ #
45
+ # @return [Boolean]
46
+ #
47
+ attr_reader :debug
48
+ ##
49
+ # Logger for {#debug}, default is `MiniMagick::Logger.new(STDOUT)`, but
50
+ # you can override it, for example if you want the logs to be written to
51
+ # a file.
52
+ #
53
+ # @return [Logger]
54
+ #
55
+ attr_accessor :logger
56
+
57
+ ##
58
+ # If set to `true`, it will `identify` every newly created image, and raise
59
+ # `MiniMagick::Invalid` if the image is not valid. Useful for validating
60
+ # user input, although it adds a bit of overhead. Defaults to `true`.
61
+ #
62
+ # @return [Boolean]
63
+ #
64
+ attr_accessor :validate_on_create
65
+ ##
66
+ # If set to `true`, it will `identify` every image that gets written (with
67
+ # {MiniMagick::Image#write}), and raise `MiniMagick::Invalid` if the image
68
+ # is not valid. Useful for validating that processing was sucessful,
69
+ # although it adds a bit of overhead. Defaults to `true`.
70
+ #
71
+ # @return [Boolean]
72
+ #
73
+ attr_accessor :validate_on_write
74
+
75
+ ##
76
+ # If set to `false`, it will not raise errors when ImageMagick returns
77
+ # status code different than 0. Defaults to `true`.
78
+ #
79
+ # @return [Boolean]
80
+ #
81
+ attr_accessor :whiny
82
+
83
+ ##
84
+ # Instructs MiniMagick how to execute the shell commands. Available
85
+ # APIs are "open3" (default) and "posix-spawn" (requires the "posix-spawn"
86
+ # gem).
87
+ #
88
+ # @return [String]
89
+ #
90
+ attr_accessor :shell_api
91
+
92
+ def self.extended(base)
93
+ base.validate_on_create = true
94
+ base.validate_on_write = true
95
+ base.whiny = true
96
+ base.shell_api = "open3"
97
+ base.logger = Logger.new($stdout).tap { |l| l.level = Logger::INFO }
98
+ end
99
+
100
+ ##
101
+ # @yield [self]
102
+ # @example
103
+ # MiniMagick.configure do |config|
104
+ # config.cli = :graphicsmagick
105
+ # config.timeout = 5
106
+ # end
107
+ #
108
+ def configure
109
+ yield self
110
+ end
111
+
112
+ CLI_DETECTION = {
113
+ imagemagick: "mogrify",
114
+ graphicsmagick: "gm",
115
+ imagemagick7: "magick",
116
+ }
117
+
118
+ # @private (for backwards compatibility)
119
+ def processor
120
+ @processor ||= CLI_DETECTION.values.detect do |processor|
121
+ MiniMagick::Utilities.which(processor)
122
+ end
123
+ end
124
+
125
+ # @private (for backwards compatibility)
126
+ def processor=(processor)
127
+ @processor = processor.to_s
128
+
129
+ unless CLI_DETECTION.value?(@processor)
130
+ raise ArgumentError,
131
+ "processor has to be set to either \"magick\", \"mogrify\" or \"gm\"" \
132
+ ", was set to #{@processor.inspect}"
133
+ end
134
+ end
135
+
136
+ ##
137
+ # Get [ImageMagick](http://www.imagemagick.org) or
138
+ # [GraphicsMagick](http://www.graphicsmagick.org).
139
+ #
140
+ # @return [Symbol] `:imagemagick` or `:graphicsmagick`
141
+ #
142
+ def cli
143
+ if instance_variable_defined?("@cli")
144
+ instance_variable_get("@cli")
145
+ else
146
+ cli = CLI_DETECTION.key(processor) or
147
+ fail MiniMagick::Error, "You must have ImageMagick or GraphicsMagick installed"
148
+
149
+ instance_variable_set("@cli", cli)
150
+ end
151
+ end
152
+
153
+ ##
154
+ # Set whether you want to use [ImageMagick](http://www.imagemagick.org) or
155
+ # [GraphicsMagick](http://www.graphicsmagick.org).
156
+ #
157
+ def cli=(value)
158
+ @cli = value
159
+
160
+ if not CLI_DETECTION.key?(@cli)
161
+ raise ArgumentError,
162
+ "CLI has to be set to either :imagemagick, :imagemagick7 or :graphicsmagick" \
163
+ ", was set to #{@cli.inspect}"
164
+ end
165
+ end
166
+
167
+ ##
168
+ # If you set the path of CLI tools, you can get the path of the
169
+ # executables.
170
+ #
171
+ # @return [String]
172
+ #
173
+ def cli_path
174
+ if instance_variable_defined?("@cli_path")
175
+ instance_variable_get("@cli_path")
176
+ else
177
+ processor_path = instance_variable_get("@processor_path") if instance_variable_defined?("@processor_path")
178
+
179
+ instance_variable_set("@cli_path", processor_path)
180
+ end
181
+ end
182
+
183
+ ##
184
+ # When set to `true`, it outputs each command to STDOUT in their shell
185
+ # version.
186
+ #
187
+ def debug=(value)
188
+ warn "MiniMagick.debug is deprecated and will be removed in MiniMagick 5. Use `MiniMagick.logger.level = Logger::DEBUG` instead."
189
+ logger.level = value ? Logger::DEBUG : Logger::INFO
190
+ end
191
+
192
+ # Backwards compatibility
193
+ def reload_tools
194
+ warn "MiniMagick.reload_tools is deprecated because it is no longer necessary"
195
+ end
196
+
197
+ end
198
+ end
@@ -0,0 +1,192 @@
1
+ require "json"
2
+
3
+ module MiniMagick
4
+ class Image
5
+ # @private
6
+ class Info
7
+ ASCII_ENCODED_EXIF_KEYS = %w[ExifVersion FlashPixVersion]
8
+
9
+ def initialize(path)
10
+ @path = path
11
+ @info = {}
12
+ end
13
+
14
+ def [](value, *args)
15
+ case value
16
+ when "format", "width", "height", "dimensions", "size", "human_size"
17
+ cheap_info(value)
18
+ when "colorspace"
19
+ colorspace
20
+ when "mime_type"
21
+ mime_type
22
+ when "resolution"
23
+ resolution(*args)
24
+ when "signature"
25
+ signature
26
+ when /^EXIF\:/i
27
+ raw_exif(value)
28
+ when "exif"
29
+ exif
30
+ when "details"
31
+ details
32
+ when "data"
33
+ data
34
+ else
35
+ raw(value)
36
+ end
37
+ end
38
+
39
+ def clear
40
+ @info.clear
41
+ end
42
+
43
+ def cheap_info(value)
44
+ @info.fetch(value) do
45
+ format, width, height, size = self["%m %w %h %b"].split(" ")
46
+
47
+ path = @path
48
+ path = path.match(/\[\d+\]$/).pre_match if path =~ /\[\d+\]$/
49
+
50
+ @info.update(
51
+ "format" => format,
52
+ "width" => Integer(width),
53
+ "height" => Integer(height),
54
+ "dimensions" => [Integer(width), Integer(height)],
55
+ "size" => File.size(path),
56
+ "human_size" => size,
57
+ )
58
+
59
+ @info.fetch(value)
60
+ end
61
+ rescue ArgumentError, TypeError
62
+ raise MiniMagick::Invalid, "image data can't be read"
63
+ end
64
+
65
+ def colorspace
66
+ @info["colorspace"] ||= self["%r"]
67
+ end
68
+
69
+ def mime_type
70
+ "image/#{self["format"].downcase}"
71
+ end
72
+
73
+ def resolution(unit = nil)
74
+ output = identify do |b|
75
+ b.units unit if unit
76
+ b.format "%x %y"
77
+ end
78
+ output.split(" ").map(&:to_i)
79
+ end
80
+
81
+ def raw_exif(value)
82
+ self["%[#{value}]"]
83
+ end
84
+
85
+ def exif
86
+ @info["exif"] ||= (
87
+ hash = {}
88
+ output = self["%[EXIF:*]"]
89
+
90
+ output.each_line do |line|
91
+ line = line.chomp("\n")
92
+
93
+ case MiniMagick.cli
94
+ when :imagemagick, :imagemagick7
95
+ if match = line.match(/^exif:/)
96
+ key, value = match.post_match.split("=", 2)
97
+ value = decode_comma_separated_ascii_characters(value) if ASCII_ENCODED_EXIF_KEYS.include?(key)
98
+ hash[key] = value
99
+ else
100
+ hash[hash.keys.last] << "\n#{line}"
101
+ end
102
+ when :graphicsmagick
103
+ next if line == "unknown"
104
+ key, value = line.split("=", 2)
105
+ value.gsub!("\\012", "\n") # convert "\012" characters to newlines
106
+ hash[key] = value
107
+ end
108
+ end
109
+
110
+ hash
111
+ )
112
+ end
113
+
114
+ def raw(value)
115
+ @info["raw:#{value}"] ||= identify { |b| b.format(value) }
116
+ end
117
+
118
+ def signature
119
+ @info["signature"] ||= self["%#"]
120
+ end
121
+
122
+ def details
123
+ warn "[MiniMagick] MiniMagick::Image#details has been deprecated, as it was causing too many parsing errors. You should use MiniMagick::Image#data instead, which differs in a way that the keys are in camelcase." if MiniMagick.imagemagick? || MiniMagick.imagemagick7?
124
+
125
+ @info["details"] ||= (
126
+ details_string = identify(&:verbose)
127
+ key_stack = []
128
+ details_string.lines.to_a[1..-1].each_with_object({}) do |line, details_hash|
129
+ next if !line.valid_encoding? || line.strip.length.zero?
130
+
131
+ level = line[/^\s*/].length / 2 - 1
132
+ if level >= 0
133
+ key_stack.pop until key_stack.size <= level
134
+ else
135
+ # Some metadata, such as SVG clipping paths, will be saved without
136
+ # indentation, resulting in a level of -1
137
+ last_key = details_hash.keys.last
138
+ details_hash[last_key] = '' if details_hash[last_key].empty?
139
+ details_hash[last_key] << line
140
+ next
141
+ end
142
+
143
+ key, _, value = line.partition(/:[\s]/).map(&:strip)
144
+ hash = key_stack.inject(details_hash) { |_hash, _key| _hash.fetch(_key) }
145
+ if value.empty?
146
+ hash[key] = {}
147
+ key_stack.push key
148
+ else
149
+ hash[key] = value
150
+ end
151
+ end
152
+ )
153
+ end
154
+
155
+ def data
156
+ raise Error, "MiniMagick::Image#data isn't supported on GraphicsMagick. Use MiniMagick::Image#details instead." if MiniMagick.graphicsmagick?
157
+
158
+ @info["data"] ||= (
159
+ json = MiniMagick::Tool::Convert.new do |convert|
160
+ convert << path
161
+ convert << "json:"
162
+ end
163
+
164
+ data = JSON.parse(json)
165
+ data = data.fetch(0) if data.is_a?(Array)
166
+ data.fetch("image")
167
+ )
168
+ end
169
+
170
+ def identify
171
+ MiniMagick::Tool::Identify.new do |builder|
172
+ yield builder if block_given?
173
+ builder << path
174
+ end
175
+ end
176
+
177
+ private
178
+
179
+ def decode_comma_separated_ascii_characters(encoded_value)
180
+ return encoded_value unless encoded_value.include?(',')
181
+ encoded_value.scan(/\d+/).map(&:to_i).map(&:chr).join
182
+ end
183
+
184
+ def path
185
+ value = @path
186
+ value += "[0]" unless value =~ /\[\d+\]$/
187
+ value
188
+ end
189
+
190
+ end
191
+ end
192
+ end