micro_magick 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +4 -0
- data/Gemfile +4 -0
- data/README.md +76 -0
- data/Rakefile +5 -0
- data/lib/micro_magick/convert.rb +37 -0
- data/lib/micro_magick/version.rb +3 -0
- data/lib/micro_magick.rb +48 -0
- data/micro_magick.gemspec +22 -0
- data/test/640.jpg +0 -0
- data/test/test_micro_magick.rb +46 -0
- metadata +89 -0
data/.gitignore
ADDED
data/Gemfile
ADDED
data/README.md
ADDED
@@ -0,0 +1,76 @@
|
|
1
|
+
# Simplest possible ruby wrapper for [ImageMagick](http://www.imagemagick.org/) and [GraphicsMagick](http://www.graphicsmagick.org/)
|
2
|
+
|
3
|
+
### OMG, SRSLY?
|
4
|
+
|
5
|
+
Yes. Seriously.
|
6
|
+
|
7
|
+
### The other five libraries didn't make you happy?
|
8
|
+
|
9
|
+
No.
|
10
|
+
|
11
|
+
### OK, Sunshine, cry me a river.
|
12
|
+
|
13
|
+
All I wanted was something that
|
14
|
+
|
15
|
+
* didn't create temporary files unnecessarily (like mini_magick)
|
16
|
+
* didn't fail with valid geometry specifications, like ```640x480>``` (like mini_magick and quick_magick)
|
17
|
+
* didn't assume you only needed to resize your images (like imagery)
|
18
|
+
* didn't think you're going to run a public image caching service (like magickly)
|
19
|
+
|
20
|
+
## Usage
|
21
|
+
|
22
|
+
```micro_magick``` is an exec wrapper for the ```convert``` command, which reads from an image
|
23
|
+
source, performs operations on it, and saves the result to a different file.
|
24
|
+
|
25
|
+
```ruby
|
26
|
+
img = MicroMagick::Convert.new("/path/to/image.jpg")
|
27
|
+
img.strip
|
28
|
+
img.quality(85)
|
29
|
+
img.resize("640x480>")
|
30
|
+
img.write("/different/path/image-640x480.jpg")
|
31
|
+
```
|
32
|
+
|
33
|
+
This results in the following system call:
|
34
|
+
|
35
|
+
```gm convert -size 640x480 /path/to/image.jpg -strip -quality 85 -resize "640x480>" /different/path/image-640x480.jpg```
|
36
|
+
|
37
|
+
Note that all of ```convert```'s options are supported, but ```micro_magick``` does no validations.
|
38
|
+
A ```MicroMagick::ArgumentError``` will be raised on ```.write``` if
|
39
|
+
convert writes anything to stderr or the return value is not 0.
|
40
|
+
|
41
|
+
Note also that GraphicsMagick will be used automatically, if it's in ruby's PATH, and then will fall back to ImageMagick,
|
42
|
+
but you can force the library MicroMagick uses by calling ```MicroMagick.use(:graphicsmagick)``` or ```MicroMagick.use(:imagemagick)```.
|
43
|
+
|
44
|
+
In-place image edits through ```mogrify``` are not supported (yet).
|
45
|
+
|
46
|
+
### GraphicsMagick versus ImageMagick
|
47
|
+
|
48
|
+
In resizing a 2248x4000 image to 640x480:
|
49
|
+
* GraphicsMagick takes 141 milliseconds. ImageMagick takes over 550 millis.
|
50
|
+
* GraphicsMagick outputs a 37K JPG, ImageMagick outputs a 94K JPG, with no detectable visual differences.
|
51
|
+
|
52
|
+
At least in my testing, GraphicsMagick blows ImageMagick out of the water.
|
53
|
+
|
54
|
+
Not only is it 4 times faster, it produces 2.5x smaller output with the same quality--WIN WIN.
|
55
|
+
|
56
|
+
## Installation
|
57
|
+
|
58
|
+
You'll want to [install GraphicsMagick](http://www.graphicsmagick.org/README.html), then
|
59
|
+
|
60
|
+
```
|
61
|
+
gem install micro_magick
|
62
|
+
```
|
63
|
+
|
64
|
+
or add to your Gemfile:
|
65
|
+
|
66
|
+
```
|
67
|
+
gem 'micro_magick'
|
68
|
+
```
|
69
|
+
|
70
|
+
and run ```bundle```.
|
71
|
+
|
72
|
+
## Change history
|
73
|
+
|
74
|
+
### 0.0.1
|
75
|
+
|
76
|
+
Let's get this party started.
|
data/Rakefile
ADDED
@@ -0,0 +1,37 @@
|
|
1
|
+
require 'shellwords'
|
2
|
+
|
3
|
+
module MicroMagick
|
4
|
+
class Convert
|
5
|
+
def initialize(input_file)
|
6
|
+
@args = [Shellwords.escape(input_file)]
|
7
|
+
end
|
8
|
+
|
9
|
+
def command
|
10
|
+
([MicroMagick.cmd_prefix, "convert", @pre_input] + @args).compact.join(" ")
|
11
|
+
end
|
12
|
+
|
13
|
+
def write(output_file)
|
14
|
+
@args << Shellwords.escape(output_file)
|
15
|
+
MicroMagick.exec command
|
16
|
+
end
|
17
|
+
|
18
|
+
def method_missing(method, *args, &block)
|
19
|
+
if @pre_input.nil? && [:geometry, :resize, :sample, :scale].include?(method)
|
20
|
+
dimensions = args.first
|
21
|
+
# let's give the -size render hint to gm, but only if we're a resize call, and we have simple dimensions:
|
22
|
+
if dimensions && (simple_dim = dimensions.scan(/(\d+x\d+)/).first)
|
23
|
+
@pre_input = "-size #{simple_dim}"
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
if method == :strip
|
28
|
+
# ImageMagick knows that ```-strip```, means ```+profile "*"```
|
29
|
+
@args << '+profile'
|
30
|
+
@args << Shellwords.escape('*')
|
31
|
+
else
|
32
|
+
@args << "-#{method.to_s}"
|
33
|
+
end
|
34
|
+
@args += args.compact.collect { |ea| Shellwords.escape(ea.to_s) }
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
data/lib/micro_magick.rb
ADDED
@@ -0,0 +1,48 @@
|
|
1
|
+
require "micro_magick/version"
|
2
|
+
require "micro_magick/convert"
|
3
|
+
require "tempfile"
|
4
|
+
|
5
|
+
module MicroMagick
|
6
|
+
|
7
|
+
InvalidArgument = Class.new(StandardError)
|
8
|
+
|
9
|
+
ENGINE2PREFIX = { :imagemagick => nil, :graphicsmagick => "gm" }
|
10
|
+
|
11
|
+
# @param engine must be :imagemagick, :graphicsmagick, or nil (which means reset to default behavior,
|
12
|
+
# which means the next run will determine if GraphicsMagick or ImageMagick is installed)
|
13
|
+
def self.use(engine)
|
14
|
+
unless engine.nil? || ENGINE2PREFIX.keys.include?(engine)
|
15
|
+
raise InvalidArgument, "Unknown graphics engine #{engine}"
|
16
|
+
end
|
17
|
+
@engine = engine
|
18
|
+
end
|
19
|
+
|
20
|
+
def self.cmd_prefix
|
21
|
+
@engine ||= begin
|
22
|
+
if system("hash gm 2>&-")
|
23
|
+
:graphicsmagick
|
24
|
+
elsif system("hash convert 2>&-")
|
25
|
+
:imagemagick
|
26
|
+
else
|
27
|
+
raise InvalidArgument, "Please install either GraphicsMagick or ImageMagick"
|
28
|
+
end
|
29
|
+
end
|
30
|
+
ENGINE2PREFIX[@engine]
|
31
|
+
end
|
32
|
+
|
33
|
+
def self.exec(cmd)
|
34
|
+
stderr_file = Tempfile.new('stderr')
|
35
|
+
stderr_path = stderr_file.path
|
36
|
+
stderr_file.close
|
37
|
+
result = `#{cmd} 2>"#{stderr_path}"`
|
38
|
+
stderr = File.read(stderr_path).strip
|
39
|
+
stderr_file.delete
|
40
|
+
if $?.exitstatus != 0 || !stderr.empty?
|
41
|
+
raise InvalidArgument, "#{cmd} failed: #{stderr}"
|
42
|
+
end
|
43
|
+
result
|
44
|
+
end
|
45
|
+
|
46
|
+
end
|
47
|
+
|
48
|
+
|
@@ -0,0 +1,22 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
$:.push File.expand_path("../lib", __FILE__)
|
3
|
+
require "micro_magick/version"
|
4
|
+
|
5
|
+
Gem::Specification.new do |s|
|
6
|
+
s.name = "micro_magick"
|
7
|
+
s.version = MicroMagick::VERSION
|
8
|
+
s.authors = ["Matthew McEachen"]
|
9
|
+
s.email = ["matthew-github@mceachen.org"]
|
10
|
+
s.homepage = ""
|
11
|
+
s.summary = %q{Simplest ImageMagick/GraphicsMagick ruby wrapper EVAR}
|
12
|
+
s.description = %q{Simplest ImageMagick/GraphicsMagick ruby wrapper EVAR}
|
13
|
+
|
14
|
+
s.rubyforge_project = "micro_magick"
|
15
|
+
|
16
|
+
s.files = `git ls-files`.split("\n")
|
17
|
+
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
18
|
+
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
19
|
+
s.require_paths = ["lib"]
|
20
|
+
|
21
|
+
s.add_development_dependency "rake"
|
22
|
+
end
|
data/test/640.jpg
ADDED
Binary file
|
@@ -0,0 +1,46 @@
|
|
1
|
+
require "test/unit"
|
2
|
+
require "shellwords"
|
3
|
+
require "micro_magick"
|
4
|
+
|
5
|
+
class TestMicroMagick < Test::Unit::TestCase
|
6
|
+
|
7
|
+
def test_use
|
8
|
+
MicroMagick.use(:graphicsmagick)
|
9
|
+
assert_equal MicroMagick.cmd_prefix, "gm"
|
10
|
+
MicroMagick.use(:imagemagick)
|
11
|
+
assert_equal MicroMagick.cmd_prefix, nil
|
12
|
+
|
13
|
+
# This shouldn't throw:
|
14
|
+
MicroMagick.use(nil)
|
15
|
+
# eh, ok, now we should stub out system
|
16
|
+
# and verify that the next call to cmd_prefix
|
17
|
+
# calls `hash gm`?
|
18
|
+
|
19
|
+
# Meh, let's just assume that the test running machine has gm in their PATH.
|
20
|
+
assert_equal MicroMagick.cmd_prefix, "gm"
|
21
|
+
|
22
|
+
assert_raise MicroMagick::InvalidArgument do
|
23
|
+
MicroMagick.use(:boink)
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
def test_convert
|
28
|
+
i = MicroMagick::Convert.new("test/640.jpg")
|
29
|
+
i.strip
|
30
|
+
i.quality(85)
|
31
|
+
i.gravity("Center")
|
32
|
+
i.crop("250x250")
|
33
|
+
i.resize("128x128")
|
34
|
+
tmp = Tempfile.new('out.jpg')
|
35
|
+
outfile = tmp.path
|
36
|
+
tmp.close
|
37
|
+
tmp.delete
|
38
|
+
assert !File.exist?(outfile)
|
39
|
+
i.write(outfile)
|
40
|
+
assert_equal i.command, "gm convert -size 128x128 test/640.jpg +profile \\* " +
|
41
|
+
"-quality 85 -gravity Center -crop 250x250 -resize 128x128 " +
|
42
|
+
Shellwords.escape(outfile)
|
43
|
+
assert File.exist?(outfile)
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
metadata
ADDED
@@ -0,0 +1,89 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: micro_magick
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
hash: 29
|
5
|
+
prerelease:
|
6
|
+
segments:
|
7
|
+
- 0
|
8
|
+
- 0
|
9
|
+
- 1
|
10
|
+
version: 0.0.1
|
11
|
+
platform: ruby
|
12
|
+
authors:
|
13
|
+
- Matthew McEachen
|
14
|
+
autorequire:
|
15
|
+
bindir: bin
|
16
|
+
cert_chain: []
|
17
|
+
|
18
|
+
date: 2012-03-01 00:00:00 Z
|
19
|
+
dependencies:
|
20
|
+
- !ruby/object:Gem::Dependency
|
21
|
+
prerelease: false
|
22
|
+
requirement: &id001 !ruby/object:Gem::Requirement
|
23
|
+
none: false
|
24
|
+
requirements:
|
25
|
+
- - ">="
|
26
|
+
- !ruby/object:Gem::Version
|
27
|
+
hash: 3
|
28
|
+
segments:
|
29
|
+
- 0
|
30
|
+
version: "0"
|
31
|
+
type: :development
|
32
|
+
name: rake
|
33
|
+
version_requirements: *id001
|
34
|
+
description: Simplest ImageMagick/GraphicsMagick ruby wrapper EVAR
|
35
|
+
email:
|
36
|
+
- matthew-github@mceachen.org
|
37
|
+
executables: []
|
38
|
+
|
39
|
+
extensions: []
|
40
|
+
|
41
|
+
extra_rdoc_files: []
|
42
|
+
|
43
|
+
files:
|
44
|
+
- .gitignore
|
45
|
+
- Gemfile
|
46
|
+
- README.md
|
47
|
+
- Rakefile
|
48
|
+
- lib/micro_magick.rb
|
49
|
+
- lib/micro_magick/convert.rb
|
50
|
+
- lib/micro_magick/version.rb
|
51
|
+
- micro_magick.gemspec
|
52
|
+
- test/640.jpg
|
53
|
+
- test/test_micro_magick.rb
|
54
|
+
homepage: ""
|
55
|
+
licenses: []
|
56
|
+
|
57
|
+
post_install_message:
|
58
|
+
rdoc_options: []
|
59
|
+
|
60
|
+
require_paths:
|
61
|
+
- lib
|
62
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
63
|
+
none: false
|
64
|
+
requirements:
|
65
|
+
- - ">="
|
66
|
+
- !ruby/object:Gem::Version
|
67
|
+
hash: 3
|
68
|
+
segments:
|
69
|
+
- 0
|
70
|
+
version: "0"
|
71
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
72
|
+
none: false
|
73
|
+
requirements:
|
74
|
+
- - ">="
|
75
|
+
- !ruby/object:Gem::Version
|
76
|
+
hash: 3
|
77
|
+
segments:
|
78
|
+
- 0
|
79
|
+
version: "0"
|
80
|
+
requirements: []
|
81
|
+
|
82
|
+
rubyforge_project: micro_magick
|
83
|
+
rubygems_version: 1.8.17
|
84
|
+
signing_key:
|
85
|
+
specification_version: 3
|
86
|
+
summary: Simplest ImageMagick/GraphicsMagick ruby wrapper EVAR
|
87
|
+
test_files:
|
88
|
+
- test/640.jpg
|
89
|
+
- test/test_micro_magick.rb
|