mini_magick 3.4 → 3.6.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.
- data/MIT-LICENSE +1 -1
- data/lib/mini_magick/version.rb +3 -0
- data/lib/mini_magick.rb +86 -76
- data/test/command_builder_test.rb +48 -5
- data/test/files/composited.jpg +0 -0
- data/test/files/erroneous.jpg +0 -0
- data/test/files/special! /"chars'.gif +0 -0
- data/test/image_test.rb +54 -10
- data/test/test_helper.rb +12 -10
- metadata +33 -13
- data/README.rdoc +0 -119
- data/VERSION +0 -1
data/MIT-LICENSE
CHANGED
data/lib/mini_magick.rb
CHANGED
|
@@ -2,10 +2,12 @@ require 'tempfile'
|
|
|
2
2
|
require 'subexec'
|
|
3
3
|
require 'stringio'
|
|
4
4
|
require 'pathname'
|
|
5
|
+
require 'shellwords'
|
|
5
6
|
|
|
6
7
|
module MiniMagick
|
|
7
8
|
class << self
|
|
8
9
|
attr_accessor :processor
|
|
10
|
+
attr_accessor :processor_path
|
|
9
11
|
attr_accessor :timeout
|
|
10
12
|
|
|
11
13
|
|
|
@@ -20,21 +22,21 @@ module MiniMagick
|
|
|
20
22
|
self.processor = "gm"
|
|
21
23
|
end
|
|
22
24
|
end
|
|
23
|
-
|
|
25
|
+
|
|
24
26
|
def image_magick_version
|
|
25
27
|
@@version ||= Gem::Version.create(`mogrify --version`.split(" ")[2].split("-").first)
|
|
26
28
|
end
|
|
27
|
-
|
|
29
|
+
|
|
28
30
|
def minimum_image_magick_version
|
|
29
31
|
@@minimum_version ||= Gem::Version.create("6.6.3")
|
|
30
32
|
end
|
|
31
|
-
|
|
33
|
+
|
|
32
34
|
def valid_version_installed?
|
|
33
35
|
image_magick_version >= minimum_image_magick_version
|
|
34
36
|
end
|
|
35
37
|
end
|
|
36
38
|
|
|
37
|
-
MOGRIFY_COMMANDS = %w{adaptive-blur adaptive-resize adaptive-sharpen adjoin affine alpha annotate antialias append authenticate auto-gamma auto-level auto-orient background bench
|
|
39
|
+
MOGRIFY_COMMANDS = %w{adaptive-blur adaptive-resize adaptive-sharpen adjoin affine alpha annotate antialias append attenuate authenticate auto-gamma auto-level auto-orient backdrop background bench bias black-point-compensation black-threshold blend blue-primary blue-shift blur border bordercolor borderwidth brightness-contrast cache caption cdl channel charcoal chop clamp clip clip-mask clip-path clone clut coalesce colorize colormap color-matrix colors colorspace combine comment compose composite compress contrast contrast-stretch convolve crop cycle debug decipher deconstruct define delay delete density depth descend deskew despeckle direction displace display dispose dissimilarity-threshold dissolve distort dither draw duplicate edge emboss encipher encoding endian enhance equalize evaluate evaluate-sequence extent extract family features fft fill filter flatten flip floodfill flop font foreground format frame function fuzz fx gamma gaussian-blur geometry gravity green-primary hald-clut help highlight-color iconGeometry iconic identify ift immutable implode insert intent interlace interpolate interline-spacing interword-spacing kerning label lat layers level level-colors limit linear-stretch linewidth liquid-rescale list log loop lowlight-color magnify map mask mattecolor median metric mode modulate monitor monochrome morph morphology mosaic motion-blur name negate noise normalize opaque ordered-dither orient page paint path pause pen perceptible ping pointsize polaroid poly posterize precision preview print process profile quality quantize quiet radial-blur raise random-threshold red-primary regard-warnings region remap remote render repage resample resize respect-parentheses reverse roll rotate sample sampling-factor scale scene screen seed segment selective-blur separate sepia-tone set shade shadow shared-memory sharpen shave shear sigmoidal-contrast silent size sketch smush snaps solarize sparse-color splice spread statistic stegano stereo stretch strip stroke strokewidth style subimage-search swap swirl synchronize taint text-font texture threshold thumbnail tile tile-offset tint title transform transparent transparent-color transpose transverse treedepth trim type undercolor unique-colors units unsharp update verbose version view vignette virtual-pixel visual watermark wave weight white-point white-threshold window window-group write}
|
|
38
40
|
|
|
39
41
|
IMAGE_CREATION_OPERATORS = %w{canvas caption gradient label logo pattern plasma radial radient rose text tile xc }
|
|
40
42
|
|
|
@@ -62,7 +64,9 @@ module MiniMagick
|
|
|
62
64
|
def read(stream, ext = nil)
|
|
63
65
|
if stream.is_a?(String)
|
|
64
66
|
stream = StringIO.new(stream)
|
|
65
|
-
elsif stream.is_a?(
|
|
67
|
+
elsif stream.is_a?(StringIO)
|
|
68
|
+
# Do nothing, we want a StringIO-object
|
|
69
|
+
elsif stream.respond_to? :path
|
|
66
70
|
if File.respond_to?(:binread)
|
|
67
71
|
stream = StringIO.new File.binread(stream.path.to_s)
|
|
68
72
|
else
|
|
@@ -103,8 +107,8 @@ module MiniMagick
|
|
|
103
107
|
image = create(".dat", validate = false) { |f| f.write(blob) }
|
|
104
108
|
# Use ImageMagick to convert the raw data file to an image file of the desired format:
|
|
105
109
|
converted_image_path = image.path[0..-4] + format
|
|
106
|
-
|
|
107
|
-
cmd = CommandBuilder.new("convert",
|
|
110
|
+
arguments = ["-size", "#{columns}x#{rows}", "-depth", "#{depth}", "#{map}:#{image.path}", "#{converted_image_path}"]
|
|
111
|
+
cmd = CommandBuilder.new("convert", *arguments) #Example: convert -size 256x256 -depth 16 gray:blob.dat blob.png
|
|
108
112
|
image.run(cmd)
|
|
109
113
|
# Update the image instance with the path of the properly formatted image, and return:
|
|
110
114
|
image.path = converted_image_path
|
|
@@ -183,10 +187,6 @@ module MiniMagick
|
|
|
183
187
|
@tempfile = tempfile # ensures that the tempfile will stick around until this image is garbage collected.
|
|
184
188
|
end
|
|
185
189
|
|
|
186
|
-
def escaped_path
|
|
187
|
-
Pathname.new(@path).to_s.inspect
|
|
188
|
-
end
|
|
189
|
-
|
|
190
190
|
# Checks to make sure that MiniMagick can read the file and understand it.
|
|
191
191
|
#
|
|
192
192
|
# This uses the 'identify' command line utility to check the file. If you are having
|
|
@@ -195,7 +195,7 @@ module MiniMagick
|
|
|
195
195
|
#
|
|
196
196
|
# @return [Boolean]
|
|
197
197
|
def valid?
|
|
198
|
-
run_command("identify",
|
|
198
|
+
run_command("identify", path)
|
|
199
199
|
true
|
|
200
200
|
rescue MiniMagick::Invalid
|
|
201
201
|
false
|
|
@@ -221,29 +221,29 @@ module MiniMagick
|
|
|
221
221
|
# Why do I go to the trouble of putting in newlines? Because otherwise animated gifs screw everything up
|
|
222
222
|
case value.to_s
|
|
223
223
|
when "colorspace"
|
|
224
|
-
run_command("identify", "-
|
|
224
|
+
run_command("identify", "-format", '%r\n', path).split("\n")[0].strip
|
|
225
225
|
when "format"
|
|
226
|
-
run_command("identify", "-
|
|
226
|
+
run_command("identify", "-format", '%m\n', path).split("\n")[0]
|
|
227
227
|
when "height"
|
|
228
|
-
run_command("identify", "-
|
|
228
|
+
run_command("identify", "-format", '%h\n', path).split("\n")[0].to_i
|
|
229
229
|
when "width"
|
|
230
|
-
run_command("identify", "-
|
|
230
|
+
run_command("identify", "-format", '%w\n', path).split("\n")[0].to_i
|
|
231
231
|
when "dimensions"
|
|
232
|
-
run_command("identify", "-
|
|
232
|
+
run_command("identify", "-format", '%w %h\n', path).split("\n")[0].split.map{|v|v.to_i}
|
|
233
233
|
when "size"
|
|
234
|
-
File.size(
|
|
234
|
+
File.size(path) # Do this because calling identify -format "%b" on an animated gif fails!
|
|
235
235
|
when "original_at"
|
|
236
236
|
# Get the EXIF original capture as a Time object
|
|
237
237
|
Time.local(*self["EXIF:DateTimeOriginal"].split(/:|\s+/)) rescue nil
|
|
238
238
|
when /^EXIF\:/i
|
|
239
|
-
result = run_command('identify', '-
|
|
239
|
+
result = run_command('identify', '-format', "%[#{value}]", path).chop
|
|
240
240
|
if result.include?(",")
|
|
241
241
|
read_character_data(result)
|
|
242
242
|
else
|
|
243
243
|
result
|
|
244
244
|
end
|
|
245
245
|
else
|
|
246
|
-
run_command('identify', '-
|
|
246
|
+
run_command('identify', '-format', value, path).split("\n")[0]
|
|
247
247
|
end
|
|
248
248
|
end
|
|
249
249
|
|
|
@@ -253,7 +253,7 @@ module MiniMagick
|
|
|
253
253
|
#
|
|
254
254
|
# @return [String] Whatever the result from the command line is. May not be terribly useful.
|
|
255
255
|
def <<(*args)
|
|
256
|
-
run_command("mogrify", *args <<
|
|
256
|
+
run_command("mogrify", *args << path)
|
|
257
257
|
end
|
|
258
258
|
|
|
259
259
|
# This is used to change the format of the image. That is, from "tiff to jpg" or something like that.
|
|
@@ -267,29 +267,30 @@ module MiniMagick
|
|
|
267
267
|
# pages (starting with 0). You can choose which page you want to manipulate. We default to the
|
|
268
268
|
# first page.
|
|
269
269
|
#
|
|
270
|
+
# If you would like to convert between animated formats, pass nil as your
|
|
271
|
+
# page and ImageMagick will copy all of the pages.
|
|
272
|
+
#
|
|
270
273
|
# @param format [String] The target format... like 'jpg', 'gif', 'tiff', etc.
|
|
271
|
-
# @param page [Integer] If this is an animated gif, say which 'page' you want
|
|
274
|
+
# @param page [Integer] If this is an animated gif, say which 'page' you want
|
|
275
|
+
# with an integer. Default 0 will convert only the first page; 'nil' will
|
|
276
|
+
# convert all pages.
|
|
272
277
|
# @return [nil]
|
|
273
278
|
def format(format, page = 0)
|
|
274
279
|
c = CommandBuilder.new('mogrify', '-format', format)
|
|
275
280
|
yield c if block_given?
|
|
276
|
-
|
|
281
|
+
if page
|
|
282
|
+
c << "#{path}[#{page}]"
|
|
283
|
+
else
|
|
284
|
+
c << path
|
|
285
|
+
end
|
|
277
286
|
run(c)
|
|
278
287
|
|
|
279
|
-
old_path =
|
|
280
|
-
|
|
281
|
-
File.delete(old_path) if old_path !=
|
|
288
|
+
old_path = path
|
|
289
|
+
self.path = path.sub(/(\.\w*)?$/, ".#{format}")
|
|
290
|
+
File.delete(old_path) if old_path != path
|
|
282
291
|
|
|
283
|
-
unless File.exists?(
|
|
284
|
-
|
|
285
|
-
FileUtils.copy_file(@path.sub(".#{format}", "-#{page}.#{format}"), @path)
|
|
286
|
-
rescue => ex
|
|
287
|
-
raise MiniMagick::Error, "Unable to format to #{format}; #{ex}" unless File.exist?(@path)
|
|
288
|
-
end
|
|
289
|
-
end
|
|
290
|
-
ensure
|
|
291
|
-
Dir[@path.sub(/(\.\w+)?$/, "-[0-9]*.#{format}")].each do |fname|
|
|
292
|
-
File.unlink(fname)
|
|
292
|
+
unless File.exists?(path)
|
|
293
|
+
raise MiniMagick::Error, "Unable to format to #{format}"
|
|
293
294
|
end
|
|
294
295
|
end
|
|
295
296
|
|
|
@@ -307,10 +308,10 @@ module MiniMagick
|
|
|
307
308
|
# Writes the temporary image that we are using for processing to the output path
|
|
308
309
|
def write(output_to)
|
|
309
310
|
if output_to.kind_of?(String) || !output_to.respond_to?(:write)
|
|
310
|
-
FileUtils.copy_file
|
|
311
|
-
run_command "identify", output_to.to_s
|
|
311
|
+
FileUtils.copy_file path, output_to
|
|
312
|
+
run_command "identify", output_to.to_s # Verify that we have a good image
|
|
312
313
|
else # stream
|
|
313
|
-
File.open(
|
|
314
|
+
File.open(path, "rb") do |f|
|
|
314
315
|
f.binmode
|
|
315
316
|
while chunk = f.read(8192)
|
|
316
317
|
output_to.write(chunk)
|
|
@@ -323,7 +324,7 @@ module MiniMagick
|
|
|
323
324
|
# Gives you raw image data back
|
|
324
325
|
# @return [String] binary string
|
|
325
326
|
def to_blob
|
|
326
|
-
f = File.new
|
|
327
|
+
f = File.new path
|
|
327
328
|
f.binmode
|
|
328
329
|
f.read
|
|
329
330
|
ensure
|
|
@@ -339,7 +340,7 @@ module MiniMagick
|
|
|
339
340
|
# Look here to find all the commands (http://www.imagemagick.org/script/mogrify.php)
|
|
340
341
|
def method_missing(symbol, *args)
|
|
341
342
|
combine_options do |c|
|
|
342
|
-
c.
|
|
343
|
+
c.send(symbol, *args)
|
|
343
344
|
end
|
|
344
345
|
end
|
|
345
346
|
|
|
@@ -353,20 +354,15 @@ module MiniMagick
|
|
|
353
354
|
# end
|
|
354
355
|
#
|
|
355
356
|
# @yieldparam command [CommandBuilder]
|
|
356
|
-
def combine_options(tool =
|
|
357
|
+
def combine_options(tool = "mogrify", &block)
|
|
357
358
|
c = CommandBuilder.new(tool)
|
|
358
359
|
|
|
359
|
-
c <<
|
|
360
|
+
c << path if tool.to_s == "convert"
|
|
360
361
|
block.call(c)
|
|
361
|
-
c <<
|
|
362
|
+
c << path
|
|
362
363
|
run(c)
|
|
363
364
|
end
|
|
364
365
|
|
|
365
|
-
# Check to see if we are running on win32 -- we need to escape things differently
|
|
366
|
-
def windows?
|
|
367
|
-
RUBY_PLATFORM =~ /mswin|mingw|cygwin/
|
|
368
|
-
end
|
|
369
|
-
|
|
370
366
|
def composite(other_image, output_extension = 'jpg', &block)
|
|
371
367
|
begin
|
|
372
368
|
second_tempfile = Tempfile.new(output_extension)
|
|
@@ -385,15 +381,11 @@ module MiniMagick
|
|
|
385
381
|
return Image.new(second_tempfile.path, second_tempfile)
|
|
386
382
|
end
|
|
387
383
|
|
|
388
|
-
# Outputs a carriage-return delimited format string for Unix and Windows
|
|
389
|
-
def format_option(format)
|
|
390
|
-
windows? ? "\"#{format}\\n\"" : "\"#{format}\\\\n\""
|
|
391
|
-
end
|
|
392
|
-
|
|
393
384
|
def run_command(command, *args)
|
|
394
385
|
# -ping "efficiently determine image characteristics."
|
|
395
386
|
if command == 'identify'
|
|
396
387
|
args.unshift '-ping'
|
|
388
|
+
args.unshift '-quiet' unless MiniMagick.processor.to_s == 'gm'
|
|
397
389
|
end
|
|
398
390
|
|
|
399
391
|
run(CommandBuilder.new(command, *args))
|
|
@@ -440,31 +432,53 @@ module MiniMagick
|
|
|
440
432
|
end
|
|
441
433
|
|
|
442
434
|
class CommandBuilder
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
def initialize(command, *options)
|
|
447
|
-
@command = command
|
|
435
|
+
def initialize(tool, *options)
|
|
436
|
+
@tool = tool
|
|
448
437
|
@args = []
|
|
449
438
|
options.each { |arg| push(arg) }
|
|
450
439
|
end
|
|
451
440
|
|
|
452
441
|
def command
|
|
453
|
-
"#{
|
|
442
|
+
com = "#{@tool} #{args.join(' ')}".strip
|
|
443
|
+
com = "#{MiniMagick.processor} #{com}" unless MiniMagick.processor.nil?
|
|
444
|
+
|
|
445
|
+
com = File.join MiniMagick.processor_path, com unless MiniMagick.processor_path.nil?
|
|
446
|
+
com.strip
|
|
447
|
+
end
|
|
448
|
+
|
|
449
|
+
def args
|
|
450
|
+
@args.map(&:shellescape)
|
|
454
451
|
end
|
|
455
452
|
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
453
|
+
# Add each mogrify command in both underscore and dash format
|
|
454
|
+
MOGRIFY_COMMANDS.each do |mogrify_command|
|
|
455
|
+
|
|
456
|
+
# Example of what is generated here:
|
|
457
|
+
#
|
|
458
|
+
# def auto_orient(*options)
|
|
459
|
+
# add_command("auto-orient", *options)
|
|
460
|
+
# self
|
|
461
|
+
# end
|
|
462
|
+
# alias_method :"auto-orient", :auto_orient
|
|
463
|
+
|
|
464
|
+
dashed_command = mogrify_command.to_s.gsub("_","-")
|
|
465
|
+
underscored_command = mogrify_command.to_s.gsub("-","_")
|
|
466
|
+
|
|
467
|
+
define_method(underscored_command) do |*options|
|
|
468
|
+
add_command(__method__.to_s.gsub("_","-"), *options)
|
|
462
469
|
self
|
|
463
|
-
|
|
464
|
-
|
|
470
|
+
end
|
|
471
|
+
alias_method dashed_command, underscored_command
|
|
472
|
+
end
|
|
473
|
+
|
|
474
|
+
def format(*options)
|
|
475
|
+
raise Error, "You must call 'format' on the image object directly!"
|
|
476
|
+
end
|
|
477
|
+
|
|
478
|
+
IMAGE_CREATION_OPERATORS.each do |operator|
|
|
479
|
+
define_method operator do |*options|
|
|
480
|
+
add_creation_operator(__method__.to_s, *options)
|
|
465
481
|
self
|
|
466
|
-
else
|
|
467
|
-
super(symbol, *args)
|
|
468
482
|
end
|
|
469
483
|
end
|
|
470
484
|
|
|
@@ -472,7 +486,7 @@ module MiniMagick
|
|
|
472
486
|
push(@args.pop.gsub(/^-/, '+'))
|
|
473
487
|
if options.any?
|
|
474
488
|
options.each do |o|
|
|
475
|
-
push
|
|
489
|
+
push o
|
|
476
490
|
end
|
|
477
491
|
end
|
|
478
492
|
end
|
|
@@ -481,14 +495,10 @@ module MiniMagick
|
|
|
481
495
|
push "-#{command}"
|
|
482
496
|
if options.any?
|
|
483
497
|
options.each do |o|
|
|
484
|
-
push
|
|
498
|
+
push o
|
|
485
499
|
end
|
|
486
500
|
end
|
|
487
501
|
end
|
|
488
|
-
|
|
489
|
-
def escape_string(value)
|
|
490
|
-
'"' + value + '"'
|
|
491
|
-
end
|
|
492
502
|
|
|
493
503
|
def add_creation_operator(command, *options)
|
|
494
504
|
creation_command = command
|
|
@@ -3,10 +3,26 @@ require 'test_helper'
|
|
|
3
3
|
class CommandBuilderTest < Test::Unit::TestCase
|
|
4
4
|
include MiniMagick
|
|
5
5
|
|
|
6
|
+
def setup
|
|
7
|
+
@processor_path = MiniMagick.processor_path
|
|
8
|
+
@processor = MiniMagick.processor
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
def teardown
|
|
12
|
+
MiniMagick.processor_path = @processor_path
|
|
13
|
+
MiniMagick.processor = @processor
|
|
14
|
+
end
|
|
15
|
+
|
|
6
16
|
def test_basic
|
|
7
17
|
c = CommandBuilder.new("test")
|
|
8
18
|
c.resize "30x40"
|
|
9
|
-
assert_equal
|
|
19
|
+
assert_equal '-resize 30x40', c.args.join(" ")
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def test_full_command
|
|
23
|
+
c = CommandBuilder.new("test")
|
|
24
|
+
c.resize "30x40"
|
|
25
|
+
assert_equal "test -resize 30x40", c.command
|
|
10
26
|
end
|
|
11
27
|
|
|
12
28
|
def test_complicated
|
|
@@ -14,15 +30,15 @@ class CommandBuilderTest < Test::Unit::TestCase
|
|
|
14
30
|
c.resize "30x40"
|
|
15
31
|
c.alpha "1 3 4"
|
|
16
32
|
c.resize "mome fingo"
|
|
17
|
-
assert_equal
|
|
33
|
+
assert_equal '-resize 30x40 -alpha 1\ 3\ 4 -resize mome\ fingo', c.args.join(" ")
|
|
18
34
|
end
|
|
19
35
|
|
|
20
36
|
def test_plus_modifier_and_multiple_options
|
|
21
37
|
c = CommandBuilder.new("test")
|
|
22
38
|
c.distort.+ 'srt', '0.6 20'
|
|
23
|
-
assert_equal
|
|
39
|
+
assert_equal '\+distort srt 0.6\ 20', c.args.join(" ")
|
|
24
40
|
end
|
|
25
|
-
|
|
41
|
+
|
|
26
42
|
def test_valid_command
|
|
27
43
|
begin
|
|
28
44
|
c = CommandBuilder.new("test", "path")
|
|
@@ -38,10 +54,37 @@ class CommandBuilderTest < Test::Unit::TestCase
|
|
|
38
54
|
c.auto_orient
|
|
39
55
|
assert_equal "-auto-orient", c.args.join(" ")
|
|
40
56
|
end
|
|
41
|
-
|
|
57
|
+
|
|
58
|
+
def test_dashed_via_send
|
|
59
|
+
c = CommandBuilder.new("test")
|
|
60
|
+
c.send("auto-orient")
|
|
61
|
+
assert_equal "-auto-orient", c.args.join(" ")
|
|
62
|
+
end
|
|
63
|
+
|
|
42
64
|
def test_canvas
|
|
43
65
|
c = CommandBuilder.new('test')
|
|
44
66
|
c.canvas 'black'
|
|
45
67
|
assert_equal "canvas:black", c.args.join
|
|
46
68
|
end
|
|
69
|
+
|
|
70
|
+
def test_set
|
|
71
|
+
c = CommandBuilder.new("test")
|
|
72
|
+
c.set "colorspace RGB"
|
|
73
|
+
assert_equal 'test -set colorspace\ RGB', c.command
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
def test_processor_path
|
|
77
|
+
MiniMagick.processor_path = "/a/strange/path"
|
|
78
|
+
c = CommandBuilder.new('test')
|
|
79
|
+
c.auto_orient
|
|
80
|
+
assert_equal c.command, "/a/strange/path/test -auto-orient"
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
def test_processor_path_with_processor
|
|
84
|
+
MiniMagick.processor_path = "/a/strange/path"
|
|
85
|
+
MiniMagick.processor = "processor"
|
|
86
|
+
c = CommandBuilder.new('test')
|
|
87
|
+
c.auto_orient
|
|
88
|
+
assert_equal c.command, "/a/strange/path/processor test -auto-orient"
|
|
89
|
+
end
|
|
47
90
|
end
|
data/test/files/composited.jpg
CHANGED
|
Binary file
|
|
Binary file
|
|
Binary file
|
data/test/image_test.rb
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
require 'test_helper'
|
|
2
|
+
require 'digest/md5'
|
|
2
3
|
|
|
3
4
|
#MiniMagick.processor = :gm
|
|
4
5
|
|
|
@@ -14,6 +15,19 @@ class ImageTest < Test::Unit::TestCase
|
|
|
14
15
|
end
|
|
15
16
|
end
|
|
16
17
|
|
|
18
|
+
def test_image_from_tempfile
|
|
19
|
+
tempfile = Tempfile.new('magick')
|
|
20
|
+
|
|
21
|
+
File.open(SIMPLE_IMAGE_PATH, 'rb') do |f|
|
|
22
|
+
tempfile.write(f.read)
|
|
23
|
+
tempfile.rewind
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
image = Image.read(tempfile)
|
|
27
|
+
assert image.valid?
|
|
28
|
+
image.destroy!
|
|
29
|
+
end
|
|
30
|
+
|
|
17
31
|
def test_image_open
|
|
18
32
|
image = Image.open(SIMPLE_IMAGE_PATH)
|
|
19
33
|
assert image.valid?
|
|
@@ -52,7 +66,7 @@ class ImageTest < Test::Unit::TestCase
|
|
|
52
66
|
assert image.valid?
|
|
53
67
|
image.destroy!
|
|
54
68
|
end
|
|
55
|
-
|
|
69
|
+
|
|
56
70
|
def test_reformat_with_capitalized_extension
|
|
57
71
|
image = Image.open(CAP_EXT_PATH)
|
|
58
72
|
image.format "jpg"
|
|
@@ -111,11 +125,20 @@ class ImageTest < Test::Unit::TestCase
|
|
|
111
125
|
assert_equal 150, image[:width]
|
|
112
126
|
assert_equal 55, image[:height]
|
|
113
127
|
assert_equal [150, 55], image[:dimensions]
|
|
114
|
-
|
|
128
|
+
assert_true String == image[:colorspace].class
|
|
115
129
|
assert_match(/^gif$/i, image[:format])
|
|
116
130
|
image.destroy!
|
|
117
131
|
end
|
|
118
132
|
|
|
133
|
+
def test_erroneous_image_meta_info
|
|
134
|
+
image = Image.new(ERRONEOUS_IMAGE_PATH)
|
|
135
|
+
assert_equal 10, image[:width]
|
|
136
|
+
assert_equal 10, image[:height]
|
|
137
|
+
assert_equal [10, 10], image[:dimensions]
|
|
138
|
+
assert_equal('JPEG', image[:format])
|
|
139
|
+
image.destroy!
|
|
140
|
+
end
|
|
141
|
+
|
|
119
142
|
def test_tiff
|
|
120
143
|
image = Image.new(TIFF_IMAGE_PATH)
|
|
121
144
|
assert_equal "tiff", image[:format].to_s.downcase
|
|
@@ -176,6 +199,16 @@ class ImageTest < Test::Unit::TestCase
|
|
|
176
199
|
image.destroy!
|
|
177
200
|
end
|
|
178
201
|
|
|
202
|
+
def test_image_combine_options_with_filename_with_special_characters_in_it
|
|
203
|
+
image = Image.new(SPECIAL_CHARS_IMAGE_PATH)
|
|
204
|
+
assert_nothing_raised do
|
|
205
|
+
image.combine_options("identify") do |c|
|
|
206
|
+
c.ping
|
|
207
|
+
end
|
|
208
|
+
end
|
|
209
|
+
image.destroy!
|
|
210
|
+
end
|
|
211
|
+
|
|
179
212
|
def test_exif
|
|
180
213
|
image = Image.open(EXIF_IMAGE_PATH)
|
|
181
214
|
assert_equal('0220', image["exif:ExifVersion"])
|
|
@@ -213,6 +246,23 @@ class ImageTest < Test::Unit::TestCase
|
|
|
213
246
|
image.destroy!
|
|
214
247
|
end
|
|
215
248
|
|
|
249
|
+
def test_change_format_of_image_with_special_characters
|
|
250
|
+
tempfile = Tempfile.new('magick with special! "chars\'')
|
|
251
|
+
|
|
252
|
+
File.open(SIMPLE_IMAGE_PATH, 'rb') do |f|
|
|
253
|
+
tempfile.write(f.read)
|
|
254
|
+
tempfile.rewind
|
|
255
|
+
end
|
|
256
|
+
|
|
257
|
+
image = Image.new(tempfile.path)
|
|
258
|
+
image.format('png')
|
|
259
|
+
assert File.exists?(image.path)
|
|
260
|
+
image.destroy!
|
|
261
|
+
|
|
262
|
+
File.delete(image.path)
|
|
263
|
+
tempfile.unlink
|
|
264
|
+
end
|
|
265
|
+
|
|
216
266
|
def test_bad_method_bug
|
|
217
267
|
image = Image.open(TIFF_IMAGE_PATH)
|
|
218
268
|
begin
|
|
@@ -231,16 +281,10 @@ class ImageTest < Test::Unit::TestCase
|
|
|
231
281
|
result = image.composite(Image.open(TIFF_IMAGE_PATH)) do |c|
|
|
232
282
|
c.gravity "center"
|
|
233
283
|
end
|
|
234
|
-
|
|
284
|
+
assert_true File.exists?(result.path)
|
|
235
285
|
else
|
|
236
286
|
puts "Need at least version #{MiniMagick.minimum_image_magick_version} of ImageMagick"
|
|
237
287
|
end
|
|
238
|
-
#TODO - need to write test that works cross platform
|
|
239
|
-
#I thought the following would work but there is a 4 byte difference between the files.
|
|
240
|
-
#Not sure if it's caused from this test breaking for the right reason though..
|
|
241
|
-
#assert File.identical?(result.path, COMP_IMAGE_PATH)
|
|
242
|
-
#This following test will only work on Linux
|
|
243
|
-
assert `diff -s #{result.path} #{COMP_IMAGE_PATH}`.include?("identical") unless RUBY_PLATFORM =~ /mswin|mingw|cygwin/
|
|
244
288
|
end
|
|
245
289
|
|
|
246
290
|
# http://github.com/probablycorey/mini_magick/issues#issue/8
|
|
@@ -330,7 +374,7 @@ class ImageTest < Test::Unit::TestCase
|
|
|
330
374
|
png = Image.open(PNG_PATH)
|
|
331
375
|
tiff = Image.open(TIFF_IMAGE_PATH)
|
|
332
376
|
hidden_gif = Image.open(GIF_WITH_JPG_EXT)
|
|
333
|
-
|
|
377
|
+
|
|
334
378
|
assert_equal "image/gif", gif.mime_type
|
|
335
379
|
assert_equal "image/jpeg", jpeg.mime_type
|
|
336
380
|
assert_equal "image/png", png.mime_type
|
data/test/test_helper.rb
CHANGED
|
@@ -7,14 +7,16 @@ require File.expand_path('../../lib/mini_magick', __FILE__)
|
|
|
7
7
|
|
|
8
8
|
module MiniMagickTestFiles
|
|
9
9
|
test_files = File.expand_path(File.dirname(__FILE__) + "/files")
|
|
10
|
-
SIMPLE_IMAGE_PATH
|
|
11
|
-
MINUS_IMAGE_PATH
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
10
|
+
SIMPLE_IMAGE_PATH = test_files + "/simple.gif"
|
|
11
|
+
MINUS_IMAGE_PATH = test_files + "/simple-minus.gif"
|
|
12
|
+
SPECIAL_CHARS_IMAGE_PATH = test_files + "/special! \"chars'.gif"
|
|
13
|
+
TIFF_IMAGE_PATH = test_files + "/leaves (spaced).tiff"
|
|
14
|
+
NOT_AN_IMAGE_PATH = test_files + "/not_an_image.php"
|
|
15
|
+
GIF_WITH_JPG_EXT = test_files + "/actually_a_gif.jpg"
|
|
16
|
+
EXIF_IMAGE_PATH = test_files + "/trogdor.jpg"
|
|
17
|
+
CAP_EXT_PATH = test_files + "/trogdor_capitalized.JPG"
|
|
18
|
+
ANIMATION_PATH = test_files + "/animation.gif"
|
|
19
|
+
PNG_PATH = test_files + "/png.png"
|
|
20
|
+
COMP_IMAGE_PATH = test_files + "/composited.jpg"
|
|
21
|
+
ERRONEOUS_IMAGE_PATH = test_files + "/erroneous.jpg"
|
|
20
22
|
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
|
+
version: 3.6.0
|
|
5
5
|
prerelease:
|
|
6
6
|
platform: ruby
|
|
7
7
|
authors:
|
|
@@ -11,11 +11,11 @@ authors:
|
|
|
11
11
|
autorequire:
|
|
12
12
|
bindir: bin
|
|
13
13
|
cert_chain: []
|
|
14
|
-
date:
|
|
14
|
+
date: 2013-05-21 00:00:00.000000000 Z
|
|
15
15
|
dependencies:
|
|
16
16
|
- !ruby/object:Gem::Dependency
|
|
17
17
|
name: subexec
|
|
18
|
-
requirement:
|
|
18
|
+
requirement: !ruby/object:Gem::Requirement
|
|
19
19
|
none: false
|
|
20
20
|
requirements:
|
|
21
21
|
- - ~>
|
|
@@ -23,10 +23,15 @@ dependencies:
|
|
|
23
23
|
version: 0.2.1
|
|
24
24
|
type: :runtime
|
|
25
25
|
prerelease: false
|
|
26
|
-
version_requirements:
|
|
26
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
27
|
+
none: false
|
|
28
|
+
requirements:
|
|
29
|
+
- - ~>
|
|
30
|
+
- !ruby/object:Gem::Version
|
|
31
|
+
version: 0.2.1
|
|
27
32
|
- !ruby/object:Gem::Dependency
|
|
28
33
|
name: rake
|
|
29
|
-
requirement:
|
|
34
|
+
requirement: !ruby/object:Gem::Requirement
|
|
30
35
|
none: false
|
|
31
36
|
requirements:
|
|
32
37
|
- - ! '>='
|
|
@@ -34,10 +39,15 @@ dependencies:
|
|
|
34
39
|
version: '0'
|
|
35
40
|
type: :development
|
|
36
41
|
prerelease: false
|
|
37
|
-
version_requirements:
|
|
42
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
43
|
+
none: false
|
|
44
|
+
requirements:
|
|
45
|
+
- - ! '>='
|
|
46
|
+
- !ruby/object:Gem::Version
|
|
47
|
+
version: '0'
|
|
38
48
|
- !ruby/object:Gem::Dependency
|
|
39
49
|
name: test-unit
|
|
40
|
-
requirement:
|
|
50
|
+
requirement: !ruby/object:Gem::Requirement
|
|
41
51
|
none: false
|
|
42
52
|
requirements:
|
|
43
53
|
- - ! '>='
|
|
@@ -45,7 +55,12 @@ dependencies:
|
|
|
45
55
|
version: '0'
|
|
46
56
|
type: :development
|
|
47
57
|
prerelease: false
|
|
48
|
-
version_requirements:
|
|
58
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
59
|
+
none: false
|
|
60
|
+
requirements:
|
|
61
|
+
- - ! '>='
|
|
62
|
+
- !ruby/object:Gem::Version
|
|
63
|
+
version: '0'
|
|
49
64
|
description: ''
|
|
50
65
|
email:
|
|
51
66
|
- probablycorey@gmail.com
|
|
@@ -55,28 +70,29 @@ executables: []
|
|
|
55
70
|
extensions: []
|
|
56
71
|
extra_rdoc_files: []
|
|
57
72
|
files:
|
|
58
|
-
- README.rdoc
|
|
59
|
-
- VERSION
|
|
60
73
|
- MIT-LICENSE
|
|
61
74
|
- Rakefile
|
|
62
75
|
- lib/mini_gmagick.rb
|
|
76
|
+
- lib/mini_magick/version.rb
|
|
63
77
|
- lib/mini_magick.rb
|
|
64
78
|
- test/command_builder_test.rb
|
|
65
79
|
- test/files/actually_a_gif.jpg
|
|
66
80
|
- test/files/animation.gif
|
|
67
81
|
- test/files/composited.jpg
|
|
82
|
+
- test/files/erroneous.jpg
|
|
68
83
|
- test/files/leaves (spaced).tiff
|
|
69
84
|
- test/files/not_an_image.php
|
|
70
85
|
- test/files/png.png
|
|
71
86
|
- test/files/simple-minus.gif
|
|
72
87
|
- test/files/simple.gif
|
|
88
|
+
- test/files/special! "chars'.gif
|
|
73
89
|
- test/files/trogdor.jpg
|
|
74
90
|
- test/files/trogdor_capitalized.JPG
|
|
75
91
|
- test/image_test.rb
|
|
76
92
|
- test/leaves (spaced).tiff
|
|
77
93
|
- test/test_helper.rb
|
|
78
94
|
- test/trogdor_capitalized.JPG
|
|
79
|
-
homepage:
|
|
95
|
+
homepage: https://github.com/minimagick/minimagick
|
|
80
96
|
licenses: []
|
|
81
97
|
post_install_message:
|
|
82
98
|
rdoc_options: []
|
|
@@ -94,9 +110,10 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
94
110
|
- - ! '>='
|
|
95
111
|
- !ruby/object:Gem::Version
|
|
96
112
|
version: '0'
|
|
97
|
-
requirements:
|
|
113
|
+
requirements:
|
|
114
|
+
- You must have ImageMagick or GraphicsMagick installed
|
|
98
115
|
rubyforge_project:
|
|
99
|
-
rubygems_version: 1.8.
|
|
116
|
+
rubygems_version: 1.8.23
|
|
100
117
|
signing_key:
|
|
101
118
|
specification_version: 3
|
|
102
119
|
summary: Manipulate images with minimal use of memory via ImageMagick / GraphicsMagick
|
|
@@ -105,14 +122,17 @@ test_files:
|
|
|
105
122
|
- test/files/actually_a_gif.jpg
|
|
106
123
|
- test/files/animation.gif
|
|
107
124
|
- test/files/composited.jpg
|
|
125
|
+
- test/files/erroneous.jpg
|
|
108
126
|
- test/files/leaves (spaced).tiff
|
|
109
127
|
- test/files/not_an_image.php
|
|
110
128
|
- test/files/png.png
|
|
111
129
|
- test/files/simple-minus.gif
|
|
112
130
|
- test/files/simple.gif
|
|
131
|
+
- test/files/special! "chars'.gif
|
|
113
132
|
- test/files/trogdor.jpg
|
|
114
133
|
- test/files/trogdor_capitalized.JPG
|
|
115
134
|
- test/image_test.rb
|
|
116
135
|
- test/leaves (spaced).tiff
|
|
117
136
|
- test/test_helper.rb
|
|
118
137
|
- test/trogdor_capitalized.JPG
|
|
138
|
+
has_rdoc:
|
data/README.rdoc
DELETED
|
@@ -1,119 +0,0 @@
|
|
|
1
|
-
= MiniMagick
|
|
2
|
-
|
|
3
|
-
A ruby wrapper for ImageMagick or GraphicsMagick command line.
|
|
4
|
-
|
|
5
|
-
Tested on both Ruby 1.9.2 and Ruby 1.8.7.
|
|
6
|
-
|
|
7
|
-
== Why?
|
|
8
|
-
|
|
9
|
-
I was using RMagick and loving it, but it was eating up huge amounts
|
|
10
|
-
of memory. A simple script like this...
|
|
11
|
-
|
|
12
|
-
Magick::read("image.jpg") do |f|
|
|
13
|
-
f.write("manipulated.jpg")
|
|
14
|
-
end
|
|
15
|
-
|
|
16
|
-
...would use over 100 Megs of Ram. On my local machine this wasn't a
|
|
17
|
-
problem, but on my hosting server the ruby apps would crash because of
|
|
18
|
-
their 100 Meg memory limit.
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
== Solution!
|
|
22
|
-
|
|
23
|
-
Using MiniMagick the ruby processes memory remains small (it spawns
|
|
24
|
-
ImageMagick's command line program mogrify which takes up some memory
|
|
25
|
-
as well, but is much smaller compared to RMagick)
|
|
26
|
-
|
|
27
|
-
MiniMagick gives you access to all the commandline options ImageMagick
|
|
28
|
-
has (Found here http://www.imagemagick.org/script/mogrify.php)
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
== Examples
|
|
32
|
-
|
|
33
|
-
Want to make a thumbnail from a file...
|
|
34
|
-
|
|
35
|
-
image = MiniMagick::Image.open("input.jpg")
|
|
36
|
-
image.resize "100x100"
|
|
37
|
-
image.write "output.jpg"
|
|
38
|
-
|
|
39
|
-
Want to make a thumbnail from a blob...
|
|
40
|
-
|
|
41
|
-
image = MiniMagick::Image.read(blob)
|
|
42
|
-
image.resize "100x100"
|
|
43
|
-
image.write "output.jpg"
|
|
44
|
-
|
|
45
|
-
Got an incoming IOStream?
|
|
46
|
-
|
|
47
|
-
image = MiniMagick::Image.read(stream)
|
|
48
|
-
|
|
49
|
-
Want to make a thumbnail of a remote image?
|
|
50
|
-
|
|
51
|
-
image = MiniMagick::Image.open("http://www.google.com/images/logos/logo.png")
|
|
52
|
-
image.resize "5x5"
|
|
53
|
-
image.format "gif"
|
|
54
|
-
image.write "localcopy.gif"
|
|
55
|
-
|
|
56
|
-
Need to combine several options?
|
|
57
|
-
|
|
58
|
-
image = MiniMagick::Image.open("input.jpg")
|
|
59
|
-
image.combine_options do |c|
|
|
60
|
-
c.sample "50%"
|
|
61
|
-
c.rotate "-90>"
|
|
62
|
-
end
|
|
63
|
-
image.write "output.jpg"
|
|
64
|
-
|
|
65
|
-
Want to composite two images? Super easy! (Aka, put a watermark on!)
|
|
66
|
-
|
|
67
|
-
image = Image.open("original.png")
|
|
68
|
-
result = image.composite(Image.open("watermark.png", "jpg") do |c|
|
|
69
|
-
c.gravity "center"
|
|
70
|
-
end
|
|
71
|
-
result.write "my_output_file.jpg"
|
|
72
|
-
|
|
73
|
-
Want to manipulate an image at its source (You won't have to write it
|
|
74
|
-
out because the transformations are done on that file)
|
|
75
|
-
|
|
76
|
-
image = MiniMagick::Image.new("input.jpg")
|
|
77
|
-
image.resize "100x100"
|
|
78
|
-
|
|
79
|
-
Want to get some meta-information out?
|
|
80
|
-
|
|
81
|
-
image = MiniMagick::Image.open("input.jpg")
|
|
82
|
-
image[:width] # will get the width (you can also use :height and :format)
|
|
83
|
-
image["EXIF:BitsPerSample"] # It also can get all the EXIF tags
|
|
84
|
-
image["%m:%f %wx%h"] # Or you can use one of the many options of the format command
|
|
85
|
-
|
|
86
|
-
Want to use an internal image creation to create a big black square?
|
|
87
|
-
|
|
88
|
-
image = MiniMagick::Image.create 'jpg', false do |c|
|
|
89
|
-
c.size '1024x1024' # creates image option '-size 1024x1024'
|
|
90
|
-
c.canvas 'black' # creates image creation operator 'canvas:black'
|
|
91
|
-
end
|
|
92
|
-
|
|
93
|
-
For more on the format command see
|
|
94
|
-
http://www.imagemagick.org/script/command-line-options.php#format
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
== Windows Users
|
|
98
|
-
|
|
99
|
-
When passing in a blob or IOStream, Windows users need to make sure they read the file in as binary.
|
|
100
|
-
|
|
101
|
-
#This way works on Windows
|
|
102
|
-
buffer = StringIO.new(File.open(IMAGE_PATH,"rb") { |f| f.read })
|
|
103
|
-
MiniMagick::Image.read(buffer)
|
|
104
|
-
|
|
105
|
-
#You may run into problems doing it this way
|
|
106
|
-
buffer = StringIO.new(File.read(IMAGE_PATH))
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
== Using GraphicsMagick
|
|
110
|
-
|
|
111
|
-
Simply set
|
|
112
|
-
|
|
113
|
-
MiniMagick.processor = :gm
|
|
114
|
-
|
|
115
|
-
And you are sorted.
|
|
116
|
-
|
|
117
|
-
== Requirements
|
|
118
|
-
|
|
119
|
-
You must have ImageMagick or GraphicsMagick installed.
|
data/VERSION
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
3.4
|