mini_magick 4.0.0.rc → 4.0.0
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.
Potentially problematic release.
This version of mini_magick might be problematic. Click here for more details.
- checksums.yaml +4 -4
- data/lib/mini_magick/image.rb +26 -0
- data/lib/mini_magick/image/info.rb +24 -6
- data/lib/mini_magick/shell.rb +2 -0
- data/lib/mini_magick/tool.rb +47 -30
- data/lib/mini_magick/tool/animate.rb +2 -2
- data/lib/mini_magick/tool/compare.rb +2 -2
- data/lib/mini_magick/tool/composite.rb +2 -2
- data/lib/mini_magick/tool/conjure.rb +2 -2
- data/lib/mini_magick/tool/convert.rb +2 -2
- data/lib/mini_magick/tool/display.rb +2 -2
- data/lib/mini_magick/tool/identify.rb +2 -2
- data/lib/mini_magick/tool/import.rb +2 -2
- data/lib/mini_magick/tool/mogrify.rb +2 -2
- data/lib/mini_magick/tool/montage.rb +2 -2
- data/lib/mini_magick/tool/stream.rb +2 -2
- data/lib/mini_magick/version.rb +1 -1
- data/spec/fixtures/exif.jpg +0 -0
- data/spec/lib/mini_magick/image_spec.rb +63 -10
- data/spec/lib/mini_magick/shell_spec.rb +6 -6
- data/spec/lib/mini_magick/tool_spec.rb +21 -4
- metadata +4 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 65e1d54473e9a429c269d44123e8a6977bf489fe
|
4
|
+
data.tar.gz: 7b2b4762e6ee9d6d47ade148b65df993c3b9e08e
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 4852bcf9522da52f7603a2ef96635312b91fef2e72dbcaa77dbec94dddd8e949e4c34d3e6ccc3da8588e42efe6c43b01cace0166d840f40c478966252f0390d0
|
7
|
+
data.tar.gz: 77bd9eac7c1a015ad7e6cc6de77657a210fc6b7bbb907928aafb08a0bb0b0c237e85a2ca4cd7ecd75cdfda7b55732352ebda096f46adb699ea62b52695385feb
|
data/lib/mini_magick/image.rb
CHANGED
@@ -149,6 +149,16 @@ module MiniMagick
|
|
149
149
|
combine_options(&block) if block
|
150
150
|
end
|
151
151
|
|
152
|
+
def eql?(other)
|
153
|
+
self.class.equal?(other.class) &&
|
154
|
+
signature == other.signature
|
155
|
+
end
|
156
|
+
alias == eql?
|
157
|
+
|
158
|
+
def hash
|
159
|
+
signature.hash
|
160
|
+
end
|
161
|
+
|
152
162
|
##
|
153
163
|
# Returns raw image data.
|
154
164
|
#
|
@@ -232,6 +242,18 @@ module MiniMagick
|
|
232
242
|
# @return [Array<Integer>]
|
233
243
|
#
|
234
244
|
attribute :resolution
|
245
|
+
##
|
246
|
+
# Returns the message digest of this image as a SHA-256, hexidecimal
|
247
|
+
# encoded string. This signature uniquely identifies the image and is
|
248
|
+
# convenient for determining if an image has been modified or whether two
|
249
|
+
# images are identical.
|
250
|
+
#
|
251
|
+
# @example
|
252
|
+
# image.signature #=> "60a7848c4ca6e36b8e2c5dea632ecdc29e9637791d2c59ebf7a54c0c6a74ef7e"
|
253
|
+
# @see http://www.imagemagick.org/api/signature.php
|
254
|
+
# @return [String]
|
255
|
+
#
|
256
|
+
attribute :signature
|
235
257
|
|
236
258
|
##
|
237
259
|
# Use this method if you want to access raw Identify's format API.
|
@@ -358,6 +380,10 @@ module MiniMagick
|
|
358
380
|
end
|
359
381
|
end
|
360
382
|
|
383
|
+
def respond_to_missing?(method_name, include_private = false)
|
384
|
+
MiniMagick::Tool::Mogrify.new.respond_to?(method_name, include_private)
|
385
|
+
end
|
386
|
+
|
361
387
|
##
|
362
388
|
# Writes the temporary file out to either a file location (by passing in a
|
363
389
|
# String) or by passing in a Stream that you can #write(chunk) to
|
@@ -2,6 +2,7 @@ module MiniMagick
|
|
2
2
|
class Image
|
3
3
|
# @private
|
4
4
|
class Info
|
5
|
+
ASCII_ENCODED_EXIF_KEYS = %w[ExifVersion FlashPixVersion]
|
5
6
|
|
6
7
|
def initialize(path)
|
7
8
|
@path = path
|
@@ -18,6 +19,8 @@ module MiniMagick
|
|
18
19
|
mime_type
|
19
20
|
when "resolution"
|
20
21
|
resolution(*args)
|
22
|
+
when "signature"
|
23
|
+
signature
|
21
24
|
when /^EXIF\:/i
|
22
25
|
raw_exif(value)
|
23
26
|
when "exif"
|
@@ -76,11 +79,11 @@ module MiniMagick
|
|
76
79
|
output = self["%[EXIF:*]"]
|
77
80
|
pairs = output.gsub(/^exif:/, "").split("\n").map { |line| line.split("=") }
|
78
81
|
exif = Hash[pairs].tap do |hash|
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
82
|
+
ASCII_ENCODED_EXIF_KEYS.each do |key|
|
83
|
+
next unless hash.has_key?(key)
|
84
|
+
|
85
|
+
value = hash[key]
|
86
|
+
hash[key] = decode_comma_separated_ascii_characters(value)
|
84
87
|
end
|
85
88
|
end
|
86
89
|
|
@@ -89,7 +92,16 @@ module MiniMagick
|
|
89
92
|
end
|
90
93
|
|
91
94
|
def raw(value)
|
92
|
-
|
95
|
+
key = "raw:#{value}"
|
96
|
+
@info.fetch(key) do
|
97
|
+
@info[key] = identify { |b| b.format(value) }
|
98
|
+
end
|
99
|
+
end
|
100
|
+
|
101
|
+
def signature
|
102
|
+
@info.fetch("signature") do
|
103
|
+
@info["signature"] = self["%#"]
|
104
|
+
end
|
93
105
|
end
|
94
106
|
|
95
107
|
def identify
|
@@ -99,6 +111,12 @@ module MiniMagick
|
|
99
111
|
end
|
100
112
|
end
|
101
113
|
|
114
|
+
def decode_comma_separated_ascii_characters(encoded_value)
|
115
|
+
return encoded_value unless encoded_value.include?(',')
|
116
|
+
|
117
|
+
encoded_value.scan(/\d+/).map(&:to_i).map(&:chr).join
|
118
|
+
end
|
119
|
+
|
102
120
|
end
|
103
121
|
end
|
104
122
|
end
|
data/lib/mini_magick/shell.rb
CHANGED
data/lib/mini_magick/tool.rb
CHANGED
@@ -59,9 +59,16 @@ module MiniMagick
|
|
59
59
|
# @private
|
60
60
|
attr_reader :name, :args
|
61
61
|
|
62
|
-
|
63
|
-
|
64
|
-
|
62
|
+
# @param whiny [Boolean] Whether to raise errors on exit codes different
|
63
|
+
# than 0.
|
64
|
+
# @example
|
65
|
+
# MiniMagick::Tool::Identify.new(false) do |identify|
|
66
|
+
# identify.help # returns exit status 1, which would otherwise throw an error
|
67
|
+
# end
|
68
|
+
def initialize(name, whiny = true)
|
69
|
+
@name = name
|
70
|
+
@whiny = whiny
|
71
|
+
@args = []
|
65
72
|
end
|
66
73
|
|
67
74
|
##
|
@@ -80,7 +87,7 @@ module MiniMagick
|
|
80
87
|
#
|
81
88
|
# @return [String] Output of the command
|
82
89
|
#
|
83
|
-
def call(whiny =
|
90
|
+
def call(whiny = @whiny)
|
84
91
|
shell = MiniMagick::Shell.new(whiny)
|
85
92
|
shell.run(command).strip
|
86
93
|
end
|
@@ -128,6 +135,16 @@ module MiniMagick
|
|
128
135
|
self
|
129
136
|
end
|
130
137
|
|
138
|
+
##
|
139
|
+
# Merges a list of raw options.
|
140
|
+
#
|
141
|
+
# @return [self]
|
142
|
+
#
|
143
|
+
def merge!(new_args)
|
144
|
+
new_args.each { |arg| self << arg }
|
145
|
+
self
|
146
|
+
end
|
147
|
+
|
131
148
|
##
|
132
149
|
# Changes the last operator to its "plus" form.
|
133
150
|
#
|
@@ -139,9 +156,9 @@ module MiniMagick
|
|
139
156
|
#
|
140
157
|
# @return [self]
|
141
158
|
#
|
142
|
-
def +(
|
143
|
-
args.
|
144
|
-
|
159
|
+
def +(*values)
|
160
|
+
args[-1] = args[-1].sub(/^-/, '+')
|
161
|
+
self.merge!(values)
|
145
162
|
self
|
146
163
|
end
|
147
164
|
|
@@ -155,23 +172,20 @@ module MiniMagick
|
|
155
172
|
#
|
156
173
|
# @private
|
157
174
|
#
|
158
|
-
class OptionMethods < Module
|
175
|
+
class OptionMethods < Module # think about it for a minute
|
159
176
|
|
160
177
|
def self.instances
|
161
178
|
@instances ||= []
|
162
179
|
end
|
163
180
|
|
164
|
-
def
|
165
|
-
|
166
|
-
|
167
|
-
|
181
|
+
def initialize(tool_name)
|
182
|
+
@tool_name = tool_name
|
183
|
+
reload_methods
|
184
|
+
self.class.instances << self
|
168
185
|
end
|
169
186
|
|
170
|
-
def
|
171
|
-
|
172
|
-
@tool_name = tool_name
|
173
|
-
reload_methods
|
174
|
-
end
|
187
|
+
def to_s
|
188
|
+
"OptionMethods(#{@tool_name})"
|
175
189
|
end
|
176
190
|
|
177
191
|
##
|
@@ -179,15 +193,12 @@ module MiniMagick
|
|
179
193
|
#
|
180
194
|
def reload_methods
|
181
195
|
instance_methods(false).each { |method| undef_method(method) }
|
182
|
-
|
183
|
-
|
184
|
-
plasma tile pattern label caption text]
|
185
|
-
|
186
|
-
help = (MiniMagick::Tool.new(@tool_name) << "-help").call(false)
|
187
|
-
cli_options = help.scan(/^\s+-[a-z\-]+/).map(&:strip)
|
188
|
-
self.option *cli_options
|
196
|
+
creation_operator *creation_operators
|
197
|
+
option *cli_options
|
189
198
|
end
|
190
199
|
|
200
|
+
private
|
201
|
+
|
191
202
|
##
|
192
203
|
# Creates method based on command-line option's name.
|
193
204
|
#
|
@@ -199,10 +210,10 @@ module MiniMagick
|
|
199
210
|
#
|
200
211
|
def option(*options)
|
201
212
|
options.each do |option|
|
202
|
-
define_method(option[1..-1].gsub('-', '_')) do |
|
203
|
-
|
204
|
-
|
205
|
-
|
213
|
+
define_method(option[1..-1].gsub('-', '_')) do |*values|
|
214
|
+
self << option
|
215
|
+
self.merge!(values)
|
216
|
+
self
|
206
217
|
end
|
207
218
|
end
|
208
219
|
end
|
@@ -223,8 +234,14 @@ module MiniMagick
|
|
223
234
|
end
|
224
235
|
end
|
225
236
|
|
226
|
-
def
|
227
|
-
|
237
|
+
def creation_operators
|
238
|
+
%w[xc canvas logo rose gradient radial-gradient
|
239
|
+
plasma tile pattern label caption text]
|
240
|
+
end
|
241
|
+
|
242
|
+
def cli_options
|
243
|
+
help = MiniMagick::Tool.new(@tool_name, false) { |b| b << "-help" }
|
244
|
+
cli_options = help.scan(/^\s+-[a-z\-]+/).map(&:strip)
|
228
245
|
end
|
229
246
|
|
230
247
|
end
|
data/lib/mini_magick/version.rb
CHANGED
data/spec/fixtures/exif.jpg
CHANGED
Binary file
|
@@ -119,6 +119,35 @@ require "stringio"
|
|
119
119
|
end
|
120
120
|
end
|
121
121
|
|
122
|
+
describe "equivalence" do
|
123
|
+
subject(:image) { described_class.new(image_path) }
|
124
|
+
let(:same_image) { described_class.new(image_path) }
|
125
|
+
let(:other_image) { described_class.new(image_path(:exif)) }
|
126
|
+
|
127
|
+
it "is #== and #eql? to itself" do
|
128
|
+
expect(image).to eq(image)
|
129
|
+
expect(image).to eql(image)
|
130
|
+
end
|
131
|
+
|
132
|
+
it "is #== and #eql? to an instance of the same image" do
|
133
|
+
expect(image).to eq(same_image)
|
134
|
+
expect(image).to eql(same_image)
|
135
|
+
end
|
136
|
+
|
137
|
+
it "is not #== nor #eql? to an instance of a different image" do
|
138
|
+
expect(image).not_to eq(other_image)
|
139
|
+
expect(image).not_to eql(other_image)
|
140
|
+
end
|
141
|
+
|
142
|
+
it "generates the same hash code for an instance of the same image" do
|
143
|
+
expect(image.hash).to eq(same_image.hash)
|
144
|
+
end
|
145
|
+
|
146
|
+
it "generates different same hash codes for a different image" do
|
147
|
+
expect(image.hash).not_to eq(other_image.hash)
|
148
|
+
end
|
149
|
+
end
|
150
|
+
|
122
151
|
describe "#format" do
|
123
152
|
subject { described_class.open(image_path(:jpg)) }
|
124
153
|
|
@@ -225,6 +254,7 @@ require "stringio"
|
|
225
254
|
expect(subject[:dimensions]).to all(be_a(Fixnum))
|
226
255
|
expect(subject[:colorspace]).to be_a(String)
|
227
256
|
expect(subject[:format]).to match(/[A-Z]/)
|
257
|
+
expect(subject[:signature]).to match(/[[:alnum:]]{64}/)
|
228
258
|
end
|
229
259
|
|
230
260
|
it "supports string keys" do
|
@@ -233,11 +263,17 @@ require "stringio"
|
|
233
263
|
expect(subject["dimensions"]).to all(be_a(Fixnum))
|
234
264
|
expect(subject["colorspace"]).to be_a(String)
|
235
265
|
expect(subject["format"]).to match(/[A-Z]/)
|
266
|
+
expect(subject['signature']).to match(/[[:alnum:]]{64}/)
|
236
267
|
end
|
237
268
|
|
238
269
|
it "reads exif" do
|
239
270
|
subject = described_class.new(image_path(:exif))
|
271
|
+
gps_latitude = subject.exif["GPSLatitude"].split(/\s*,\s*/)
|
272
|
+
gps_longitude = subject.exif["GPSLongitude"].split(/\s*,\s*/)
|
273
|
+
|
240
274
|
expect(subject["EXIF:ColorSpace"]).to eq "1"
|
275
|
+
expect(gps_latitude.size).to eq 3
|
276
|
+
expect(gps_longitude.size).to eq 3
|
241
277
|
end
|
242
278
|
|
243
279
|
it "passes unknown values directly to -format" do
|
@@ -254,6 +290,7 @@ require "stringio"
|
|
254
290
|
expect(subject.size).to be_a(Fixnum).and be_nonzero
|
255
291
|
expect(subject.colorspace).to be_a(String)
|
256
292
|
expect(subject.resolution).to all(be_a(Fixnum))
|
293
|
+
expect(subject.signature).to match(/[[:alnum:]]{64}/)
|
257
294
|
end
|
258
295
|
|
259
296
|
describe "#exif" do
|
@@ -262,6 +299,10 @@ require "stringio"
|
|
262
299
|
it "returns a hash of EXIF data" do
|
263
300
|
expect(subject.exif["DateTimeOriginal"]).to be_a(String)
|
264
301
|
end
|
302
|
+
|
303
|
+
it "decodes the ExifVersion" do
|
304
|
+
expect(subject.exif["ExifVersion"]).to eq("0221")
|
305
|
+
end
|
265
306
|
end
|
266
307
|
|
267
308
|
describe "#resolution" do
|
@@ -299,19 +340,31 @@ require "stringio"
|
|
299
340
|
end
|
300
341
|
end
|
301
342
|
|
302
|
-
describe "
|
303
|
-
|
304
|
-
|
305
|
-
|
306
|
-
|
343
|
+
describe "missing methods" do
|
344
|
+
context "for a known method" do
|
345
|
+
it "is executed by #method_missing" do
|
346
|
+
expect { subject.resize '20x30!' }
|
347
|
+
.to change { subject.dimensions }.to [20, 30]
|
348
|
+
end
|
349
|
+
|
350
|
+
it "returns self" do
|
351
|
+
expect(subject.resize('20x30!')).to eq subject
|
352
|
+
end
|
307
353
|
|
308
|
-
|
309
|
-
|
310
|
-
|
354
|
+
it "can be responed to" do
|
355
|
+
expect(subject.respond_to?(:resize)).to eq true
|
356
|
+
end
|
311
357
|
end
|
312
358
|
|
313
|
-
|
314
|
-
|
359
|
+
context "for an unknown method" do
|
360
|
+
it "fails with a NoMethodError" do
|
361
|
+
expect { subject.foo }
|
362
|
+
.to raise_error(NoMethodError, /MiniMagick::Image/)
|
363
|
+
end
|
364
|
+
|
365
|
+
it "cannot be responded to" do
|
366
|
+
expect(subject.respond_to?(:foo)).to eq false
|
367
|
+
end
|
315
368
|
end
|
316
369
|
end
|
317
370
|
|
@@ -32,6 +32,12 @@ RSpec.describe MiniMagick::Shell do
|
|
32
32
|
allow(subject).to receive(:execute).and_return(["stdout", "", 127])
|
33
33
|
expect(subject.run(%W[foo])).to eq "stdout"
|
34
34
|
end
|
35
|
+
|
36
|
+
it "prints to stderr output to $stderr in non-whiny mode" do
|
37
|
+
subject = described_class.new(false)
|
38
|
+
allow(subject).to receive(:execute).and_return(["", "stderr", 1])
|
39
|
+
expect { subject.run(%W[foo]) }.to output("stderr").to_stderr
|
40
|
+
end
|
35
41
|
end
|
36
42
|
|
37
43
|
describe "#execute" do
|
@@ -40,12 +46,6 @@ RSpec.describe MiniMagick::Shell do
|
|
40
46
|
expect(stdout).to match("GIF")
|
41
47
|
end
|
42
48
|
|
43
|
-
it "timeouts afer a period of time" do
|
44
|
-
allow(MiniMagick).to receive(:timeout).and_return(0.001)
|
45
|
-
expect { subject.execute(%W[identify -format %[EXIF:*] #{image_path(:exif)}]) }
|
46
|
-
.to raise_error(Timeout::Error)
|
47
|
-
end
|
48
|
-
|
49
49
|
it "logs the command and execution time in debug mode" do
|
50
50
|
allow(MiniMagick).to receive(:debug).and_return(true)
|
51
51
|
expect { subject.execute(%W[identify #{image_path(:gif)}]) }.
|
@@ -48,16 +48,26 @@ RSpec.describe MiniMagick::Tool do
|
|
48
48
|
|
49
49
|
describe "#<<" do
|
50
50
|
it "adds argument to the args list" do
|
51
|
-
subject << "foo" << "bar"
|
52
|
-
expect(subject.args).to eq %W[foo bar]
|
51
|
+
subject << "foo" << "bar" << 123
|
52
|
+
expect(subject.args).to eq %W[foo bar 123]
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
describe "#merge!" do
|
57
|
+
it "adds arguments to the args list" do
|
58
|
+
subject << "pre-existing"
|
59
|
+
subject.merge! ["foo", 123]
|
60
|
+
expect(subject.args).to eq %W[pre-existing foo 123]
|
53
61
|
end
|
54
62
|
end
|
55
63
|
|
56
64
|
describe "#+" do
|
57
65
|
it "switches the last option to + form" do
|
66
|
+
subject.help
|
58
67
|
subject.help.+
|
59
|
-
subject.debug.+
|
60
|
-
|
68
|
+
subject.debug.+ "foo"
|
69
|
+
subject.debug.+ 8, "bar"
|
70
|
+
expect(subject.args).to eq %W[-help +help +debug foo +debug 8 bar]
|
61
71
|
end
|
62
72
|
end
|
63
73
|
|
@@ -87,4 +97,11 @@ RSpec.describe MiniMagick::Tool do
|
|
87
97
|
expect(subject).not_to respond_to(:quiet)
|
88
98
|
expect(subject).to respond_to(:ping)
|
89
99
|
end
|
100
|
+
|
101
|
+
it "doesn't raise errors when false is passed to the constructor" do
|
102
|
+
subject.help
|
103
|
+
subject.call(false)
|
104
|
+
|
105
|
+
MiniMagick::Tool::Identify.new(false, &:help)
|
106
|
+
end
|
90
107
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: mini_magick
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 4.0.0
|
4
|
+
version: 4.0.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Corey Johnson
|
@@ -12,7 +12,7 @@ authors:
|
|
12
12
|
autorequire:
|
13
13
|
bindir: bin
|
14
14
|
cert_chain: []
|
15
|
-
date: 2014-
|
15
|
+
date: 2014-11-14 00:00:00.000000000 Z
|
16
16
|
dependencies:
|
17
17
|
- !ruby/object:Gem::Dependency
|
18
18
|
name: rake
|
@@ -104,9 +104,9 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
104
104
|
version: '0'
|
105
105
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
106
106
|
requirements:
|
107
|
-
- - "
|
107
|
+
- - ">="
|
108
108
|
- !ruby/object:Gem::Version
|
109
|
-
version:
|
109
|
+
version: '0'
|
110
110
|
requirements:
|
111
111
|
- You must have ImageMagick or GraphicsMagick installed
|
112
112
|
rubyforge_project:
|