dimension 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +2 -0
- data/README.md +50 -0
- data/Rakefile +2 -0
- data/benchmark.rb +28 -0
- data/bin/dimension +11 -0
- data/dimension.gemspec +21 -0
- data/examples/assets/black.gif +0 -0
- data/examples/assets/chair.jpg +0 -0
- data/examples/assets/the-two-towers.png +0 -0
- data/examples/assets/window.jpg +0 -0
- data/examples/sinatra.rb +32 -0
- data/lib/dimension/image.rb +106 -0
- data/lib/dimension/processors/image_magick.rb +75 -0
- data/lib/dimension/processors/imlib2.rb +141 -0
- data/lib/dimension/version.rb +7 -0
- data/lib/dimension.rb +39 -0
- metadata +60 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: d1be13d491cf7820b7fdd352dac29074884ee584
|
4
|
+
data.tar.gz: 1cf3a7360986cebb5d83089ad33b7fe85aa171b7
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 1541bb58760ef65bb60df5342b7fe1f85ae9a5fc4b36d4ec896be9d204749eb38cd631e40748c61af7f341865fe2c5068b49cb6453307092f7e31f7d97f025a6
|
7
|
+
data.tar.gz: 7d992bb47aeaeb109d92cd3d0944912012bf4f29fb278c7375122bc5b37cbc8076246e0672f891dd9383696196f1f1d31c8d4f008c1718ae8059f6a9579111df
|
data/.gitignore
ADDED
data/README.md
ADDED
@@ -0,0 +1,50 @@
|
|
1
|
+
Resizer
|
2
|
+
=======
|
3
|
+
|
4
|
+
Fast, simplified image resizing for Ruby. No ImageMagick.
|
5
|
+
|
6
|
+
``` rb
|
7
|
+
require 'resizer'
|
8
|
+
|
9
|
+
thumb = Resizer.open('tux.png')
|
10
|
+
thumb.generate('100x100') # => { :width => 100, :height => 100 }
|
11
|
+
thumb.save('resized.png')
|
12
|
+
```
|
13
|
+
|
14
|
+
Or generate and write file automatically.
|
15
|
+
|
16
|
+
``` rb
|
17
|
+
thumb = Resizer.new('tux.png')
|
18
|
+
thumb.generate!('100x300!') # will write file as 'tux-100x300.png'
|
19
|
+
```
|
20
|
+
|
21
|
+
# In memory processing
|
22
|
+
|
23
|
+
Yes sir, we have it.
|
24
|
+
|
25
|
+
``` rb
|
26
|
+
thumb = Resizer.open(params[:file])
|
27
|
+
thumb.generate('200x300#')
|
28
|
+
thumb.image_data
|
29
|
+
```
|
30
|
+
|
31
|
+
You can also pass a block, which will ensure the original image is closed after processing.
|
32
|
+
|
33
|
+
``` rb
|
34
|
+
get '/resize/:file' do
|
35
|
+
thumb = Resizer.open(params[:file])
|
36
|
+
thumb.generate('200x300#') do |res|
|
37
|
+
@out = thumb.to_response
|
38
|
+
end
|
39
|
+
@out.to_response
|
40
|
+
end
|
41
|
+
```
|
42
|
+
|
43
|
+
# Resizing geometries
|
44
|
+
|
45
|
+
This is taken directly from the excellent Dragonfly gem.
|
46
|
+
|
47
|
+
Copyright
|
48
|
+
=========
|
49
|
+
|
50
|
+
(c) Fork, Ltd. MIT Licensed.
|
data/Rakefile
ADDED
data/benchmark.rb
ADDED
@@ -0,0 +1,28 @@
|
|
1
|
+
require './lib/resizer'
|
2
|
+
require 'benchmark'
|
3
|
+
|
4
|
+
file = ARGV[0] or abort('File needed')
|
5
|
+
geometry = ARGV[1] or abort('Geometry required: 100x100#ne')
|
6
|
+
|
7
|
+
out = "#{File.basename(file)}.out#{File.extname(file)}"
|
8
|
+
puts "Processing #{file}"
|
9
|
+
|
10
|
+
Benchmark.bm do |x|
|
11
|
+
|
12
|
+
x.report do
|
13
|
+
Resizer.processor = 'imlib2'
|
14
|
+
a = Resizer.open(file)
|
15
|
+
res = a.generate!(geometry)
|
16
|
+
puts res.inspect
|
17
|
+
end
|
18
|
+
|
19
|
+
sleep 1
|
20
|
+
|
21
|
+
x.report do
|
22
|
+
Resizer.processor = 'image_magick'
|
23
|
+
b = Resizer.open(file)
|
24
|
+
res = b.generate!(geometry)
|
25
|
+
puts res.inspect
|
26
|
+
end
|
27
|
+
|
28
|
+
end
|
data/bin/dimension
ADDED
@@ -0,0 +1,11 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require './lib/dimension'
|
4
|
+
require 'benchmark'
|
5
|
+
|
6
|
+
file = ARGV[0] or abort('File needed. Try with examples/assets/chair.jpg')
|
7
|
+
geometry = ARGV[1] or abort('Geometry required. Example: 100x100')
|
8
|
+
|
9
|
+
thumb = Dimension.open(file)
|
10
|
+
res = thumb.generate!(geometry)
|
11
|
+
# puts res.inspect
|
data/dimension.gemspec
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
require File.expand_path("../lib/dimension/version", __FILE__)
|
3
|
+
|
4
|
+
Gem::Specification.new do |s|
|
5
|
+
s.name = "dimension"
|
6
|
+
s.version = Dimension::VERSION
|
7
|
+
s.platform = Gem::Platform::RUBY
|
8
|
+
s.authors = ['Tomás Pollak']
|
9
|
+
s.email = ['tomas@forkhq.com']
|
10
|
+
s.homepage = "https://github.com/tomas/dimension"
|
11
|
+
s.summary = "Native, in-process image resizing in Ruby."
|
12
|
+
s.description = "Yes, there are other graphic libraries besides ImageMagick."
|
13
|
+
|
14
|
+
s.required_rubygems_version = ">= 1.3.6"
|
15
|
+
s.rubyforge_project = "dimension"
|
16
|
+
|
17
|
+
s.files = `git ls-files`.split("\n")
|
18
|
+
s.executables = `git ls-files`.split("\n").map{|f| f =~ /^bin\/(.*)/ ? $1 : nil}.compact
|
19
|
+
s.require_path = 'lib'
|
20
|
+
# s.bindir = 'bin'
|
21
|
+
end
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
data/examples/sinatra.rb
ADDED
@@ -0,0 +1,32 @@
|
|
1
|
+
ROOT = File.expand_path(File.dirname(__FILE__))
|
2
|
+
|
3
|
+
require 'sinatra'
|
4
|
+
require ROOT + '/../lib/resizer'
|
5
|
+
|
6
|
+
get '/' do
|
7
|
+
images = Dir.glob(File.join(ROOT, 'assets') + '/*')
|
8
|
+
links = images.map do |i|
|
9
|
+
name = File.basename(i)
|
10
|
+
"<a href='/images/#{name}'>#{name}</a>"
|
11
|
+
end
|
12
|
+
'<ul><li>' + links.join('</li><li>') + '</li></ul>'
|
13
|
+
end
|
14
|
+
|
15
|
+
get '/images/:file' do
|
16
|
+
file = File.join(ROOT, 'assets', params[:file])
|
17
|
+
|
18
|
+
if params[:geometry].nil?
|
19
|
+
puts "Returning original file: #{file}"
|
20
|
+
return send_file file
|
21
|
+
end
|
22
|
+
|
23
|
+
begin
|
24
|
+
thumb = Resizer.open(file)
|
25
|
+
rescue => e
|
26
|
+
return e.message
|
27
|
+
end
|
28
|
+
|
29
|
+
thumb.generate(params[:geometry]) do
|
30
|
+
thumb.to_response
|
31
|
+
end
|
32
|
+
end
|
@@ -0,0 +1,106 @@
|
|
1
|
+
require 'fileutils'
|
2
|
+
|
3
|
+
module Dimension
|
4
|
+
|
5
|
+
class Image
|
6
|
+
|
7
|
+
GRAVITIES = {
|
8
|
+
'nw' => 'NorthWest',
|
9
|
+
'n' => 'North',
|
10
|
+
'ne' => 'NorthEast',
|
11
|
+
'w' => 'West',
|
12
|
+
'c' => 'Center',
|
13
|
+
'e' => 'East',
|
14
|
+
'sw' => 'SouthWest',
|
15
|
+
's' => 'South',
|
16
|
+
'se' => 'SouthEast'
|
17
|
+
}
|
18
|
+
|
19
|
+
# Geometry string patterns
|
20
|
+
RESIZE_GEOMETRY = /^(\d+)?x(\d+)?[><%^!]?$|^\d+@$/ # e.g. '300x200!'
|
21
|
+
CROPPED_RESIZE_GEOMETRY = /^(\d+)x(\d+)#(\w{1,2})?$/ # e.g. '20x50#ne'
|
22
|
+
CROP_GEOMETRY = /^(\d+)x(\d+)([+-]\d+)?([+-]\d+)?(\w{1,2})?$/ # e.g. '30x30+10+10'
|
23
|
+
|
24
|
+
attr_reader :file
|
25
|
+
|
26
|
+
def initialize(file)
|
27
|
+
unless Dimension.processor
|
28
|
+
raise "No processor set! Please set Dimension.processor = 'imlib2' or 'image_magick'"
|
29
|
+
end
|
30
|
+
|
31
|
+
@file = File.expand_path(file)
|
32
|
+
raise ArgumentError, "File not found: #{@file}" unless File.exist?(@file)
|
33
|
+
log "File loaded: #{file}. Geometry: #{geometry.join('x')}"
|
34
|
+
end
|
35
|
+
|
36
|
+
def generate(geometry, &block)
|
37
|
+
new_geometry = resize_to(geometry)
|
38
|
+
if block_given?
|
39
|
+
out = yield(new_geometry)
|
40
|
+
close
|
41
|
+
end
|
42
|
+
out || self
|
43
|
+
end
|
44
|
+
|
45
|
+
def generate!(geometry, output_file = nil)
|
46
|
+
resize_to(geometry)
|
47
|
+
save(output_file) && self
|
48
|
+
end
|
49
|
+
|
50
|
+
def resize_to(geometry)
|
51
|
+
case geometry
|
52
|
+
when RESIZE_GEOMETRY
|
53
|
+
log "Resize -- #{$1}x#{$2}"
|
54
|
+
resize($1, $2)
|
55
|
+
when CROPPED_RESIZE_GEOMETRY
|
56
|
+
log "Resize and crop -- width: #{$1}, height: #{$2}, gravity: #{$3}"
|
57
|
+
resize_and_crop($1, $2, $3)
|
58
|
+
when CROP_GEOMETRY
|
59
|
+
log "Crop -- width: #{$1}, height: #{$2}, x: #{$3}, y: #{$4}, gravity: #{$5}"
|
60
|
+
crop($1, $2, $3, $4, $5)
|
61
|
+
else
|
62
|
+
raise ArgumentError, "Didn't recognise the geometry string #{geometry}"
|
63
|
+
end
|
64
|
+
|
65
|
+
new_geometry = get_new_geometry
|
66
|
+
{:width => new_geometry[0], :height => new_geometry[1]}
|
67
|
+
end
|
68
|
+
|
69
|
+
def save(out_file)
|
70
|
+
new_geometry = get_new_geometry
|
71
|
+
|
72
|
+
if out_file.nil?
|
73
|
+
out_file = file.sub(File.extname(file), '-' + new_geometry.join('x') + File.extname(file))
|
74
|
+
end
|
75
|
+
|
76
|
+
log "Writing file: #{out_file}"
|
77
|
+
save_as(out_file) or return false
|
78
|
+
close
|
79
|
+
|
80
|
+
{:file => out_file, :width => new_geometry[0], :height => new_geometry[1]}
|
81
|
+
end
|
82
|
+
|
83
|
+
def to_s
|
84
|
+
image_data
|
85
|
+
end
|
86
|
+
|
87
|
+
def to_a
|
88
|
+
to_response
|
89
|
+
end
|
90
|
+
|
91
|
+
def inspect
|
92
|
+
geometry = get_new_geometry
|
93
|
+
"#<Dimension::Image:#{object_id} @width=#{geometry[0]}, @height=#{geometry[1]}>"
|
94
|
+
end
|
95
|
+
|
96
|
+
def to_response(env = nil)
|
97
|
+
[200, {'Content-Type' => "image/#{format}"}, image_data]
|
98
|
+
end
|
99
|
+
|
100
|
+
def log(msg)
|
101
|
+
puts "[Dimension::#{Dimension.processor}] #{msg}"
|
102
|
+
end
|
103
|
+
|
104
|
+
end
|
105
|
+
|
106
|
+
end
|
@@ -0,0 +1,75 @@
|
|
1
|
+
module ImageMagickProcessor
|
2
|
+
|
3
|
+
def geometry
|
4
|
+
[image_details[:width], image_details[:height]]
|
5
|
+
end
|
6
|
+
|
7
|
+
def format
|
8
|
+
image_details[:format]
|
9
|
+
end
|
10
|
+
|
11
|
+
def image_data
|
12
|
+
IO.read(@temp_file)
|
13
|
+
end
|
14
|
+
|
15
|
+
def save_as(new_file_path)
|
16
|
+
return if new_file_path == @temp_file
|
17
|
+
FileUtils.mv(@temp_file, new_file_path)
|
18
|
+
end
|
19
|
+
|
20
|
+
def get_new_geometry
|
21
|
+
self.class.new(@temp_file).geometry
|
22
|
+
end
|
23
|
+
|
24
|
+
def save!
|
25
|
+
FileUtils.mv(@temp_file, file)
|
26
|
+
end
|
27
|
+
|
28
|
+
def close
|
29
|
+
log "Removing temp file: #{@temp_file}"
|
30
|
+
FileUtils.rm_f(@temp_file)
|
31
|
+
end
|
32
|
+
|
33
|
+
private
|
34
|
+
|
35
|
+
def resize(w, h)
|
36
|
+
convert "-resize #{w}x#{h}"
|
37
|
+
end
|
38
|
+
|
39
|
+
def resize_and_crop(w, h, gravity)
|
40
|
+
gravity = self.class::GRAVITIES[gravity || 'c']
|
41
|
+
convert "-resize #{w}x#{h}^^ -gravity #{gravity} -crop #{w}x#{h}+0+0 +repage"
|
42
|
+
end
|
43
|
+
|
44
|
+
def crop(width, height, x = 0, y = 0, gravity)
|
45
|
+
raise ArgumentError, "you can't give a crop offset and gravity at the same time" if x != 0 and gravity
|
46
|
+
|
47
|
+
x = '+' + x unless x[/^[+-]/]
|
48
|
+
y = '+' + y unless y[/^[+-]/]
|
49
|
+
args = "-crop #{w}x#{h}#{x}#{y} +repage"
|
50
|
+
|
51
|
+
if gravity and g = self.class::GRAVITIES[gravity]
|
52
|
+
args = "-gravity #{gravity} #{args}"
|
53
|
+
end
|
54
|
+
|
55
|
+
convert args
|
56
|
+
end
|
57
|
+
|
58
|
+
def convert(args)
|
59
|
+
@temp_file = "/tmp/#{$$}.#{File.basename(file)}"
|
60
|
+
out = `convert "#{file}" #{args} "#{@temp_file}"`
|
61
|
+
end
|
62
|
+
|
63
|
+
def image_details
|
64
|
+
@image_details ||= identify(file)
|
65
|
+
end
|
66
|
+
|
67
|
+
def identify(path)
|
68
|
+
out = `identify -ping -format '%m %w %h' "#{path}"`
|
69
|
+
format, width, height = out.split
|
70
|
+
{ :format => format.downcase,
|
71
|
+
:width => width.to_i,
|
72
|
+
:height => height.to_i }
|
73
|
+
end
|
74
|
+
|
75
|
+
end
|
@@ -0,0 +1,141 @@
|
|
1
|
+
require 'imlib2'
|
2
|
+
|
3
|
+
module Imlib2Processor
|
4
|
+
|
5
|
+
def image
|
6
|
+
@image ||= Imlib2::Image.load(@file)
|
7
|
+
end
|
8
|
+
|
9
|
+
def geometry
|
10
|
+
[image.w, image.h]
|
11
|
+
end
|
12
|
+
|
13
|
+
def format
|
14
|
+
image.format # .gsub('jpeg', 'jpg')
|
15
|
+
rescue ArgumentError
|
16
|
+
File.extname(file).sub('.', '')
|
17
|
+
end
|
18
|
+
|
19
|
+
def to_rgba
|
20
|
+
bytes = data.bytes
|
21
|
+
(1..bytes.length).step(4).map { |i| bytes[i..i+2] << bytes[i-1] }.flatten
|
22
|
+
end
|
23
|
+
|
24
|
+
# transforms data (RGBA buffer) into a array of RGB values
|
25
|
+
def to_rgb
|
26
|
+
bytes = data.bytes
|
27
|
+
(1..bytes.length).step(4).map { |i| [bytes[i-1],bytes[i],bytes[i+1]] }.flatten
|
28
|
+
end
|
29
|
+
|
30
|
+
def image_data
|
31
|
+
unless @temp_file
|
32
|
+
@temp_file = "/tmp/#{$$}.#{File.basename(file)}"
|
33
|
+
save_as(@temp_file)
|
34
|
+
end
|
35
|
+
IO.read(@temp_file)
|
36
|
+
end
|
37
|
+
|
38
|
+
def save_as(new_file_path)
|
39
|
+
image.save(new_file_path)
|
40
|
+
end
|
41
|
+
|
42
|
+
def save!
|
43
|
+
image.save(file)
|
44
|
+
end
|
45
|
+
|
46
|
+
def close
|
47
|
+
log "Closing image."
|
48
|
+
FileUtils.rm(@temp_file) if @temp_file
|
49
|
+
image.delete!(true) # free image, and de-cache it too
|
50
|
+
end
|
51
|
+
|
52
|
+
def get_new_geometry
|
53
|
+
geometry
|
54
|
+
end
|
55
|
+
|
56
|
+
# http://pablotron.org/software/imlib2-ruby/doc/
|
57
|
+
#
|
58
|
+
# iw, ih = old_image.width, old_image.height
|
59
|
+
# new_w, new_h = iw - 20, ih - 20
|
60
|
+
# values = [10, 10, iw - 10, iw - 10, new_w, new_h]
|
61
|
+
# new_image = old_image.crop_scaled values
|
62
|
+
|
63
|
+
def resize(w, h)
|
64
|
+
new_w, new_h = get_resize_geometry(w, h, false)
|
65
|
+
crop_scaled(0, 0, new_w, new_h)
|
66
|
+
end
|
67
|
+
|
68
|
+
# def resize_and_fill(w, h)
|
69
|
+
# new_w, new_h = get_resize_geometry(w, h, false)
|
70
|
+
# x = (w.to_i - new_w)
|
71
|
+
# y = (h.to_i - new_h)
|
72
|
+
# image.crop_scaled!(x*-1, y*-1, image.w + x*2, image.h + y*2, w.to_i, h.to_i)
|
73
|
+
# end
|
74
|
+
|
75
|
+
def resize_and_crop(w, h, gravity)
|
76
|
+
new_w, new_h = get_resize_geometry(w, h, true)
|
77
|
+
crop_scaled(0, 0, new_w, new_h)
|
78
|
+
# crop_scaled(0, 0, w, h)
|
79
|
+
|
80
|
+
offset = get_offset(w, h, gravity)
|
81
|
+
# original_height = image.h
|
82
|
+
# original_width = image.w
|
83
|
+
|
84
|
+
image.crop!(offset[0], offset[1], w.to_i, h.to_i)
|
85
|
+
# crop_scaled(offset[0], offset[1], new_w, new_h)
|
86
|
+
end
|
87
|
+
|
88
|
+
def crop(width, height, x, y, gravity)
|
89
|
+
rect = [x || 0, y || 0, width.to_i, height.to_i]
|
90
|
+
image.crop!(rect)
|
91
|
+
end
|
92
|
+
|
93
|
+
def crop_scaled(x, y, new_w, new_h)
|
94
|
+
log "Resizing #{image.w}x#{image.h} to #{new_w}x#{new_h}. Offset at #{x},#{y}"
|
95
|
+
image.crop_scaled!(x, y, image.w, image.h, new_w.to_i, new_h.to_i)
|
96
|
+
end
|
97
|
+
|
98
|
+
def get_offset(w, h, gravity = 'c')
|
99
|
+
if gravity.nil? or gravity == '' or gravity == 'c'
|
100
|
+
return get_center_offset(w, h)
|
101
|
+
else
|
102
|
+
raise 'Not implemented'
|
103
|
+
end
|
104
|
+
end
|
105
|
+
|
106
|
+
def get_center_offset(w, h)
|
107
|
+
w_diff = image.w - w.to_i
|
108
|
+
h_diff = image.h - h.to_i
|
109
|
+
log "Width diff: #{w_diff}"
|
110
|
+
log "Height diff: #{h_diff}"
|
111
|
+
|
112
|
+
if w_diff == h_diff
|
113
|
+
return [0, 0]
|
114
|
+
elsif w_diff > h_diff
|
115
|
+
return [w_diff.to_f/2, 0]
|
116
|
+
else
|
117
|
+
return [0, h_diff.to_f/2]
|
118
|
+
end
|
119
|
+
end
|
120
|
+
|
121
|
+
def get_resize_geometry(w, h, to_longer = true)
|
122
|
+
if to_longer
|
123
|
+
if image.w < image.h
|
124
|
+
new_h = ((w.to_f / image.w) * image.h).round
|
125
|
+
return w.to_i, new_h
|
126
|
+
else
|
127
|
+
new_w = ((h.to_f / image.h) * image.w).round
|
128
|
+
return new_w, h.to_i
|
129
|
+
end
|
130
|
+
else
|
131
|
+
if w && image.w >= image.h
|
132
|
+
new_h = ((w.to_f / image.w) * image.h).round
|
133
|
+
return w.to_i, new_h
|
134
|
+
else
|
135
|
+
new_w = ((h.to_f / image.h) * image.w).round
|
136
|
+
return new_w, h.to_i
|
137
|
+
end
|
138
|
+
end
|
139
|
+
end
|
140
|
+
|
141
|
+
end
|
data/lib/dimension.rb
ADDED
@@ -0,0 +1,39 @@
|
|
1
|
+
# require File.expand_path(File.dirname(__FILE__)) + '/image'
|
2
|
+
require 'dimension/image'
|
3
|
+
|
4
|
+
module Dimension
|
5
|
+
|
6
|
+
ROOT = File.expand_path(File.dirname(__FILE__))
|
7
|
+
|
8
|
+
PROCESSORS = {
|
9
|
+
'imlib2' => 'Imlib2Processor',
|
10
|
+
'image_magick' => 'ImageMagickProcessor'
|
11
|
+
}
|
12
|
+
|
13
|
+
def self.processor
|
14
|
+
@processor
|
15
|
+
end
|
16
|
+
|
17
|
+
def self.processor=(name)
|
18
|
+
@processor = PROCESSORS[name] or raise "Processor not found: #{name}"
|
19
|
+
# require File.join(ROOT, 'dimension', 'processors', name)
|
20
|
+
require_relative "dimension/processors/#{name}"
|
21
|
+
Image.include(Kernel.const_get(@processor))
|
22
|
+
end
|
23
|
+
|
24
|
+
def self.open(file)
|
25
|
+
Image.new(file)
|
26
|
+
end
|
27
|
+
|
28
|
+
end
|
29
|
+
|
30
|
+
begin
|
31
|
+
require 'imlib2'
|
32
|
+
Dimension.processor = 'imlib2'
|
33
|
+
rescue LoadError
|
34
|
+
if system("convert -h")
|
35
|
+
Dimension.processor = 'image_magick'
|
36
|
+
else
|
37
|
+
puts "No available processors found. Please install ruby-imlib2 or ImageMagick."
|
38
|
+
end
|
39
|
+
end
|
metadata
ADDED
@@ -0,0 +1,60 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: dimension
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Tomás Pollak
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2014-04-04 00:00:00.000000000 Z
|
12
|
+
dependencies: []
|
13
|
+
description: Yes, there are other graphic libraries besides ImageMagick.
|
14
|
+
email:
|
15
|
+
- tomas@forkhq.com
|
16
|
+
executables:
|
17
|
+
- dimension
|
18
|
+
extensions: []
|
19
|
+
extra_rdoc_files: []
|
20
|
+
files:
|
21
|
+
- ".gitignore"
|
22
|
+
- README.md
|
23
|
+
- Rakefile
|
24
|
+
- benchmark.rb
|
25
|
+
- bin/dimension
|
26
|
+
- dimension.gemspec
|
27
|
+
- examples/assets/black.gif
|
28
|
+
- examples/assets/chair.jpg
|
29
|
+
- examples/assets/the-two-towers.png
|
30
|
+
- examples/assets/window.jpg
|
31
|
+
- examples/sinatra.rb
|
32
|
+
- lib/dimension.rb
|
33
|
+
- lib/dimension/image.rb
|
34
|
+
- lib/dimension/processors/image_magick.rb
|
35
|
+
- lib/dimension/processors/imlib2.rb
|
36
|
+
- lib/dimension/version.rb
|
37
|
+
homepage: https://github.com/tomas/dimension
|
38
|
+
licenses: []
|
39
|
+
metadata: {}
|
40
|
+
post_install_message:
|
41
|
+
rdoc_options: []
|
42
|
+
require_paths:
|
43
|
+
- lib
|
44
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
45
|
+
requirements:
|
46
|
+
- - ">="
|
47
|
+
- !ruby/object:Gem::Version
|
48
|
+
version: '0'
|
49
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
50
|
+
requirements:
|
51
|
+
- - ">="
|
52
|
+
- !ruby/object:Gem::Version
|
53
|
+
version: 1.3.6
|
54
|
+
requirements: []
|
55
|
+
rubyforge_project: dimension
|
56
|
+
rubygems_version: 2.2.0
|
57
|
+
signing_key:
|
58
|
+
specification_version: 4
|
59
|
+
summary: Native, in-process image resizing in Ruby.
|
60
|
+
test_files: []
|