image_processing 0.11.2 → 1.0.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.
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
|