mini_magick 3.8.0 → 3.8.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.
Potentially problematic release.
This version of mini_magick might be problematic. Click here for more details.
- checksums.yaml +4 -4
- data/lib/mini_magick.rb +12 -26
- data/lib/mini_magick/command_builder.rb +6 -22
- data/lib/mini_magick/image.rb +121 -102
- data/lib/mini_magick/utilities.rb +26 -0
- data/lib/mini_magick/version.rb +15 -1
- data/spec/files/actually_a_gif.jpg +0 -0
- data/spec/files/animation.gif +0 -0
- data/spec/files/composited.jpg +0 -0
- data/spec/files/erroneous.jpg +0 -0
- data/spec/files/layers.psd +0 -0
- data/spec/files/leaves (spaced).tiff +0 -0
- data/spec/files/not_an_image.php +1 -0
- data/spec/files/png.png +0 -0
- data/spec/files/simple-minus.gif +0 -0
- data/spec/files/simple.gif +0 -0
- data/spec/files/trogdor.jpg +0 -0
- data/spec/files/trogdor_capitalized.JPG +0 -0
- data/spec/lib/mini_magick/command_builder_spec.rb +153 -0
- data/spec/lib/mini_magick/image_spec.rb +499 -0
- data/spec/lib/mini_magick_spec.rb +63 -0
- data/spec/spec_helper.rb +29 -0
- metadata +40 -8
@@ -1,4 +1,6 @@
|
|
1
1
|
require 'rbconfig'
|
2
|
+
require 'shellwords'
|
3
|
+
require 'pathname'
|
2
4
|
|
3
5
|
module MiniMagick
|
4
6
|
module Utilities
|
@@ -22,6 +24,18 @@ module MiniMagick
|
|
22
24
|
RbConfig::CONFIG['host_os'] =~ /mswin|mingw|cygwin/
|
23
25
|
end
|
24
26
|
|
27
|
+
def escape(value)
|
28
|
+
if windows?
|
29
|
+
windows_escape(value)
|
30
|
+
else
|
31
|
+
shell_escape(value)
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
def shell_escape(value)
|
36
|
+
Shellwords.escape(value)
|
37
|
+
end
|
38
|
+
|
25
39
|
def windows_escape(value)
|
26
40
|
# For Windows, ^ is the escape char, equivalent to \ in Unix.
|
27
41
|
escaped = value.gsub(/\^/, '^^').gsub(/>/, '^>')
|
@@ -31,6 +45,18 @@ module MiniMagick
|
|
31
45
|
escaped
|
32
46
|
end
|
33
47
|
end
|
48
|
+
|
49
|
+
def path(path)
|
50
|
+
if windows?
|
51
|
+
# For Windows, if a path contains space char, you need to quote it,
|
52
|
+
# otherwise you SHOULD NOT quote it. If you quote a path that does
|
53
|
+
# not contains space, it will not work.
|
54
|
+
pathname = Pathname.new(path).to_s
|
55
|
+
path.include?(' ') ? pathname.inspect : pathname
|
56
|
+
else
|
57
|
+
path
|
58
|
+
end
|
59
|
+
end
|
34
60
|
end
|
35
61
|
end
|
36
62
|
end
|
data/lib/mini_magick/version.rb
CHANGED
@@ -1,3 +1,17 @@
|
|
1
1
|
module MiniMagick
|
2
|
-
|
2
|
+
##
|
3
|
+
# Returns the version of the currently loaded MiniMagick as
|
4
|
+
# a <tt>Gem::Version</tt>.
|
5
|
+
def self.version
|
6
|
+
Gem::Version.new VERSION::STRING
|
7
|
+
end
|
8
|
+
|
9
|
+
module VERSION
|
10
|
+
MAJOR = 3
|
11
|
+
MINOR = 8
|
12
|
+
TINY = 1
|
13
|
+
PRE = nil
|
14
|
+
|
15
|
+
STRING = [MAJOR, MINOR, TINY, PRE].compact.join('.')
|
16
|
+
end
|
3
17
|
end
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
@@ -0,0 +1 @@
|
|
1
|
+
<?php I am so not an image ?>
|
data/spec/files/png.png
ADDED
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
@@ -0,0 +1,153 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
# All tests tagged as `ported` are ported from
|
4
|
+
# testunit tests and are there for backwards compatibility
|
5
|
+
|
6
|
+
MiniMagick.processor = :mogrify
|
7
|
+
|
8
|
+
describe MiniMagick::CommandBuilder do
|
9
|
+
before do
|
10
|
+
@processor = MiniMagick.processor
|
11
|
+
@processor_path = MiniMagick.processor_path
|
12
|
+
end
|
13
|
+
|
14
|
+
after do
|
15
|
+
MiniMagick.processor_path = @processor_path
|
16
|
+
MiniMagick.processor = @processor
|
17
|
+
end
|
18
|
+
|
19
|
+
describe 'ported from testunit', :ported => true do
|
20
|
+
let(:builder) { described_class.new('test') }
|
21
|
+
|
22
|
+
it 'builds a basic command' do
|
23
|
+
builder.resize '30x40'
|
24
|
+
expect(builder.args.join(' ')).to eq '-resize 30x40'
|
25
|
+
end
|
26
|
+
|
27
|
+
it 'builds a full command' do
|
28
|
+
builder.resize '30x40'
|
29
|
+
expect(builder.command).to eq 'test -resize 30x40'
|
30
|
+
end
|
31
|
+
|
32
|
+
describe 'windows only', :if => MiniMagick::Utilities.windows? do
|
33
|
+
it 'builds a complicated command' do
|
34
|
+
builder.resize '30x40'
|
35
|
+
builder.alpha '1 3 4'
|
36
|
+
builder.resize 'mome fingo'
|
37
|
+
expect(builder.args.join(' ')).to eq '-resize 30x40 -alpha 1 3 4 -resize mome fingo'
|
38
|
+
end
|
39
|
+
|
40
|
+
it 'builds a command with multiple options and plus modifier' do
|
41
|
+
builder.distort.+ 'srt', '0.6 20'
|
42
|
+
expect(builder.args.join(' ')).to eq '+distort srt 0.6 20'
|
43
|
+
end
|
44
|
+
|
45
|
+
it 'sets a colorspace correctly' do
|
46
|
+
builder.set 'colorspace RGB'
|
47
|
+
expect(builder.command).to eq 'test -set colorspace RGB'
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
describe 'not windows', :if => !MiniMagick::Utilities.windows? do
|
52
|
+
it 'builds a complicated command' do
|
53
|
+
builder.resize '30x40'
|
54
|
+
builder.alpha '1 3 4'
|
55
|
+
builder.resize 'mome fingo'
|
56
|
+
expect(builder.args.join(' ')).to eq '-resize 30x40 -alpha 1\ 3\ 4 -resize mome\ fingo'
|
57
|
+
end
|
58
|
+
|
59
|
+
it 'sets a colorspace correctly' do
|
60
|
+
builder.set 'colorspace RGB'
|
61
|
+
expect(builder.command).to eq 'test -set colorspace\ RGB'
|
62
|
+
end
|
63
|
+
|
64
|
+
it 'builds a command with multiple options and plus modifier' do
|
65
|
+
builder.distort.+ 'srt', '0.6 20'
|
66
|
+
expect(builder.args.join(' ')).to eq '\+distort srt 0.6\ 20'
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
describe 'common verbs between morgify and image creation operators' do
|
71
|
+
context 'mogrify' do
|
72
|
+
let(:builder) { described_class.new('mogrify') }
|
73
|
+
|
74
|
+
it 'builds the command' do
|
75
|
+
builder.caption 'caption_text'
|
76
|
+
expect(builder.command).to eq 'mogrify -caption caption_text'
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
context 'other' do
|
81
|
+
it 'builds the command' do
|
82
|
+
builder.caption 'caption_text'
|
83
|
+
expect(builder.command).to eq 'test caption:caption_text'
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
it 'raises error when command is invalid' do
|
89
|
+
expect {
|
90
|
+
command = described_class.new('test', 'path')
|
91
|
+
command.input 2
|
92
|
+
}.to raise_error
|
93
|
+
end
|
94
|
+
|
95
|
+
it 'builds a dashed command' do
|
96
|
+
builder.auto_orient
|
97
|
+
expect(builder.args.join(' ')).to eq '-auto-orient'
|
98
|
+
end
|
99
|
+
|
100
|
+
it 'builds a dashed command via send' do
|
101
|
+
builder.send('auto-orient')
|
102
|
+
expect(builder.args.join(' ')).to eq '-auto-orient'
|
103
|
+
end
|
104
|
+
|
105
|
+
it 'builds a canvas command' do
|
106
|
+
builder.canvas 'black'
|
107
|
+
expect(builder.args.join(' ')).to eq 'canvas:black'
|
108
|
+
end
|
109
|
+
|
110
|
+
it 'sets a processor path correctly' do
|
111
|
+
MiniMagick.processor_path = '/a/strange/path'
|
112
|
+
builder.auto_orient
|
113
|
+
expect(builder.command).to eq '/a/strange/path/test -auto-orient'
|
114
|
+
end
|
115
|
+
|
116
|
+
it 'builds a processor path with processor' do
|
117
|
+
MiniMagick.processor_path = '/a/strange/path'
|
118
|
+
MiniMagick.processor = 'processor'
|
119
|
+
builder.auto_orient
|
120
|
+
expect(builder.command).to eq '/a/strange/path/processor test -auto-orient'
|
121
|
+
end
|
122
|
+
end
|
123
|
+
|
124
|
+
describe 'deprecated' do
|
125
|
+
let(:builder) { described_class.new('test') }
|
126
|
+
before { MiniMagick.processor = nil }
|
127
|
+
|
128
|
+
it 'builds a full command' do
|
129
|
+
builder.resize '30x40'
|
130
|
+
expect(builder.command).to eq 'test -resize 30x40'
|
131
|
+
end
|
132
|
+
|
133
|
+
context 'windows only', :if => MiniMagick::Utilities.windows? do
|
134
|
+
it 'sets a colorspace correctly' do
|
135
|
+
builder.set 'colorspace RGB'
|
136
|
+
expect(builder.command).to eq 'test -set colorspace RGB'
|
137
|
+
end
|
138
|
+
end
|
139
|
+
|
140
|
+
context 'not windows', :if => !MiniMagick::Utilities.windows? do
|
141
|
+
it 'sets a colorspace correctly' do
|
142
|
+
builder.set 'colorspace RGB'
|
143
|
+
expect(builder.command).to eq 'test -set colorspace\ RGB'
|
144
|
+
end
|
145
|
+
end
|
146
|
+
|
147
|
+
it 'sets a processor path correctly' do
|
148
|
+
MiniMagick.processor_path = '/a/strange/path'
|
149
|
+
builder.auto_orient
|
150
|
+
expect(builder.command).to eq '/a/strange/path/test -auto-orient'
|
151
|
+
end
|
152
|
+
end
|
153
|
+
end
|
@@ -0,0 +1,499 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'pathname'
|
3
|
+
require 'tempfile'
|
4
|
+
|
5
|
+
MiniMagick.processor = :mogrify
|
6
|
+
|
7
|
+
describe MiniMagick::Image do
|
8
|
+
context 'when ImageMagick and GraphicsMagick are both unavailable' do
|
9
|
+
before do
|
10
|
+
MiniMagick::Utilities.expects(:which).at_least_once.returns(nil)
|
11
|
+
MiniMagick.instance_variable_set(:@processor, nil)
|
12
|
+
@old_path = ENV['PATH']
|
13
|
+
ENV['PATH'] = ''
|
14
|
+
end
|
15
|
+
|
16
|
+
after do
|
17
|
+
ENV['PATH'] = @old_path
|
18
|
+
end
|
19
|
+
|
20
|
+
it "raises an exception with 'No such file' in the message" do
|
21
|
+
begin
|
22
|
+
described_class.open(SIMPLE_IMAGE_PATH)
|
23
|
+
rescue => e
|
24
|
+
expect(e.message).to match(/(No such file|not found)/)
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
describe 'ported from testunit', :ported => true do
|
30
|
+
it 'reads image from blob' do
|
31
|
+
File.open(SIMPLE_IMAGE_PATH, 'rb') do |f|
|
32
|
+
image = described_class.read(f.read)
|
33
|
+
expect(image).to be_valid
|
34
|
+
image.destroy!
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
it 'reads image from tempfile', :if => !MiniMagick::Utilities.windows? do
|
39
|
+
tempfile = Tempfile.new('magick')
|
40
|
+
|
41
|
+
File.open(SIMPLE_IMAGE_PATH, 'rb') do |f|
|
42
|
+
tempfile.write(f.read)
|
43
|
+
tempfile.rewind
|
44
|
+
end
|
45
|
+
|
46
|
+
image = described_class.read(tempfile)
|
47
|
+
expect(image).to be_valid
|
48
|
+
image.destroy!
|
49
|
+
end
|
50
|
+
|
51
|
+
# from https://github.com/minimagick/minimagick/issues/163
|
52
|
+
it 'annotates image with whitespace' do
|
53
|
+
image = described_class.open(SIMPLE_IMAGE_PATH)
|
54
|
+
|
55
|
+
expect {
|
56
|
+
message = 'a b'
|
57
|
+
|
58
|
+
image.combine_options do |c|
|
59
|
+
c.gravity 'SouthWest'
|
60
|
+
c.fill 'white'
|
61
|
+
c.stroke 'black'
|
62
|
+
c.strokewidth '2'
|
63
|
+
c.pointsize '48'
|
64
|
+
c.interline_spacing '-9'
|
65
|
+
c.annotate '0', message
|
66
|
+
end
|
67
|
+
}.to_not raise_error
|
68
|
+
end
|
69
|
+
|
70
|
+
it 'opens image' do
|
71
|
+
image = described_class.open(SIMPLE_IMAGE_PATH)
|
72
|
+
expect(image).to be_valid
|
73
|
+
image.destroy!
|
74
|
+
end
|
75
|
+
|
76
|
+
it 'reads image from buffer' do
|
77
|
+
buffer = StringIO.new File.open(SIMPLE_IMAGE_PATH, 'rb') { |f| f.read }
|
78
|
+
image = described_class.read(buffer)
|
79
|
+
expect(image).to be_valid
|
80
|
+
image.destroy!
|
81
|
+
end
|
82
|
+
|
83
|
+
describe '.create' do
|
84
|
+
subject(:create) do
|
85
|
+
described_class.create do |f|
|
86
|
+
# Had to replace the old File.read with the following to work across all platforms
|
87
|
+
f.write(File.open(SIMPLE_IMAGE_PATH, 'rb') { |fi| fi.read })
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
it 'creates an image' do
|
92
|
+
expect {
|
93
|
+
image = create
|
94
|
+
image.destroy!
|
95
|
+
}.to_not raise_error
|
96
|
+
end
|
97
|
+
|
98
|
+
describe 'validation' do
|
99
|
+
before do
|
100
|
+
@old_validate = MiniMagick.validate_on_create
|
101
|
+
MiniMagick.validate_on_create = validate
|
102
|
+
end
|
103
|
+
|
104
|
+
context 'MiniMagick.validate_on_create = true' do
|
105
|
+
let(:validate) { true }
|
106
|
+
|
107
|
+
it 'validates image' do
|
108
|
+
described_class.any_instance.expects(:valid?).returns(true)
|
109
|
+
create
|
110
|
+
end
|
111
|
+
end
|
112
|
+
|
113
|
+
context 'MiniMagick.validate_on_create = false' do
|
114
|
+
let(:validate) { false }
|
115
|
+
|
116
|
+
it 'skips validation' do
|
117
|
+
described_class.any_instance.expects(:valid?).never
|
118
|
+
create
|
119
|
+
end
|
120
|
+
end
|
121
|
+
|
122
|
+
after { MiniMagick.validate_on_create = @old_validate }
|
123
|
+
end
|
124
|
+
end
|
125
|
+
|
126
|
+
it 'loads a new image' do
|
127
|
+
expect {
|
128
|
+
image = described_class.new(SIMPLE_IMAGE_PATH)
|
129
|
+
image.destroy!
|
130
|
+
}.to_not raise_error
|
131
|
+
end
|
132
|
+
|
133
|
+
it 'loads remote image' do
|
134
|
+
image = described_class.open('http://upload.wikimedia.org/wikipedia/en/b/bc/Wiki.png')
|
135
|
+
expect(image).to be_valid
|
136
|
+
image.destroy!
|
137
|
+
end
|
138
|
+
|
139
|
+
it 'loads remote image with complex url' do
|
140
|
+
image = described_class.open(
|
141
|
+
'http://a0.twimg.com/a/1296609216/images/fronts/logo_withbird_home.png?extra=foo&plus=bar'
|
142
|
+
)
|
143
|
+
expect(image).to be_valid
|
144
|
+
image.destroy!
|
145
|
+
end
|
146
|
+
|
147
|
+
it 'reformats an image with a given extension' do
|
148
|
+
expect {
|
149
|
+
image = described_class.open(CAP_EXT_PATH)
|
150
|
+
image.format 'jpg'
|
151
|
+
}.to_not raise_error
|
152
|
+
end
|
153
|
+
|
154
|
+
describe '#write' do
|
155
|
+
it 'reformats a PSD with a given a extension and all layers' do
|
156
|
+
expect {
|
157
|
+
image = described_class.open(PSD_IMAGE_PATH)
|
158
|
+
image.format('jpg', nil)
|
159
|
+
}.to_not raise_error
|
160
|
+
end
|
161
|
+
|
162
|
+
it 'opens and writes an image' do
|
163
|
+
output_path = 'output.gif'
|
164
|
+
begin
|
165
|
+
image = described_class.new(SIMPLE_IMAGE_PATH)
|
166
|
+
image.write output_path
|
167
|
+
expect(File.exist?(output_path)).to be(true)
|
168
|
+
ensure
|
169
|
+
File.delete output_path
|
170
|
+
end
|
171
|
+
image.destroy!
|
172
|
+
end
|
173
|
+
|
174
|
+
it 'opens and writes an image with space in its filename' do
|
175
|
+
output_path = 'test output.gif'
|
176
|
+
begin
|
177
|
+
image = described_class.new(SIMPLE_IMAGE_PATH)
|
178
|
+
image.write output_path
|
179
|
+
|
180
|
+
expect(File.exist?(output_path)).to be(true)
|
181
|
+
ensure
|
182
|
+
File.delete output_path
|
183
|
+
end
|
184
|
+
image.destroy!
|
185
|
+
end
|
186
|
+
|
187
|
+
it 'writes an image with stream' do
|
188
|
+
stream = StringIO.new
|
189
|
+
image = described_class.open(SIMPLE_IMAGE_PATH)
|
190
|
+
image.write("#{Dir.tmpdir}/foo.gif")
|
191
|
+
image.write(stream)
|
192
|
+
expect(described_class.read(stream.string)).to be_valid
|
193
|
+
image.destroy!
|
194
|
+
end
|
195
|
+
|
196
|
+
describe 'validation' do
|
197
|
+
let(:image) { described_class.new(SIMPLE_IMAGE_PATH) }
|
198
|
+
let(:output_path) { 'output.gif' }
|
199
|
+
|
200
|
+
before do
|
201
|
+
@old_validate = MiniMagick.validate_on_write
|
202
|
+
MiniMagick.validate_on_write = validate
|
203
|
+
end
|
204
|
+
|
205
|
+
subject(:write) { image.write output_path }
|
206
|
+
|
207
|
+
context 'MiniMagick.validate_on_write = true' do
|
208
|
+
let(:validate) { true }
|
209
|
+
|
210
|
+
it 'runs post-validation' do
|
211
|
+
image.expects(:run_command).with('identify', output_path)
|
212
|
+
write
|
213
|
+
end
|
214
|
+
end
|
215
|
+
|
216
|
+
context 'MiniMagick.validate_on_write = false' do
|
217
|
+
let(:validate) { false }
|
218
|
+
|
219
|
+
it 'runs post-validation' do
|
220
|
+
image.expects(:run_command).never
|
221
|
+
write
|
222
|
+
end
|
223
|
+
end
|
224
|
+
|
225
|
+
after do
|
226
|
+
image.destroy!
|
227
|
+
File.delete output_path
|
228
|
+
MiniMagick.validate_on_write = @old_validate
|
229
|
+
end
|
230
|
+
end
|
231
|
+
end
|
232
|
+
|
233
|
+
it 'tells when an image is invalid' do
|
234
|
+
image = described_class.new(NOT_AN_IMAGE_PATH)
|
235
|
+
expect(image).not_to be_valid
|
236
|
+
image.destroy!
|
237
|
+
end
|
238
|
+
|
239
|
+
it "raises error when opening a file that isn't an image" do
|
240
|
+
expect {
|
241
|
+
image = described_class.open(NOT_AN_IMAGE_PATH)
|
242
|
+
image.destroy
|
243
|
+
}.to raise_error(MiniMagick::Invalid)
|
244
|
+
end
|
245
|
+
|
246
|
+
it "raises error when imagemagick raised an error during processing" do
|
247
|
+
image = described_class.open(SIMPLE_IMAGE_PATH)
|
248
|
+
image.rotate "invalid_value"
|
249
|
+
expect { image.run_queue }.to raise_error(MiniMagick::Error)
|
250
|
+
end
|
251
|
+
|
252
|
+
it 'inspects image meta info' do
|
253
|
+
image = described_class.new(SIMPLE_IMAGE_PATH)
|
254
|
+
expect(image[:width]).to be(150)
|
255
|
+
expect(image[:height]).to be(55)
|
256
|
+
expect(image[:dimensions]).to match_array [150, 55]
|
257
|
+
expect(image[:colorspace]).to be_an_instance_of(String)
|
258
|
+
expect(image[:format]).to match(/^gif$/i)
|
259
|
+
image.destroy!
|
260
|
+
end
|
261
|
+
|
262
|
+
it 'supports string keys for dimension attributes' do
|
263
|
+
image = described_class.new(SIMPLE_IMAGE_PATH)
|
264
|
+
expect(image["width"]).to be(150)
|
265
|
+
expect(image["height"]).to be(55)
|
266
|
+
expect(image["dimensions"]).to match_array [150, 55]
|
267
|
+
image.destroy!
|
268
|
+
end
|
269
|
+
|
270
|
+
it 'inspects an erroneus image meta info' do
|
271
|
+
image = described_class.new(ERRONEOUS_IMAGE_PATH)
|
272
|
+
expect(image[:width]).to be(10)
|
273
|
+
expect(image[:height]).to be(10)
|
274
|
+
expect(image[:dimensions]).to match_array [10, 10]
|
275
|
+
expect(image[:format]).to eq 'JPEG'
|
276
|
+
image.destroy!
|
277
|
+
end
|
278
|
+
|
279
|
+
it 'inspects meta info from tiff images' do
|
280
|
+
image = described_class.new(TIFF_IMAGE_PATH)
|
281
|
+
expect(image[:format].to_s.downcase).to eq 'tiff'
|
282
|
+
expect(image[:width]).to be(50)
|
283
|
+
expect(image[:height]).to be(41)
|
284
|
+
image.destroy!
|
285
|
+
end
|
286
|
+
|
287
|
+
it 'inspects a gif with jpg format correctly' do
|
288
|
+
image = described_class.new(GIF_WITH_JPG_EXT)
|
289
|
+
expect(image[:format].to_s.downcase).to eq 'gif'
|
290
|
+
image.destroy!
|
291
|
+
end
|
292
|
+
|
293
|
+
it 'resizes an image correctly' do
|
294
|
+
image = described_class.open(SIMPLE_IMAGE_PATH)
|
295
|
+
image.resize '20x30!'
|
296
|
+
|
297
|
+
expect(image[:width]).to be(20)
|
298
|
+
expect(image[:height]).to be(30)
|
299
|
+
expect(image[:format]).to match(/^gif$/i)
|
300
|
+
image.destroy!
|
301
|
+
end
|
302
|
+
|
303
|
+
it 'resizes an image with minimum dimensions' do
|
304
|
+
image = described_class.open(SIMPLE_IMAGE_PATH)
|
305
|
+
original_width, original_height = image[:width], image[:height]
|
306
|
+
image.resize "#{original_width + 10}x#{original_height + 10}>"
|
307
|
+
|
308
|
+
expect(image[:width]).to be original_width
|
309
|
+
expect(image[:height]).to be original_height
|
310
|
+
image.destroy!
|
311
|
+
end
|
312
|
+
|
313
|
+
it 'combines options to create an image with resize and blur' do
|
314
|
+
image = described_class.open(SIMPLE_IMAGE_PATH)
|
315
|
+
image.combine_options do |c|
|
316
|
+
c.resize '20x30!'
|
317
|
+
c.blur '50'
|
318
|
+
end
|
319
|
+
|
320
|
+
expect(image[:width]).to be(20)
|
321
|
+
expect(image[:height]).to be(30)
|
322
|
+
expect(image[:format]).to match(/\Agif\z/i)
|
323
|
+
image.destroy!
|
324
|
+
end
|
325
|
+
|
326
|
+
it "combines options to create an image even with minuses symbols on it's name it" do
|
327
|
+
image = described_class.open(SIMPLE_IMAGE_PATH)
|
328
|
+
background = '#000000'
|
329
|
+
expect {
|
330
|
+
image.combine_options do |c|
|
331
|
+
c.draw "image Over 0,0 10,10 '#{MINUS_IMAGE_PATH}'"
|
332
|
+
c.thumbnail '300x500>'
|
333
|
+
c.background background
|
334
|
+
end
|
335
|
+
}.to_not raise_error
|
336
|
+
image.destroy!
|
337
|
+
end
|
338
|
+
|
339
|
+
it 'inspects the EXIF of an image' do
|
340
|
+
image = described_class.open(EXIF_IMAGE_PATH)
|
341
|
+
expect(image['exif:ExifVersion']).to eq '0220'
|
342
|
+
image = described_class.open(SIMPLE_IMAGE_PATH)
|
343
|
+
expect(image['EXIF:ExifVersion']).to be_empty
|
344
|
+
image.destroy!
|
345
|
+
end
|
346
|
+
|
347
|
+
it 'inspects the original at of an image' do
|
348
|
+
image = described_class.open(EXIF_IMAGE_PATH)
|
349
|
+
expect(image[:original_at]).to eq Time.local('2005', '2', '23', '23', '17', '24')
|
350
|
+
image = described_class.open(SIMPLE_IMAGE_PATH)
|
351
|
+
expect(image[:original_at]).to be_nil
|
352
|
+
image.destroy!
|
353
|
+
end
|
354
|
+
|
355
|
+
it 'has the same path for tempfile and image' do
|
356
|
+
image = described_class.open(TIFF_IMAGE_PATH)
|
357
|
+
expect(image.instance_eval('@tempfile.path')).to eq image.path
|
358
|
+
image.destroy!
|
359
|
+
end
|
360
|
+
|
361
|
+
it 'has the tempfile at path after format' do
|
362
|
+
image = described_class.open(TIFF_IMAGE_PATH)
|
363
|
+
image.format('png')
|
364
|
+
expect(File.exist?(image.path)).to be(true)
|
365
|
+
image.destroy!
|
366
|
+
end
|
367
|
+
|
368
|
+
it "hasn't previous tempfile at path after format" do
|
369
|
+
image = described_class.open(TIFF_IMAGE_PATH)
|
370
|
+
before = image.path.dup
|
371
|
+
image.format('png')
|
372
|
+
expect(File.exist?(before)).to be(false)
|
373
|
+
image.destroy!
|
374
|
+
end
|
375
|
+
|
376
|
+
it 'changes the format of image with special characters', :if => !MiniMagick::Utilities.windows? do
|
377
|
+
tempfile = Tempfile.new('magick with special! "chars\'')
|
378
|
+
|
379
|
+
File.open(SIMPLE_IMAGE_PATH, 'rb') do |file|
|
380
|
+
tempfile.write(file.read)
|
381
|
+
tempfile.rewind
|
382
|
+
end
|
383
|
+
|
384
|
+
image = described_class.new(tempfile.path)
|
385
|
+
image.format('png')
|
386
|
+
expect(File.exist?(image.path)).to be(true)
|
387
|
+
image.destroy!
|
388
|
+
|
389
|
+
File.delete(image.path)
|
390
|
+
tempfile.unlink
|
391
|
+
end
|
392
|
+
|
393
|
+
it 'raises exception when calling wrong method' do
|
394
|
+
image = described_class.open(TIFF_IMAGE_PATH)
|
395
|
+
expect { image.to_blog }.to raise_error(NoMethodError)
|
396
|
+
image.to_blob
|
397
|
+
image.destroy!
|
398
|
+
end
|
399
|
+
|
400
|
+
it 'can create a composite of two images' do
|
401
|
+
image = described_class.open(EXIF_IMAGE_PATH)
|
402
|
+
result = image.composite(described_class.open(TIFF_IMAGE_PATH)) do |c|
|
403
|
+
c.gravity 'center'
|
404
|
+
end
|
405
|
+
expect(File.exist?(result.path)).to be(true)
|
406
|
+
end
|
407
|
+
|
408
|
+
# https://github.com/minimagick/minimagick/issues/212
|
409
|
+
it 'can create a composite of two images with mask' do
|
410
|
+
image = described_class.open(EXIF_IMAGE_PATH)
|
411
|
+
result = image.composite(described_class.open(TIFF_IMAGE_PATH), 'jpg', described_class.open(PNG_PATH)) do |c|
|
412
|
+
c.gravity 'center'
|
413
|
+
end
|
414
|
+
expect(File.exist?(result.path)).to be(true)
|
415
|
+
end
|
416
|
+
|
417
|
+
# https://github.com/minimagick/minimagick/issues/8
|
418
|
+
it 'has issue 8 fixed' do
|
419
|
+
image = described_class.open(SIMPLE_IMAGE_PATH)
|
420
|
+
expect {
|
421
|
+
image.combine_options do |c|
|
422
|
+
c.sample '50%'
|
423
|
+
c.rotate '-90>'
|
424
|
+
end
|
425
|
+
}.to_not raise_error
|
426
|
+
image.destroy!
|
427
|
+
end
|
428
|
+
|
429
|
+
# https://github.com/minimagick/minimagick/issues/8
|
430
|
+
it 'has issue 15 fixed' do
|
431
|
+
expect {
|
432
|
+
image = described_class.open(Pathname.new(SIMPLE_IMAGE_PATH))
|
433
|
+
output = Pathname.new('test.gif')
|
434
|
+
image.write(output)
|
435
|
+
}.to_not raise_error
|
436
|
+
FileUtils.rm('test.gif')
|
437
|
+
end
|
438
|
+
|
439
|
+
# https://github.com/minimagick/minimagick/issues/37
|
440
|
+
it 'respects the language set' do
|
441
|
+
original_lang = ENV['LANG']
|
442
|
+
ENV['LANG'] = 'fr_FR.UTF-8'
|
443
|
+
|
444
|
+
expect {
|
445
|
+
image = described_class.open(NOT_AN_IMAGE_PATH)
|
446
|
+
image.destroy
|
447
|
+
}.to raise_error(MiniMagick::Invalid)
|
448
|
+
|
449
|
+
ENV['LANG'] = original_lang
|
450
|
+
end
|
451
|
+
|
452
|
+
it 'can import pixels with default format' do
|
453
|
+
columns = 325
|
454
|
+
rows = 200
|
455
|
+
depth = 16 # 16 bits (2 bytes) per pixel
|
456
|
+
map = 'gray'
|
457
|
+
pixels = Array.new(columns * rows) { |i| i }
|
458
|
+
blob = pixels.pack('S*') # unsigned short, native byte order
|
459
|
+
image = described_class.import_pixels(blob, columns, rows, depth, map)
|
460
|
+
|
461
|
+
expect(image).to be_valid
|
462
|
+
expect(image[:format].to_s.downcase).to eq 'png'
|
463
|
+
expect(image[:width]).to eq columns
|
464
|
+
expect(image[:height]).to eq rows
|
465
|
+
image.write("#{Dir.tmpdir}/imported_pixels_image.png")
|
466
|
+
end
|
467
|
+
|
468
|
+
it 'can import pixels with custom format' do
|
469
|
+
columns = 325
|
470
|
+
rows = 200
|
471
|
+
depth = 16 # 16 bits (2 bytes) per pixel
|
472
|
+
map = 'gray'
|
473
|
+
format = 'jpeg'
|
474
|
+
pixels = Array.new(columns * rows) { |i| i }
|
475
|
+
blob = pixels.pack('S*') # unsigned short, native byte order
|
476
|
+
image = described_class.import_pixels(blob, columns, rows, depth, map, format)
|
477
|
+
|
478
|
+
expect(image).to be_valid
|
479
|
+
expect(image[:format].to_s.downcase).to eq format
|
480
|
+
expect(image[:width]).to eq columns
|
481
|
+
expect(image[:height]).to eq rows
|
482
|
+
image.write("#{Dir.tmpdir}/imported_pixels_image." + format)
|
483
|
+
end
|
484
|
+
|
485
|
+
it 'loads mimetype correctly' do
|
486
|
+
gif = described_class.open(SIMPLE_IMAGE_PATH)
|
487
|
+
jpeg = described_class.open(EXIF_IMAGE_PATH)
|
488
|
+
png = described_class.open(PNG_PATH)
|
489
|
+
tiff = described_class.open(TIFF_IMAGE_PATH)
|
490
|
+
hidden_gif = described_class.open(GIF_WITH_JPG_EXT)
|
491
|
+
|
492
|
+
expect(gif.mime_type).to eq 'image/gif'
|
493
|
+
expect(jpeg.mime_type).to eq 'image/jpeg'
|
494
|
+
expect(png.mime_type).to eq 'image/png'
|
495
|
+
expect(tiff.mime_type).to eq 'image/tiff'
|
496
|
+
expect(hidden_gif.mime_type).to eq 'image/gif'
|
497
|
+
end
|
498
|
+
end
|
499
|
+
end
|