image_processing 0.11.2 → 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of image_processing might be problematic. Click here for more details.
- checksums.yaml +4 -4
- data/CHANGELOG.md +22 -0
- data/README.md +75 -18
- data/image_processing.gemspec +3 -2
- data/lib/image_processing/builder.rb +4 -2
- data/lib/image_processing/chainable.rb +27 -24
- data/lib/image_processing/mini_magick.rb +41 -31
- data/lib/image_processing/processor.rb +1 -1
- data/lib/image_processing/version.rb +1 -1
- data/lib/image_processing/vips.rb +21 -15
- metadata +34 -29
- data/lib/image_processing/mini_magick/deprecated_api.rb +0 -120
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 8c6647897aed5a610f76eae2edef4327ec092653
|
4
|
+
data.tar.gz: '09335920e634fc2cb83a8be2111dda2c340421e2'
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: f1fbf330dc866bcabe44121cdf1f27ee488db46cbcdcc0d6cbfae07b95c9064740047d5faf63a02fc2ce6e11e14b8cf425dfa59ae716ff964ec5947a5e98be96
|
7
|
+
data.tar.gz: 332f2ad092e5ea7a5bda88388d152d11f8a788cd7659cb53e8370a83fcd5358c4078d677af6d89e594adfa04e050d12b2fcd4dcb1d2586020449b5285f098cb1
|
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,25 @@
|
|
1
|
+
## 1.0.0 (2018-04-04)
|
2
|
+
|
3
|
+
* Depend on `mini_magick` and `ruby-vips` gems (@janko-m, @mokolabs)
|
4
|
+
|
5
|
+
* [minimagick] Remove deprecated API in favor of the chainable API (@janko-m)
|
6
|
+
|
7
|
+
* [core] Rename `Builder#default_options` to `Builder#options` (@janko-m)
|
8
|
+
|
9
|
+
* [minimagick] Remove `:fail` loader option in favor of the existing `:regard_warnings` (@janko-m)
|
10
|
+
|
11
|
+
* [vips, minimagick] Don't fail on warnings when loading the image (@janko-m)
|
12
|
+
|
13
|
+
* [vips] Don't apply `Vips::Image#autorot` if `:autorotate` loader option was passed in (@janko-m)
|
14
|
+
|
15
|
+
* [minimagick] Allow using value `nil` to add ImageMagick options that don't have a value (@janko-m)
|
16
|
+
|
17
|
+
* [vips] Accept `:quality` saver option as an alias to `:Q` (@janko-m)
|
18
|
+
|
19
|
+
* [minimagick] Automatically sharpen thumbnails after resizing (@janko-m, @mokolabs)
|
20
|
+
|
21
|
+
* [vips] Automatically sharpen thumbnails after resizing (@janko-m, @mokolabs)
|
22
|
+
|
1
23
|
## 0.11.2 (2018-03-31)
|
2
24
|
|
3
25
|
* [minimagick] Avoid `#resize_*` operations stripping data by switching back to `-resize` (@janko-m)
|
data/README.md
CHANGED
@@ -1,17 +1,44 @@
|
|
1
1
|
# ImageProcessing
|
2
2
|
|
3
|
-
Provides higher-level image processing
|
4
|
-
when
|
3
|
+
Provides higher-level image processing helpers that are commonly needed
|
4
|
+
when handling image uploads.
|
5
|
+
|
6
|
+
This gem can process images with either [ImageMagick] or [libvips] libraries.
|
7
|
+
ImageMagick is a good default choice, especially if you are migrating from
|
8
|
+
another gem or library that uses ImageMagick. libvips is a newer library that
|
9
|
+
can process images [very rapidly][libvips performance] (up to 10x faster than
|
10
|
+
ImageMagick).
|
11
|
+
|
12
|
+
|
13
|
+
## Goal
|
14
|
+
|
15
|
+
The goal of this project is to have a single gem that contains all the
|
16
|
+
helper methods needed to resize and process images.
|
17
|
+
|
18
|
+
Currently, existing attachment gems (like Paperclip, CarrierWave, Refile,
|
19
|
+
Dragonfly, ActiveStorage, and others) implement their own custom image
|
20
|
+
helper methods. But why? That's not very DRY, is it?
|
21
|
+
|
22
|
+
Let's be honest. Image processing is a dark, mysterious art. So we want to
|
23
|
+
combine every great idea from all of these separate gems into a single awesome
|
24
|
+
library that is constantly updated with best-practice thinking about
|
25
|
+
how to resize and process images.
|
5
26
|
|
6
|
-
The goal of this project is to have a single place where common image
|
7
|
-
processing helper methods are maintained, instead of Paperclip, CarrierWave,
|
8
|
-
Refile, Dragonfly and ActiveStorage each implementing their own versions.
|
9
27
|
|
10
28
|
## Installation
|
11
29
|
|
12
|
-
|
13
|
-
|
14
|
-
```
|
30
|
+
1. Install ImageMagick and/or libvips:
|
31
|
+
|
32
|
+
```sh
|
33
|
+
$ brew install imagemagick vips
|
34
|
+
```
|
35
|
+
|
36
|
+
2. Add the gem to your Gemfile:
|
37
|
+
|
38
|
+
```rb
|
39
|
+
gem "image_processing", "~> 1.0"
|
40
|
+
```
|
41
|
+
|
15
42
|
|
16
43
|
## Usage
|
17
44
|
|
@@ -28,10 +55,10 @@ processed = ImageProcessing::MiniMagick
|
|
28
55
|
.convert("png")
|
29
56
|
.call
|
30
57
|
|
31
|
-
processed #=> #<
|
58
|
+
processed #=> #<Tempfile:/var/folders/.../image_processing20180316-18446-1j247h6.png>
|
32
59
|
```
|
33
60
|
|
34
|
-
This allows easy branching when generating multiple
|
61
|
+
This allows easy branching when generating multiple derivates:
|
35
62
|
|
36
63
|
```rb
|
37
64
|
require "image_processing/vips"
|
@@ -70,6 +97,25 @@ processed = ImageProcessing::MiniMagick
|
|
70
97
|
.resize_to_limit!(400, 400) # bang method
|
71
98
|
```
|
72
99
|
|
100
|
+
You can inspect the pipeline options at any point before executing it:
|
101
|
+
|
102
|
+
```rb
|
103
|
+
pipeline = ImageProcessing::MiniMagick
|
104
|
+
.source(image)
|
105
|
+
.loader(page: 1)
|
106
|
+
.convert("png")
|
107
|
+
.resize_to_limit(400, 400)
|
108
|
+
.strip
|
109
|
+
|
110
|
+
pipeline.options
|
111
|
+
# => {:source=>#<File:/path/to/source.jpg>,
|
112
|
+
# :loader=>{:page=>1},
|
113
|
+
# :saver=>{},
|
114
|
+
# :format=>"png",
|
115
|
+
# :operations=>[[:resize_to_limit, [400, 400]], [:strip, []]],
|
116
|
+
# :processor_class=>ImageProcessing::MiniMagick::Processor}
|
117
|
+
```
|
118
|
+
|
73
119
|
The source object needs to responds to `#path`, or be a String, a Pathname, or
|
74
120
|
a `Vips::Image`/`MiniMagick::Tool` object.
|
75
121
|
|
@@ -80,10 +126,10 @@ ImageProcessing::Vips.source(Pathname.new("source.jpg"))
|
|
80
126
|
ImageProcessing::Vips.source(Vips::Image.new_from_file("source.jpg"))
|
81
127
|
```
|
82
128
|
|
83
|
-
|
84
|
-
object. You can save processing result to a specific location by
|
85
|
-
`:destination` to `#call
|
86
|
-
|
129
|
+
When `#call` is called without options, the result of processing is a
|
130
|
+
`Tempfile` object. You can save the processing result to a specific location by
|
131
|
+
passing `:destination` to `#call`, or pass `save: false` to retrieve the raw
|
132
|
+
`Vips::Image`/`MiniMagick::Tool` object.
|
87
133
|
|
88
134
|
```rb
|
89
135
|
pipeline = ImageProcessing::Vips.source(image)
|
@@ -100,10 +146,10 @@ You can continue reading the API documentation for specific modules:
|
|
100
146
|
|
101
147
|
See the **[wiki]** for additional "How To" guides for common scenarios.
|
102
148
|
|
149
|
+
|
103
150
|
## Contributing
|
104
151
|
|
105
|
-
|
106
|
-
can install them with Homebrew:
|
152
|
+
Our test suite requires both `imagemagick` and `libvips` libraries to be installed.
|
107
153
|
|
108
154
|
```
|
109
155
|
$ brew install imagemagick vips
|
@@ -115,18 +161,29 @@ Afterwards you can run tests with
|
|
115
161
|
$ bundle exec rake test
|
116
162
|
```
|
117
163
|
|
164
|
+
|
165
|
+
## Feedback
|
166
|
+
|
167
|
+
We welcome your feedback! What would you like to see added to image_processing?
|
168
|
+
How can we improve this gem? Open an issue and let us know!
|
169
|
+
|
170
|
+
|
118
171
|
## Credits
|
119
172
|
|
120
173
|
The `ImageProcessing::MiniMagick` functionality was extracted from
|
121
|
-
[refile-mini_magick].
|
174
|
+
[refile-mini_magick]. The chainable interface was heavily inspired by
|
175
|
+
[HTTP.rb].
|
176
|
+
|
122
177
|
|
123
178
|
## License
|
124
179
|
|
125
180
|
[MIT](LICENSE.txt)
|
126
181
|
|
127
|
-
[
|
182
|
+
[libvips]: http://jcupitt.github.io/libvips/
|
128
183
|
[ImageMagick]: https://www.imagemagick.org
|
129
184
|
[`ImageProcessing::Vips`]: /doc/vips.md#imageprocessingvips
|
130
185
|
[`ImageProcessing::MiniMagick`]: /doc/minimagick.md#imageprocessingminimagick
|
131
186
|
[refile-mini_magick]: https://github.com/refile/refile-mini_magick
|
132
187
|
[wiki]: https://github.com/janko-m/image_processing/wiki
|
188
|
+
[HTTP.rb]: https://github.com/httprb/http
|
189
|
+
[libvips performance]: https://github.com/jcupitt/libvips/wiki/Speed-and-memory-use
|
data/image_processing.gemspec
CHANGED
@@ -16,11 +16,12 @@ Gem::Specification.new do |spec|
|
|
16
16
|
spec.files = Dir["README.md", "LICENSE.txt", "CHANGELOG.md", "lib/**/*.rb", "*.gemspec"]
|
17
17
|
spec.require_paths = ["lib"]
|
18
18
|
|
19
|
+
spec.add_dependency "mini_magick", "~> 4.0"
|
20
|
+
spec.add_dependency "ruby-vips", ">= 2.0.10", "< 3"
|
21
|
+
|
19
22
|
spec.add_development_dependency "rake"
|
20
23
|
spec.add_development_dependency "minitest", "~> 5.8"
|
21
24
|
spec.add_development_dependency "minitest-hooks", ">= 1.4.2"
|
22
25
|
spec.add_development_dependency "minispec-metadata"
|
23
|
-
spec.add_development_dependency "mini_magick", ">= 4.3.5"
|
24
|
-
spec.add_development_dependency "ruby-vips", ">= 2.0.0"
|
25
26
|
spec.add_development_dependency "phashion" unless RUBY_ENGINE == "jruby"
|
26
27
|
end
|
@@ -2,12 +2,14 @@ module ImageProcessing
|
|
2
2
|
class Builder
|
3
3
|
include Chainable
|
4
4
|
|
5
|
+
attr_reader :options
|
6
|
+
|
5
7
|
def initialize(options)
|
6
|
-
@
|
8
|
+
@options = options
|
7
9
|
end
|
8
10
|
|
9
11
|
def call!(**options)
|
10
|
-
Pipeline.new(
|
12
|
+
Pipeline.new(self.options).call(**options)
|
11
13
|
end
|
12
14
|
end
|
13
15
|
end
|
@@ -1,30 +1,23 @@
|
|
1
1
|
module ImageProcessing
|
2
2
|
module Chainable
|
3
3
|
def source(file)
|
4
|
-
branch
|
4
|
+
branch source: file
|
5
5
|
end
|
6
6
|
|
7
7
|
def convert(format)
|
8
|
-
branch
|
8
|
+
branch format: format
|
9
9
|
end
|
10
10
|
|
11
11
|
def loader(**options)
|
12
|
-
loader
|
13
|
-
branch default_options.merge(loader: loader)
|
12
|
+
branch loader: options
|
14
13
|
end
|
15
14
|
|
16
15
|
def saver(**options)
|
17
|
-
saver
|
18
|
-
branch default_options.merge(saver: saver)
|
19
|
-
end
|
20
|
-
|
21
|
-
def operation(name, *args)
|
22
|
-
operations = default_options[:operations] + [[name, args]]
|
23
|
-
branch default_options.merge(operations: operations)
|
16
|
+
branch saver: options
|
24
17
|
end
|
25
18
|
|
26
19
|
def custom(&block)
|
27
|
-
|
20
|
+
operation :custom, block
|
28
21
|
end
|
29
22
|
|
30
23
|
def method_missing(name, *args)
|
@@ -37,29 +30,39 @@ module ImageProcessing
|
|
37
30
|
end
|
38
31
|
end
|
39
32
|
|
33
|
+
def operation(name, *args)
|
34
|
+
branch operations: [[name, args]]
|
35
|
+
end
|
36
|
+
|
40
37
|
def call(file = nil, destination: nil, **call_options)
|
41
|
-
options =
|
38
|
+
options = {}
|
42
39
|
options = options.merge(source: file) if file
|
43
40
|
options = options.merge(destination: destination) if destination
|
44
41
|
|
45
42
|
branch(options).call!(**call_options)
|
46
43
|
end
|
47
44
|
|
48
|
-
def branch(
|
45
|
+
def branch(loader: nil, saver: nil, operations: nil, **other_options)
|
46
|
+
options = respond_to?(:options) ? self.options : DEFAULT_OPTIONS
|
47
|
+
|
48
|
+
options = options.merge(loader: options[:loader].merge(loader)) if loader
|
49
|
+
options = options.merge(saver: options[:saver].merge(saver)) if saver
|
50
|
+
options = options.merge(operations: options[:operations] + operations) if operations
|
49
51
|
options = options.merge(processor_class: self::Processor) unless self.is_a?(Builder)
|
52
|
+
options = options.merge(other_options)
|
53
|
+
|
54
|
+
options.freeze
|
50
55
|
|
51
56
|
Builder.new(options)
|
52
57
|
end
|
53
58
|
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
}
|
63
|
-
end
|
59
|
+
DEFAULT_OPTIONS = {
|
60
|
+
source: nil,
|
61
|
+
loader: {},
|
62
|
+
saver: {},
|
63
|
+
format: nil,
|
64
|
+
operations: [],
|
65
|
+
processor_class: nil,
|
66
|
+
}.freeze
|
64
67
|
end
|
65
68
|
end
|
@@ -1,14 +1,10 @@
|
|
1
|
-
gem "mini_magick", "~> 4.0"
|
2
1
|
require "mini_magick"
|
3
|
-
|
4
2
|
require "image_processing"
|
5
|
-
require "image_processing/mini_magick/deprecated_api"
|
6
3
|
|
7
4
|
module ImageProcessing
|
8
5
|
module MiniMagick
|
9
6
|
def self.valid_image?(file)
|
10
7
|
::MiniMagick::Tool::Convert.new do |convert|
|
11
|
-
convert.regard_warnings
|
12
8
|
convert << file.path
|
13
9
|
convert << "null:"
|
14
10
|
end
|
@@ -18,27 +14,28 @@ module ImageProcessing
|
|
18
14
|
end
|
19
15
|
|
20
16
|
class Processor < ImageProcessing::Processor
|
21
|
-
IMAGE_CLASS
|
17
|
+
IMAGE_CLASS = ::MiniMagick::Tool
|
18
|
+
SHARPEN_PARAMETERS = { radius: 0, sigma: 1 }
|
22
19
|
|
23
|
-
def resize_to_limit(magick, width, height)
|
24
|
-
magick
|
20
|
+
def resize_to_limit(magick, width, height, **options)
|
21
|
+
thumbnail(magick, "#{width}x#{height}>", **options)
|
25
22
|
end
|
26
23
|
|
27
|
-
def resize_to_fit(magick, width, height)
|
28
|
-
magick
|
24
|
+
def resize_to_fit(magick, width, height, **options)
|
25
|
+
thumbnail(magick, "#{width}x#{height}", **options)
|
29
26
|
end
|
30
27
|
|
31
|
-
def resize_to_fill(magick, width, height, gravity: "Center")
|
32
|
-
magick
|
28
|
+
def resize_to_fill(magick, width, height, gravity: "Center", **options)
|
29
|
+
thumbnail(magick, "#{width}x#{height}^", **options)
|
33
30
|
magick.gravity gravity
|
34
31
|
magick.background "rgba(255,255,255,0.0)" # transparent
|
35
32
|
magick.extent "#{width}x#{height}"
|
36
33
|
end
|
37
34
|
|
38
|
-
def resize_and_pad(magick, width, height, background: :transparent, gravity: "Center")
|
35
|
+
def resize_and_pad(magick, width, height, background: :transparent, gravity: "Center", **options)
|
39
36
|
background = "rgba(255,255,255,0.0)" if background.to_s == "transparent"
|
40
37
|
|
41
|
-
magick
|
38
|
+
thumbnail(magick, "#{width}x#{height}", **options)
|
42
39
|
magick.background background
|
43
40
|
magick.gravity gravity
|
44
41
|
magick.extent "#{width}x#{height}"
|
@@ -46,22 +43,20 @@ module ImageProcessing
|
|
46
43
|
|
47
44
|
def limits(magick, options)
|
48
45
|
limit_args = options.flat_map { |type, value| %W[-limit #{type} #{value}] }
|
49
|
-
magick
|
50
|
-
magick
|
46
|
+
prepend_args(magick, limit_args)
|
51
47
|
end
|
52
48
|
|
53
49
|
def append(magick, *args)
|
54
50
|
magick.merge! args
|
55
51
|
end
|
56
52
|
|
57
|
-
def load_image(path_or_magick, page: nil, geometry: nil,
|
53
|
+
def load_image(path_or_magick, page: nil, geometry: nil, auto_orient: true, **options)
|
58
54
|
if path_or_magick.is_a?(::MiniMagick::Tool)
|
59
55
|
magick = path_or_magick
|
60
56
|
else
|
61
57
|
source_path = path_or_magick
|
62
58
|
magick = ::MiniMagick::Tool::Convert.new
|
63
59
|
|
64
|
-
apply_define(magick, define)
|
65
60
|
apply_options(magick, options)
|
66
61
|
|
67
62
|
input_path = source_path
|
@@ -71,14 +66,11 @@ module ImageProcessing
|
|
71
66
|
magick << input_path
|
72
67
|
end
|
73
68
|
|
74
|
-
magick.regard_warnings if fail
|
75
69
|
magick.auto_orient if auto_orient
|
76
|
-
|
77
70
|
magick
|
78
71
|
end
|
79
72
|
|
80
|
-
def save_image(magick, destination_path,
|
81
|
-
apply_define(magick, define)
|
73
|
+
def save_image(magick, destination_path, **options)
|
82
74
|
apply_options(magick, options)
|
83
75
|
|
84
76
|
magick << destination_path
|
@@ -88,6 +80,31 @@ module ImageProcessing
|
|
88
80
|
|
89
81
|
private
|
90
82
|
|
83
|
+
def thumbnail(magick, geometry, sharpen: {})
|
84
|
+
magick.resize(geometry)
|
85
|
+
magick.sharpen(sharpen_value(sharpen)) if sharpen
|
86
|
+
magick
|
87
|
+
end
|
88
|
+
|
89
|
+
def sharpen_value(parameters)
|
90
|
+
parameters = SHARPEN_PARAMETERS.merge(parameters)
|
91
|
+
radius, sigma = parameters.values_at(:radius, :sigma)
|
92
|
+
|
93
|
+
"#{radius}x#{sigma}"
|
94
|
+
end
|
95
|
+
|
96
|
+
def apply_options(magick, define: {}, **options)
|
97
|
+
options.each do |option, value|
|
98
|
+
case value
|
99
|
+
when true, nil then magick.send(option)
|
100
|
+
when false then magick.send(option).+
|
101
|
+
else magick.send(option, *value)
|
102
|
+
end
|
103
|
+
end
|
104
|
+
|
105
|
+
apply_define(magick, define)
|
106
|
+
end
|
107
|
+
|
91
108
|
def apply_define(magick, define)
|
92
109
|
define.each do |namespace, options|
|
93
110
|
namespace = namespace.to_s.gsub("_", "-")
|
@@ -100,19 +117,12 @@ module ImageProcessing
|
|
100
117
|
end
|
101
118
|
end
|
102
119
|
|
103
|
-
def
|
104
|
-
|
105
|
-
|
106
|
-
when true then magick.send(option)
|
107
|
-
when false then magick.send(option).+
|
108
|
-
else magick.send(option, *value)
|
109
|
-
end
|
110
|
-
end
|
120
|
+
def prepend_args(magick, args)
|
121
|
+
magick.args.replace args + magick.args
|
122
|
+
magick
|
111
123
|
end
|
112
124
|
end
|
113
125
|
|
114
126
|
extend Chainable
|
115
|
-
|
116
|
-
include DeprecatedApi
|
117
127
|
end
|
118
128
|
end
|
@@ -1,6 +1,4 @@
|
|
1
|
-
gem "ruby-vips", "~> 2.0"
|
2
1
|
require "vips"
|
3
|
-
|
4
2
|
require "image_processing"
|
5
3
|
|
6
4
|
fail "image_processing/vips requires libvips 8.6+" unless Vips.at_least_libvips?(8, 6)
|
@@ -8,17 +6,18 @@ fail "image_processing/vips requires libvips 8.6+" unless Vips.at_least_libvips?
|
|
8
6
|
module ImageProcessing
|
9
7
|
module Vips
|
10
8
|
def self.valid_image?(file)
|
11
|
-
::Vips::Image.new_from_file(file.path, access: :sequential
|
9
|
+
::Vips::Image.new_from_file(file.path, access: :sequential).avg
|
12
10
|
true
|
13
11
|
rescue ::Vips::Error
|
14
12
|
false
|
15
13
|
end
|
16
14
|
|
17
15
|
class Processor < ImageProcessing::Processor
|
18
|
-
IMAGE_CLASS
|
19
|
-
#
|
20
|
-
|
21
|
-
|
16
|
+
IMAGE_CLASS = ::Vips::Image
|
17
|
+
# default sharpening mask that provides a fast and mild sharpen
|
18
|
+
SHARPEN_MASK = ::Vips::Image.new_from_array [[-1, -1, -1],
|
19
|
+
[-1, 32, -1],
|
20
|
+
[-1, -1, -1]], 24
|
22
21
|
|
23
22
|
def apply_operation(name, image, *args)
|
24
23
|
result = super
|
@@ -27,23 +26,23 @@ module ImageProcessing
|
|
27
26
|
|
28
27
|
def resize_to_limit(image, width, height, **options)
|
29
28
|
width, height = default_dimensions(width, height)
|
30
|
-
image
|
29
|
+
generate_thumbnail(image, width, height, size: :down, **options)
|
31
30
|
end
|
32
31
|
|
33
32
|
def resize_to_fit(image, width, height, **options)
|
34
33
|
width, height = default_dimensions(width, height)
|
35
|
-
image
|
34
|
+
generate_thumbnail(image, width, height, **options)
|
36
35
|
end
|
37
36
|
|
38
37
|
def resize_to_fill(image, width, height, **options)
|
39
|
-
image
|
38
|
+
generate_thumbnail(image, width, height, crop: :centre, **options)
|
40
39
|
end
|
41
40
|
|
42
41
|
def resize_and_pad(image, width, height, gravity: "centre", extend: nil, background: nil, alpha: nil, **options)
|
43
42
|
embed_options = { extend: extend, background: background }
|
44
43
|
embed_options.reject! { |name, value| value.nil? }
|
45
44
|
|
46
|
-
image = image
|
45
|
+
image = generate_thumbnail(image, width, height, **options)
|
47
46
|
image = add_alpha(image) if alpha && !has_alpha?(image)
|
48
47
|
image.gravity(gravity, width, height, **embed_options)
|
49
48
|
end
|
@@ -55,14 +54,15 @@ module ImageProcessing
|
|
55
54
|
source_path = path_or_image
|
56
55
|
options = select_valid_loader_options(source_path, options)
|
57
56
|
|
58
|
-
image = ::Vips::Image.new_from_file(source_path,
|
57
|
+
image = ::Vips::Image.new_from_file(source_path, **options)
|
59
58
|
end
|
60
59
|
|
61
|
-
image = image.autorot if autorot
|
60
|
+
image = image.autorot if autorot && !options.key?(:autorotate)
|
62
61
|
image
|
63
62
|
end
|
64
63
|
|
65
|
-
def save_image(image, destination_path, **options)
|
64
|
+
def save_image(image, destination_path, quality: nil, **options)
|
65
|
+
options = options.merge(Q: quality) if quality
|
66
66
|
options = select_valid_saver_options(destination_path, options)
|
67
67
|
|
68
68
|
image.write_to_file(destination_path, **options)
|
@@ -70,6 +70,12 @@ module ImageProcessing
|
|
70
70
|
|
71
71
|
private
|
72
72
|
|
73
|
+
def generate_thumbnail(image, width, height, sharpen: SHARPEN_MASK, **options)
|
74
|
+
image = image.thumbnail_image(width, height: height, **options)
|
75
|
+
image = image.conv(sharpen) if sharpen
|
76
|
+
image
|
77
|
+
end
|
78
|
+
|
73
79
|
# Port of libvips' vips_addalpha().
|
74
80
|
def add_alpha(image)
|
75
81
|
max_alpha = (image.interpretation == :grey16 || image.interpretation == :rgb16) ? 65535 : 255
|
@@ -86,7 +92,7 @@ module ImageProcessing
|
|
86
92
|
def default_dimensions(width, height)
|
87
93
|
raise Error, "either width or height must be specified" unless width || height
|
88
94
|
|
89
|
-
[width || MAX_COORD, height || MAX_COORD]
|
95
|
+
[width || ::Vips::MAX_COORD, height || ::Vips::MAX_COORD]
|
90
96
|
end
|
91
97
|
|
92
98
|
def select_valid_loader_options(source_path, options)
|
metadata
CHANGED
@@ -1,99 +1,105 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: image_processing
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 1.0.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Janko Marohnić
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2018-
|
11
|
+
date: 2018-04-04 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
|
-
name:
|
14
|
+
name: mini_magick
|
15
15
|
requirement: !ruby/object:Gem::Requirement
|
16
16
|
requirements:
|
17
|
-
- - "
|
17
|
+
- - "~>"
|
18
18
|
- !ruby/object:Gem::Version
|
19
|
-
version: '0'
|
20
|
-
type: :
|
19
|
+
version: '4.0'
|
20
|
+
type: :runtime
|
21
21
|
prerelease: false
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
23
23
|
requirements:
|
24
|
-
- - "
|
24
|
+
- - "~>"
|
25
25
|
- !ruby/object:Gem::Version
|
26
|
-
version: '0'
|
26
|
+
version: '4.0'
|
27
27
|
- !ruby/object:Gem::Dependency
|
28
|
-
name:
|
28
|
+
name: ruby-vips
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
30
30
|
requirements:
|
31
|
-
- - "
|
31
|
+
- - ">="
|
32
32
|
- !ruby/object:Gem::Version
|
33
|
-
version:
|
34
|
-
|
33
|
+
version: 2.0.10
|
34
|
+
- - "<"
|
35
|
+
- !ruby/object:Gem::Version
|
36
|
+
version: '3'
|
37
|
+
type: :runtime
|
35
38
|
prerelease: false
|
36
39
|
version_requirements: !ruby/object:Gem::Requirement
|
37
40
|
requirements:
|
38
|
-
- - "
|
41
|
+
- - ">="
|
39
42
|
- !ruby/object:Gem::Version
|
40
|
-
version:
|
43
|
+
version: 2.0.10
|
44
|
+
- - "<"
|
45
|
+
- !ruby/object:Gem::Version
|
46
|
+
version: '3'
|
41
47
|
- !ruby/object:Gem::Dependency
|
42
|
-
name:
|
48
|
+
name: rake
|
43
49
|
requirement: !ruby/object:Gem::Requirement
|
44
50
|
requirements:
|
45
51
|
- - ">="
|
46
52
|
- !ruby/object:Gem::Version
|
47
|
-
version:
|
53
|
+
version: '0'
|
48
54
|
type: :development
|
49
55
|
prerelease: false
|
50
56
|
version_requirements: !ruby/object:Gem::Requirement
|
51
57
|
requirements:
|
52
58
|
- - ">="
|
53
59
|
- !ruby/object:Gem::Version
|
54
|
-
version:
|
60
|
+
version: '0'
|
55
61
|
- !ruby/object:Gem::Dependency
|
56
|
-
name:
|
62
|
+
name: minitest
|
57
63
|
requirement: !ruby/object:Gem::Requirement
|
58
64
|
requirements:
|
59
|
-
- - "
|
65
|
+
- - "~>"
|
60
66
|
- !ruby/object:Gem::Version
|
61
|
-
version: '
|
67
|
+
version: '5.8'
|
62
68
|
type: :development
|
63
69
|
prerelease: false
|
64
70
|
version_requirements: !ruby/object:Gem::Requirement
|
65
71
|
requirements:
|
66
|
-
- - "
|
72
|
+
- - "~>"
|
67
73
|
- !ruby/object:Gem::Version
|
68
|
-
version: '
|
74
|
+
version: '5.8'
|
69
75
|
- !ruby/object:Gem::Dependency
|
70
|
-
name:
|
76
|
+
name: minitest-hooks
|
71
77
|
requirement: !ruby/object:Gem::Requirement
|
72
78
|
requirements:
|
73
79
|
- - ">="
|
74
80
|
- !ruby/object:Gem::Version
|
75
|
-
version: 4.
|
81
|
+
version: 1.4.2
|
76
82
|
type: :development
|
77
83
|
prerelease: false
|
78
84
|
version_requirements: !ruby/object:Gem::Requirement
|
79
85
|
requirements:
|
80
86
|
- - ">="
|
81
87
|
- !ruby/object:Gem::Version
|
82
|
-
version: 4.
|
88
|
+
version: 1.4.2
|
83
89
|
- !ruby/object:Gem::Dependency
|
84
|
-
name:
|
90
|
+
name: minispec-metadata
|
85
91
|
requirement: !ruby/object:Gem::Requirement
|
86
92
|
requirements:
|
87
93
|
- - ">="
|
88
94
|
- !ruby/object:Gem::Version
|
89
|
-
version:
|
95
|
+
version: '0'
|
90
96
|
type: :development
|
91
97
|
prerelease: false
|
92
98
|
version_requirements: !ruby/object:Gem::Requirement
|
93
99
|
requirements:
|
94
100
|
- - ">="
|
95
101
|
- !ruby/object:Gem::Version
|
96
|
-
version:
|
102
|
+
version: '0'
|
97
103
|
- !ruby/object:Gem::Dependency
|
98
104
|
name: phashion
|
99
105
|
requirement: !ruby/object:Gem::Requirement
|
@@ -123,7 +129,6 @@ files:
|
|
123
129
|
- lib/image_processing/builder.rb
|
124
130
|
- lib/image_processing/chainable.rb
|
125
131
|
- lib/image_processing/mini_magick.rb
|
126
|
-
- lib/image_processing/mini_magick/deprecated_api.rb
|
127
132
|
- lib/image_processing/pipeline.rb
|
128
133
|
- lib/image_processing/processor.rb
|
129
134
|
- lib/image_processing/version.rb
|
@@ -1,120 +0,0 @@
|
|
1
|
-
require "tempfile"
|
2
|
-
require "fileutils"
|
3
|
-
|
4
|
-
module ImageProcessing
|
5
|
-
module MiniMagick
|
6
|
-
module DeprecatedApi
|
7
|
-
def self.included(base)
|
8
|
-
base.extend(self)
|
9
|
-
end
|
10
|
-
|
11
|
-
def self.deprecated_processing_method(name, &body)
|
12
|
-
define_method(name) do |*args, &block|
|
13
|
-
return ImageProcessing::MiniMagick.send(name, *args, &block) if self != ImageProcessing::MiniMagick
|
14
|
-
return super(*args, &block) unless args.first.respond_to?(:read)
|
15
|
-
|
16
|
-
warn "[IMAGE_PROCESSING DEPRECATION WARNING] This API is deprecated and will be removed in ImageProcessing 1.0. Please use the new chainable API."
|
17
|
-
|
18
|
-
file = args.shift
|
19
|
-
|
20
|
-
if file.respond_to?(:path)
|
21
|
-
instance_exec(file, *args, block, &body)
|
22
|
-
else
|
23
|
-
Utils.copy_to_tempfile(file) do |tempfile|
|
24
|
-
instance_exec(tempfile, *args, block, &body)
|
25
|
-
end
|
26
|
-
end
|
27
|
-
end
|
28
|
-
|
29
|
-
define_method("#{name}!") do |*args, &block|
|
30
|
-
return ImageProcessing::MiniMagick.send("#{name}!", *args, &block) if self != ImageProcessing::MiniMagick
|
31
|
-
return super(*args, &block) unless args.first.respond_to?(:read)
|
32
|
-
|
33
|
-
processed = send(name, *args, &block)
|
34
|
-
source = args.first
|
35
|
-
|
36
|
-
if name == :convert
|
37
|
-
File.delete(source.path)
|
38
|
-
else
|
39
|
-
processed.close
|
40
|
-
FileUtils.mv processed.path, source.path
|
41
|
-
source.open if source.is_a?(Tempfile)
|
42
|
-
end
|
43
|
-
|
44
|
-
source
|
45
|
-
end
|
46
|
-
end
|
47
|
-
|
48
|
-
deprecated_processing_method :resize_to_limit do |file, *args, block|
|
49
|
-
source(file)
|
50
|
-
.custom(&block)
|
51
|
-
.resize_to_limit!(*args)
|
52
|
-
end
|
53
|
-
|
54
|
-
deprecated_processing_method :resize_to_fit do |file, *args, block|
|
55
|
-
source(file)
|
56
|
-
.custom(&block)
|
57
|
-
.resize_to_fit!(*args)
|
58
|
-
end
|
59
|
-
|
60
|
-
deprecated_processing_method :resize_to_fill do |file, *args, block|
|
61
|
-
source(file)
|
62
|
-
.custom(&block)
|
63
|
-
.resize_to_fill!(*args)
|
64
|
-
end
|
65
|
-
|
66
|
-
deprecated_processing_method :resize_and_pad do |file, *args, block|
|
67
|
-
source(file)
|
68
|
-
.custom(&block)
|
69
|
-
.resize_and_pad!(*args)
|
70
|
-
end
|
71
|
-
|
72
|
-
deprecated_processing_method :convert do |file, format, page = nil, block|
|
73
|
-
source(file)
|
74
|
-
.loader(page: page)
|
75
|
-
.custom(&block)
|
76
|
-
.convert!(format)
|
77
|
-
end
|
78
|
-
|
79
|
-
deprecated_processing_method :auto_orient do |file, *args, block|
|
80
|
-
source(file)
|
81
|
-
.custom(&block)
|
82
|
-
.auto_orient!(*args)
|
83
|
-
end
|
84
|
-
|
85
|
-
deprecated_processing_method :resample do |file, width, height, block|
|
86
|
-
source(file)
|
87
|
-
.custom(&block)
|
88
|
-
.resample!("#{width}x#{height}")
|
89
|
-
end
|
90
|
-
|
91
|
-
deprecated_processing_method :crop do |file, width, height, x_offset = 0, y_offset = 0, block|
|
92
|
-
source(file)
|
93
|
-
.custom(&block)
|
94
|
-
.crop!("#{width}x#{height}+#{x_offset}+#{y_offset}")
|
95
|
-
end
|
96
|
-
|
97
|
-
deprecated_processing_method :corrupted? do |file, block|
|
98
|
-
valid_image?(file)
|
99
|
-
end
|
100
|
-
|
101
|
-
module Utils
|
102
|
-
module_function
|
103
|
-
|
104
|
-
def copy_to_tempfile(io)
|
105
|
-
extension = File.extname(io.path) if io.respond_to?(:path)
|
106
|
-
tempfile = Tempfile.new(["image_processing", extension.to_s], binmode: true)
|
107
|
-
|
108
|
-
IO.copy_stream(io, tempfile)
|
109
|
-
|
110
|
-
io.rewind
|
111
|
-
tempfile.open # refresh content
|
112
|
-
|
113
|
-
yield tempfile
|
114
|
-
ensure
|
115
|
-
tempfile.close! if tempfile
|
116
|
-
end
|
117
|
-
end
|
118
|
-
end
|
119
|
-
end
|
120
|
-
end
|