image_processing 2.0.3 → 2.2.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/CHANGELOG.md +9 -1
- data/lib/image_processing/mini_magick.rb +31 -8
- data/lib/image_processing/pipeline.rb +5 -1
- data/lib/image_processing/processor.rb +4 -2
- data/lib/image_processing/version.rb +1 -1
- data/lib/image_processing/vips.rb +14 -2
- metadata +1 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 5b790f3dd08c310a2413cb8cb6b33a9c602edb3509cdd1de2c8f94ebea702f17
|
|
4
|
+
data.tar.gz: 99d87927f2a6603939332f61292c2b2b582fecc5832b4562a92e8a5170e862d9
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 00b2e0b0b250473b55e4ca415fd00f1c9fa50458e2c280a4110949838c344cb49c52b5afe023e0c75b8e435460f55517a1aeb8497ae1adf72fdca1de3fab59e2
|
|
7
|
+
data.tar.gz: a87c6791a8dbc06d5e40a6a64aaefd7803a382aac5071e238f7f7bface47d026405603bb6da9cc4534f9472f65d2e70bf4614cd75b9962506781a2818ad81b73
|
data/CHANGELOG.md
CHANGED
|
@@ -1,4 +1,12 @@
|
|
|
1
|
-
## 2.0
|
|
1
|
+
## 2.2.0 (2026-09-29)
|
|
2
|
+
|
|
3
|
+
* Save in the `#convert` format when the destination path has no extension, such as a `/dev/fd/N` path (thanks to @flavorjones)
|
|
4
|
+
|
|
5
|
+
## 2.1.0 (2026-09-01)
|
|
6
|
+
|
|
7
|
+
* [minimagick] Add `inherit_fds:` so a loader can name an already-open input (thanks to @flavorjones)
|
|
8
|
+
|
|
9
|
+
## 2.0.3 (2026-08-06)
|
|
2
10
|
|
|
3
11
|
* Prevent remote code execution when operation names come from user input, closing bypasses through the `#operation` meta-builder, `#method_missing`, and nested `#send` calls (reported by @szymonsec)
|
|
4
12
|
|
|
@@ -9,11 +9,20 @@ module ImageProcessing
|
|
|
9
9
|
module MiniMagick
|
|
10
10
|
extend Chainable
|
|
11
11
|
|
|
12
|
-
|
|
12
|
+
# mini_magick gained `inherit_fds:` on MiniMagick::Shell#execute in 5.4.0.
|
|
13
|
+
INHERIT_FDS_MINIMUM_VERSION = Gem::Version.new("5.4.0")
|
|
14
|
+
|
|
15
|
+
def self.convert_shim(inherit_fds: nil, &block)
|
|
16
|
+
if inherit_fds && ::MiniMagick.version < INHERIT_FDS_MINIMUM_VERSION
|
|
17
|
+
raise LoadError, "The `inherit_fds` loader option requires mini_magick #{INHERIT_FDS_MINIMUM_VERSION} or newer, but mini_magick #{::MiniMagick.version} is loaded. Please upgrade the gem."
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
options = inherit_fds ? { inherit_fds: inherit_fds } : {}
|
|
21
|
+
|
|
13
22
|
if ::MiniMagick.respond_to?(:convert)
|
|
14
|
-
::MiniMagick.convert(&block)
|
|
23
|
+
::MiniMagick.convert(**options, &block)
|
|
15
24
|
else
|
|
16
|
-
::MiniMagick::Tool::Convert.new(&block)
|
|
25
|
+
::MiniMagick::Tool::Convert.new(**options, &block)
|
|
17
26
|
end
|
|
18
27
|
end
|
|
19
28
|
|
|
@@ -37,12 +46,16 @@ module ImageProcessing
|
|
|
37
46
|
# Initializes the image on disk into a MiniMagick::Tool object. Accepts
|
|
38
47
|
# additional options related to loading the image (e.g. geometry).
|
|
39
48
|
# Additionally auto-orients the image to be upright.
|
|
40
|
-
|
|
49
|
+
# `inherit_fds` names IO objects the tool inherits, so the source may be a
|
|
50
|
+
# `/dev/fd/N` path. The source stays a path, so `loader`, `page` and
|
|
51
|
+
# `geometry` still apply to it, which they would not if the caller passed
|
|
52
|
+
# a pre-built MiniMagick::Tool carrying the descriptor.
|
|
53
|
+
def self.load_image(path_or_magick, loader: nil, page: nil, geometry: nil, auto_orient: true, inherit_fds: nil, **options)
|
|
41
54
|
if path_or_magick.is_a?(::MiniMagick::Tool)
|
|
42
55
|
magick = path_or_magick
|
|
43
56
|
else
|
|
44
57
|
source_path = path_or_magick
|
|
45
|
-
magick = ::ImageProcessing::MiniMagick.convert_shim
|
|
58
|
+
magick = ::ImageProcessing::MiniMagick.convert_shim(inherit_fds: inherit_fds)
|
|
46
59
|
|
|
47
60
|
Utils.apply_options(magick, **options)
|
|
48
61
|
|
|
@@ -60,11 +73,21 @@ module ImageProcessing
|
|
|
60
73
|
|
|
61
74
|
# Calls the built ImageMagick command to perform processing and save
|
|
62
75
|
# the result to disk. Accepts additional options related to saving the
|
|
63
|
-
# image (e.g. quality).
|
|
64
|
-
|
|
76
|
+
# image (e.g. quality). `format` names the output format when given,
|
|
77
|
+
# otherwise ImageMagick infers it from the path's extension.
|
|
78
|
+
def self.save_image(magick, destination_path, format = nil, allow_splitting: false, **options)
|
|
65
79
|
Utils.apply_options(magick, **options)
|
|
66
80
|
|
|
67
|
-
|
|
81
|
+
if format
|
|
82
|
+
# ImageMagick reads everything before the first colon as the
|
|
83
|
+
# format, so a format carrying a colon could redirect the output.
|
|
84
|
+
format = format.to_s
|
|
85
|
+
fail Error, "invalid format: #{format.inspect}" unless format.ascii_only? && format.match?(/\A\w+\z/)
|
|
86
|
+
|
|
87
|
+
magick << "#{format}:#{destination_path}"
|
|
88
|
+
else
|
|
89
|
+
magick << destination_path
|
|
90
|
+
end
|
|
68
91
|
magick.call
|
|
69
92
|
|
|
70
93
|
Utils.disallow_split_layers!(destination_path) unless allow_splitting
|
|
@@ -21,7 +21,11 @@ module ImageProcessing
|
|
|
21
21
|
call_processor
|
|
22
22
|
elsif destination
|
|
23
23
|
handle_destination do
|
|
24
|
-
|
|
24
|
+
if format && !determine_format(destination)
|
|
25
|
+
call_processor(destination: destination, format: format)
|
|
26
|
+
else
|
|
27
|
+
call_processor(destination: destination)
|
|
28
|
+
end
|
|
25
29
|
end
|
|
26
30
|
else
|
|
27
31
|
create_tempfile do |tempfile|
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
module ImageProcessing
|
|
2
2
|
# Abstract class inherited by individual processors.
|
|
3
3
|
class Processor
|
|
4
|
-
def self.call(source:, loader:, operations:, saver:, destination: nil)
|
|
4
|
+
def self.call(source:, loader:, operations:, saver:, destination: nil, format: nil)
|
|
5
5
|
unless source.is_a?(String) || source.is_a?(self::ACCUMULATOR_CLASS)
|
|
6
6
|
fail Error, "invalid source: #{source.inspect}"
|
|
7
7
|
end
|
|
@@ -19,7 +19,9 @@ module ImageProcessing
|
|
|
19
19
|
accumulator = apply_operation(accumulator, operation)
|
|
20
20
|
end
|
|
21
21
|
|
|
22
|
-
if destination
|
|
22
|
+
if destination && format
|
|
23
|
+
save_image(accumulator, destination, format, **saver)
|
|
24
|
+
elsif destination
|
|
23
25
|
save_image(accumulator, destination, **saver)
|
|
24
26
|
else
|
|
25
27
|
accumulator
|
|
@@ -56,12 +56,24 @@ module ImageProcessing
|
|
|
56
56
|
|
|
57
57
|
# Writes the Vips::Image object to disk. This starts the processing
|
|
58
58
|
# pipeline defined in the Vips::Image object. Accepts additional
|
|
59
|
-
# saver-specific options (e.g. quality).
|
|
60
|
-
|
|
59
|
+
# saver-specific options (e.g. quality). The saver is chosen by `format`
|
|
60
|
+
# when given, otherwise by the path's extension.
|
|
61
|
+
def self.save_image(image, path, format = nil, saver: nil, quality: nil, **options)
|
|
61
62
|
options[:Q] = quality if quality
|
|
62
63
|
|
|
63
64
|
if saver
|
|
64
65
|
image.public_send(:"#{saver}save", path, **options)
|
|
66
|
+
elsif format
|
|
67
|
+
# Savers such as heifsave pick their encoding from the suffix (AV1
|
|
68
|
+
# for ".avif"), so save through a target, which takes the suffix
|
|
69
|
+
# separately from the path.
|
|
70
|
+
saver = ::Vips.vips_foreign_find_save_target(".#{format}")
|
|
71
|
+
fail ::Vips::Error, "No known saver for '#{format}'." unless saver
|
|
72
|
+
|
|
73
|
+
filename = ::Vips.p2str(::Vips.vips_filename_get_filename(path))
|
|
74
|
+
option_string = ::Vips.p2str(::Vips.vips_filename_get_options(path))
|
|
75
|
+
options = Utils.select_valid_options(saver, options)
|
|
76
|
+
image.write_to_target(::Vips::Target.new_to_file(filename), ".#{format}#{option_string}", **options)
|
|
65
77
|
else
|
|
66
78
|
options = Utils.select_valid_saver_options(path, options)
|
|
67
79
|
image.write_to_file(path, **options)
|