mojo_magick 0.3.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/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
|