miso 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- data/LICENSE +20 -0
- data/README +55 -0
- data/Rakefile +54 -0
- data/TODO +2 -0
- data/VERSION +1 -0
- data/html/classes/Miso.html +133 -0
- data/html/classes/Miso/Factory.html +278 -0
- data/html/classes/Miso/Image.html +394 -0
- data/html/classes/Miso/Processor.html +379 -0
- data/html/classes/Miso/Processor/CoreImage.html +246 -0
- data/html/classes/Miso/Processor/ImageMagick.html +345 -0
- data/html/classes/Miso/Processor/NotImplementedError.html +111 -0
- data/html/created.rid +1 -0
- data/html/files/LICENSE.html +133 -0
- data/html/files/README.html +156 -0
- data/html/files/lib/miso/factory_rb.html +101 -0
- data/html/files/lib/miso/image_rb.html +101 -0
- data/html/files/lib/miso/processor/core_image_rb.html +108 -0
- data/html/files/lib/miso/processor/image_magick_rb.html +110 -0
- data/html/files/lib/miso/processor_rb.html +101 -0
- data/html/files/lib/miso_rb.html +101 -0
- data/html/fr_class_index.html +33 -0
- data/html/fr_file_index.html +34 -0
- data/html/fr_method_index.html +62 -0
- data/html/index.html +24 -0
- data/html/rdoc-style.css +208 -0
- data/lib/miso.rb +5 -0
- data/lib/miso/factory.rb +53 -0
- data/lib/miso/image.rb +51 -0
- data/lib/miso/processor.rb +61 -0
- data/lib/miso/processor/core_image.rb +27 -0
- data/lib/miso/processor/image_magick.rb +59 -0
- data/spec/api/factory_spec.rb +31 -0
- data/spec/api/image_spec.rb +115 -0
- data/spec/api/processor/image_magick_spec.rb +22 -0
- data/spec/api/processor_spec.rb +41 -0
- data/spec/fixtures/120x100.png +0 -0
- data/spec/start.rb +30 -0
- metadata +97 -0
@@ -0,0 +1,61 @@
|
|
1
|
+
module Miso
|
2
|
+
class Processor
|
3
|
+
autoload :CoreImage, 'miso/processor/core_image'
|
4
|
+
autoload :ImageMagick, 'miso/processor/image_magick'
|
5
|
+
|
6
|
+
class NotImplementedError < StandardError; end
|
7
|
+
|
8
|
+
class << self
|
9
|
+
# Sets the default processor class.
|
10
|
+
attr_writer :processor_class
|
11
|
+
|
12
|
+
# Sets the default processor classes list.
|
13
|
+
attr_writer :processor_classes
|
14
|
+
|
15
|
+
# The default processor class.
|
16
|
+
#
|
17
|
+
# Returns either the assigned processor, or otherwise finds the first
|
18
|
+
# processor, that is available on the machine, from the processor_classes
|
19
|
+
# array.
|
20
|
+
def processor_class
|
21
|
+
@processor_class ||= processor_classes.find { |c| c.available? }
|
22
|
+
raise "None of the Miso::Processor classes is available." unless @processor_class
|
23
|
+
@processor_class
|
24
|
+
end
|
25
|
+
|
26
|
+
# The list of processor classes.
|
27
|
+
#
|
28
|
+
# When no explicit processor_class is set this list is iterated, from
|
29
|
+
# first to last, and the first available processor on the machine is used.
|
30
|
+
def processor_classes
|
31
|
+
@processor_classes ||= [CoreImage, ImageMagick]
|
32
|
+
end
|
33
|
+
|
34
|
+
def available?
|
35
|
+
raise NotImplementedError, "The class `#{name}' does not implement ::available?."
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
attr_reader :input_file
|
40
|
+
|
41
|
+
def initialize(input_file)
|
42
|
+
@input_file = input_file
|
43
|
+
end
|
44
|
+
|
45
|
+
def crop(width, height)
|
46
|
+
raise NotImplementedError, "The class `#{self.class.name}' does not implement #crop."
|
47
|
+
end
|
48
|
+
|
49
|
+
def fit(width, height)
|
50
|
+
raise NotImplementedError, "The class `#{self.class.name}' does not implement #fit."
|
51
|
+
end
|
52
|
+
|
53
|
+
def dimensions
|
54
|
+
raise NotImplementedError, "The class `#{self.class.name}' does not implement #dimensions."
|
55
|
+
end
|
56
|
+
|
57
|
+
def write(output_file)
|
58
|
+
raise NotImplementedError, "The class `#{self.class.name}' does not implement #write."
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
module Miso
|
2
|
+
class Processor
|
3
|
+
class CoreImage < Processor
|
4
|
+
def self.available?
|
5
|
+
available = $:.any? { |path| File.exist? File.join(path, 'osx/cocoa.rb') }
|
6
|
+
require 'osx/cocoa'
|
7
|
+
available
|
8
|
+
end
|
9
|
+
|
10
|
+
def crop(width, height)
|
11
|
+
# ...
|
12
|
+
end
|
13
|
+
|
14
|
+
def fit(width, height)
|
15
|
+
# ...
|
16
|
+
end
|
17
|
+
|
18
|
+
def dimensions
|
19
|
+
# ...
|
20
|
+
end
|
21
|
+
|
22
|
+
def write(output_file)
|
23
|
+
# ...
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,59 @@
|
|
1
|
+
begin
|
2
|
+
require 'rubygems'
|
3
|
+
gem 'executioner', '>= 0.2'
|
4
|
+
rescue LoadError
|
5
|
+
end
|
6
|
+
require 'executioner'
|
7
|
+
require 'fileutils'
|
8
|
+
|
9
|
+
module Miso
|
10
|
+
class Processor
|
11
|
+
class ImageMagick < Processor
|
12
|
+
def self.available?
|
13
|
+
`which convert`
|
14
|
+
$?.success
|
15
|
+
end
|
16
|
+
|
17
|
+
def crop(width, height)
|
18
|
+
dimensions = "#{width}x#{height}"
|
19
|
+
operations << "-resize #{dimensions}^ -gravity center -crop #{dimensions}+0+0!"
|
20
|
+
end
|
21
|
+
|
22
|
+
def fit(width, height)
|
23
|
+
operations << "-resize #{width}x#{height}"
|
24
|
+
end
|
25
|
+
|
26
|
+
def dimensions
|
27
|
+
if info = identify(input_file) and match = /\s(\d+)x(\d+)\+/.match(info)
|
28
|
+
match.to_a[1..2].map { |d| d.to_i }
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
def write(output_file)
|
33
|
+
options = operations.join(' ')
|
34
|
+
operations.clear
|
35
|
+
convert(input_file, output_file, options)
|
36
|
+
end
|
37
|
+
|
38
|
+
include Executioner
|
39
|
+
executable :convert
|
40
|
+
executable :identify
|
41
|
+
|
42
|
+
alias_method :_convert, :convert
|
43
|
+
def convert(source_path, output_path, options)
|
44
|
+
ensure_output_directory(output_path)
|
45
|
+
_convert "'#{source_path}' #{options} '#{output_path}'"
|
46
|
+
end
|
47
|
+
|
48
|
+
private
|
49
|
+
|
50
|
+
def operations
|
51
|
+
@operations ||= []
|
52
|
+
end
|
53
|
+
|
54
|
+
def ensure_output_directory(path)
|
55
|
+
FileUtils.mkdir_p(File.dirname(path))
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
require File.expand_path('../../start', __FILE__)
|
2
|
+
|
3
|
+
describe "A Miso::Factory instance" do
|
4
|
+
before do
|
5
|
+
Miso::Processor.processor_class = Miso::Processor
|
6
|
+
|
7
|
+
Miso::Processor.any_instance.stubs(:write)
|
8
|
+
|
9
|
+
@input_file = '/image.png'
|
10
|
+
@output_file = '/output_image.png'
|
11
|
+
@image = Miso::Image.new(@input_file)
|
12
|
+
|
13
|
+
Miso::Image.stubs(:new).with(@input_file, Miso::Processor).returns(@image)
|
14
|
+
Miso::Image.stubs(:new).with(@output_file, Miso::Processor)
|
15
|
+
|
16
|
+
@factory = Miso::Factory.new
|
17
|
+
end
|
18
|
+
|
19
|
+
after do
|
20
|
+
Miso::Processor.processor_class = nil
|
21
|
+
end
|
22
|
+
|
23
|
+
it "should store operations that are to be applied later on" do
|
24
|
+
@factory.crop(123, 456).fit(123, 456)
|
25
|
+
|
26
|
+
@image.expects(:crop).with(123, 456)
|
27
|
+
@image.expects(:fit).with(123, 456)
|
28
|
+
|
29
|
+
@factory.apply(@input_file, @output_file)
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,115 @@
|
|
1
|
+
require File.expand_path('../../start', __FILE__)
|
2
|
+
|
3
|
+
describe "Miso::Image, concerning initialization" do
|
4
|
+
class FakeProcessor; end
|
5
|
+
|
6
|
+
before do
|
7
|
+
Miso::Processor.processor_class = nil
|
8
|
+
end
|
9
|
+
|
10
|
+
after do
|
11
|
+
Miso::Processor.processor_class = nil
|
12
|
+
end
|
13
|
+
|
14
|
+
it "should initialize with only a file argument and use the default processor class" do
|
15
|
+
Miso::Processor.processor_class = Miso::Processor::ImageMagick
|
16
|
+
image = Miso::Image.new('/image.png')
|
17
|
+
|
18
|
+
image.processor.input_file.should == '/image.png'
|
19
|
+
image.processor.class.should == Miso::Processor::ImageMagick
|
20
|
+
end
|
21
|
+
|
22
|
+
it "should initialize with a file and processor class" do
|
23
|
+
image = Miso::Image.new('/image.png', Miso::Processor::ImageMagick)
|
24
|
+
|
25
|
+
image.processor.input_file.should == '/image.png'
|
26
|
+
image.processor.class.should == Miso::Processor::ImageMagick
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
describe "An instance of Miso::Image, concerning forwarding calls to the processor" do
|
31
|
+
before do
|
32
|
+
Miso::Processor.any_instance.stubs(:fit)
|
33
|
+
Miso::Processor.any_instance.stubs(:crop)
|
34
|
+
|
35
|
+
@image = Miso::Image.new('/image.png', Miso::Processor)
|
36
|
+
end
|
37
|
+
|
38
|
+
it "should forward #crop to the processor" do
|
39
|
+
@image.processor.expects(:crop).with(123, 456)
|
40
|
+
@image.crop(123, 456)
|
41
|
+
end
|
42
|
+
|
43
|
+
it "should return self when calling #crop" do
|
44
|
+
@image.crop(123, 456).should.be @image
|
45
|
+
end
|
46
|
+
|
47
|
+
it "should forward #fit to the processor" do
|
48
|
+
@image.processor.expects(:fit).with(123, 456)
|
49
|
+
@image.fit(123, 456)
|
50
|
+
end
|
51
|
+
|
52
|
+
it "should return self instance when calling #fit" do
|
53
|
+
@image.fit(123, 456).should.be @image
|
54
|
+
end
|
55
|
+
|
56
|
+
it "should forward #dimensions to the processor and return the result" do
|
57
|
+
@image.processor.expects(:dimensions).returns([123, 456])
|
58
|
+
@image.dimensions.should == [123, 456]
|
59
|
+
end
|
60
|
+
|
61
|
+
it "should forward #write to the processor and forward its output file to the new instance of Miso::Image" do
|
62
|
+
@image.processor.expects(:write).with('/output_image.png')
|
63
|
+
output_image = @image.write('/output_image.png')
|
64
|
+
output_image.processor.input_file.should == '/output_image.png'
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
describe "An instance of Miso::Image, concerning combined methods" do
|
69
|
+
before do
|
70
|
+
Miso::Processor.any_instance.stubs(:fit)
|
71
|
+
Miso::Processor.any_instance.stubs(:crop)
|
72
|
+
|
73
|
+
@image = Miso::Image.new('/image.png', Miso::Processor)
|
74
|
+
end
|
75
|
+
|
76
|
+
it "should call #fit to scale and preserve aspect ratio, then call #crop" do
|
77
|
+
@image.expects(:fit).with(123, 456).returns(@image)
|
78
|
+
@image.expects(:crop).with(123, 456).returns(@image)
|
79
|
+
|
80
|
+
@image.crop_fitting(123, 456)
|
81
|
+
end
|
82
|
+
|
83
|
+
it "should return self when calling #crop_fitting" do
|
84
|
+
@image.crop_fitting(123, 456).should.be @image
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
describe "Miso::Image, concerning shortcut class methods" do
|
89
|
+
before do
|
90
|
+
@input_file = fixture_file('120x100.png')
|
91
|
+
@output_file = temp_file('cropped_to_40x30.png')
|
92
|
+
@image = Miso::Image.new(@input_file, Miso::Processor)
|
93
|
+
|
94
|
+
Miso::Image.stubs(:new).with(@input_file, nil).returns(@image)
|
95
|
+
end
|
96
|
+
|
97
|
+
it "should crop to specified dimensions" do
|
98
|
+
@image.expects(:crop).with(40, 30).returns(@image)
|
99
|
+
@image.expects(:write).with(@output_file)
|
100
|
+
|
101
|
+
Miso::Image.crop(@input_file, @output_file, 40, 30)
|
102
|
+
end
|
103
|
+
|
104
|
+
it "should fit to specified dimensions, conserving the original aspect ratio" do
|
105
|
+
@image.expects(:fit).with(40, 30).returns(@image)
|
106
|
+
@image.expects(:write).with(@output_file)
|
107
|
+
|
108
|
+
Miso::Image.fit(@input_file, @output_file, 40, 30)
|
109
|
+
end
|
110
|
+
|
111
|
+
it "should return its dimensions" do
|
112
|
+
@image.expects(:dimensions).returns([120, 100])
|
113
|
+
Miso::Image.dimensions(@input_file).should == [120, 100]
|
114
|
+
end
|
115
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
require File.expand_path('../../../start', __FILE__)
|
2
|
+
|
3
|
+
describe "An instance of Miso::Processor::ImageMagick" do
|
4
|
+
before do
|
5
|
+
@image_120_x_100 = Miso::Image.new(fixture_file('120x100.png'), Miso::Processor::ImageMagick)
|
6
|
+
@output_file = temp_file('temp.png')
|
7
|
+
end
|
8
|
+
|
9
|
+
it "should crop to specified dimensions" do
|
10
|
+
@image_120_x_100.crop(40, 30).write(@output_file).dimensions.should == [40, 30]
|
11
|
+
@image_120_x_100.crop(40, 33).write(@output_file).dimensions.should == [40, 33]
|
12
|
+
end
|
13
|
+
|
14
|
+
it "should fit to specified dimensions, conserving the original aspect ratio" do
|
15
|
+
@image_120_x_100.fit(40, 30).write(@output_file).dimensions.should == [36, 30]
|
16
|
+
@image_120_x_100.fit(40, 34).write(@output_file).dimensions.should == [40, 33]
|
17
|
+
end
|
18
|
+
|
19
|
+
it "should return its dimensions" do
|
20
|
+
@image_120_x_100.dimensions.should == [120, 100]
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
require File.expand_path('../../start', __FILE__)
|
2
|
+
|
3
|
+
describe "Miso::Processor" do
|
4
|
+
before do
|
5
|
+
Miso::Processor.processor_class = nil
|
6
|
+
end
|
7
|
+
|
8
|
+
after do
|
9
|
+
Miso::Processor.processor_class = nil
|
10
|
+
end
|
11
|
+
|
12
|
+
it "should assign the processor class to use" do
|
13
|
+
Miso::Processor.processor_class = Miso::Processor::ImageMagick
|
14
|
+
Miso::Processor.processor_class.should.be Miso::Processor::ImageMagick
|
15
|
+
end
|
16
|
+
|
17
|
+
it "should find the first available processor class" do
|
18
|
+
Miso::Processor.processor_classes = [
|
19
|
+
stub(:available? => false),
|
20
|
+
stub(:available? => true),
|
21
|
+
stub(:available? => false)
|
22
|
+
]
|
23
|
+
|
24
|
+
Miso::Processor.processor_class.should.be Miso::Processor.processor_classes[1]
|
25
|
+
end
|
26
|
+
|
27
|
+
it "should raise if no available processor class is found" do
|
28
|
+
Miso::Processor.processor_classes = [
|
29
|
+
stub(:available? => false),
|
30
|
+
stub(:available? => false)
|
31
|
+
]
|
32
|
+
|
33
|
+
lambda {
|
34
|
+
Miso::Processor.processor_class
|
35
|
+
}.should.raise
|
36
|
+
end
|
37
|
+
|
38
|
+
it "should initialize with an input file" do
|
39
|
+
Miso::Processor.new('/image.png').input_file.should == '/image.png'
|
40
|
+
end
|
41
|
+
end
|
Binary file
|
data/spec/start.rb
ADDED
@@ -0,0 +1,30 @@
|
|
1
|
+
require 'rubygems' rescue LoadError
|
2
|
+
require 'test/spec'
|
3
|
+
require 'mocha'
|
4
|
+
|
5
|
+
require 'fileutils'
|
6
|
+
|
7
|
+
$:.unshift(File.expand_path('../../lib', __FILE__))
|
8
|
+
|
9
|
+
require 'miso'
|
10
|
+
require 'miso/processor'
|
11
|
+
|
12
|
+
class Test::Unit::TestCase
|
13
|
+
TMP_DIR = File.expand_path('../tmp', __FILE__)
|
14
|
+
|
15
|
+
def setup
|
16
|
+
FileUtils.mkdir_p(TMP_DIR)
|
17
|
+
end
|
18
|
+
|
19
|
+
def teardown
|
20
|
+
FileUtils.rm_rf(TMP_DIR)
|
21
|
+
end
|
22
|
+
|
23
|
+
def fixture_file(name)
|
24
|
+
File.expand_path("../fixtures/#{name}", __FILE__)
|
25
|
+
end
|
26
|
+
|
27
|
+
def temp_file(filename)
|
28
|
+
File.join(TMP_DIR, filename)
|
29
|
+
end
|
30
|
+
end
|
metadata
ADDED
@@ -0,0 +1,97 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: miso
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Manfred Stienstra
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
|
12
|
+
date: 2009-10-20 00:00:00 +02:00
|
13
|
+
default_executable:
|
14
|
+
dependencies: []
|
15
|
+
|
16
|
+
description: Miso is a unified API for simple image operations commonly used on the web.
|
17
|
+
email: manfred@fngtps.com
|
18
|
+
executables: []
|
19
|
+
|
20
|
+
extensions: []
|
21
|
+
|
22
|
+
extra_rdoc_files:
|
23
|
+
- LICENSE
|
24
|
+
- README
|
25
|
+
files:
|
26
|
+
- LICENSE
|
27
|
+
- README
|
28
|
+
- Rakefile
|
29
|
+
- TODO
|
30
|
+
- VERSION
|
31
|
+
- html/classes/Miso.html
|
32
|
+
- html/classes/Miso/Factory.html
|
33
|
+
- html/classes/Miso/Image.html
|
34
|
+
- html/classes/Miso/Processor.html
|
35
|
+
- html/classes/Miso/Processor/CoreImage.html
|
36
|
+
- html/classes/Miso/Processor/ImageMagick.html
|
37
|
+
- html/classes/Miso/Processor/NotImplementedError.html
|
38
|
+
- html/created.rid
|
39
|
+
- html/files/LICENSE.html
|
40
|
+
- html/files/README.html
|
41
|
+
- html/files/lib/miso/factory_rb.html
|
42
|
+
- html/files/lib/miso/image_rb.html
|
43
|
+
- html/files/lib/miso/processor/core_image_rb.html
|
44
|
+
- html/files/lib/miso/processor/image_magick_rb.html
|
45
|
+
- html/files/lib/miso/processor_rb.html
|
46
|
+
- html/files/lib/miso_rb.html
|
47
|
+
- html/fr_class_index.html
|
48
|
+
- html/fr_file_index.html
|
49
|
+
- html/fr_method_index.html
|
50
|
+
- html/index.html
|
51
|
+
- html/rdoc-style.css
|
52
|
+
- lib/miso.rb
|
53
|
+
- lib/miso/factory.rb
|
54
|
+
- lib/miso/image.rb
|
55
|
+
- lib/miso/processor.rb
|
56
|
+
- lib/miso/processor/core_image.rb
|
57
|
+
- lib/miso/processor/image_magick.rb
|
58
|
+
- spec/api/factory_spec.rb
|
59
|
+
- spec/api/image_spec.rb
|
60
|
+
- spec/api/processor/image_magick_spec.rb
|
61
|
+
- spec/api/processor_spec.rb
|
62
|
+
- spec/fixtures/120x100.png
|
63
|
+
- spec/start.rb
|
64
|
+
has_rdoc: true
|
65
|
+
homepage: http://github.com/Fingertips/miso
|
66
|
+
licenses: []
|
67
|
+
|
68
|
+
post_install_message:
|
69
|
+
rdoc_options:
|
70
|
+
- --charset=UTF-8
|
71
|
+
require_paths:
|
72
|
+
- lib
|
73
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
74
|
+
requirements:
|
75
|
+
- - ">="
|
76
|
+
- !ruby/object:Gem::Version
|
77
|
+
version: "0"
|
78
|
+
version:
|
79
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
80
|
+
requirements:
|
81
|
+
- - ">="
|
82
|
+
- !ruby/object:Gem::Version
|
83
|
+
version: "0"
|
84
|
+
version:
|
85
|
+
requirements: []
|
86
|
+
|
87
|
+
rubyforge_project:
|
88
|
+
rubygems_version: 1.3.5
|
89
|
+
signing_key:
|
90
|
+
specification_version: 3
|
91
|
+
summary: Miso is a unified API for simple image operations commonly used on the web.
|
92
|
+
test_files:
|
93
|
+
- spec/api/factory_spec.rb
|
94
|
+
- spec/api/image_spec.rb
|
95
|
+
- spec/api/processor/image_magick_spec.rb
|
96
|
+
- spec/api/processor_spec.rb
|
97
|
+
- spec/start.rb
|