dimension 0.3.1 → 0.4.0
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.
- 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:
|