dimension 0.3.1 → 0.4.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +42 -10
- data/benchmark.rb +32 -10
- data/dimension.gemspec +0 -3
- data/lib/dimension/image.rb +3 -3
- data/lib/dimension/middleware.rb +9 -9
- data/lib/dimension/processors/vips.rb +15 -17
- data/lib/dimension/scanner.rb +8 -8
- data/lib/dimension/version.rb +2 -2
- metadata +4 -5
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 934d06b88507ea43564e933aba941dcde54293b9
|
4
|
+
data.tar.gz: 0d3b5b21ee450cfc6e8f6799ae20d470cadacdf7
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 95282e3ef84f4c5080099ee0235b58440b36f6837aecc129041ad810d08aaeb1a2fefd44fe9aecb2276550ade6228d74470e509556b38f782617625de83d21cc
|
7
|
+
data.tar.gz: 70c108c122b74bee2d922d1405520fb28471ce2adac8b36351b3d061729de81ccc4377855e908591efde5b2142e0b1601b0b9ed30b1c831608d82ecefd2ebd29
|
data/README.md
CHANGED
@@ -1,7 +1,6 @@
|
|
1
|
-
Dimension
|
2
|
-
=========
|
1
|
+
# Dimension
|
3
2
|
|
4
|
-
|
3
|
+
Lightweight image resizing for Ruby, either with vips, imlib2 or ImageMagick.
|
5
4
|
|
6
5
|
``` rb
|
7
6
|
require 'dimension'
|
@@ -18,7 +17,7 @@ Or generate and write file automatically.
|
|
18
17
|
thumb.generate!('100x300!') # will write file as 'tux-100x300.png'
|
19
18
|
```
|
20
19
|
|
21
|
-
|
20
|
+
## In memory processing
|
22
21
|
|
23
22
|
Yes sir, we have it.
|
24
23
|
|
@@ -39,16 +38,49 @@ You can also pass a block, which will ensure the original image is closed after
|
|
39
38
|
end
|
40
39
|
```
|
41
40
|
|
42
|
-
#
|
41
|
+
# Installation
|
43
42
|
|
44
|
-
|
43
|
+
For vips backend:
|
45
44
|
|
46
|
-
|
47
|
-
|
45
|
+
# install library
|
46
|
+
apt install libvips42
|
47
|
+
# then, the ruby bindings
|
48
|
+
gem install ruby-vips
|
49
|
+
# and in case you don't get a libvips.so symlink
|
50
|
+
sudo ln -s /usr/lib/x86_64-linux-gnu/libvips.so.42 /usr/lib/x86_64-linux-gnu/libvips.so
|
51
|
+
|
52
|
+
For imlib2 backend:
|
53
|
+
|
54
|
+
# install deps
|
55
|
+
sudo apt install libimlib2-dev
|
56
|
+
# clone repo
|
57
|
+
git clone https://github.com/pepabo/imlib2-ruby
|
58
|
+
cd imlib2-ruby
|
59
|
+
# build/install
|
60
|
+
ruby extconf.rb
|
61
|
+
make
|
62
|
+
make install
|
63
|
+
# and clean up
|
64
|
+
cd ..
|
65
|
+
rm -Rf imlib2-ruby
|
66
|
+
|
67
|
+
For ImageMagick, there's no gem required. Just make sure the binaries (identify, convert) are in place:
|
68
|
+
|
69
|
+
sudo apt install imagemagick
|
70
|
+
|
71
|
+
# TODO
|
72
|
+
|
73
|
+
- [ ] Support for N/S/W/E gravities.
|
74
|
+
- [ ] Tests (e.g. ensure geometry calculation works equally across backends).
|
75
|
+
|
76
|
+
# Related
|
77
|
+
|
78
|
+
- [Dragonfly gem](http://markevans.github.io/dragonfly). This is where the original inspiration came from.
|
79
|
+
|
80
|
+
# Author
|
48
81
|
|
49
82
|
Written by Tomás Pollak.
|
50
83
|
|
51
|
-
Copyright
|
52
|
-
=========
|
84
|
+
# Copyright
|
53
85
|
|
54
86
|
(c) Fork, Ltd. MIT Licensed.
|
data/benchmark.rb
CHANGED
@@ -2,27 +2,49 @@ require './lib/dimension'
|
|
2
2
|
require 'benchmark'
|
3
3
|
|
4
4
|
file = ARGV[0] or abort('File needed')
|
5
|
-
geometry = ARGV[1] or abort('Geometry required: 100x100
|
5
|
+
geometry = ARGV[1] or abort('Geometry required: 100x100')
|
6
6
|
|
7
|
-
|
7
|
+
ext = File.extname(file)
|
8
|
+
base = File.basename(file, ext)
|
8
9
|
puts "Processing #{file}"
|
9
10
|
|
10
11
|
Benchmark.bm do |x|
|
11
12
|
|
12
|
-
|
13
|
+
begin
|
13
14
|
Dimension.processor = 'imlib2'
|
14
|
-
|
15
|
-
|
16
|
-
|
15
|
+
x.report do
|
16
|
+
a = Dimension.open(file)
|
17
|
+
res = a.generate!(geometry, [base, '-imlib2', ext].join)
|
18
|
+
puts res.inspect
|
19
|
+
end
|
20
|
+
rescue LoadError
|
21
|
+
puts "imlib2 missing."
|
17
22
|
end
|
18
23
|
|
19
24
|
sleep 1
|
20
25
|
|
21
|
-
|
26
|
+
begin
|
22
27
|
Dimension.processor = 'image_magick'
|
23
|
-
|
24
|
-
|
25
|
-
|
28
|
+
x.report do
|
29
|
+
b = Dimension.open(file)
|
30
|
+
res = b.generate!(geometry, [base, '-image_magick', ext].join)
|
31
|
+
puts res.inspect
|
32
|
+
end
|
33
|
+
rescue LoadError => e
|
34
|
+
puts "imagemagick missing."
|
35
|
+
end
|
36
|
+
|
37
|
+
sleep 1
|
38
|
+
|
39
|
+
begin
|
40
|
+
Dimension.processor = 'vips'
|
41
|
+
x.report do
|
42
|
+
b = Dimension.open(file)
|
43
|
+
res = b.generate!(geometry, [base, '-vips', ext].join)
|
44
|
+
puts res.inspect
|
45
|
+
end
|
46
|
+
rescue LoadError => e
|
47
|
+
puts "vips missing."
|
26
48
|
end
|
27
49
|
|
28
50
|
end
|
data/dimension.gemspec
CHANGED
@@ -10,10 +10,7 @@ Gem::Specification.new do |s|
|
|
10
10
|
s.homepage = "https://github.com/tomas/dimension"
|
11
11
|
s.summary = "Native, in-process image resizing in Ruby."
|
12
12
|
s.description = "Yes, there are other graphic libraries besides ImageMagick."
|
13
|
-
|
14
13
|
s.required_rubygems_version = ">= 1.3.6"
|
15
|
-
s.rubyforge_project = "dimension"
|
16
|
-
|
17
14
|
s.files = `git ls-files`.split("\n")
|
18
15
|
s.executables = `git ls-files`.split("\n").map{|f| f =~ /^bin\/(.*)/ ? $1 : nil}.compact
|
19
16
|
s.require_path = 'lib'
|
data/lib/dimension/image.rb
CHANGED
@@ -53,13 +53,13 @@ class Image
|
|
53
53
|
|
54
54
|
def resize_to(geometry)
|
55
55
|
case geometry
|
56
|
-
when RESIZE_GEOMETRY
|
56
|
+
when RESIZE_GEOMETRY # e.g. '300x200!'
|
57
57
|
log "Resize -- #{$1}x#{$2}"
|
58
58
|
resize($1, $2)
|
59
|
-
when CROPPED_RESIZE_GEOMETRY
|
59
|
+
when CROPPED_RESIZE_GEOMETRY # e.g. '20x50:ne'
|
60
60
|
log "Resize and crop -- width: #{$1}, height: #{$2}, gravity: #{$3}"
|
61
61
|
resize_and_crop($1, $2, $3)
|
62
|
-
when CROP_GEOMETRY
|
62
|
+
when CROP_GEOMETRY # e.g. '30x30+10+10'
|
63
63
|
log "Crop -- width: #{$1}, height: #{$2}, x: #{$3}, y: #{$4}, gravity: #{$5}"
|
64
64
|
crop($1, $2, $3, $4, $5)
|
65
65
|
else
|
data/lib/dimension/middleware.rb
CHANGED
@@ -4,35 +4,35 @@ require 'rack/throttle'
|
|
4
4
|
module Dimension
|
5
5
|
|
6
6
|
class Middleware
|
7
|
-
|
7
|
+
|
8
8
|
EXCEEDED = [403, {'Content-Type' => 'text/plain'}, ['Limit Exceeded.']]
|
9
|
-
|
9
|
+
|
10
10
|
def initialize(app, opts = {})
|
11
11
|
@app = app
|
12
12
|
@root = File.expand_path(opts[:root] || Dir.pwd())
|
13
13
|
@save = opts[:save]
|
14
|
-
|
14
|
+
|
15
15
|
if opts[:throttle]
|
16
16
|
@throttle = Rack::Throttle::Interval.new(self, :min => opts[:throttle])
|
17
17
|
end
|
18
18
|
end
|
19
|
-
|
19
|
+
|
20
20
|
def call(env)
|
21
21
|
url = env['PATH_INFO']
|
22
22
|
geometry = url[/-([0-9x:-]+)\.(png|gif|jpe?g)/i, 1]
|
23
|
-
|
23
|
+
|
24
24
|
return @app.call(env) unless geometry
|
25
25
|
|
26
26
|
resized = File.join(@root, url)
|
27
27
|
original = resized.sub("-#{geometry}", '')
|
28
|
-
|
28
|
+
|
29
29
|
if !File.exist?(resized) and File.exist?(original)
|
30
|
-
|
30
|
+
|
31
31
|
if @throttle
|
32
32
|
req = Rack::Request.new(env)
|
33
33
|
return EXCEEDED unless @throttle.allowed?(req)
|
34
34
|
end
|
35
|
-
|
35
|
+
|
36
36
|
# puts 'Processing image: ' + file
|
37
37
|
image = Dimension.open(original)
|
38
38
|
image.generate(geometry) do
|
@@ -46,7 +46,7 @@ module Dimension
|
|
46
46
|
# puts "Error processing image: #{e.message}"
|
47
47
|
@app.call(env)
|
48
48
|
end
|
49
|
-
|
49
|
+
|
50
50
|
end
|
51
51
|
|
52
52
|
end
|
@@ -1,33 +1,31 @@
|
|
1
1
|
# from examples at
|
2
|
-
# - https://github.com/eltiare/carrierwave-
|
3
|
-
# - https://github.com/jcupitt/ruby-
|
4
|
-
|
2
|
+
# - https://github.com/eltiare/carrierwave-Vips/blob/master/lib/carrierwave/Vips.rb
|
3
|
+
# - https://github.com/jcupitt/ruby-Vips/tree/master/examples
|
5
4
|
require 'vips'
|
6
5
|
|
7
6
|
module VipsProcessor
|
8
7
|
|
9
8
|
FORMAT_OPTS = {
|
10
9
|
'jpeg' => { :quality => 0.9 },
|
11
|
-
'png' => { :compression =>
|
10
|
+
'png' => { :compression => 8, :interlace => false }
|
12
11
|
}
|
13
12
|
|
14
13
|
SHARPEN_MASK = begin
|
15
|
-
|
14
|
+
::Vips::Image.new_from_array [
|
16
15
|
[ -1, -1, -1 ],
|
17
16
|
[ -1, 24, -1 ],
|
18
17
|
[ -1, -1, -1 ]
|
19
|
-
]
|
20
|
-
::VIPS::Mask.new conv_mask, 16
|
18
|
+
], 16
|
21
19
|
end
|
22
20
|
|
23
21
|
def image
|
24
22
|
@image ||= if format == 'jpeg'
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
23
|
+
Vips::Image.jpeg(@file, :sequential => true)
|
24
|
+
elsif format == 'png'
|
25
|
+
Vips::Image.png(@file, :sequential => true)
|
26
|
+
else
|
27
|
+
Vips::Image.new(@file)
|
28
|
+
end
|
31
29
|
end
|
32
30
|
|
33
31
|
def geometry
|
@@ -53,7 +51,7 @@ module VipsProcessor
|
|
53
51
|
def close
|
54
52
|
log "Closing image and cutting thread..."
|
55
53
|
@image = nil
|
56
|
-
|
54
|
+
Vips::thread_shutdown
|
57
55
|
# image.delete!(true) # free image, and de-cache it too
|
58
56
|
end
|
59
57
|
|
@@ -133,9 +131,9 @@ module VipsProcessor
|
|
133
131
|
|
134
132
|
def writer_class
|
135
133
|
case format
|
136
|
-
when 'jpeg' then
|
137
|
-
when 'png' then
|
138
|
-
else
|
134
|
+
when 'jpeg' then Vips::JPEGWriter
|
135
|
+
when 'png' then Vips::PNGWriter
|
136
|
+
else Vips::Writer
|
139
137
|
end
|
140
138
|
end
|
141
139
|
|
data/lib/dimension/scanner.rb
CHANGED
@@ -3,7 +3,7 @@ require 'logger'
|
|
3
3
|
require 'uri'
|
4
4
|
|
5
5
|
module Dimension
|
6
|
-
|
6
|
+
|
7
7
|
class Scanner
|
8
8
|
|
9
9
|
def initialize(opts = {})
|
@@ -11,23 +11,23 @@ module Dimension
|
|
11
11
|
@root = File.expand_path(opts.delete(:root))
|
12
12
|
@log_output = opts.delete(:log_output) || STDOUT
|
13
13
|
end
|
14
|
-
|
14
|
+
|
15
15
|
def process(content)
|
16
16
|
images = content.scan(/([a-z\-_0-9\/\:\.]*\.(jpg|jpeg|png|gif))/i)
|
17
17
|
return [] if images.empty?
|
18
|
-
|
18
|
+
|
19
19
|
paths = images.map { |img| URI.parse(img[0]).path }.uniq
|
20
20
|
paths.map do |path|
|
21
|
-
|
21
|
+
|
22
22
|
full = File.join(@root, path)
|
23
23
|
if File.exist?(full)
|
24
24
|
logger.info "Image exists in #{@root}: #{path}"
|
25
25
|
next
|
26
26
|
end
|
27
|
-
|
27
|
+
|
28
28
|
logger.info "Image not found! #{path}"
|
29
29
|
no_extension = File.basename(path, File.extname(path))
|
30
|
-
|
30
|
+
|
31
31
|
if geometry = no_extension[/((\d+)?x(\d+)?.?)$/i, 1]
|
32
32
|
original = File.join(@root, path.sub(/-?#{geometry}/, ''))
|
33
33
|
|
@@ -48,11 +48,11 @@ module Dimension
|
|
48
48
|
end
|
49
49
|
|
50
50
|
private
|
51
|
-
|
51
|
+
|
52
52
|
def logger
|
53
53
|
Logger.new(@log_output)
|
54
54
|
end
|
55
|
-
|
55
|
+
|
56
56
|
def resize_image(file, geometry, destination)
|
57
57
|
thumb = Dimension.open(file)
|
58
58
|
thumb.generate!(geometry, destination)
|
data/lib/dimension/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: dimension
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.4.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Tomás Pollak
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2017-10-06 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rack-throttle
|
@@ -71,10 +71,9 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
71
71
|
- !ruby/object:Gem::Version
|
72
72
|
version: 1.3.6
|
73
73
|
requirements: []
|
74
|
-
rubyforge_project:
|
75
|
-
rubygems_version: 2.
|
74
|
+
rubyforge_project:
|
75
|
+
rubygems_version: 2.5.1
|
76
76
|
signing_key:
|
77
77
|
specification_version: 4
|
78
78
|
summary: Native, in-process image resizing in Ruby.
|
79
79
|
test_files: []
|
80
|
-
has_rdoc:
|