micro_magick 0.0.1
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 +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
|