image_processing 1.9.3 → 1.12.2
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/CHANGELOG.md +36 -0
- data/README.md +47 -4
- data/image_processing.gemspec +4 -4
- data/lib/image_processing/builder.rb +18 -2
- data/lib/image_processing/chainable.rb +38 -24
- data/lib/image_processing/mini_magick.rb +19 -9
- data/lib/image_processing/pipeline.rb +8 -2
- data/lib/image_processing/processor.rb +18 -10
- data/lib/image_processing/version.rb +1 -1
- data/lib/image_processing/vips.rb +10 -9
- metadata +13 -11
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 31d06cb35ac94ec0787b21dd2118626f3a3a96685efab0d7eb58d9079b1fbf2c
|
4
|
+
data.tar.gz: 8f840074b8fe9511e59f4f005d144e39c9aba4d0699a48c29ffc6cb2513ec645
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 1d0fb1d9363b9b85e1895d05849a5c29b2c50b8213bf9e9d6ff8c2e1391a9bf6448a4e319a4cfd747183ec741ac42d6b1b1b9629ee91d97cc4a287ec6615042c
|
7
|
+
data.tar.gz: dd31dd0ca012ceb35aa276c5e00efd3e9bd2c40246f9b063ea39280ea13c546373fa641518fb55ebcf0e9d00ad6020be995b8d8636c8a3939bda31c643485cef
|
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,39 @@
|
|
1
|
+
## 1.12.2 (2022-03-01)
|
2
|
+
|
3
|
+
* Prevent remote shell execution when using `#apply` with operations coming from user input (@janko)
|
4
|
+
|
5
|
+
## 1.12.1 (2020-11-06)
|
6
|
+
|
7
|
+
* Fix format fallback for files ending with a dot on Ruby 2.7+ (@coding-chimp)
|
8
|
+
|
9
|
+
## 1.12.0 (2020-09-20)
|
10
|
+
|
11
|
+
* Add instrumentation support via `#instrumenter` (@janko)
|
12
|
+
|
13
|
+
## 1.11.0 (2020-05-17)
|
14
|
+
|
15
|
+
* [minimagick] Handle destination format having no file extension (@janko)
|
16
|
+
|
17
|
+
* [minimagick] Disable sharpening on `#resize_*` operators by default (@flori)
|
18
|
+
|
19
|
+
* [minimagick] Add `#crop` which accepts `left, top, width, height` arguments (@janko)
|
20
|
+
|
21
|
+
## 1.10.3 (2020-01-12)
|
22
|
+
|
23
|
+
* [vips] Fix auto-rotation not working in certain cases on libvips 8.9.0 (@janko)
|
24
|
+
|
25
|
+
## 1.10.2 (2020-01-11)
|
26
|
+
|
27
|
+
* Fix Ruby 2.7 warnings for separation of positional and keyword arguments (@kamipo, @janko)
|
28
|
+
|
29
|
+
## 1.10.1 (2020-01-07)
|
30
|
+
|
31
|
+
* [vips] Fix compatibility with ruby-vips 2.0.17+ (@janko)
|
32
|
+
|
33
|
+
## 1.10.0 (2019-12-18)
|
34
|
+
|
35
|
+
* [minimagick] Add `:loader` option for explicitly setting input file type (@janko)
|
36
|
+
|
1
37
|
## 1.9.3 (2019-08-11)
|
2
38
|
|
3
39
|
* [vips] Use integer precision when sharpening for better quality (@metaskills)
|
data/README.md
CHANGED
@@ -29,10 +29,18 @@ how to resize and process images.
|
|
29
29
|
|
30
30
|
1. Install ImageMagick and/or libvips:
|
31
31
|
|
32
|
-
|
32
|
+
In a Mac terminal:
|
33
|
+
|
34
|
+
```sh
|
33
35
|
$ brew install imagemagick vips
|
34
36
|
```
|
35
37
|
|
38
|
+
In a debian/ubuntu terminal:
|
39
|
+
|
40
|
+
```sh
|
41
|
+
$ sudo apt install imagemagick libvips
|
42
|
+
```
|
43
|
+
|
36
44
|
2. Add the gem to your Gemfile:
|
37
45
|
|
38
46
|
```rb
|
@@ -42,9 +50,9 @@ how to resize and process images.
|
|
42
50
|
|
43
51
|
## Usage
|
44
52
|
|
45
|
-
Processing is performed through [`ImageProcessing::Vips`] or
|
46
|
-
[`ImageProcessing::MiniMagick`] modules. Both modules share the same
|
47
|
-
API for defining the processing pipeline:
|
53
|
+
Processing is performed through **[`ImageProcessing::Vips`]** or
|
54
|
+
**[`ImageProcessing::MiniMagick`]** modules. Both modules share the same
|
55
|
+
chainable API for defining the processing pipeline:
|
48
56
|
|
49
57
|
```rb
|
50
58
|
require "image_processing/mini_magick"
|
@@ -148,15 +156,50 @@ You can continue reading the API documentation for specific modules:
|
|
148
156
|
See the **[wiki]** for additional "How To" guides for common scenarios. The wiki
|
149
157
|
is publicly editable, so you're encouraged to add your own guides.
|
150
158
|
|
159
|
+
## Instrumentation
|
160
|
+
|
161
|
+
You can register an `#instrumenter` block for a given pipeline, which will wrap
|
162
|
+
the pipeline execution, allowing you to record performance metrics.
|
163
|
+
|
164
|
+
```rb
|
165
|
+
pipeline = ImageProcessing::Vips.instrumenter do |**options, &processing|
|
166
|
+
options[:source] #=> #<File:...>
|
167
|
+
options[:loader] #=> { fail: true }
|
168
|
+
options[:saver] #=> { quality: 85 }
|
169
|
+
options[:format] #=> "png"
|
170
|
+
options[:operations] #=> [[:resize_to_limit, 500, 500], [:flip, [:horizontal]]]
|
171
|
+
options[:processor] #=> ImageProcessing::Vips::Processor
|
172
|
+
|
173
|
+
ActiveSupport::Notifications.instrument("process.image_processing", **options) do
|
174
|
+
processing.call # calls the pipeline
|
175
|
+
end
|
176
|
+
end
|
177
|
+
|
178
|
+
pipeline
|
179
|
+
.source(image)
|
180
|
+
.loader(fail: true)
|
181
|
+
.saver(quality: 85)
|
182
|
+
.convert("png")
|
183
|
+
.resize_to_limit(500, 500)
|
184
|
+
.flip(:horizontal)
|
185
|
+
.call # calls instrumenter
|
186
|
+
```
|
151
187
|
|
152
188
|
## Contributing
|
153
189
|
|
154
190
|
Our test suite requires both `imagemagick` and `libvips` libraries to be installed.
|
155
191
|
|
192
|
+
In a Mac terminal:
|
193
|
+
|
156
194
|
```
|
157
195
|
$ brew install imagemagick vips
|
158
196
|
```
|
159
197
|
|
198
|
+
In a debian/ubuntu terminal:
|
199
|
+
```shell
|
200
|
+
sudo apt install imagemagick libvips
|
201
|
+
```
|
202
|
+
|
160
203
|
Afterwards you can run tests with
|
161
204
|
|
162
205
|
```
|
data/image_processing.gemspec
CHANGED
@@ -6,8 +6,8 @@ Gem::Specification.new do |spec|
|
|
6
6
|
|
7
7
|
spec.required_ruby_version = ">= 2.3"
|
8
8
|
|
9
|
-
spec.summary = "
|
10
|
-
spec.description = "
|
9
|
+
spec.summary = "High-level wrapper for processing images for the web with ImageMagick or libvips."
|
10
|
+
spec.description = "High-level wrapper for processing images for the web with ImageMagick or libvips."
|
11
11
|
spec.homepage = "https://github.com/janko/image_processing"
|
12
12
|
spec.authors = ["Janko Marohnić"]
|
13
13
|
spec.email = ["janko.marohnic@gmail.com"]
|
@@ -17,11 +17,11 @@ Gem::Specification.new do |spec|
|
|
17
17
|
spec.require_paths = ["lib"]
|
18
18
|
|
19
19
|
spec.add_dependency "mini_magick", ">= 4.9.5", "< 5"
|
20
|
-
spec.add_dependency "ruby-vips", ">= 2.0.
|
20
|
+
spec.add_dependency "ruby-vips", ">= 2.0.17", "< 3"
|
21
21
|
|
22
22
|
spec.add_development_dependency "rake"
|
23
23
|
spec.add_development_dependency "minitest", "~> 5.8"
|
24
24
|
spec.add_development_dependency "minitest-hooks", ">= 1.4.2"
|
25
25
|
spec.add_development_dependency "minispec-metadata"
|
26
|
-
spec.add_development_dependency "
|
26
|
+
spec.add_development_dependency "dhash-vips"
|
27
27
|
end
|
@@ -9,8 +9,24 @@ module ImageProcessing
|
|
9
9
|
end
|
10
10
|
|
11
11
|
# Calls the pipeline to perform the processing from built options.
|
12
|
-
def call!(**
|
13
|
-
|
12
|
+
def call!(**call_options)
|
13
|
+
instrument do
|
14
|
+
Pipeline.new(pipeline_options).call(**call_options)
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
private
|
19
|
+
|
20
|
+
def instrument
|
21
|
+
return yield unless options[:instrumenter]
|
22
|
+
|
23
|
+
result = nil
|
24
|
+
options[:instrumenter].call(**pipeline_options) { result = yield }
|
25
|
+
result
|
26
|
+
end
|
27
|
+
|
28
|
+
def pipeline_options
|
29
|
+
options.reject { |key, _| key == :instrumenter }
|
14
30
|
end
|
15
31
|
end
|
16
32
|
end
|
@@ -21,6 +21,11 @@ module ImageProcessing
|
|
21
21
|
branch saver: options
|
22
22
|
end
|
23
23
|
|
24
|
+
# Register instrumentation block that will be called around the pipeline.
|
25
|
+
def instrumenter(&block)
|
26
|
+
branch instrumenter: block
|
27
|
+
end
|
28
|
+
|
24
29
|
# Add multiple operations as a hash or an array.
|
25
30
|
#
|
26
31
|
# .apply(resize_to_limit: [400, 400], strip: true)
|
@@ -29,24 +34,17 @@ module ImageProcessing
|
|
29
34
|
def apply(operations)
|
30
35
|
operations.inject(self) do |builder, (name, argument)|
|
31
36
|
if argument == true || argument == nil
|
32
|
-
builder.
|
37
|
+
builder.public_send(name)
|
33
38
|
elsif argument.is_a?(Array)
|
34
|
-
builder.
|
39
|
+
builder.public_send(name, *argument)
|
40
|
+
elsif argument.is_a?(Hash)
|
41
|
+
builder.public_send(name, **argument)
|
35
42
|
else
|
36
|
-
builder.
|
43
|
+
builder.public_send(name, argument)
|
37
44
|
end
|
38
45
|
end
|
39
46
|
end
|
40
47
|
|
41
|
-
# Assume that any unknown method names an operation supported by the
|
42
|
-
# processor. Add a bang ("!") if you want processing to be performed.
|
43
|
-
def method_missing(name, *args, &block)
|
44
|
-
return super if name.to_s.end_with?("?")
|
45
|
-
return send(name.to_s.chomp("!"), *args, &block).call if name.to_s.end_with?("!")
|
46
|
-
|
47
|
-
operation(name, *args, &block)
|
48
|
-
end
|
49
|
-
|
50
48
|
# Add an operation defined by the processor.
|
51
49
|
def operation(name, *args, &block)
|
52
50
|
branch operations: [[name, args, *block]]
|
@@ -56,26 +54,42 @@ module ImageProcessing
|
|
56
54
|
# the source file and destination.
|
57
55
|
def call(file = nil, destination: nil, **call_options)
|
58
56
|
options = {}
|
59
|
-
options =
|
60
|
-
options =
|
57
|
+
options[:source] = file if file
|
58
|
+
options[:destination] = destination if destination
|
61
59
|
|
62
|
-
branch(options).call!(**call_options)
|
60
|
+
branch(**options).call!(**call_options)
|
63
61
|
end
|
64
62
|
|
65
63
|
# Creates a new builder object, merging current options with new options.
|
66
|
-
def branch(
|
67
|
-
|
64
|
+
def branch(**new_options)
|
65
|
+
if self.is_a?(Builder)
|
66
|
+
options = self.options
|
67
|
+
else
|
68
|
+
options = DEFAULT_OPTIONS.merge(processor: self::Processor)
|
69
|
+
end
|
68
70
|
|
69
|
-
options = options.merge(
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
71
|
+
options = options.merge(new_options) do |key, old_value, new_value|
|
72
|
+
case key
|
73
|
+
when :loader, :saver then old_value.merge(new_value)
|
74
|
+
when :operations then old_value + new_value
|
75
|
+
else new_value
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
Builder.new(options.freeze)
|
80
|
+
end
|
74
81
|
|
75
|
-
|
82
|
+
private
|
76
83
|
|
77
|
-
|
84
|
+
# Assume that any unknown method names an operation supported by the
|
85
|
+
# processor. Add a bang ("!") if you want processing to be performed.
|
86
|
+
def method_missing(name, *args, &block)
|
87
|
+
return super if name.to_s.end_with?("?")
|
88
|
+
return send(name.to_s.chomp("!"), *args, &block).call if name.to_s.end_with?("!")
|
89
|
+
|
90
|
+
operation(name, *args, &block)
|
78
91
|
end
|
92
|
+
ruby2_keywords(:method_missing) if respond_to?(:ruby2_keywords, true)
|
79
93
|
|
80
94
|
# Empty options which the builder starts with.
|
81
95
|
DEFAULT_OPTIONS = {
|
@@ -25,20 +25,21 @@ module ImageProcessing
|
|
25
25
|
# Initializes the image on disk into a MiniMagick::Tool object. Accepts
|
26
26
|
# additional options related to loading the image (e.g. geometry).
|
27
27
|
# Additionally auto-orients the image to be upright.
|
28
|
-
def self.load_image(path_or_magick, page: nil, geometry: nil, auto_orient: true, **options)
|
28
|
+
def self.load_image(path_or_magick, loader: nil, page: nil, geometry: nil, auto_orient: true, **options)
|
29
29
|
if path_or_magick.is_a?(::MiniMagick::Tool)
|
30
30
|
magick = path_or_magick
|
31
31
|
else
|
32
32
|
source_path = path_or_magick
|
33
33
|
magick = ::MiniMagick::Tool::Convert.new
|
34
34
|
|
35
|
-
Utils.apply_options(magick, options)
|
35
|
+
Utils.apply_options(magick, **options)
|
36
36
|
|
37
|
-
|
38
|
-
|
39
|
-
|
37
|
+
input = source_path
|
38
|
+
input = "#{loader}:#{input}" if loader
|
39
|
+
input += "[#{page}]" if page
|
40
|
+
input += "[#{geometry}]" if geometry
|
40
41
|
|
41
|
-
magick <<
|
42
|
+
magick << input
|
42
43
|
end
|
43
44
|
|
44
45
|
magick.auto_orient if auto_orient
|
@@ -49,7 +50,7 @@ module ImageProcessing
|
|
49
50
|
# the result to disk. Accepts additional options related to saving the
|
50
51
|
# image (e.g. quality).
|
51
52
|
def self.save_image(magick, destination_path, allow_splitting: false, **options)
|
52
|
-
Utils.apply_options(magick, options)
|
53
|
+
Utils.apply_options(magick, **options)
|
53
54
|
|
54
55
|
magick << destination_path
|
55
56
|
magick.call
|
@@ -85,6 +86,15 @@ module ImageProcessing
|
|
85
86
|
magick.extent "#{width}x#{height}"
|
86
87
|
end
|
87
88
|
|
89
|
+
# Crops the image with the specified crop points.
|
90
|
+
def crop(*args)
|
91
|
+
case args.count
|
92
|
+
when 1 then magick.crop(*args)
|
93
|
+
when 4 then magick.crop("#{args[2]}x#{args[3]}+#{args[0]}+#{args[1]}")
|
94
|
+
else fail ArgumentError, "wrong number of arguments (expected 1 or 4, got #{args.count})"
|
95
|
+
end
|
96
|
+
end
|
97
|
+
|
88
98
|
# Rotates the image by an arbitrary angle. For angles that are not
|
89
99
|
# multiple of 90 degrees an optional background color can be specified to
|
90
100
|
# fill in the gaps.
|
@@ -160,7 +170,7 @@ module ImageProcessing
|
|
160
170
|
|
161
171
|
# Resizes the image using the specified geometry, and sharpens the
|
162
172
|
# resulting thumbnail.
|
163
|
-
def thumbnail(geometry, sharpen:
|
173
|
+
def thumbnail(geometry, sharpen: nil)
|
164
174
|
magick.resize(geometry)
|
165
175
|
|
166
176
|
if sharpen
|
@@ -191,7 +201,7 @@ module ImageProcessing
|
|
191
201
|
# format, ImageMagick will create multiple images, one for each layer.
|
192
202
|
# We want to warn the user that this is probably not what they wanted.
|
193
203
|
def disallow_split_layers!(destination_path)
|
194
|
-
layers = Dir[destination_path.sub(
|
204
|
+
layers = Dir[destination_path.sub(/(\.\w+)?$/, '-*\0')]
|
195
205
|
|
196
206
|
if layers.any?
|
197
207
|
layers.each { |path| File.delete(path) }
|
@@ -37,9 +37,9 @@ module ImageProcessing
|
|
37
37
|
|
38
38
|
# Determines the appropriate destination image format.
|
39
39
|
def destination_format
|
40
|
-
format =
|
40
|
+
format = determine_format(destination) if destination
|
41
41
|
format ||= self.format
|
42
|
-
format ||=
|
42
|
+
format ||= determine_format(source_path) if source_path
|
43
43
|
|
44
44
|
format || DEFAULT_FORMAT
|
45
45
|
end
|
@@ -93,5 +93,11 @@ module ImageProcessing
|
|
93
93
|
@source
|
94
94
|
end
|
95
95
|
end
|
96
|
+
|
97
|
+
def determine_format(file_path)
|
98
|
+
extension = File.extname(file_path)
|
99
|
+
|
100
|
+
extension[1..-1] if extension.size > 1
|
101
|
+
end
|
96
102
|
end
|
97
103
|
end
|
@@ -34,19 +34,12 @@ module ImageProcessing
|
|
34
34
|
const_set(:ACCUMULATOR_CLASS, klass)
|
35
35
|
end
|
36
36
|
|
37
|
-
#
|
38
|
-
# defined on the processor (macro), calls it. Otherwise calls the
|
39
|
-
# operation directly on the accumulator object. This provides a common
|
40
|
-
# umbrella above defined macros and direct operations.
|
37
|
+
# Delegates to #apply_operation.
|
41
38
|
def self.apply_operation(accumulator, (name, args, block))
|
42
|
-
|
43
|
-
instance = new(accumulator)
|
44
|
-
instance.public_send(name, *args, &block)
|
45
|
-
else
|
46
|
-
accumulator.send(name, *args, &block)
|
47
|
-
end
|
39
|
+
new(accumulator).apply_operation(name, *args, &block)
|
48
40
|
end
|
49
41
|
|
42
|
+
# Whether the processor supports resizing the image upon loading.
|
50
43
|
def self.supports_resize_on_load?
|
51
44
|
false
|
52
45
|
end
|
@@ -55,6 +48,21 @@ module ImageProcessing
|
|
55
48
|
@accumulator = accumulator
|
56
49
|
end
|
57
50
|
|
51
|
+
# Calls the operation to perform the processing. If the operation is
|
52
|
+
# defined on the processor (macro), calls the method. Otherwise calls the
|
53
|
+
# operation directly on the accumulator object. This provides a common
|
54
|
+
# umbrella above defined macros and direct operations.
|
55
|
+
def apply_operation(name, *args, &block)
|
56
|
+
receiver = respond_to?(name) ? self : @accumulator
|
57
|
+
|
58
|
+
if args.last.is_a?(Hash)
|
59
|
+
kwargs = args.pop
|
60
|
+
receiver.public_send(name, *args, **kwargs, &block)
|
61
|
+
else
|
62
|
+
receiver.public_send(name, *args, &block)
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
58
66
|
# Calls the given block with the accumulator object. Useful for when you
|
59
67
|
# want to access the accumulator object directly.
|
60
68
|
def custom(&block)
|
@@ -54,7 +54,7 @@ module ImageProcessing
|
|
54
54
|
# pipeline defined in the Vips::Image object. Accepts additional
|
55
55
|
# saver-specific options (e.g. quality).
|
56
56
|
def self.save_image(image, path, saver: nil, quality: nil, **options)
|
57
|
-
options =
|
57
|
+
options[:Q] = quality if quality
|
58
58
|
|
59
59
|
if saver
|
60
60
|
image.public_send(:"#{saver}save", path, **options)
|
@@ -138,8 +138,13 @@ module ImageProcessing
|
|
138
138
|
# resize on load
|
139
139
|
image = ::Vips::Image.thumbnail(self.image, width, height: height, **options)
|
140
140
|
else
|
141
|
+
# we're already calling Image#autorot when loading the image
|
142
|
+
no_rotate = ::Vips.at_least_libvips?(8, 8) ? { no_rotate: true } : { auto_rotate: false }
|
143
|
+
options = no_rotate.merge(options)
|
144
|
+
|
141
145
|
image = self.image.thumbnail_image(width, height: height, **options)
|
142
146
|
end
|
147
|
+
|
143
148
|
image = image.conv(sharpen, precision: :integer) if sharpen
|
144
149
|
image
|
145
150
|
end
|
@@ -187,15 +192,11 @@ module ImageProcessing
|
|
187
192
|
# output image format. Each of these loaders and savers accept slightly
|
188
193
|
# different options, so to allow the user to be able to specify options
|
189
194
|
# for a specific loader/saver and have it ignored for other
|
190
|
-
# loaders/savers, we do
|
191
|
-
#
|
195
|
+
# loaders/savers, we do some introspection and filter out options that
|
196
|
+
# don't exist for a particular loader or saver.
|
192
197
|
def select_valid_options(operation_name, options)
|
193
|
-
|
194
|
-
|
195
|
-
operation_options = operation.get_construct_args
|
196
|
-
.select { |name, flags| (flags & ::Vips::ARGUMENT_INPUT) != 0 }
|
197
|
-
.select { |name, flags| (flags & ::Vips::ARGUMENT_REQUIRED) == 0 }
|
198
|
-
.map(&:first).map(&:to_sym)
|
198
|
+
introspect = ::Vips::Introspect.get(operation_name)
|
199
|
+
operation_options = introspect.optional_input.keys.map(&:to_sym)
|
199
200
|
|
200
201
|
options.select { |name, value| operation_options.include?(name) }
|
201
202
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: image_processing
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.12.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Janko Marohnić
|
8
|
-
autorequire:
|
8
|
+
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2022-03-01 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: mini_magick
|
@@ -36,7 +36,7 @@ dependencies:
|
|
36
36
|
requirements:
|
37
37
|
- - ">="
|
38
38
|
- !ruby/object:Gem::Version
|
39
|
-
version: 2.0.
|
39
|
+
version: 2.0.17
|
40
40
|
- - "<"
|
41
41
|
- !ruby/object:Gem::Version
|
42
42
|
version: '3'
|
@@ -46,7 +46,7 @@ dependencies:
|
|
46
46
|
requirements:
|
47
47
|
- - ">="
|
48
48
|
- !ruby/object:Gem::Version
|
49
|
-
version: 2.0.
|
49
|
+
version: 2.0.17
|
50
50
|
- - "<"
|
51
51
|
- !ruby/object:Gem::Version
|
52
52
|
version: '3'
|
@@ -107,7 +107,7 @@ dependencies:
|
|
107
107
|
- !ruby/object:Gem::Version
|
108
108
|
version: '0'
|
109
109
|
- !ruby/object:Gem::Dependency
|
110
|
-
name:
|
110
|
+
name: dhash-vips
|
111
111
|
requirement: !ruby/object:Gem::Requirement
|
112
112
|
requirements:
|
113
113
|
- - ">="
|
@@ -120,7 +120,8 @@ dependencies:
|
|
120
120
|
- - ">="
|
121
121
|
- !ruby/object:Gem::Version
|
122
122
|
version: '0'
|
123
|
-
description:
|
123
|
+
description: High-level wrapper for processing images for the web with ImageMagick
|
124
|
+
or libvips.
|
124
125
|
email:
|
125
126
|
- janko.marohnic@gmail.com
|
126
127
|
executables: []
|
@@ -143,7 +144,7 @@ homepage: https://github.com/janko/image_processing
|
|
143
144
|
licenses:
|
144
145
|
- MIT
|
145
146
|
metadata: {}
|
146
|
-
post_install_message:
|
147
|
+
post_install_message:
|
147
148
|
rdoc_options: []
|
148
149
|
require_paths:
|
149
150
|
- lib
|
@@ -158,8 +159,9 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
158
159
|
- !ruby/object:Gem::Version
|
159
160
|
version: '0'
|
160
161
|
requirements: []
|
161
|
-
rubygems_version: 3.
|
162
|
-
signing_key:
|
162
|
+
rubygems_version: 3.3.3
|
163
|
+
signing_key:
|
163
164
|
specification_version: 4
|
164
|
-
summary:
|
165
|
+
summary: High-level wrapper for processing images for the web with ImageMagick or
|
166
|
+
libvips.
|
165
167
|
test_files: []
|