tupalo-mini_magick 1.2.5

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/.gitignore ADDED
@@ -0,0 +1 @@
1
+ /pkg
data/MIT-LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ Copyright (c) 2005 Corey Johnson probablycorey@gmail.com
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21
+
data/README.rdoc ADDED
@@ -0,0 +1,72 @@
1
+ = MiniMagick
2
+
3
+ A ruby wrapper for ImageMagick command line.
4
+
5
+
6
+ == Why?
7
+
8
+ I was using RMagick and loving it, but it was eating up huge amounts
9
+ of memory. A simple script like this...
10
+
11
+ Magick::read("image.jpg") do |f|
12
+ f.write("manipulated.jpg")
13
+ end
14
+
15
+ ...would use over 100 Megs of Ram. On my local machine this wasn't a
16
+ problem, but on my hosting server the ruby apps would crash because of
17
+ their 100 Meg memory limit.
18
+
19
+
20
+ == Solution!
21
+
22
+ Using MiniMagick the ruby processes memory remains small (it spawns
23
+ ImageMagick's command line program mogrify which takes up some memory
24
+ as well, but is much smaller compared to RMagick)
25
+
26
+ MiniMagick gives you access to all the commandline options ImageMagick
27
+ has (Found here http://www.imagemagick.org/script/mogrify.php)
28
+
29
+
30
+ == Examples
31
+
32
+ Want to make a thumbnail from a file...
33
+
34
+ image = MiniMagick::Image.from_file("input.jpg")
35
+ image.resize "100x100"
36
+ image.write("output.jpg")
37
+
38
+ Want to make a thumbnail from a blob...
39
+
40
+ image = MiniMagick::Image.from_blob(blob)
41
+ image.resize "100x100"
42
+ image.write("output.jpg")
43
+
44
+ Need to combine several options?
45
+
46
+ image = MiniMagick::Image.from_file("input.jpg")
47
+ image.combine_options do |c|
48
+ c.sample "50%"
49
+ c.rotate "-90>"
50
+ end
51
+ image.write("output.jpg")
52
+
53
+ Want to manipulate an image at its source (You won't have to write it
54
+ out because the transformations are done on that file)
55
+
56
+ image = MiniMagick::Image.new("input.jpg")
57
+ image.resize "100x100"
58
+
59
+ Want to get some meta-information out?
60
+
61
+ image = MiniMagick::Image.from_file("input.jpg")
62
+ image[:width] # will get the width (you can also use :height and :format)
63
+ image["EXIF:BitsPerSample"] # It also can get all the EXIF tags
64
+ image["%m:%f %wx%h"] # Or you can use one of the many options of the format command
65
+
66
+ For more on the format command see
67
+ http://www.imagemagick.org/script/command-line-options.php#format
68
+
69
+
70
+ == Requirements
71
+
72
+ You must have ImageMagick installed.
data/Rakefile ADDED
@@ -0,0 +1,39 @@
1
+ require 'rake'
2
+ require 'rake/testtask'
3
+ require 'rake/rdoctask'
4
+
5
+ $:.unshift(File.dirname(__FILE__) + "/lib")
6
+ require 'mini_magick'
7
+
8
+ desc 'Default: run unit tests.'
9
+ task :default => :test
10
+
11
+ desc 'Test the mini_magick plugin.'
12
+ Rake::TestTask.new(:test) do |t|
13
+ t.libs << 'lib'
14
+ t.pattern = 'test/**/*_test.rb'
15
+ t.verbose = true
16
+ end
17
+
18
+ desc 'Generate documentation for the mini_magick plugin.'
19
+ Rake::RDocTask.new(:rdoc) do |rdoc|
20
+ rdoc.rdoc_dir = 'rdoc'
21
+ rdoc.title = 'MiniMagick'
22
+ rdoc.options << '--line-numbers'
23
+ rdoc.options << '--inline-source'
24
+ rdoc.rdoc_files.include('README.rdoc')
25
+ rdoc.rdoc_files.include('lib/**/*.rb')
26
+ end
27
+
28
+ begin
29
+ require 'jeweler'
30
+ Jeweler::Tasks.new do |gemspec|
31
+ gemspec.name = "mini_magick"
32
+ gemspec.summary = "Manipulate images with minimal use of memory."
33
+ gemspec.email = "probablycorey@gmail.com"
34
+ gemspec.homepage = "http://github.com/probablycorey/mini_magick"
35
+ gemspec.authors = ["Corey Johnson"]
36
+ end
37
+ rescue LoadError
38
+ puts "Jeweler not available. Install it with: sudo gem install technicalpickles-jeweler -s http://gems.github.com"
39
+ end
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 1.2.5
@@ -0,0 +1,9 @@
1
+ require "tempfile"
2
+
3
+ module MiniMagick
4
+ class ImageTempFile < Tempfile
5
+ def make_tmpname(ext, n)
6
+ 'mini_magick%d-%d%s' % [$$, n, ext ? ".#{ext}" : '']
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,223 @@
1
+ require "open-uri"
2
+ require "stringio"
3
+ require "fileutils"
4
+ require "open3"
5
+
6
+ require File.join(File.dirname(__FILE__), '/image_temp_file')
7
+
8
+ module MiniMagick
9
+ class MiniMagickError < RuntimeError; end
10
+
11
+ class Image
12
+ attr :path
13
+ attr :tempfile
14
+ attr :output
15
+
16
+ # Class Methods
17
+ # -------------
18
+ class << self
19
+ def from_blob(blob, ext = nil)
20
+ begin
21
+ tempfile = ImageTempFile.new(ext)
22
+ tempfile.binmode
23
+ tempfile.write(blob)
24
+ ensure
25
+ tempfile.close if tempfile
26
+ end
27
+
28
+ return self.new(tempfile.path, tempfile)
29
+ end
30
+
31
+ # Use this if you don't want to overwrite the image file
32
+ def open(image_path)
33
+ File.open(image_path, "rb") do |f|
34
+ self.from_blob(f.read, File.extname(image_path))
35
+ end
36
+ end
37
+ alias_method :from_file, :open
38
+ end
39
+
40
+ # Instance Methods
41
+ # ----------------
42
+ def initialize(input_path, tempfile=nil)
43
+ @path = input_path
44
+ @tempfile = tempfile # ensures that the tempfile will stick around until this image is garbage collected.
45
+
46
+ # Ensure that the file is an image
47
+ run_command("identify", @path)
48
+ end
49
+
50
+ # For reference see http://www.imagemagick.org/script/command-line-options.php#format
51
+ def [](value)
52
+ # Why do I go to the trouble of putting in newlines? Because otherwise animated gifs screw everything up
53
+ case value.to_s
54
+ when "format"
55
+ run_command("identify", "-format", format_option("%m"), @path).split("\n")[0]
56
+ when "height"
57
+ run_command("identify", "-format", format_option("%h"), @path).split("\n")[0].to_i
58
+ when "width"
59
+ run_command("identify", "-format", format_option("%w"), @path).split("\n")[0].to_i
60
+ when "dimensions"
61
+ run_command("identify", "-format", format_option("%w %h"), @path).split("\n")[0].split.map{|v|v.to_i}
62
+ when "size"
63
+ File.size(@path) # Do this because calling identify -format "%b" on an animated gif fails!
64
+ when "original_at"
65
+ # Get the EXIF original capture as a Time object
66
+ Time.local(*self["EXIF:DateTimeOriginal"].split(/:|\s+/)) rescue nil
67
+ when /^EXIF\:/i
68
+ run_command('identify', '-format', "\"%[#{value}]\"", @path).chop
69
+ else
70
+ run_command('identify', '-format', "\"#{value}\"", @path).split("\n")[0]
71
+ end
72
+ end
73
+
74
+ # Sends raw commands to imagemagick's mogrify command. The image path is automatically appended to the command
75
+ def <<(*args)
76
+ run_command("mogrify", *args << @path)
77
+ end
78
+
79
+ # This is a 'special' command because it needs to change @path to reflect the new extension
80
+ # Formatting an animation into a non-animated type will result in ImageMagick creating multiple
81
+ # pages (starting with 0). You can choose which page you want to manipulate. We default to the
82
+ # first page.
83
+ def format(format, page=0)
84
+ run_command("mogrify", "-format", format, @path)
85
+
86
+ old_path = @path.dup
87
+ @path.sub!(/(\.\w+)?$/, ".#{format}")
88
+ File.delete(old_path) unless old_path == @path
89
+
90
+ unless File.exists?(@path)
91
+ begin
92
+ FileUtils.copy_file(@path.sub(".#{format}", "-#{page}.#{format}"), @path)
93
+ rescue e
94
+ raise MiniMagickError, "Unable to format to #{format}; #{e}" unless File.exist?(@path)
95
+ end
96
+ end
97
+ ensure
98
+ Dir[@path.sub(/(\.\w+)?$/, "-[0-9]*.#{format}")].each do |fname|
99
+ File.unlink(fname)
100
+ end
101
+ end
102
+
103
+ # Writes the temporary image that we are using for processing to the output path
104
+ def write(output_path)
105
+ FileUtils.copy_file @path, output_path
106
+ run_command "identify", output_path # Verify that we have a good image
107
+ end
108
+
109
+ # Give you raw data back
110
+ def to_blob
111
+ f = File.new @path
112
+ f.binmode
113
+ f.read
114
+ ensure
115
+ f.close if f
116
+ end
117
+
118
+ # If an unknown method is called then it is sent through the morgrify program
119
+ # Look here to find all the commands (http://www.imagemagick.org/script/mogrify.php)
120
+ def method_missing(symbol, *args)
121
+ args.push(@path) # push the path onto the end
122
+ run_command("mogrify", "-#{symbol}", *args)
123
+ self
124
+ end
125
+
126
+ # You can use multiple commands together using this method
127
+ def combine_options(&block)
128
+ c = CommandBuilder.new
129
+ block.call c
130
+ run_command("mogrify", *c.args << @path)
131
+ end
132
+
133
+ # Check to see if we are running on win32 -- we need to escape things differently
134
+ def windows?
135
+ !(RUBY_PLATFORM =~ /win32/).nil?
136
+ end
137
+
138
+ # Outputs a carriage-return delimited format string for Unix and Windows
139
+ def format_option(format)
140
+ windows? ? "#{format}\\n" : "#{format}\\\\n"
141
+ end
142
+
143
+ def run_command(command, *args)
144
+ args.collect! do |arg|
145
+ # args can contain characters like '>' so we must escape them, but don't quote switches
146
+ if arg !~ /^[\+\-]/
147
+ "\"#{arg}\""
148
+ else
149
+ arg.to_s
150
+ end
151
+ end
152
+
153
+ command = "#{command} #{args.join(' ')}"
154
+ output = `#{command} 2>&1`
155
+
156
+ if $?.exitstatus != 0
157
+ raise MiniMagickError, "ImageMagick command (#{command.inspect}) failed: #{{:status_code => $?, :output => output}.inspect}"
158
+ else
159
+ output
160
+ end
161
+ end
162
+ end
163
+
164
+ # Combines multiple images into a single montage via ImageMagick's montage script
165
+ class Montage
166
+ # Class Methods
167
+ # -------------
168
+
169
+ # To create a montage simply call Montage.new with the images you want combine,
170
+ # the path to the output file and any command line options you may want.
171
+ # You will be returned a MiniMagick::Image instance for the new montage:
172
+ #
173
+ # image1 = MiniMagick::Image.open('alice.png')
174
+ # image2 = MiniMagick::Image.open('bob.png')
175
+ # output_image = MiniMagick::Composite.new([image1, image2], 'jpg', :background => '#336699')
176
+ # output_image.write('montage.jpg')
177
+ #
178
+ # The above example would combine the two images into a new JPEG file using a background color of #336699.
179
+ # The the image is saved using the standard Image.save method.
180
+ #
181
+ # The 'montage' script has several options, see here: http://www.imagemagick.org/script/montage.php
182
+ def self.new(images, output_extension, options={})
183
+ begin
184
+ tempfile = ImageTempFile.new(output_extension)
185
+ tempfile.binmode
186
+ ensure
187
+ tempfile.close
188
+ end
189
+
190
+ args = options.collect { |key,value| "-#{key.to_s} #{value.to_s}" } # collect hash parts into arguments
191
+ images.each do |image|
192
+ args.push image.path
193
+ end
194
+ args.push(tempfile.path)
195
+
196
+ # This is a little hacky - cannikin's CommandeRunner would be a useful
197
+ # alternative (http://github.com/cannikin/mini_magick).
198
+ Image.new(images.first.path).run_command('montage', *args)
199
+ return Image.open(tempfile.path)
200
+ end
201
+
202
+ def run
203
+ end
204
+
205
+ end
206
+
207
+ class CommandBuilder
208
+ attr :args
209
+
210
+ def initialize
211
+ @args = []
212
+ end
213
+
214
+ def method_missing(symbol, *args)
215
+ @args << "-#{symbol}"
216
+ @args += args
217
+ end
218
+
219
+ def +(value)
220
+ @args << "+#{value}"
221
+ end
222
+ end
223
+ end
@@ -0,0 +1,55 @@
1
+ # -*- encoding: utf-8 -*-
2
+
3
+ Gem::Specification.new do |s|
4
+ s.name = %q{tupalo-mini_magick}
5
+ s.version = "1.2.5"
6
+
7
+ s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
8
+ s.authors = ["Corey Johnson"]
9
+ s.date = %q{2009-05-27}
10
+ s.description = %q{This is a fork of peplins fork of the mini_magick gem. It includes support for the montage command.}
11
+ s.email = %q{thomas@tupalo.com}
12
+ s.extra_rdoc_files = [
13
+ "README.rdoc"
14
+ ]
15
+ s.files = [
16
+ ".gitignore",
17
+ "MIT-LICENSE",
18
+ "README.rdoc",
19
+ "Rakefile",
20
+ "VERSION",
21
+ "lib/image_temp_file.rb",
22
+ "lib/mini_magick.rb",
23
+ "mini_magick.gemspec",
24
+ "test/actually_a_gif.jpg",
25
+ "test/animation.gif",
26
+ "test/command_builder_test.rb",
27
+ "test/image_temp_file_test.rb",
28
+ "test/image_test.rb",
29
+ "test/leaves.tiff",
30
+ "test/not_an_image.php",
31
+ "test/simple.gif",
32
+ "test/trogdor.jpg"
33
+ ]
34
+ s.has_rdoc = true
35
+ s.homepage = %q{http://github.com/fadr/tupalo-mini_magick}
36
+ s.rdoc_options = ["--charset=UTF-8"]
37
+ s.require_paths = ["lib"]
38
+ s.rubygems_version = %q{1.3.1}
39
+ s.summary = %q{Manipulate images with minimal use of memory.}
40
+ s.test_files = [
41
+ "test/command_builder_test.rb",
42
+ "test/image_temp_file_test.rb",
43
+ "test/image_test.rb"
44
+ ]
45
+
46
+ if s.respond_to? :specification_version then
47
+ current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
48
+ s.specification_version = 2
49
+
50
+ if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
51
+ else
52
+ end
53
+ else
54
+ end
55
+ end
Binary file
Binary file
@@ -0,0 +1,20 @@
1
+ require 'test/unit'
2
+ require File.join(File.dirname(__FILE__), '../lib/mini_magick')
3
+
4
+ class CommandBuilderTest < Test::Unit::TestCase
5
+ include MiniMagick
6
+
7
+ def test_basic
8
+ c = CommandBuilder.new
9
+ c.resize "30x40"
10
+ assert_equal "-resize 30x40", c.args.join(" ")
11
+ end
12
+
13
+ def test_complicated
14
+ c = CommandBuilder.new
15
+ c.resize "30x40"
16
+ c.input 1, 3, 4
17
+ c.lingo "mome fingo"
18
+ assert_equal "-resize 30x40 -input 1 3 4 -lingo mome fingo", c.args.join(" ")
19
+ end
20
+ end