mini_magick 3.8.1 → 4.9.4

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.
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
@@ -1,499 +0,0 @@
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
@@ -1,63 +0,0 @@
1
- require 'spec_helper'
2
-
3
- describe MiniMagick do
4
- context 'which util' do
5
- it 'identifies when mogrify exists' do
6
- expect(MiniMagick::Utilities.which('mogrify')).not_to be_nil
7
- end
8
-
9
- it 'identifies when gm exists' do
10
- expect(MiniMagick::Utilities.which('gm')).not_to be_nil
11
- end
12
-
13
- it 'returns nil on nonexistent executables' do
14
- expect(MiniMagick::Utilities.which('yogrify')).to be_nil
15
- end
16
- end
17
-
18
- context '.mogrify?' do
19
- it 'returns true if minimagick is using mogrify' do
20
- described_class.processor = :mogrify
21
- expect(described_class.mogrify?).to eq true
22
- end
23
-
24
- it 'returns false if minimagick is not using mogrify' do
25
- described_class.processor = :gm
26
- expect(described_class.mogrify?).to eq false
27
- end
28
-
29
- it 'sets the processor if not set' do
30
- described_class.processor = nil
31
- described_class.mogrify?
32
- expect(described_class.processor).to eq :mogrify
33
- end
34
- end
35
-
36
- context '.gm?' do
37
- it 'returns true if minimagick is using gm' do
38
- described_class.processor = :gm
39
- expect(described_class).to be_gm
40
- end
41
-
42
- it 'returns false if minimagick is not using gm' do
43
- described_class.processor = :mogrify
44
- expect(described_class).not_to be_gm
45
- end
46
-
47
- it 'sets the processor if not set' do
48
- described_class.processor = nil
49
- described_class.gm?
50
- expect(described_class.processor).to eq :mogrify
51
- end
52
- end
53
-
54
- context 'validation' do
55
- it 'validates on create' do
56
- expect(MiniMagick.validate_on_create).to eq(true)
57
- end
58
-
59
- it 'validates on write' do
60
- expect(MiniMagick.validate_on_write).to eq(true)
61
- end
62
- end
63
- end
data/spec/spec_helper.rb DELETED
@@ -1,29 +0,0 @@
1
- require 'rubygems'
2
- require 'bundler/setup'
3
- require 'rspec'
4
- require 'mocha/api'
5
-
6
- require 'mini_magick'
7
-
8
- RSpec.configure do |config|
9
- config.mock_framework = :mocha
10
- config.color = true
11
- config.formatter = 'documentation'
12
- config.raise_errors_for_deprecations!
13
- end
14
-
15
- # Image files from testunit port to RSpec
16
- test_files = File.expand_path(File.dirname(__FILE__) + '/files')
17
- TEST_FILES_PATH = test_files
18
- SIMPLE_IMAGE_PATH = test_files + '/simple.gif'
19
- MINUS_IMAGE_PATH = test_files + '/simple-minus.gif'
20
- TIFF_IMAGE_PATH = test_files + '/leaves (spaced).tiff'
21
- NOT_AN_IMAGE_PATH = test_files + '/not_an_image.php'
22
- GIF_WITH_JPG_EXT = test_files + '/actually_a_gif.jpg'
23
- EXIF_IMAGE_PATH = test_files + '/trogdor.jpg'
24
- CAP_EXT_PATH = test_files + '/trogdor_capitalized.JPG'
25
- ANIMATION_PATH = test_files + '/animation.gif'
26
- PNG_PATH = test_files + '/png.png'
27
- COMP_IMAGE_PATH = test_files + '/composited.jpg'
28
- ERRONEOUS_IMAGE_PATH = test_files + '/erroneous.jpg'
29
- PSD_IMAGE_PATH = test_files + '/layers.psd'