dragonfly-minimagick 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 +6 -0
- data/README.markdown +17 -0
- data/Rakefile +12 -0
- data/dragonfly-minimagick.gemspec +24 -0
- data/lib/dragonfly-minimagick.rb +16 -0
- data/lib/dragonfly-minimagick/analyser.rb +67 -0
- data/lib/dragonfly-minimagick/config.rb +40 -0
- data/lib/dragonfly-minimagick/encoder.rb +62 -0
- data/lib/dragonfly-minimagick/generator.rb +156 -0
- data/lib/dragonfly-minimagick/processor.rb +155 -0
- data/lib/dragonfly-minimagick/utils.rb +49 -0
- data/lib/dragonfly-minimagick/version.rb +5 -0
- data/samples/beach.png +0 -0
- data/spec/dragonfly-minimagick/analyser_spec.rb +67 -0
- data/spec/dragonfly-minimagick/config_spec.rb +23 -0
- data/spec/dragonfly-minimagick/encoder_spec.rb +36 -0
- data/spec/dragonfly-minimagick/generator_spectmp.rb +106 -0
- data/spec/dragonfly-minimagick/processor_spec.rb +234 -0
- data/spec/spec.log +1 -0
- data/spec/spec_helper.rb +25 -0
- data/spec/support/image_matchers.rb +47 -0
- metadata +115 -0
data/.gitignore
ADDED
data/Gemfile
ADDED
data/README.markdown
ADDED
@@ -0,0 +1,17 @@
|
|
1
|
+
Dragonfly-Minimagick
|
2
|
+
=================
|
3
|
+
|
4
|
+
Dragonfly-Minimagick was extracted from the original dragonfly code and provides an analyser, processor, encoder and generator for Dragonfly using the MiniMagick image library.
|
5
|
+
|
6
|
+
It shouldn't be necessary and is provided here in case it's needed for some reason!
|
7
|
+
|
8
|
+
Usage
|
9
|
+
-----
|
10
|
+
|
11
|
+
require 'dragonfly-minimagick'
|
12
|
+
Dragonfly[:images].configure_with(:minimagick)
|
13
|
+
|
14
|
+
In Rails, the above would be done in an initializer.
|
15
|
+
|
16
|
+
See the [dragonfly documentation](http://markevans.github.com/dragonfly) for more info, as the equivalent ImageMagick methods have the same API.
|
17
|
+
|
data/Rakefile
ADDED
@@ -0,0 +1,12 @@
|
|
1
|
+
require 'bundler'
|
2
|
+
Bundler::GemHelper.install_tasks
|
3
|
+
|
4
|
+
require 'rake'
|
5
|
+
|
6
|
+
require 'rspec/core'
|
7
|
+
require 'rspec/core/rake_task'
|
8
|
+
RSpec::Core::RakeTask.new(:spec) do |spec|
|
9
|
+
spec.pattern = FileList['spec/**/*_spec.rb']
|
10
|
+
end
|
11
|
+
|
12
|
+
task :default => :spec
|
@@ -0,0 +1,24 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
$:.push File.expand_path("../lib", __FILE__)
|
3
|
+
require "dragonfly-minimagick/version"
|
4
|
+
|
5
|
+
Gem::Specification.new do |s|
|
6
|
+
s.name = "dragonfly-minimagick"
|
7
|
+
s.version = Dragonfly::Minimagick::VERSION
|
8
|
+
s.authors = ["Paul Spieker"]
|
9
|
+
s.email = ["p.spieker@duenos.de"]
|
10
|
+
s.homepage = "https://github.com/spieker/dragonfly-minimagick"
|
11
|
+
s.summary = %q{Use MiniMagick for image processing within Dragonfly}
|
12
|
+
s.description = %q{Not yet completely implemented}
|
13
|
+
|
14
|
+
s.rubyforge_project = "dragonfly-minimagick"
|
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_dependency("dragonfly", [">= 0.9"])
|
22
|
+
s.add_dependency("mini_magick", ["~> 3.3"])
|
23
|
+
s.add_development_dependency("rspec", [">= 2.0"])
|
24
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
require "dragonfly-minimagick/version"
|
2
|
+
|
3
|
+
module Dragonfly
|
4
|
+
module Minimagick
|
5
|
+
# Your code goes here...
|
6
|
+
end
|
7
|
+
end
|
8
|
+
|
9
|
+
require 'dragonfly-minimagick/analyser'
|
10
|
+
require 'dragonfly-minimagick/processor'
|
11
|
+
require 'dragonfly-minimagick/encoder'
|
12
|
+
require 'dragonfly-minimagick/generator'
|
13
|
+
require 'dragonfly-minimagick/config'
|
14
|
+
|
15
|
+
Dragonfly::App.register_configuration(:minimagick){ Dragonfly::Minimagick::Config }
|
16
|
+
Dragonfly::App.register_configuration(:mini_magick){ Dragonfly::Minimagick::Config }
|
@@ -0,0 +1,67 @@
|
|
1
|
+
require 'mini_magick'
|
2
|
+
require 'dragonfly'
|
3
|
+
require 'dragonfly-minimagick/utils'
|
4
|
+
|
5
|
+
module Dragonfly
|
6
|
+
module Minimagick
|
7
|
+
class Analyser
|
8
|
+
|
9
|
+
include Utils
|
10
|
+
include Dragonfly::Configurable
|
11
|
+
|
12
|
+
def width(temp_object)
|
13
|
+
ping_minimagick_image(temp_object) do |image|
|
14
|
+
image[:width]
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
def height(temp_object)
|
19
|
+
ping_minimagick_image(temp_object) do |image|
|
20
|
+
image[:height]
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
def aspect_ratio(temp_object)
|
25
|
+
ping_minimagick_image(temp_object) do |image|
|
26
|
+
image[:width].to_f / image[:height].to_f
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
def portrait?(temp_object)
|
31
|
+
ping_minimagick_image(temp_object) do |image|
|
32
|
+
image[:width] <= image[:height]
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
def landscape?(temp_object)
|
37
|
+
ping_minimagick_image(temp_object) do |image|
|
38
|
+
image[:width] >= image[:height]
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
def depth(temp_object)
|
43
|
+
minimagick_image(temp_object) do |image|
|
44
|
+
image.verbose.match(/(\d{1,2})-bit/)[1].to_i
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
def number_of_colours(temp_object)
|
49
|
+
minimagick_image(temp_object) do |image|
|
50
|
+
# image.colors
|
51
|
+
0
|
52
|
+
end
|
53
|
+
end
|
54
|
+
alias number_of_colors number_of_colours
|
55
|
+
|
56
|
+
def format(temp_object)
|
57
|
+
ping_minimagick_image(temp_object) do |image|
|
58
|
+
image[:format].downcase.to_sym
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
def image?(temp_object)
|
63
|
+
!!catch(:unable_to_handle){ format(temp_object) }
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
module Dragonfly
|
2
|
+
module Minimagick
|
3
|
+
|
4
|
+
# Minimagick is a saved configuration for Dragonfly apps, which does the following:
|
5
|
+
# - registers an minimagick analyser
|
6
|
+
# - registers an minimagick processor
|
7
|
+
# - registers an minimagick encoder
|
8
|
+
# - registers an minimagick generator
|
9
|
+
# - adds thumb shortcuts like '280x140!', etc.
|
10
|
+
# Look at the source code for apply_configuration to see exactly how it configures the app.
|
11
|
+
module Config
|
12
|
+
def self.apply_configuration(app, opts={})
|
13
|
+
app.configure do |c|
|
14
|
+
c.analyser.register(Analyser) do |a|
|
15
|
+
end
|
16
|
+
c.processor.register(Processor) do |p|
|
17
|
+
end
|
18
|
+
c.encoder.register(Encoder) do |e|
|
19
|
+
end
|
20
|
+
c.generator.register(Generator) do |g|
|
21
|
+
end
|
22
|
+
c.job :thumb do |geometry, format|
|
23
|
+
process :thumb, geometry
|
24
|
+
encode format if format
|
25
|
+
end
|
26
|
+
c.job :gif do
|
27
|
+
encode :gif
|
28
|
+
end
|
29
|
+
c.job :jpg do
|
30
|
+
encode :jpg
|
31
|
+
end
|
32
|
+
c.job :png do
|
33
|
+
encode :png
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
end
|
40
|
+
end
|
@@ -0,0 +1,62 @@
|
|
1
|
+
require 'mini_magick'
|
2
|
+
require 'dragonfly'
|
3
|
+
require 'dragonfly-minimagick/utils'
|
4
|
+
|
5
|
+
module Dragonfly
|
6
|
+
module Minimagick
|
7
|
+
class Encoder
|
8
|
+
|
9
|
+
include Utils
|
10
|
+
include Dragonfly::Configurable
|
11
|
+
|
12
|
+
configurable_attr :supported_formats, [
|
13
|
+
:ai,
|
14
|
+
:bmp,
|
15
|
+
:eps,
|
16
|
+
:gif,
|
17
|
+
:gif87,
|
18
|
+
:ico,
|
19
|
+
:j2c,
|
20
|
+
:jp2,
|
21
|
+
:jpeg,
|
22
|
+
:jpg,
|
23
|
+
:pbm,
|
24
|
+
:pcd,
|
25
|
+
:pct,
|
26
|
+
:pcx,
|
27
|
+
:pdf,
|
28
|
+
:pict,
|
29
|
+
:pjpeg,
|
30
|
+
:png,
|
31
|
+
:png24,
|
32
|
+
:png32,
|
33
|
+
:png8,
|
34
|
+
:pnm,
|
35
|
+
:ppm,
|
36
|
+
:ps,
|
37
|
+
:psd,
|
38
|
+
:ras,
|
39
|
+
:tga,
|
40
|
+
:tiff,
|
41
|
+
:wbmp,
|
42
|
+
:xbm,
|
43
|
+
:xpm,
|
44
|
+
:xwd
|
45
|
+
]
|
46
|
+
|
47
|
+
def encode(temp_object, format, encoding={})
|
48
|
+
format = format.to_s.downcase
|
49
|
+
throw :unable_to_handle unless supported_formats.include?(format.to_sym)
|
50
|
+
minimagick_image(temp_object) do |image|
|
51
|
+
if image[:format].downcase == format
|
52
|
+
temp_object # do nothing
|
53
|
+
else
|
54
|
+
image.format(format)
|
55
|
+
image
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
@@ -0,0 +1,156 @@
|
|
1
|
+
require 'mini_magick'
|
2
|
+
require 'dragonfly'
|
3
|
+
require 'dragonfly-minimagick/utils'
|
4
|
+
|
5
|
+
module Dragonfly
|
6
|
+
module Minimagick
|
7
|
+
class Generator
|
8
|
+
|
9
|
+
FONT_STYLES = {
|
10
|
+
'normal' => 'normal', #Magick::NormalStyle,
|
11
|
+
'italic' => 'italic', #Magick::ItalicStyle,
|
12
|
+
'oblique' => 'oblique' #Magick::ObliqueStyle
|
13
|
+
}
|
14
|
+
|
15
|
+
FONT_STRETCHES = {
|
16
|
+
'normal' => 'normal', #Magick::NormalStretch,
|
17
|
+
'semi-condensed' => 'semi-condensed', #Magick::SemiCondensedStretch,
|
18
|
+
'condensed' => 'condensed', #Magick::CondensedStretch,
|
19
|
+
'extra-condensed' => 'extra-condensed', #Magick::ExtraCondensedStretch,
|
20
|
+
'ultra-condensed' => 'ultra-condensed', #Magick::UltraCondensedStretch,
|
21
|
+
'semi-expanded' => 'semi-expanded', #Magick::SemiExpandedStretch,
|
22
|
+
'expanded' => 'expanded', #Magick::ExpandedStretch,
|
23
|
+
'extra-expanded' => 'extra-expanded', #Magick::ExtraExpandedStretch,
|
24
|
+
'ultra-expanded' => 'ultra-expanded' #Magick::UltraExpandedStretch
|
25
|
+
}
|
26
|
+
|
27
|
+
FONT_WEIGHTS = {
|
28
|
+
'normal' => 'normal', #Magick::NormalWeight,
|
29
|
+
'bold' => 'bold', #Magick::BoldWeight,
|
30
|
+
'bolder' => 'bolder', #Magick::BolderWeight,
|
31
|
+
'lighter' => 'lighter', #Magick::LighterWeight,
|
32
|
+
'100' => 100,
|
33
|
+
'200' => 200,
|
34
|
+
'300' => 300,
|
35
|
+
'400' => 400,
|
36
|
+
'500' => 500,
|
37
|
+
'600' => 600,
|
38
|
+
'700' => 700,
|
39
|
+
'800' => 800,
|
40
|
+
'900' => 900
|
41
|
+
}
|
42
|
+
|
43
|
+
include Utils
|
44
|
+
include Dragonfly::Configurable
|
45
|
+
|
46
|
+
def plasma(width, height, format='png')
|
47
|
+
image = MiniMagick::Image.read("plasma:fractal"){self.size = "#{width}x#{height}"}.first
|
48
|
+
image.format = format.to_s
|
49
|
+
content = write_to_tempfile(image)
|
50
|
+
image.destroy!
|
51
|
+
[
|
52
|
+
content,
|
53
|
+
{:format => format.to_sym, :name => "plasma.#{format}"}
|
54
|
+
]
|
55
|
+
end
|
56
|
+
|
57
|
+
def text(text_string, opts={})
|
58
|
+
opts = Dragonfly::HashWithCssStyleKeys[opts]
|
59
|
+
|
60
|
+
draw = MiniMagick::Draw.new
|
61
|
+
draw.gravity = 'center'
|
62
|
+
draw.text_antialias = true
|
63
|
+
|
64
|
+
# Font size
|
65
|
+
font_size = (opts[:font_size] || 12).to_i
|
66
|
+
|
67
|
+
# Scale up the text for better quality -
|
68
|
+
# it will be reshrunk at the end
|
69
|
+
s = scale_factor_for(font_size)
|
70
|
+
|
71
|
+
# Settings
|
72
|
+
draw.pointsize = font_size * s
|
73
|
+
draw.font = opts[:font] if opts[:font]
|
74
|
+
draw.font_family = opts[:font_family] if opts[:font_family]
|
75
|
+
draw.fill = opts[:color] if opts[:color]
|
76
|
+
draw.stroke = opts[:stroke_color] if opts[:stroke_color]
|
77
|
+
draw.font_style = FONT_STYLES[opts[:font_style]] if opts[:font_style]
|
78
|
+
draw.font_stretch = FONT_STRETCHES[opts[:font_stretch]] if opts[:font_stretch]
|
79
|
+
draw.font_weight = FONT_WEIGHTS[opts[:font_weight]] if opts[:font_weight]
|
80
|
+
|
81
|
+
# Padding
|
82
|
+
# NB the values are scaled up by the scale factor
|
83
|
+
pt, pr, pb, pl = parse_padding_string(opts[:padding]) if opts[:padding]
|
84
|
+
padding_top = (opts[:padding_top] || pt || 0) * s
|
85
|
+
padding_right = (opts[:padding_right] || pr || 0) * s
|
86
|
+
padding_bottom = (opts[:padding_bottom] || pb || 0) * s
|
87
|
+
padding_left = (opts[:padding_left] || pl || 0) * s
|
88
|
+
|
89
|
+
# Calculate (scaled up) dimensions
|
90
|
+
metrics = draw.get_type_metrics(text_string)
|
91
|
+
width, height = metrics.width, metrics.height
|
92
|
+
|
93
|
+
scaled_up_width = padding_left + width + padding_right
|
94
|
+
scaled_up_height = padding_top + height + padding_bottom
|
95
|
+
|
96
|
+
# Draw the background
|
97
|
+
image = MiniMagick::Image.new(scaled_up_width, scaled_up_height){
|
98
|
+
self.background_color = opts[:background_color] || 'transparent'
|
99
|
+
}
|
100
|
+
# Draw the text
|
101
|
+
draw.annotate(image, width, height, padding_left, padding_top, text_string)
|
102
|
+
|
103
|
+
# Scale back down again
|
104
|
+
image.scale!(1/s)
|
105
|
+
|
106
|
+
format = opts[:format] || :png
|
107
|
+
image.format = format.to_s
|
108
|
+
|
109
|
+
# Output image either as a string or a tempfile
|
110
|
+
content = write_to_tempfile(image)
|
111
|
+
image.destroy!
|
112
|
+
[
|
113
|
+
content,
|
114
|
+
{:format => format, :name => "text.#{format}"}
|
115
|
+
]
|
116
|
+
end
|
117
|
+
|
118
|
+
private
|
119
|
+
|
120
|
+
# Use css-style padding declaration, i.e.
|
121
|
+
# 10 (all sides)
|
122
|
+
# 10 5 (top/bottom, left/right)
|
123
|
+
# 10 5 10 (top, left/right, bottom)
|
124
|
+
# 10 5 10 5 (top, right, bottom, left)
|
125
|
+
def parse_padding_string(str)
|
126
|
+
padding_parts = str.gsub('px','').split(/\s+/).map{|px| px.to_i}
|
127
|
+
case padding_parts.size
|
128
|
+
when 1
|
129
|
+
p = padding_parts.first
|
130
|
+
[p,p,p,p]
|
131
|
+
when 2
|
132
|
+
p,q = padding_parts
|
133
|
+
[p,q,p,q]
|
134
|
+
when 3
|
135
|
+
p,q,r = padding_parts
|
136
|
+
[p,q,r,q]
|
137
|
+
when 4
|
138
|
+
padding_parts
|
139
|
+
else raise ArgumentError, "Couldn't parse padding string '#{str}' - should be a css-style string"
|
140
|
+
end
|
141
|
+
end
|
142
|
+
|
143
|
+
def scale_factor_for(font_size)
|
144
|
+
# Scale approximately to 64 if below
|
145
|
+
min_size = 64
|
146
|
+
if font_size < min_size
|
147
|
+
(min_size.to_f / font_size).ceil
|
148
|
+
else
|
149
|
+
1
|
150
|
+
end.to_f
|
151
|
+
end
|
152
|
+
|
153
|
+
end
|
154
|
+
|
155
|
+
end
|
156
|
+
end
|
@@ -0,0 +1,155 @@
|
|
1
|
+
require 'mini_magick'
|
2
|
+
require 'dragonfly'
|
3
|
+
require 'dragonfly-minimagick/utils'
|
4
|
+
|
5
|
+
module Dragonfly
|
6
|
+
module Minimagick
|
7
|
+
class Processor
|
8
|
+
|
9
|
+
GRAVITIES = {
|
10
|
+
'nw' => 'NorthWest',
|
11
|
+
'n' => 'North',
|
12
|
+
'ne' => 'NorthEast',
|
13
|
+
'w' => 'West',
|
14
|
+
'c' => 'Center',
|
15
|
+
'e' => 'East',
|
16
|
+
'sw' => 'SouthWest',
|
17
|
+
's' => 'South',
|
18
|
+
'se' => 'SouthEast'
|
19
|
+
}
|
20
|
+
|
21
|
+
# Geometry string patterns
|
22
|
+
RESIZE_GEOMETRY = /^\d*x\d*[><%^!]?$|^\d+@$/ # e.g. '300x200!'
|
23
|
+
CROPPED_RESIZE_GEOMETRY = /^(\d+)x(\d+)#(\w{1,2})?$/ # e.g. '20x50#ne'
|
24
|
+
CROP_GEOMETRY = /^(\d+)x(\d+)([+-]\d+)?([+-]\d+)?(\w{1,2})?$/ # e.g. '30x30+10+10'
|
25
|
+
THUMB_GEOMETRY = Regexp.union RESIZE_GEOMETRY, CROPPED_RESIZE_GEOMETRY, CROP_GEOMETRY
|
26
|
+
|
27
|
+
include Utils
|
28
|
+
include Dragonfly::Configurable
|
29
|
+
|
30
|
+
def crop(temp_object, opts={})
|
31
|
+
x = opts[:x].to_i
|
32
|
+
y = opts[:y].to_i
|
33
|
+
gravity = GRAVITIES[opts[:gravity]] || nil #Magick::ForgetGravity
|
34
|
+
width = opts[:width].to_i
|
35
|
+
height = opts[:height].to_i
|
36
|
+
|
37
|
+
unless opts.has_key?(:width) and opts.has_key?(:height) or opts.has_key?(:x) and opts.has_key?(:y)
|
38
|
+
return minimagick_image(temp_object) do |image|
|
39
|
+
image
|
40
|
+
end
|
41
|
+
end
|
42
|
+
minimagick_image(temp_object) do |image|
|
43
|
+
unless opts.has_key?(:width) and opts.has_key?(:height)
|
44
|
+
width = image[:width] - x
|
45
|
+
height = image[:height] - y
|
46
|
+
end
|
47
|
+
# Minimagick throws an error if the cropping area is bigger than the image,
|
48
|
+
# when the gravity is something other than nw
|
49
|
+
width = image[:width] - x if x + width > image[:width]
|
50
|
+
height = image[:height] - y if y + height > image[:height]
|
51
|
+
# p "\n\n#{opts[:width]}x#{opts[:height]}+#{opts[:x]}+#{opts[:y]} \n#{width}x#{height}+#{x}+#{y}"
|
52
|
+
image.gravity gravity unless gravity.nil? or gravity.empty?
|
53
|
+
image.crop "#{width}x#{height}+#{x}+#{y}" #(gravity, x, y, width, height)
|
54
|
+
image
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
def flip(temp_object)
|
59
|
+
minimagick_image(temp_object) do |image|
|
60
|
+
image.flip
|
61
|
+
image
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
def flop(temp_object)
|
66
|
+
minimagick_image(temp_object) do |image|
|
67
|
+
image.flop
|
68
|
+
image
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
def greyscale(temp_object, opts={})
|
73
|
+
depth = opts[:depth] || 256
|
74
|
+
minimagick_image(temp_object) do |image|
|
75
|
+
image.quantize(depth, nil) #Magick::GRAYColorspace)
|
76
|
+
image
|
77
|
+
end
|
78
|
+
end
|
79
|
+
alias grayscale greyscale
|
80
|
+
|
81
|
+
def resize(temp_object, geometry)
|
82
|
+
minimagick_image(temp_object) do |image|
|
83
|
+
# image.change_geometry!(geometry) do |cols, rows, img|
|
84
|
+
# img.resize!(cols, rows)
|
85
|
+
# end
|
86
|
+
image.resize geometry
|
87
|
+
image
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
def resize_and_crop(temp_object, opts={})
|
92
|
+
unless opts.has_key?(:width) or opts.has_key?(:height)
|
93
|
+
return minimagick_image(temp_object) do |image|
|
94
|
+
image
|
95
|
+
end
|
96
|
+
end
|
97
|
+
|
98
|
+
minimagick_image(temp_object) do |image|
|
99
|
+
width = opts[:width] ? opts[:width].to_i : image[:width]
|
100
|
+
height = opts[:height] ? opts[:height].to_i : image[:height]
|
101
|
+
gravity = GRAVITIES[opts[:gravity]] || 'center'
|
102
|
+
image.combine_options do |i|
|
103
|
+
i.resize "#{width}x#{height}^"
|
104
|
+
i.gravity gravity
|
105
|
+
i.extent "#{width}x#{height}"
|
106
|
+
end
|
107
|
+
# image.crop_resized(width, height, gravity)
|
108
|
+
image
|
109
|
+
end
|
110
|
+
end
|
111
|
+
|
112
|
+
def rotate(temp_object, amount, opts={})
|
113
|
+
args = [amount.to_f]
|
114
|
+
args << opts[:qualifier] if opts[:qualifier]
|
115
|
+
minimagick_image(temp_object) do |image|
|
116
|
+
image.background_color = opts[:background_colour] if opts[:background_colour]
|
117
|
+
image.background_color = opts[:background_color] if opts[:background_color]
|
118
|
+
image.rotate(args.join(''))
|
119
|
+
image
|
120
|
+
end
|
121
|
+
end
|
122
|
+
|
123
|
+
def thumb(temp_object, geometry)
|
124
|
+
case geometry
|
125
|
+
when RESIZE_GEOMETRY
|
126
|
+
resize(temp_object, geometry)
|
127
|
+
when CROPPED_RESIZE_GEOMETRY
|
128
|
+
resize_and_crop(temp_object, :width => $1, :height => $2, :gravity => $3)
|
129
|
+
when CROP_GEOMETRY
|
130
|
+
crop(temp_object,
|
131
|
+
:width => $1,
|
132
|
+
:height => $2,
|
133
|
+
:x => $3,
|
134
|
+
:y => $4,
|
135
|
+
:gravity => $5
|
136
|
+
)
|
137
|
+
else raise ArgumentError, "Didn't recognise the geometry string #{geometry}"
|
138
|
+
end
|
139
|
+
end
|
140
|
+
|
141
|
+
def vignette(temp_object, opts={})
|
142
|
+
x = opts[:x].to_f || temp_object.width * 0.1
|
143
|
+
y = opts[:y].to_f || temp_object.height * 0.1
|
144
|
+
radius = opts[:radius].to_f || 0.0
|
145
|
+
sigma = opts[:sigma].to_f || 10.0
|
146
|
+
|
147
|
+
minimagick_image(temp_object) do |image|
|
148
|
+
image.vignette(x, y, radius, sigma)
|
149
|
+
image
|
150
|
+
end
|
151
|
+
end
|
152
|
+
|
153
|
+
end
|
154
|
+
end
|
155
|
+
end
|
@@ -0,0 +1,49 @@
|
|
1
|
+
require 'tempfile'
|
2
|
+
require 'mini_magick'
|
3
|
+
require 'dragonfly'
|
4
|
+
|
5
|
+
module Dragonfly
|
6
|
+
module Minimagick
|
7
|
+
module Utils
|
8
|
+
|
9
|
+
include Dragonfly::Loggable
|
10
|
+
|
11
|
+
private
|
12
|
+
|
13
|
+
def minimagick_image(temp_object, &block)
|
14
|
+
image = MiniMagick::Image.open(temp_object.path)
|
15
|
+
result = block.call(image)
|
16
|
+
case result
|
17
|
+
when MiniMagick::Image
|
18
|
+
content = write_to_tempfile(result)
|
19
|
+
result.destroy!
|
20
|
+
else
|
21
|
+
content = result
|
22
|
+
end
|
23
|
+
image.destroy!
|
24
|
+
content
|
25
|
+
rescue Exception => e
|
26
|
+
log.warn("Unable to handle content in #{self.class} - got:\n#{e}")
|
27
|
+
throw :unable_to_handle
|
28
|
+
end
|
29
|
+
|
30
|
+
def ping_minimagick_image(temp_object, &block)
|
31
|
+
image = MiniMagick::Image.open(temp_object.path)
|
32
|
+
result = block.call(image)
|
33
|
+
image.destroy!
|
34
|
+
result
|
35
|
+
rescue Exception => e
|
36
|
+
log.warn("Unable to handle content in #{self.class} - got:\n#{e}")
|
37
|
+
throw :unable_to_handle
|
38
|
+
end
|
39
|
+
|
40
|
+
def write_to_tempfile(minimagick_image)
|
41
|
+
tempfile = Tempfile.new('dragonfly')
|
42
|
+
tempfile.close
|
43
|
+
minimagick_image.write(tempfile.path)
|
44
|
+
tempfile
|
45
|
+
end
|
46
|
+
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
data/samples/beach.png
ADDED
Binary file
|
@@ -0,0 +1,67 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
shared_examples_for "image analyser methods" do
|
4
|
+
|
5
|
+
# NEEDS:
|
6
|
+
# @image
|
7
|
+
# @processor
|
8
|
+
|
9
|
+
it "should return the width" do
|
10
|
+
@analyser.width(@image).should == 280
|
11
|
+
end
|
12
|
+
|
13
|
+
it "should return the height" do
|
14
|
+
@analyser.height(@image).should == 355
|
15
|
+
end
|
16
|
+
|
17
|
+
it "should return the aspect ratio" do
|
18
|
+
@analyser.aspect_ratio(@image).should == (280.0/355.0)
|
19
|
+
end
|
20
|
+
|
21
|
+
it "should say if it's portrait" do
|
22
|
+
@analyser.portrait?(@image).should be_true
|
23
|
+
end
|
24
|
+
|
25
|
+
it "should say if it's landscape" do
|
26
|
+
@analyser.landscape?(@image).should be_false
|
27
|
+
end
|
28
|
+
|
29
|
+
it "should return the number of colours" do
|
30
|
+
# @analyser.number_of_colours(@image).should == 34703
|
31
|
+
end
|
32
|
+
|
33
|
+
it "should return the depth" do
|
34
|
+
@analyser.depth(@image).should == 8
|
35
|
+
end
|
36
|
+
|
37
|
+
it "should return the format" do
|
38
|
+
@analyser.format(@image).should == :png
|
39
|
+
end
|
40
|
+
|
41
|
+
# %w(width height aspect_ratio number_of_colours depth format portrait? landscape?).each do |meth|
|
42
|
+
# it "should throw unable_to_handle in #{meth.inspect} if it's not an image file" do
|
43
|
+
# temp_object = Dragonfly::TempObject.new('blah')
|
44
|
+
# lambda{
|
45
|
+
# @analyser.send(meth, temp_object)
|
46
|
+
# }.should throw_symbol(:unable_to_handle)
|
47
|
+
# end
|
48
|
+
# end
|
49
|
+
|
50
|
+
end
|
51
|
+
|
52
|
+
describe Dragonfly::Minimagick::Analyser do
|
53
|
+
|
54
|
+
before(:each) do
|
55
|
+
image_path = SAMPLES_DIR + '/beach.png'
|
56
|
+
@image = Dragonfly::TempObject.new(File.new(image_path))
|
57
|
+
@analyser = Dragonfly::Minimagick::Analyser.new
|
58
|
+
@analyser.log = Logger.new(LOG_FILE)
|
59
|
+
end
|
60
|
+
|
61
|
+
describe "when using the filesystem" do
|
62
|
+
before(:each) do
|
63
|
+
end
|
64
|
+
it_should_behave_like "image analyser methods"
|
65
|
+
end
|
66
|
+
|
67
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Dragonfly::Minimagick::Config do
|
4
|
+
|
5
|
+
before(:each) do
|
6
|
+
@app = test_app
|
7
|
+
end
|
8
|
+
|
9
|
+
it "should configure all to use the filesystem by default" do
|
10
|
+
@app.configure_with(Dragonfly::Minimagick::Config)
|
11
|
+
end
|
12
|
+
|
13
|
+
it "should allow configuring with :minimagick" do
|
14
|
+
@app.configure_with(:minimagick)
|
15
|
+
@app.analyser.objects.first.should be_a(Dragonfly::Minimagick::Analyser)
|
16
|
+
end
|
17
|
+
|
18
|
+
it "should allow configuring with :mini_magick" do
|
19
|
+
@app.configure_with(:mini_magick)
|
20
|
+
@app.analyser.objects.first.should be_a(Dragonfly::Minimagick::Analyser)
|
21
|
+
end
|
22
|
+
|
23
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Dragonfly::Minimagick::Encoder do
|
4
|
+
|
5
|
+
before(:all) do
|
6
|
+
sample_file = SAMPLES_DIR + '/beach.png' # 280x355
|
7
|
+
@image = Dragonfly::TempObject.new(File.new(sample_file))
|
8
|
+
@encoder = Dragonfly::Minimagick::Encoder.new
|
9
|
+
end
|
10
|
+
|
11
|
+
describe "#encode" do
|
12
|
+
|
13
|
+
it "should encode the image to the correct format" do
|
14
|
+
image = @encoder.encode(@image, :gif)
|
15
|
+
image.should have_format('gif')
|
16
|
+
end
|
17
|
+
|
18
|
+
it "should throw :unable_to_handle if the format is not handleable" do
|
19
|
+
lambda{
|
20
|
+
@encoder.encode(@image, :goofy)
|
21
|
+
}.should throw_symbol(:unable_to_handle)
|
22
|
+
end
|
23
|
+
|
24
|
+
it "should do nothing if the image is already in the correct format" do
|
25
|
+
image = @encoder.encode(@image, :png)
|
26
|
+
image.should == @image
|
27
|
+
end
|
28
|
+
|
29
|
+
it "should work when not using the filesystem" do
|
30
|
+
image = @encoder.encode(@image, :gif)
|
31
|
+
image.should have_format('gif')
|
32
|
+
end
|
33
|
+
|
34
|
+
end
|
35
|
+
|
36
|
+
end
|
@@ -0,0 +1,106 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
# Needs: @generator
|
4
|
+
shared_examples_for "image generator" do
|
5
|
+
|
6
|
+
describe "generating an image with the given dimensions" do
|
7
|
+
before(:each) do
|
8
|
+
@image, @extra = @generator.plasma(23,12)
|
9
|
+
end
|
10
|
+
it {@image.should have_width(23)}
|
11
|
+
it {@image.should have_height(12)}
|
12
|
+
it {@image.should have_format('png')}
|
13
|
+
it {@extra.should == {:format => :png, :name => 'plasma.png'}}
|
14
|
+
end
|
15
|
+
|
16
|
+
describe "specifying the format" do
|
17
|
+
before(:each) do
|
18
|
+
@image, @extra = @generator.plasma(23, 12, :gif)
|
19
|
+
end
|
20
|
+
it {@image.should have_format('gif')}
|
21
|
+
it {@extra.should == {:format => :gif, :name => 'plasma.gif'}}
|
22
|
+
end
|
23
|
+
|
24
|
+
describe "text" do
|
25
|
+
before(:each) do
|
26
|
+
@text = "mmm"
|
27
|
+
end
|
28
|
+
|
29
|
+
describe "creating a text image" do
|
30
|
+
before(:each) do
|
31
|
+
@image, @extra = @generator.text(@text, :font_size => 12)
|
32
|
+
end
|
33
|
+
it {@image.should have_width(20..40)} # approximate
|
34
|
+
it {@image.should have_height(10..20)}
|
35
|
+
it {@image.should have_format('png')}
|
36
|
+
it {@extra.should == {:format => :png, :name => 'text.png'}}
|
37
|
+
end
|
38
|
+
|
39
|
+
describe "specifying the format" do
|
40
|
+
before(:each) do
|
41
|
+
@image, @extra = @generator.text(@text, :format => :gif)
|
42
|
+
end
|
43
|
+
it {@image.should have_format('gif')}
|
44
|
+
it {@extra.should == {:format => :gif, :name => 'text.gif'}}
|
45
|
+
end
|
46
|
+
|
47
|
+
describe "padding" do
|
48
|
+
before(:each) do
|
49
|
+
no_padding_text, extra = @generator.text(@text, :font_size => 12)
|
50
|
+
@width = image_properties(no_padding_text)[:width].to_i
|
51
|
+
@height = image_properties(no_padding_text)[:height].to_i
|
52
|
+
end
|
53
|
+
it "1 number shortcut" do
|
54
|
+
image, extra = @generator.text(@text, :padding => '10')
|
55
|
+
image.should have_width(@width + 20)
|
56
|
+
image.should have_height(@height + 20)
|
57
|
+
end
|
58
|
+
it "2 numbers shortcut" do
|
59
|
+
image, extra = @generator.text(@text, :padding => '10 5')
|
60
|
+
image.should have_width(@width + 10)
|
61
|
+
image.should have_height(@height + 20)
|
62
|
+
end
|
63
|
+
it "3 numbers shortcut" do
|
64
|
+
image, extra = @generator.text(@text, :padding => '10 5 8')
|
65
|
+
image.should have_width(@width + 10)
|
66
|
+
image.should have_height(@height + 18)
|
67
|
+
end
|
68
|
+
it "4 numbers shortcut" do
|
69
|
+
image, extra = @generator.text(@text, :padding => '1 2 3 4')
|
70
|
+
image.should have_width(@width + 6)
|
71
|
+
image.should have_height(@height + 4)
|
72
|
+
end
|
73
|
+
it "should override the general padding declaration with the specific one (e.g. 'padding-left')" do
|
74
|
+
image, extra = @generator.text(@text, :padding => '10', 'padding-left' => 9)
|
75
|
+
image.should have_width(@width + 19)
|
76
|
+
image.should have_height(@height + 20)
|
77
|
+
end
|
78
|
+
it "should ignore 'px' suffixes" do
|
79
|
+
image, extra = @generator.text(@text, :padding => '1px 2px 3px 4px')
|
80
|
+
image.should have_width(@width + 6)
|
81
|
+
image.should have_height(@height + 4)
|
82
|
+
end
|
83
|
+
it "bad padding string" do
|
84
|
+
lambda{
|
85
|
+
@generator.text(@text, :padding => '1 2 3 4 5')
|
86
|
+
}.should raise_error(ArgumentError)
|
87
|
+
end
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
end
|
92
|
+
|
93
|
+
|
94
|
+
describe Dragonfly::Minimagick::Generator do
|
95
|
+
|
96
|
+
before(:each) do
|
97
|
+
@generator = Dragonfly::Minimagick::Generator.new
|
98
|
+
end
|
99
|
+
|
100
|
+
describe "when using the filesystem" do
|
101
|
+
before(:each) do
|
102
|
+
end
|
103
|
+
it_should_behave_like 'image generator'
|
104
|
+
end
|
105
|
+
|
106
|
+
end
|
@@ -0,0 +1,234 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
# NEEDS:
|
4
|
+
#
|
5
|
+
# @image
|
6
|
+
# @processor
|
7
|
+
#
|
8
|
+
shared_examples_for "processing methods" do
|
9
|
+
|
10
|
+
describe "resize" do
|
11
|
+
|
12
|
+
it "should work correctly with xNN" do
|
13
|
+
image = @processor.resize(@image, 'x30')
|
14
|
+
image.should have_width(24)
|
15
|
+
image.should have_height(30)
|
16
|
+
end
|
17
|
+
|
18
|
+
it "should work correctly with NNx" do
|
19
|
+
image = @processor.resize(@image, '30x')
|
20
|
+
image.should have_width(30)
|
21
|
+
image.should have_height(38)
|
22
|
+
end
|
23
|
+
|
24
|
+
it "should work correctly with NNxNN" do
|
25
|
+
image = @processor.resize(@image, '30x30')
|
26
|
+
image.should have_width(24)
|
27
|
+
image.should have_height(30)
|
28
|
+
end
|
29
|
+
|
30
|
+
it "should work correctly with NNxNN!" do
|
31
|
+
image = @processor.resize(@image, '30x30!')
|
32
|
+
image.should have_width(30)
|
33
|
+
image.should have_height(30)
|
34
|
+
end
|
35
|
+
|
36
|
+
it "should work correctly with NNxNN%" do
|
37
|
+
image = @processor.resize(@image, '25x50%')
|
38
|
+
image.should have_width(70)
|
39
|
+
image.should have_height(178)
|
40
|
+
end
|
41
|
+
|
42
|
+
describe "NNxNN>" do
|
43
|
+
|
44
|
+
it "should not resize if the image is smaller than specified" do
|
45
|
+
image = @processor.resize(@image, '1000x1000>')
|
46
|
+
image.should have_width(280)
|
47
|
+
image.should have_height(355)
|
48
|
+
end
|
49
|
+
|
50
|
+
it "should resize if the image is larger than specified" do
|
51
|
+
image = @processor.resize(@image, '30x30>')
|
52
|
+
image.should have_width(24)
|
53
|
+
image.should have_height(30)
|
54
|
+
end
|
55
|
+
|
56
|
+
end
|
57
|
+
|
58
|
+
describe "NNxNN<" do
|
59
|
+
|
60
|
+
it "should not resize if the image is larger than specified" do
|
61
|
+
image = @processor.resize(@image, '10x10<')
|
62
|
+
image.should have_width(280)
|
63
|
+
image.should have_height(355)
|
64
|
+
end
|
65
|
+
|
66
|
+
it "should resize if the image is smaller than specified" do
|
67
|
+
image = @processor.resize(@image, '400x400<')
|
68
|
+
image.should have_width(315)
|
69
|
+
image.should have_height(400)
|
70
|
+
end
|
71
|
+
|
72
|
+
end
|
73
|
+
|
74
|
+
end
|
75
|
+
|
76
|
+
describe "crop" do # Difficult to test here other than dimensions
|
77
|
+
|
78
|
+
it "should not crop if no args given" do
|
79
|
+
image = @processor.crop(@image)
|
80
|
+
image.should have_width(280)
|
81
|
+
image.should have_height(355)
|
82
|
+
end
|
83
|
+
|
84
|
+
it "should crop using the offset given" do
|
85
|
+
image = @processor.crop(@image, :x => '7', :y => '12')
|
86
|
+
image.should have_width(273)
|
87
|
+
image.should have_height(343)
|
88
|
+
end
|
89
|
+
|
90
|
+
it "should crop using the dimensions given" do
|
91
|
+
image = @processor.crop(@image, :width => '10', :height => '20')
|
92
|
+
image.should have_width(10)
|
93
|
+
image.should have_height(20)
|
94
|
+
end
|
95
|
+
|
96
|
+
it "should crop in one dimension if given" do
|
97
|
+
image = @processor.crop(@image, :width => '10')
|
98
|
+
image.should have_width(10)
|
99
|
+
image.should have_height(355)
|
100
|
+
end
|
101
|
+
|
102
|
+
it "should take into account the gravity given" do
|
103
|
+
image1 = @processor.crop(@image, :width => '10', :height => '10', :gravity => 'nw')
|
104
|
+
image2 = @processor.crop(@image, :width => '10', :height => '10', :gravity => 'se')
|
105
|
+
image1.should_not == image2
|
106
|
+
end
|
107
|
+
|
108
|
+
it "should clip bits of the image outside of the requested crop area when not nw gravity" do
|
109
|
+
# Minimagick was previously throwing an error when the cropping area was outside the image size, when
|
110
|
+
# using a gravity other than nw
|
111
|
+
image = @processor.crop(@image, :width => '500', :height => '1000', :x => '100', :y => '200', :gravity => 'se')
|
112
|
+
image.should have_width(180)
|
113
|
+
image.should have_height(155)
|
114
|
+
end
|
115
|
+
|
116
|
+
end
|
117
|
+
|
118
|
+
describe "greyscale" do
|
119
|
+
it "should not raise an error" do
|
120
|
+
# Bit tricky to test
|
121
|
+
@processor.greyscale(@image)
|
122
|
+
end
|
123
|
+
end
|
124
|
+
|
125
|
+
describe "resize_and_crop" do
|
126
|
+
|
127
|
+
it "should do nothing if no args given" do
|
128
|
+
image = @processor.resize_and_crop(@image)
|
129
|
+
image.should have_width(280)
|
130
|
+
image.should have_height(355)
|
131
|
+
end
|
132
|
+
|
133
|
+
it "should crop to the correct dimensions" do
|
134
|
+
image = @processor.resize_and_crop(@image, :width => '100', :height => '100')
|
135
|
+
image.should have_width(100)
|
136
|
+
image.should have_height(100)
|
137
|
+
end
|
138
|
+
|
139
|
+
it "should allow cropping in one dimension" do
|
140
|
+
image = @processor.resize_and_crop(@image, :width => '100')
|
141
|
+
image.should have_width(100)
|
142
|
+
image.should have_height(355)
|
143
|
+
end
|
144
|
+
|
145
|
+
it "should take into account the gravity given" do
|
146
|
+
image1 = @processor.resize_and_crop(@image, :width => '10', :height => '10', :gravity => 'nw')
|
147
|
+
image2 = @processor.resize_and_crop(@image, :width => '10', :height => '10', :gravity => 'se')
|
148
|
+
image1.should_not == image2
|
149
|
+
end
|
150
|
+
|
151
|
+
end
|
152
|
+
|
153
|
+
describe "rotate" do
|
154
|
+
|
155
|
+
it "should rotate by 90 degrees" do
|
156
|
+
image = @processor.rotate(@image, 90)
|
157
|
+
image.should have_width(355)
|
158
|
+
image.should have_height(280)
|
159
|
+
end
|
160
|
+
|
161
|
+
it "should not rotate given a larger height and the '>' qualifier" do
|
162
|
+
image = @processor.rotate(@image, 90, :qualifier => '>')
|
163
|
+
image.should have_width(280)
|
164
|
+
image.should have_height(355)
|
165
|
+
end
|
166
|
+
|
167
|
+
it "should rotate given a larger height and the '<' qualifier" do
|
168
|
+
image = @processor.rotate(@image, 90, :qualifier => '<')
|
169
|
+
image.should have_width(355)
|
170
|
+
image.should have_height(280)
|
171
|
+
end
|
172
|
+
|
173
|
+
end
|
174
|
+
|
175
|
+
describe "thumb" do
|
176
|
+
it "should call resize if the correct string given" do
|
177
|
+
@processor.should_receive(:resize).with(@image, '30x40').and_return(image = mock)
|
178
|
+
@processor.thumb(@image, '30x40').should == image
|
179
|
+
end
|
180
|
+
it "should call resize_and_crop if the correct string given" do
|
181
|
+
@processor.should_receive(:resize_and_crop).with(@image, :width => '30', :height => '40', :gravity => 'se').and_return(image = mock)
|
182
|
+
@processor.thumb(@image, '30x40#se').should == image
|
183
|
+
end
|
184
|
+
it "should call crop if x and y given" do
|
185
|
+
@processor.should_receive(:crop).with(@image, :width => '30', :height => '40', :x => '+10', :y => '+20', :gravity => nil).and_return(image = mock)
|
186
|
+
@processor.thumb(@image, '30x40+10+20').should == image
|
187
|
+
end
|
188
|
+
it "should call crop if just gravity given" do
|
189
|
+
@processor.should_receive(:crop).with(@image, :width => '30', :height => '40', :x => nil, :y => nil, :gravity => 'sw').and_return(image = mock)
|
190
|
+
@processor.thumb(@image, '30x40sw').should == image
|
191
|
+
end
|
192
|
+
it "should call crop if x, y and gravity given" do
|
193
|
+
@processor.should_receive(:crop).with(@image, :width => '30', :height => '40', :x => '-10', :y => '-20', :gravity => 'se').and_return(image = mock)
|
194
|
+
@processor.thumb(@image, '30x40-10-20se').should == image
|
195
|
+
end
|
196
|
+
it "should raise an argument error if an unrecognized string is given" do
|
197
|
+
lambda{ @processor.thumb(@image, '30x40#ne!') }.should raise_error(ArgumentError)
|
198
|
+
end
|
199
|
+
end
|
200
|
+
|
201
|
+
describe "flip" do
|
202
|
+
it "should flip the image, leaving the same dimensions" do
|
203
|
+
image = @processor.flip(@image)
|
204
|
+
image.should have_width(280)
|
205
|
+
image.should have_height(355)
|
206
|
+
end
|
207
|
+
end
|
208
|
+
|
209
|
+
describe "flop" do
|
210
|
+
it "should flop the image, leaving the same dimensions" do
|
211
|
+
image = @processor.flop(@image)
|
212
|
+
image.should have_width(280)
|
213
|
+
image.should have_height(355)
|
214
|
+
end
|
215
|
+
end
|
216
|
+
|
217
|
+
end
|
218
|
+
|
219
|
+
|
220
|
+
describe Dragonfly::Minimagick::Processor do
|
221
|
+
|
222
|
+
before(:each) do
|
223
|
+
sample_file = SAMPLES_DIR + '/beach.png' # 280x355
|
224
|
+
@image = Dragonfly::TempObject.new(File.new(sample_file))
|
225
|
+
@processor = Dragonfly::Minimagick::Processor.new
|
226
|
+
end
|
227
|
+
|
228
|
+
describe "when using the filesystem" do
|
229
|
+
before(:each) do
|
230
|
+
end
|
231
|
+
it_should_behave_like "processing methods"
|
232
|
+
end
|
233
|
+
|
234
|
+
end
|
data/spec/spec.log
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
# Logfile created on 2011-10-28 23:20:02 +0200 by logger.rb/25413
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,25 @@
|
|
1
|
+
require "rubygems"
|
2
|
+
require "bundler"
|
3
|
+
Bundler.setup(:default, :test)
|
4
|
+
|
5
|
+
$LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
|
6
|
+
$LOAD_PATH.unshift(File.dirname(__FILE__))
|
7
|
+
require 'rspec'
|
8
|
+
require 'dragonfly-minimagick'
|
9
|
+
require 'support/image_matchers'
|
10
|
+
require 'dragonfly-minimagick/analyser'
|
11
|
+
require 'dragonfly-minimagick/config'
|
12
|
+
require 'dragonfly-minimagick/encoder'
|
13
|
+
require 'dragonfly-minimagick/generator'
|
14
|
+
require 'dragonfly-minimagick/processor'
|
15
|
+
require 'dragonfly-minimagick/utils'
|
16
|
+
|
17
|
+
SAMPLES_DIR = File.expand_path(File.dirname(__FILE__) + '/../samples') unless defined?(SAMPLES_DIR)
|
18
|
+
|
19
|
+
require 'logger'
|
20
|
+
LOG_FILE = File.dirname(__FILE__) + '/spec.log' unless defined?(LOG_FILE)
|
21
|
+
FileUtils.rm_rf(LOG_FILE)
|
22
|
+
|
23
|
+
def test_app
|
24
|
+
Dragonfly::App.send(:new)
|
25
|
+
end
|
@@ -0,0 +1,47 @@
|
|
1
|
+
def image_properties(image)
|
2
|
+
if image.is_a?(Tempfile)
|
3
|
+
tempfile = image
|
4
|
+
else
|
5
|
+
tempfile = Tempfile.new('image')
|
6
|
+
tempfile.write(image.is_a?(Dragonfly::TempObject) ? image.data : image)
|
7
|
+
tempfile.close
|
8
|
+
end
|
9
|
+
details = `identify #{tempfile.path}`
|
10
|
+
# example of details string:
|
11
|
+
# myimage.png PNG 200x100 200x100+0+0 8-bit DirectClass 31.2kb
|
12
|
+
filename, format, geometry, geometry_2, depth, image_class, size = details.split(' ')
|
13
|
+
width, height = geometry.split('x')
|
14
|
+
{
|
15
|
+
:filename => filename,
|
16
|
+
:format => format.downcase,
|
17
|
+
:width => width,
|
18
|
+
:height => height,
|
19
|
+
:depth => depth,
|
20
|
+
:image_class => image_class,
|
21
|
+
:size => size
|
22
|
+
}
|
23
|
+
end
|
24
|
+
|
25
|
+
RSpec::Matchers.define :have_width do |width|
|
26
|
+
match do |given|
|
27
|
+
width.should === image_properties(given)[:width].to_i
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
RSpec::Matchers.define :have_height do |height|
|
32
|
+
match do |given|
|
33
|
+
height.should === image_properties(given)[:height].to_i
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
RSpec::Matchers.define :have_format do |format|
|
38
|
+
match do |given|
|
39
|
+
image_properties(given)[:format].should == format
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
RSpec::Matchers.define :have_size do |size|
|
44
|
+
match do |given|
|
45
|
+
image_properties(given)[:size].should == size
|
46
|
+
end
|
47
|
+
end
|
metadata
ADDED
@@ -0,0 +1,115 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: dragonfly-minimagick
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
prerelease:
|
5
|
+
version: 0.0.1
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Paul Spieker
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
|
13
|
+
date: 2012-01-02 00:00:00 Z
|
14
|
+
dependencies:
|
15
|
+
- !ruby/object:Gem::Dependency
|
16
|
+
name: dragonfly
|
17
|
+
prerelease: false
|
18
|
+
requirement: &id001 !ruby/object:Gem::Requirement
|
19
|
+
none: false
|
20
|
+
requirements:
|
21
|
+
- - ">="
|
22
|
+
- !ruby/object:Gem::Version
|
23
|
+
version: "0.9"
|
24
|
+
type: :runtime
|
25
|
+
version_requirements: *id001
|
26
|
+
- !ruby/object:Gem::Dependency
|
27
|
+
name: mini_magick
|
28
|
+
prerelease: false
|
29
|
+
requirement: &id002 !ruby/object:Gem::Requirement
|
30
|
+
none: false
|
31
|
+
requirements:
|
32
|
+
- - ~>
|
33
|
+
- !ruby/object:Gem::Version
|
34
|
+
version: "3.3"
|
35
|
+
type: :runtime
|
36
|
+
version_requirements: *id002
|
37
|
+
- !ruby/object:Gem::Dependency
|
38
|
+
name: rspec
|
39
|
+
prerelease: false
|
40
|
+
requirement: &id003 !ruby/object:Gem::Requirement
|
41
|
+
none: false
|
42
|
+
requirements:
|
43
|
+
- - ">="
|
44
|
+
- !ruby/object:Gem::Version
|
45
|
+
version: "2.0"
|
46
|
+
type: :development
|
47
|
+
version_requirements: *id003
|
48
|
+
description: Not yet completely implemented
|
49
|
+
email:
|
50
|
+
- p.spieker@duenos.de
|
51
|
+
executables: []
|
52
|
+
|
53
|
+
extensions: []
|
54
|
+
|
55
|
+
extra_rdoc_files: []
|
56
|
+
|
57
|
+
files:
|
58
|
+
- .gitignore
|
59
|
+
- Gemfile
|
60
|
+
- README.markdown
|
61
|
+
- Rakefile
|
62
|
+
- dragonfly-minimagick.gemspec
|
63
|
+
- lib/dragonfly-minimagick.rb
|
64
|
+
- lib/dragonfly-minimagick/analyser.rb
|
65
|
+
- lib/dragonfly-minimagick/config.rb
|
66
|
+
- lib/dragonfly-minimagick/encoder.rb
|
67
|
+
- lib/dragonfly-minimagick/generator.rb
|
68
|
+
- lib/dragonfly-minimagick/processor.rb
|
69
|
+
- lib/dragonfly-minimagick/utils.rb
|
70
|
+
- lib/dragonfly-minimagick/version.rb
|
71
|
+
- samples/beach.png
|
72
|
+
- spec/dragonfly-minimagick/analyser_spec.rb
|
73
|
+
- spec/dragonfly-minimagick/config_spec.rb
|
74
|
+
- spec/dragonfly-minimagick/encoder_spec.rb
|
75
|
+
- spec/dragonfly-minimagick/generator_spectmp.rb
|
76
|
+
- spec/dragonfly-minimagick/processor_spec.rb
|
77
|
+
- spec/spec.log
|
78
|
+
- spec/spec_helper.rb
|
79
|
+
- spec/support/image_matchers.rb
|
80
|
+
homepage: https://github.com/spieker/dragonfly-minimagick
|
81
|
+
licenses: []
|
82
|
+
|
83
|
+
post_install_message:
|
84
|
+
rdoc_options: []
|
85
|
+
|
86
|
+
require_paths:
|
87
|
+
- lib
|
88
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
89
|
+
none: false
|
90
|
+
requirements:
|
91
|
+
- - ">="
|
92
|
+
- !ruby/object:Gem::Version
|
93
|
+
version: "0"
|
94
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
95
|
+
none: false
|
96
|
+
requirements:
|
97
|
+
- - ">="
|
98
|
+
- !ruby/object:Gem::Version
|
99
|
+
version: "0"
|
100
|
+
requirements: []
|
101
|
+
|
102
|
+
rubyforge_project: dragonfly-minimagick
|
103
|
+
rubygems_version: 1.8.8
|
104
|
+
signing_key:
|
105
|
+
specification_version: 3
|
106
|
+
summary: Use MiniMagick for image processing within Dragonfly
|
107
|
+
test_files:
|
108
|
+
- spec/dragonfly-minimagick/analyser_spec.rb
|
109
|
+
- spec/dragonfly-minimagick/config_spec.rb
|
110
|
+
- spec/dragonfly-minimagick/encoder_spec.rb
|
111
|
+
- spec/dragonfly-minimagick/generator_spectmp.rb
|
112
|
+
- spec/dragonfly-minimagick/processor_spec.rb
|
113
|
+
- spec/spec.log
|
114
|
+
- spec/spec_helper.rb
|
115
|
+
- spec/support/image_matchers.rb
|