mojo_magick 0.3.0
Sign up to get free protection for your applications and to get access to all the features.
- data/README +112 -0
- data/init.rb +1 -0
- data/lib/image_resources.rb +124 -0
- data/lib/mojo_magick.rb +226 -0
- data/test/fixtures/5742.jpg +0 -0
- data/test/fixtures/not_an_image.jpg +0 -0
- data/test/fixtures/tmp/5742.jpg +0 -0
- data/test/fixtures/tmp/not_an_image.jpg +0 -0
- data/test/fixtures/tmp/zero_byte_image.jpg +0 -0
- data/test/fixtures/zero_byte_image.jpg +0 -0
- data/test/mojo_magick_test.rb +248 -0
- metadata +74 -0
data/README
ADDED
@@ -0,0 +1,112 @@
|
|
1
|
+
MojoMagick
|
2
|
+
==========
|
3
|
+
|
4
|
+
MojoMagick is a "dog simple, do very little" image library. It is basically a couple of stateless
|
5
|
+
module methods that make it somewhat more convenient than calling ImageScience by hand.
|
6
|
+
|
7
|
+
The main reason to use MojoMagick is that you should consolidate your ImageScience calls into
|
8
|
+
one place, so why not do it here? If you improve on this tool, send me the patch.
|
9
|
+
|
10
|
+
This tool came about because I wanted a fast, simple, lightweight, nothing-goes-wrong-with-it-
|
11
|
+
because-it's-too-simple-to-break image tool.
|
12
|
+
|
13
|
+
Examples
|
14
|
+
========
|
15
|
+
|
16
|
+
# Obtain the size of an image (assuming image is "120wx222h")
|
17
|
+
dimensions = MojoMagick::get_image_size(test_image)
|
18
|
+
# ==> dimensions now holds a hash: {:height => 120, :width => 222}
|
19
|
+
|
20
|
+
# Resize an image so that it fits within a 100w x 200h bounding box
|
21
|
+
# (Note: this will scale an image either up or down to fit these dimensions
|
22
|
+
# which may not be what you want.)
|
23
|
+
# In this example, we overwrite our image, but if you pass in a different file for the
|
24
|
+
# second file name, a new file will be created with the resized dimensions
|
25
|
+
MojoMagick::resize('/img/test.jpg', '/img/test.jpg', {:width=>100, :height=>200})
|
26
|
+
|
27
|
+
## Code sample of how to shrink all jpg's in a folder
|
28
|
+
{{{
|
29
|
+
require 'mojo_magick'
|
30
|
+
|
31
|
+
image_folder = '/tmp/img'
|
32
|
+
Dir::glob(File::join(image_folder, '*.jpg')).each do |image|
|
33
|
+
begin
|
34
|
+
# shrink all the images *in place* to no bigger than 60pix x 60pix
|
35
|
+
MojoMagick::shrink(image, image, {:width => 60, :height => 60})
|
36
|
+
puts "Shrunk: #{image}"
|
37
|
+
rescue MojoMagick::MojoFailed => e
|
38
|
+
STDERR.puts "Unable to shrink image '#{image}' - probably an invalid image\n#{e.message}"
|
39
|
+
rescue MojoMagick::MojoMagickException => e
|
40
|
+
STDERR.puts "Unknown exception on image '#{image}'\n#{e.message}"
|
41
|
+
end
|
42
|
+
end
|
43
|
+
}}}
|
44
|
+
|
45
|
+
## More Code on setting memory limits for imagemagick
|
46
|
+
# (Be sure you�re upgraded to the current release of ImageMagick.)
|
47
|
+
|
48
|
+
# set limits on disk, area, map and ram usage
|
49
|
+
# obtain/print a hash of default limits:
|
50
|
+
puts MojoMagick::get_default_limits.inspect
|
51
|
+
# current_limits shows same values:
|
52
|
+
puts MojoMagick::get_current_limits.inspect
|
53
|
+
|
54
|
+
MojoMagick::set_limits(:area => '32mb', :disk => '0', :memory => '64mb', :map => '32mb')
|
55
|
+
puts MojoMagick::get_current_limits.inspect
|
56
|
+
|
57
|
+
### More sample code (thanks to Elliot Nelson for adding this code to the system)
|
58
|
+
# Two command-line builders, #convert and #mogrify, have been added to simplify
|
59
|
+
# complex commands. Examples included below.
|
60
|
+
|
61
|
+
# Example #convert usage:
|
62
|
+
|
63
|
+
MojoMagick::convert('source.jpg', 'dest.jpg') do |c|
|
64
|
+
c.crop '250x250+0+0'
|
65
|
+
c.repage!
|
66
|
+
c.strip
|
67
|
+
c.set 'comment', 'my favorite file'
|
68
|
+
end
|
69
|
+
|
70
|
+
# Equivalent to:
|
71
|
+
|
72
|
+
MojoMagick::raw_command('convert', 'source.jpg -crop 250x250+0+0 +repage -strip -set comment "my favorite file" dest.jpg')
|
73
|
+
|
74
|
+
# Example #mogrify usage:
|
75
|
+
|
76
|
+
MojoMagick::mogrify('image.jpg') {|i| i.shave '10x10'}
|
77
|
+
|
78
|
+
# Equivalent to:
|
79
|
+
|
80
|
+
MojoMagick::raw_command('mogrify', '-shave 10x10 image.jpg')
|
81
|
+
|
82
|
+
# Example showing some additional options:
|
83
|
+
|
84
|
+
MojoMagick::convert do |c|
|
85
|
+
c.file 'source.jpg'
|
86
|
+
c.blob my_binary_data
|
87
|
+
c.append
|
88
|
+
c.crop '256x256+0+0'
|
89
|
+
c.repage!
|
90
|
+
c.file 'output.jpg'
|
91
|
+
end
|
92
|
+
|
93
|
+
# Use .file to specify file names, .blob to create and include a tempfile. The
|
94
|
+
# bang (!) can be appended to command names to use the '+' versions
|
95
|
+
# instead of '-' versions.
|
96
|
+
|
97
|
+
Availablility
|
98
|
+
=============
|
99
|
+
SVN Repo access from here: http://trac.misuse.org/science/wiki/MojoMagick
|
100
|
+
Contact author or discuss MojoMagick here: http://www.misuse.org/science/2008/01/30/mojomagick-ruby-image-library-for-imagemagick/
|
101
|
+
|
102
|
+
|
103
|
+
Updates by Jon Rogers (jon@2rye.com)
|
104
|
+
------------------------------------
|
105
|
+
# added gemspec for building gem with bundler
|
106
|
+
# updated tests for ImageMagick 6.6
|
107
|
+
# added ability to do fill + crop resizing
|
108
|
+
# bumped version to 0.3.0
|
109
|
+
|
110
|
+
|
111
|
+
Copyright (c) 2008 Steve Midgley, released under the MIT license
|
112
|
+
Credit to Elliot Nelson for significant code contributions. Thanks Elliot!
|
data/init.rb
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require File::expand_path(File::join(File::dirname(__FILE__), 'lib', 'mojo_magick'))
|
@@ -0,0 +1,124 @@
|
|
1
|
+
# This module provides some mix-in methods to permit resource limitation commands in MojoMagick
|
2
|
+
# They're stored here simply to make MojoMagick more readable
|
3
|
+
module ImageMagickResources
|
4
|
+
module ResourceLimits
|
5
|
+
@@resource_limits = {}
|
6
|
+
|
7
|
+
# controls limits on memory and other resources for imagemagick.
|
8
|
+
# possible values for type can include:
|
9
|
+
# Area, Disk, File, Map, or Memory
|
10
|
+
# value is byte size for everything but Disk, where it's number of files
|
11
|
+
# type can be string or symbol.
|
12
|
+
# Just limiting Memory will not solve problems with imagemagick going out of
|
13
|
+
# control with resource consumption on certain bad files. You have to set disk,
|
14
|
+
# area and map limits too. Read up on imagemagick website for more.
|
15
|
+
# Different options have different units
|
16
|
+
# DISK: N GB
|
17
|
+
# AREA, MAP, MEMORY: N MB
|
18
|
+
# FILE: N num file handles
|
19
|
+
# Examples:
|
20
|
+
# # set disk to 5 gigabytes limit
|
21
|
+
# MiniMagick::Image::set_limit(:disk => 5)
|
22
|
+
# # set memory to 32mb, map to 64mb and disk to 0
|
23
|
+
# MiniMagick::Image::set_limit(:memory => 32, 'map' => 64, 'disk' => 0)
|
24
|
+
def set_limits(options)
|
25
|
+
mem_fix = 1
|
26
|
+
options.each do |resource, value|
|
27
|
+
@@resource_limits[resource.to_s.downcase.to_sym] = value.to_s
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
# remove a limit
|
32
|
+
def remove_limits(*options)
|
33
|
+
mem_fix = 1
|
34
|
+
@@resource_limits.delete_if do |resource, value|
|
35
|
+
resource == options.values_at(options.index(resource))[0].to_s.downcase.to_sym
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
# remove limits from resources
|
40
|
+
def unset_limits(options = {})
|
41
|
+
mem_fix = 1
|
42
|
+
@@resource_limits = {}
|
43
|
+
if options[:unset_env]
|
44
|
+
ENV["MAGICK_AREA_LIMIT"]=nil
|
45
|
+
ENV["MAGICK_MAP_LIMIT"]=nil
|
46
|
+
ENV["MAGICK_MEMORY_LIMIT"]=nil
|
47
|
+
ENV["MAGICK_DISK_LIMIT"]=nil
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
# returns the default limits that imagemagick is using, when run with no "-limit" parameters
|
52
|
+
# options:
|
53
|
+
# :show_actual_values => true (default false) - will return integers instead of readable values
|
54
|
+
def get_default_limits(options = {})
|
55
|
+
mem_fix = 1
|
56
|
+
parse_limits(options.merge(:get_current_limits => false))
|
57
|
+
end
|
58
|
+
|
59
|
+
# returns the limits that imagemagick is running based on any "set_limits" calls
|
60
|
+
def get_current_limits(options = {})
|
61
|
+
mem_fix = 1
|
62
|
+
parse_limits(options.merge(:get_current_limits => true))
|
63
|
+
end
|
64
|
+
|
65
|
+
alias :get_limits :get_current_limits
|
66
|
+
|
67
|
+
def parse_limits(options)
|
68
|
+
show_actual_values = options[:show_actual_values]
|
69
|
+
if options[:get_current_limits]
|
70
|
+
raw_limits = self.raw_command('identify', '-list resource')
|
71
|
+
else
|
72
|
+
# we run a raw shell command here to obtain limits without applying command line limit params
|
73
|
+
raw_limits = `identify -list resource`
|
74
|
+
end
|
75
|
+
row_limits = raw_limits.split("\n")
|
76
|
+
header = row_limits[0].chomp
|
77
|
+
data = row_limits[2].chomp
|
78
|
+
resources = header.strip.split
|
79
|
+
limits = data.strip.split
|
80
|
+
#resources = header.scan(/^ *([A-Z][a-z]+) +([A-Z][a-z]+) +([A-Z][a-z]+) +([A-Z][a-z]+) +([A-Z][a-z]+)/)[0]
|
81
|
+
#limits = data.scan(/^ *([0-9]+[.0-9a-z]+) +([0-9]+[.0-9a-z]+) +([0-9]+[.0-9a-z]+) +([0-9]+[.0-9a-z]+) +([0-9]+[.0-9a-z]+)/)[0]
|
82
|
+
actual_values = {}
|
83
|
+
readable_values = {}
|
84
|
+
resources.each_index do |i|
|
85
|
+
resource = resources[i].downcase.to_sym
|
86
|
+
scale = limits[i].match(%r{[a-z]+$}) || []
|
87
|
+
value = limits[i].match(%r{^[0-9]+})
|
88
|
+
unscaled_value = value ? value[0].to_i : -1
|
89
|
+
case scale[0]
|
90
|
+
when 'eb'
|
91
|
+
scaled_value = unscaled_value * (2 ** 60)
|
92
|
+
when 'pb'
|
93
|
+
scaled_value = unscaled_value * (2 ** 50)
|
94
|
+
when 'tb'
|
95
|
+
scaled_value = unscaled_value * (2 ** 40)
|
96
|
+
when 'gb'
|
97
|
+
scaled_value = unscaled_value * (2 ** 30)
|
98
|
+
when 'mb'
|
99
|
+
scaled_value = unscaled_value * (2 ** 20)
|
100
|
+
when 'kb'
|
101
|
+
scaled_value = unscaled_value * (2 ** 10)
|
102
|
+
when 'b'
|
103
|
+
scaled_value = unscaled_value
|
104
|
+
else
|
105
|
+
scaled_value = unscaled_value
|
106
|
+
end
|
107
|
+
actual_values[resource] = scaled_value
|
108
|
+
readable_values[resource] = limits[i]
|
109
|
+
end
|
110
|
+
# return actual values if requested in options, otherwise readable values
|
111
|
+
show_actual_values ? actual_values : readable_values
|
112
|
+
end # parse_limits
|
113
|
+
|
114
|
+
# returns a string suitable for passing as a set of imagemagick params
|
115
|
+
# that contains all the limit constraints
|
116
|
+
def get_limits_as_params
|
117
|
+
retval = ''
|
118
|
+
@@resource_limits.each do |type, value|
|
119
|
+
retval += " -limit #{type.to_s} #{value} "
|
120
|
+
end
|
121
|
+
retval
|
122
|
+
end
|
123
|
+
end
|
124
|
+
end
|
data/lib/mojo_magick.rb
ADDED
@@ -0,0 +1,226 @@
|
|
1
|
+
require File::expand_path(File::join(File::dirname(__FILE__), 'image_resources'))
|
2
|
+
require 'tempfile'
|
3
|
+
|
4
|
+
# MojoMagick is a stateless set of module methods which present a convient interface
|
5
|
+
# for accessing common tasks for ImageMagick command line library.
|
6
|
+
#
|
7
|
+
# MojoMagick is specifically designed to be efficient and simple and most importantly
|
8
|
+
# to not leak any memory. For complex image operations, you will find MojoMagick limited.
|
9
|
+
# You might consider the venerable MiniMagick or RMagick for your purposes if you care more
|
10
|
+
# about ease of use rather than speed and memory management.
|
11
|
+
|
12
|
+
# all commands raise "MojoMagick::MojoFailed" if command fails (ImageMagick determines command success status)
|
13
|
+
|
14
|
+
# Two command-line builders, #convert and #mogrify, have been added to simplify
|
15
|
+
# complex commands. Examples included below.
|
16
|
+
#
|
17
|
+
# Example #convert usage:
|
18
|
+
#
|
19
|
+
# MojoMagick::convert('source.jpg', 'dest.jpg') do |c|
|
20
|
+
# c.crop '250x250+0+0'
|
21
|
+
# c.repage!
|
22
|
+
# c.strip
|
23
|
+
# c.set 'comment', 'my favorite file'
|
24
|
+
# end
|
25
|
+
#
|
26
|
+
# Equivalent to:
|
27
|
+
#
|
28
|
+
# MojoMagick::raw_command('convert', 'source.jpg -crop 250x250+0+0 +repage -strip -set comment "my favorite file" dest.jpg')
|
29
|
+
#
|
30
|
+
# Example #mogrify usage:
|
31
|
+
#
|
32
|
+
# MojoMagick::mogrify('image.jpg') {|i| i.shave '10x10'}
|
33
|
+
#
|
34
|
+
# Equivalent to:
|
35
|
+
#
|
36
|
+
# MojoMagick::raw_command('mogrify', '-shave 10x10 image.jpg')
|
37
|
+
#
|
38
|
+
# Example showing some additional options:
|
39
|
+
#
|
40
|
+
# MojoMagick::convert do |c|
|
41
|
+
# c.file 'source.jpg'
|
42
|
+
# c.blob my_binary_data
|
43
|
+
# c.append
|
44
|
+
# c.crop '256x256+0+0'
|
45
|
+
# c.repage!
|
46
|
+
# c.file 'output.jpg'
|
47
|
+
# end
|
48
|
+
#
|
49
|
+
# Use .file to specify file names, .blob to create and include a tempfile. The
|
50
|
+
# bang (!) can be appended to command names to use the '+' versions
|
51
|
+
# instead of '-' versions.
|
52
|
+
#
|
53
|
+
module MojoMagick
|
54
|
+
|
55
|
+
VERSION = "0.2.0"
|
56
|
+
|
57
|
+
class MojoMagickException < StandardError; end
|
58
|
+
class MojoError < MojoMagickException; end
|
59
|
+
class MojoFailed < MojoMagickException; end
|
60
|
+
|
61
|
+
# enable resource limiting functionality
|
62
|
+
extend ImageMagickResources::ResourceLimits
|
63
|
+
|
64
|
+
def MojoMagick::windows?
|
65
|
+
mem_fix = 1
|
66
|
+
!(RUBY_PLATFORM =~ /win32/).nil?
|
67
|
+
end
|
68
|
+
|
69
|
+
def MojoMagick::raw_command(command, args, options = {})
|
70
|
+
# this suppress error messages to the console
|
71
|
+
err_pipe = windows? ? "2>nul" : "2>/dev/null"
|
72
|
+
begin
|
73
|
+
execute = "#{command} #{get_limits_as_params} #{args} #{err_pipe}"
|
74
|
+
retval = `#{execute}`
|
75
|
+
# guarantee that only MojoError exceptions are raised here
|
76
|
+
rescue Exception => e
|
77
|
+
raise MojoError, "#{e.class}: #{e.message}"
|
78
|
+
end
|
79
|
+
if $? && !$?.success?
|
80
|
+
err_msg = options[:err_msg] || "MojoMagick command failed: #{command}."
|
81
|
+
raise(MojoFailed, "#{err_msg} (Exit status: #{$?.exitstatus})\n Command: #{execute}")
|
82
|
+
end
|
83
|
+
retval
|
84
|
+
end
|
85
|
+
|
86
|
+
def MojoMagick::shrink(source_file, dest_file, options)
|
87
|
+
opts = options.dup
|
88
|
+
opts.delete(:expand_only)
|
89
|
+
MojoMagick::resize(source_file, dest_file, opts.merge(:shrink_only => true))
|
90
|
+
end
|
91
|
+
|
92
|
+
def MojoMagick::expand(source_file, dest_file, options)
|
93
|
+
opts = options.dup
|
94
|
+
opts.delete(:shrink_only)
|
95
|
+
MojoMagick::resize(source_file, dest_file, opts.merge(:expand_only => true))
|
96
|
+
end
|
97
|
+
|
98
|
+
# resizes an image and returns the filename written to
|
99
|
+
# options:
|
100
|
+
# :width / :height => scale to these dimensions
|
101
|
+
# :scale => pass scale options such as ">" to force shrink scaling only or "!" to force absolute width/height scaling (do not preserve aspect ratio)
|
102
|
+
# :percent => scale image to this percentage (do not specify :width/:height in this case)
|
103
|
+
def MojoMagick::resize(source_file, dest_file, options)
|
104
|
+
retval = nil
|
105
|
+
scale_options = []
|
106
|
+
scale_options << '">"' unless options[:shrink_only].nil?
|
107
|
+
scale_options << '"<"' unless options[:expand_only].nil?
|
108
|
+
scale_options << '"!"' unless options[:absolute_aspect].nil?
|
109
|
+
scale_options << '"^"' unless options[:fill].nil?
|
110
|
+
scale_options = scale_options.join(' ')
|
111
|
+
|
112
|
+
extras = []
|
113
|
+
if !options[:width].nil? && !options[:height].nil?
|
114
|
+
geometry = "#{options[:width]}X#{options[:height]}"
|
115
|
+
elsif !options[:percent].nil?
|
116
|
+
geometry = "#{options[:percent]}%"
|
117
|
+
else
|
118
|
+
raise MojoMagickError, "Unknown options for method resize: #{options.inspect}"
|
119
|
+
end
|
120
|
+
if !options[:fill].nil? && !options[:crop].nil?
|
121
|
+
extras << "-extent #{geometry}"
|
122
|
+
extras << "-gravity center"
|
123
|
+
end
|
124
|
+
retval = raw_command("convert", "\"#{source_file}\" -resize #{geometry}#{scale_options} #{extras.join(' ')} \"#{dest_file}\"")
|
125
|
+
dest_file
|
126
|
+
end
|
127
|
+
|
128
|
+
# returns an empty hash or a hash with :width and :height set (e.g. {:width => INT, :height => INT})
|
129
|
+
# raises MojoFailed when results are indeterminate (width and height could not be determined)
|
130
|
+
def MojoMagick::get_image_size(source_file)
|
131
|
+
# returns width, height of image if available, nil if not
|
132
|
+
retval = raw_command("identify", "-format \"w:%w h:%h\" \"#{source_file}\"")
|
133
|
+
return {} if !retval
|
134
|
+
width = retval.match(%r{w:([0-9]+) })
|
135
|
+
width = width ? width[1].to_i : nil
|
136
|
+
height = retval.match(%r{h:([0-9]+)})
|
137
|
+
height = height ? height[1].to_i : nil
|
138
|
+
raise(MojoFailed, "Indeterminate results in get_image_size: #{source_file}") if !height || !width
|
139
|
+
{:width=>width, :height=>height}
|
140
|
+
end
|
141
|
+
|
142
|
+
def MojoMagick::convert(source = nil, dest = nil)
|
143
|
+
opts = OptBuilder.new
|
144
|
+
opts.file source if source
|
145
|
+
yield opts
|
146
|
+
opts.file dest if dest
|
147
|
+
raw_command('convert', opts.to_s)
|
148
|
+
end
|
149
|
+
|
150
|
+
def MojoMagick::mogrify(dest = nil)
|
151
|
+
opts = OptBuilder.new
|
152
|
+
yield opts
|
153
|
+
opts.file dest if dest
|
154
|
+
raw_command('mogrify', opts.to_s)
|
155
|
+
end
|
156
|
+
|
157
|
+
# Option builder used in #convert and #mogrify helpers.
|
158
|
+
class OptBuilder
|
159
|
+
def initialize
|
160
|
+
@opts = []
|
161
|
+
end
|
162
|
+
|
163
|
+
# Add command-line options with no processing
|
164
|
+
def <<(arg)
|
165
|
+
if arg.is_a?(Array)
|
166
|
+
@opts += arg
|
167
|
+
else
|
168
|
+
@opts << arg
|
169
|
+
end
|
170
|
+
self
|
171
|
+
end
|
172
|
+
|
173
|
+
# Add files to command line, formatted if necessary
|
174
|
+
def file(*args)
|
175
|
+
args.each do |arg|
|
176
|
+
add_formatted arg
|
177
|
+
end
|
178
|
+
self
|
179
|
+
end
|
180
|
+
alias files file
|
181
|
+
|
182
|
+
# Create a temporary file for the given image and add to command line
|
183
|
+
def blob(arg)
|
184
|
+
file MojoMagick::tempfile(arg)
|
185
|
+
end
|
186
|
+
|
187
|
+
# Generic commands. Arguments will be formatted if necessary
|
188
|
+
def method_missing(command, *args)
|
189
|
+
if command.to_s[-1, 1] == '!'
|
190
|
+
@opts << "+#{command.to_s.chop}"
|
191
|
+
else
|
192
|
+
@opts << "-#{command}"
|
193
|
+
end
|
194
|
+
args.each do |arg|
|
195
|
+
add_formatted arg
|
196
|
+
end
|
197
|
+
self
|
198
|
+
end
|
199
|
+
|
200
|
+
def to_s
|
201
|
+
@opts.join ' '
|
202
|
+
end
|
203
|
+
|
204
|
+
protected
|
205
|
+
def add_formatted(arg)
|
206
|
+
# Quote anything that would cause problems on *nix or windows
|
207
|
+
if arg =~ /[<>^|&();` ]/
|
208
|
+
@opts << "\"#{arg.gsub('"', '\"')}\""
|
209
|
+
else
|
210
|
+
@opts << arg
|
211
|
+
end
|
212
|
+
end
|
213
|
+
end
|
214
|
+
|
215
|
+
def MojoMagick::tempfile(data)
|
216
|
+
file = Tempfile.new("mojo")
|
217
|
+
file.binmode
|
218
|
+
file.write(data)
|
219
|
+
file.path
|
220
|
+
ensure
|
221
|
+
file.close
|
222
|
+
end
|
223
|
+
|
224
|
+
end # MojoMagick
|
225
|
+
|
226
|
+
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
File without changes
|
File without changes
|
@@ -0,0 +1,248 @@
|
|
1
|
+
require 'test/unit'
|
2
|
+
require File::expand_path(File::join(File::dirname(__FILE__), '..', 'init'))
|
3
|
+
require 'fileutils'
|
4
|
+
require 'tempfile'
|
5
|
+
|
6
|
+
class MojoMagickTest < Test::Unit::TestCase
|
7
|
+
|
8
|
+
# we keep a fixtures path and a working path so that we can easily test image
|
9
|
+
# manipulation routines without tainting the original images
|
10
|
+
def setup
|
11
|
+
@fixtures_path = File.expand_path(File::join(File.dirname(__FILE__), 'fixtures'))
|
12
|
+
@working_path = File::join(@fixtures_path, 'tmp')
|
13
|
+
end
|
14
|
+
|
15
|
+
def reset_images
|
16
|
+
FileUtils::rm_r(@working_path) if File::exists?(@working_path)
|
17
|
+
FileUtils::mkdir(@working_path)
|
18
|
+
Dir::glob(File::join(@fixtures_path, '*')).each do |file|
|
19
|
+
FileUtils::cp(file, @working_path) if File::file?(file)
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
def test_image_management
|
24
|
+
reset_images
|
25
|
+
test_image = File::join(@working_path, '5742.jpg')
|
26
|
+
orig_image_size = File::size(test_image)
|
27
|
+
retval = MojoMagick::get_image_size(test_image)
|
28
|
+
assert_equal orig_image_size, File::size(test_image)
|
29
|
+
assert_equal 500, retval[:height]
|
30
|
+
assert_equal 333, retval[:width]
|
31
|
+
|
32
|
+
# test basic resizing
|
33
|
+
size_test_temp = Tempfile::new('mojo_test')
|
34
|
+
size_test = size_test_temp.path
|
35
|
+
retval = MojoMagick::resize(test_image, size_test, {:width=>100, :height=>100})
|
36
|
+
assert_equal size_test, retval
|
37
|
+
assert_equal orig_image_size, File::size(test_image)
|
38
|
+
assert_equal retval, size_test
|
39
|
+
new_dimensions = MojoMagick::get_image_size(size_test)
|
40
|
+
assert_equal 100, new_dimensions[:height]
|
41
|
+
assert_equal 67, new_dimensions[:width]
|
42
|
+
|
43
|
+
# we should be able to resize image right over itself
|
44
|
+
retval = MojoMagick::resize(test_image, test_image, {:width=>100, :height=>100})
|
45
|
+
assert_equal test_image, retval
|
46
|
+
assert_not_equal orig_image_size, File::size(test_image)
|
47
|
+
new_dimensions = MojoMagick::get_image_size(test_image)
|
48
|
+
assert_equal 100, new_dimensions[:height]
|
49
|
+
assert_equal 67, new_dimensions[:width]
|
50
|
+
|
51
|
+
# image shouldn't resize if we specify very large dimensions and specify "shrink_only"
|
52
|
+
reset_images
|
53
|
+
orig_image_size = File::size(test_image)
|
54
|
+
retval = MojoMagick::shrink(test_image, test_image, {:width=>1000, :height=>1000})
|
55
|
+
assert_equal test_image, retval
|
56
|
+
new_dimensions = MojoMagick::get_image_size(test_image)
|
57
|
+
assert_equal 500, new_dimensions[:height]
|
58
|
+
assert_equal 333, new_dimensions[:width]
|
59
|
+
# image should resize if we specify small dimensions and shrink_only
|
60
|
+
retval = MojoMagick::shrink(test_image, test_image, {:width=>1000, :height=>100})
|
61
|
+
assert_equal test_image, retval
|
62
|
+
new_dimensions = MojoMagick::get_image_size(test_image)
|
63
|
+
assert_equal 100, new_dimensions[:height]
|
64
|
+
assert_equal 67, new_dimensions[:width]
|
65
|
+
|
66
|
+
# image shouldn't resize if we specify small dimensions and expand_only
|
67
|
+
reset_images
|
68
|
+
orig_image_size = File::size(test_image)
|
69
|
+
retval = MojoMagick::expand(test_image, test_image, {:width=>10, :height=>10})
|
70
|
+
assert_equal test_image, retval
|
71
|
+
new_dimensions = MojoMagick::get_image_size(test_image)
|
72
|
+
assert_equal 500, new_dimensions[:height]
|
73
|
+
assert_equal 333, new_dimensions[:width]
|
74
|
+
# image should resize if we specify large dimensions and expand_only
|
75
|
+
retval = MojoMagick::expand(test_image, test_image, {:width=>1000, :height=>1000})
|
76
|
+
assert_equal test_image, retval
|
77
|
+
new_dimensions = MojoMagick::get_image_size(test_image)
|
78
|
+
assert_equal 1000, new_dimensions[:height]
|
79
|
+
assert_equal 666, new_dimensions[:width]
|
80
|
+
|
81
|
+
|
82
|
+
# test bad images
|
83
|
+
bad_image = File::join(@working_path, 'not_an_image.jpg')
|
84
|
+
zero_image = File::join(@working_path, 'zero_byte_image.jpg')
|
85
|
+
assert_raise(MojoMagick::MojoFailed) {MojoMagick::get_image_size(bad_image)}
|
86
|
+
assert_raise(MojoMagick::MojoFailed) {MojoMagick::get_image_size(zero_image)}
|
87
|
+
assert_raise(MojoMagick::MojoFailed) {MojoMagick::get_image_size('/file_does_not_exist_here_ok.jpg')}
|
88
|
+
end
|
89
|
+
|
90
|
+
def test_resource_limits
|
91
|
+
orig_limits = MojoMagick::get_default_limits
|
92
|
+
assert_equal 7, orig_limits.size
|
93
|
+
orig_limits_test = orig_limits.dup
|
94
|
+
orig_limits_test.delete_if do |resource, value|
|
95
|
+
assert [:area, :map, :disk, :memory, :file, :thread, :time].include?(resource), "Found unexpected resource #{resource}"
|
96
|
+
true
|
97
|
+
end
|
98
|
+
assert_equal 0, orig_limits_test.size
|
99
|
+
|
100
|
+
# set area to 32mb limit
|
101
|
+
MojoMagick::set_limits(:area => '32mb')
|
102
|
+
new_limits = MojoMagick::get_current_limits
|
103
|
+
assert_equal '32mb', new_limits[:area].downcase
|
104
|
+
|
105
|
+
# remove limits on area
|
106
|
+
MojoMagick::remove_limits(:area)
|
107
|
+
new_limits = MojoMagick::get_current_limits
|
108
|
+
assert_equal orig_limits[:area], new_limits[:area]
|
109
|
+
|
110
|
+
# set memory to 64 mb, disk to 0 and
|
111
|
+
MojoMagick::set_limits(:memory => '64mb', :disk => '0b')
|
112
|
+
new_limits = MojoMagick::get_current_limits(:show_actual_values => true)
|
113
|
+
assert_equal 61, new_limits[:memory]
|
114
|
+
assert_equal 0, new_limits[:disk]
|
115
|
+
|
116
|
+
# return to original/default limit values
|
117
|
+
MojoMagick::unset_limits
|
118
|
+
new_limits = MojoMagick::get_current_limits
|
119
|
+
assert_equal orig_limits, new_limits
|
120
|
+
end
|
121
|
+
|
122
|
+
def test_tempfile
|
123
|
+
# Create a tempfile and return the path
|
124
|
+
filename = MojoMagick::tempfile('binary data')
|
125
|
+
File.open(filename, 'rb') do |f|
|
126
|
+
assert_equal f.read, 'binary data'
|
127
|
+
end
|
128
|
+
end
|
129
|
+
|
130
|
+
# These tests make the assumption that if we call #raw_command with the
|
131
|
+
# correct strings, ImageMagick itself will operate correctly. We're only
|
132
|
+
# verifying that the option builder produces the correct strings.
|
133
|
+
def test_option_builder
|
134
|
+
# Passing in basic commands produces a string
|
135
|
+
b = MojoMagick::OptBuilder.new
|
136
|
+
b.strip
|
137
|
+
b.repage
|
138
|
+
assert_equal '-strip -repage', b.to_s
|
139
|
+
|
140
|
+
# Chaining commands works
|
141
|
+
b = MojoMagick::OptBuilder.new.strip.repage
|
142
|
+
assert_equal '-strip -repage', b.to_s
|
143
|
+
|
144
|
+
# Bang (!) indicates the plus version of commands
|
145
|
+
b = MojoMagick::OptBuilder.new
|
146
|
+
b.repage
|
147
|
+
b.repage!
|
148
|
+
assert_equal '-repage +repage', b.to_s
|
149
|
+
|
150
|
+
# Accepts raw data as-is
|
151
|
+
b = MojoMagick::OptBuilder.new
|
152
|
+
b.opt1
|
153
|
+
b << 'a ! b !'
|
154
|
+
b.opt2
|
155
|
+
assert_equal '-opt1 a ! b ! -opt2', b.to_s
|
156
|
+
|
157
|
+
# Treats an array of raw data as different arguments
|
158
|
+
b = MojoMagick::OptBuilder.new
|
159
|
+
b << ['leave this data','alone']
|
160
|
+
assert_equal 'leave this data alone', b.to_s
|
161
|
+
|
162
|
+
# String includes command arguments
|
163
|
+
b = MojoMagick::OptBuilder.new
|
164
|
+
b.extent '256x256+0+0'
|
165
|
+
b.crop '64x64'
|
166
|
+
assert_equal '-extent 256x256+0+0 -crop 64x64', b.to_s
|
167
|
+
|
168
|
+
# Arguments are quoted (doublequote) if appropriate
|
169
|
+
b = MojoMagick::OptBuilder.new
|
170
|
+
b.comment 'white space'
|
171
|
+
b.comment 'w&b'
|
172
|
+
b.crop '6x6^'
|
173
|
+
assert_equal '-comment "white space" -comment "w&b" -crop "6x6^"', b.to_s
|
174
|
+
|
175
|
+
# Existing doublequotes are escaped
|
176
|
+
b = MojoMagick::OptBuilder.new
|
177
|
+
b.comment 'Fred "Woot" Rook'
|
178
|
+
assert_equal '-comment "Fred \"Woot\" Rook"', b.to_s
|
179
|
+
|
180
|
+
# Multi-argument commands should not be quoted together
|
181
|
+
b = MojoMagick::OptBuilder.new
|
182
|
+
b.set 'comment', 'the "best" comment'
|
183
|
+
assert_equal '-set comment "the \"best\" comment"', b.to_s
|
184
|
+
|
185
|
+
# File and files are helper methods
|
186
|
+
b = MojoMagick::OptBuilder.new
|
187
|
+
b.files 'source.jpg', 'source2.jpg'
|
188
|
+
b.append
|
189
|
+
b.crop '64x64'
|
190
|
+
b.file 'dest%d.jpg'
|
191
|
+
assert_equal 'source.jpg source2.jpg -append -crop 64x64 dest%d.jpg', b.to_s
|
192
|
+
|
193
|
+
# Files are quoted (doublequote) if appropriate
|
194
|
+
b = MojoMagick::OptBuilder.new
|
195
|
+
b.file 'probably on windows.jpg'
|
196
|
+
assert_equal '"probably on windows.jpg"', b.to_s
|
197
|
+
|
198
|
+
# Blob is a shortcut for the #tempfile helper method
|
199
|
+
b = MojoMagick::OptBuilder.new
|
200
|
+
b.blob 'binary data'
|
201
|
+
filename = b.to_s
|
202
|
+
File.open(filename, 'rb') do |f|
|
203
|
+
assert_equal f.read, 'binary data'
|
204
|
+
end
|
205
|
+
end
|
206
|
+
|
207
|
+
def test_command_helpers
|
208
|
+
reset_images
|
209
|
+
test_image = File::join(@working_path, '5742.jpg')
|
210
|
+
out_image = File::join(@working_path, 'out1.jpg')
|
211
|
+
|
212
|
+
# Simple convert test
|
213
|
+
MojoMagick::convert do |c|
|
214
|
+
c.file test_image
|
215
|
+
c.crop '92x64+0+0'
|
216
|
+
c.repage!
|
217
|
+
c.file out_image
|
218
|
+
end
|
219
|
+
retval = MojoMagick::get_image_size(out_image)
|
220
|
+
assert_equal 92, retval[:width]
|
221
|
+
assert_equal 64, retval[:height]
|
222
|
+
|
223
|
+
# Simple mogrify test
|
224
|
+
MojoMagick::mogrify do |m|
|
225
|
+
m.crop '32x32+0+0'
|
226
|
+
m.repage!
|
227
|
+
m.file out_image
|
228
|
+
end
|
229
|
+
retval = MojoMagick::get_image_size(out_image)
|
230
|
+
assert_equal 32, retval[:width]
|
231
|
+
assert_equal 32, retval[:height]
|
232
|
+
|
233
|
+
# Convert test, using file shortcuts
|
234
|
+
MojoMagick::convert(test_image, out_image) do |c|
|
235
|
+
c.crop '100x100+0+0'
|
236
|
+
c.repage!
|
237
|
+
end
|
238
|
+
retval = MojoMagick::get_image_size(out_image)
|
239
|
+
assert_equal 100, retval[:width]
|
240
|
+
assert_equal 100, retval[:height]
|
241
|
+
|
242
|
+
# Mogrify test, using file shortcut
|
243
|
+
MojoMagick::mogrify(out_image) { |m| m.shave('25x25').repage! }
|
244
|
+
retval = MojoMagick::get_image_size(out_image)
|
245
|
+
assert_equal 50, retval[:width]
|
246
|
+
assert_equal 50, retval[:height]
|
247
|
+
end
|
248
|
+
end
|
metadata
ADDED
@@ -0,0 +1,74 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: mojo_magick
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
prerelease:
|
5
|
+
version: 0.3.0
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Steve Midgley
|
9
|
+
- Elliot Nelson
|
10
|
+
- Jon Rogers
|
11
|
+
autorequire:
|
12
|
+
bindir: bin
|
13
|
+
cert_chain: []
|
14
|
+
|
15
|
+
date: 2011-08-28 00:00:00 Z
|
16
|
+
dependencies: []
|
17
|
+
|
18
|
+
description: Simple Ruby stateless module interface to imagemagick.
|
19
|
+
email:
|
20
|
+
- public@misuse.org
|
21
|
+
- j@2rye.com
|
22
|
+
executables: []
|
23
|
+
|
24
|
+
extensions: []
|
25
|
+
|
26
|
+
extra_rdoc_files: []
|
27
|
+
|
28
|
+
files:
|
29
|
+
- README
|
30
|
+
- init.rb
|
31
|
+
- lib/image_resources.rb
|
32
|
+
- lib/mojo_magick.rb
|
33
|
+
- test/fixtures/5742.jpg
|
34
|
+
- test/fixtures/not_an_image.jpg
|
35
|
+
- test/fixtures/tmp/5742.jpg
|
36
|
+
- test/fixtures/tmp/not_an_image.jpg
|
37
|
+
- test/fixtures/tmp/zero_byte_image.jpg
|
38
|
+
- test/fixtures/zero_byte_image.jpg
|
39
|
+
- test/mojo_magick_test.rb
|
40
|
+
homepage: http://github.com/bunnymatic/mojo_magick
|
41
|
+
licenses: []
|
42
|
+
|
43
|
+
post_install_message:
|
44
|
+
rdoc_options: []
|
45
|
+
|
46
|
+
require_paths:
|
47
|
+
- lib
|
48
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
49
|
+
none: false
|
50
|
+
requirements:
|
51
|
+
- - ">="
|
52
|
+
- !ruby/object:Gem::Version
|
53
|
+
version: "0"
|
54
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
55
|
+
none: false
|
56
|
+
requirements:
|
57
|
+
- - ">="
|
58
|
+
- !ruby/object:Gem::Version
|
59
|
+
version: "0"
|
60
|
+
requirements: []
|
61
|
+
|
62
|
+
rubyforge_project: mojo_magick
|
63
|
+
rubygems_version: 1.8.5
|
64
|
+
signing_key:
|
65
|
+
specification_version: 3
|
66
|
+
summary: mojo_magick-0.3.0
|
67
|
+
test_files:
|
68
|
+
- test/fixtures/5742.jpg
|
69
|
+
- test/fixtures/not_an_image.jpg
|
70
|
+
- test/fixtures/tmp/5742.jpg
|
71
|
+
- test/fixtures/tmp/not_an_image.jpg
|
72
|
+
- test/fixtures/tmp/zero_byte_image.jpg
|
73
|
+
- test/fixtures/zero_byte_image.jpg
|
74
|
+
- test/mojo_magick_test.rb
|