oximg 0.18.0-aarch64-linux-gnu → 0.18.1-aarch64-linux-gnu
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 +27 -4
- data/exe/oximg +0 -0
- data/lib/oximg/binary.rb +8 -2
- data/lib/oximg/native/liboximg_probe.so +0 -0
- data/lib/oximg/version.rb +1 -1
- data/lib/oximg.rb +102 -7
- 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: d4d3cb7265d61a0d89d9851f6e0938951ca773603a02dcdc19ad5b8abf3d68de
|
|
4
|
+
data.tar.gz: 7cfa66df5ffac827bc245ddd387cc321054dabd6f97c97a13bf3e6b3e8ad50e5
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 1be6c2171b1eb682a4d495d3130eca32b7e856db393a5319aba109ada1f5d5cdd1e636ebf8072243894b58d6801849aa0cee30cb34d91adee4f0ff4593bfeb53
|
|
7
|
+
data.tar.gz: 5c2cf3b537d675e748cd62e3787a1008099ab2e16103ecdfee11d80a8e4b1535f81a5ebc3e3a7b5124410948042b230269f7ffae0dec5a75ea5f91770bfa6dbc
|
data/README.md
CHANGED
|
@@ -31,7 +31,8 @@ the name does not say, and `:gif` is not a `format:` you can ask for.
|
|
|
31
31
|
|
|
32
32
|
```ruby
|
|
33
33
|
Oximg.resize(source, destination, width: 0, height: 0,
|
|
34
|
-
quality: nil, format: nil, preset: nil
|
|
34
|
+
quality: nil, format: nil, preset: nil,
|
|
35
|
+
icc: nil, auto_rotate: nil)
|
|
35
36
|
```
|
|
36
37
|
|
|
37
38
|
The source is fitted within `width` x `height` and **never enlarged**. A
|
|
@@ -50,6 +51,12 @@ Oximg.resize("photo.jpg", "smaller.jpg", quality: 70)
|
|
|
50
51
|
| `quality` | 1–100, default 80. JPEG quality |
|
|
51
52
|
| `format` | `:jpg`, `:jpeg`, `:png`, `:webp`, `:avif`. Defaults to the destination's extension, else the source's own format |
|
|
52
53
|
| `preset` | `:jpegli` (default — maximum quality per byte), `:fast`, `:small` |
|
|
54
|
+
| `icc` | `:keep` or `:strip` the source's colour profile. Default: `OXIMG_ICC`, else keep |
|
|
55
|
+
| `auto_rotate` | `false` keeps the stored orientation, `true` applies the EXIF one. Default: `OXIMG_AUTO_ROTATE`, else true |
|
|
56
|
+
|
|
57
|
+
`icc` and `auto_rotate` apply to that call only, and win over the
|
|
58
|
+
environment, so a threaded job runner can treat one image differently
|
|
59
|
+
without touching `ENV`.
|
|
53
60
|
|
|
54
61
|
`resize` returns the destination path and raises `Oximg::ProcessingError`
|
|
55
62
|
on failure, carrying the binary's own message and exit status. Paths are
|
|
@@ -59,7 +66,7 @@ cannot be read as a flag.
|
|
|
59
66
|
## Stripping metadata
|
|
60
67
|
|
|
61
68
|
```ruby
|
|
62
|
-
Oximg.strip(source, destination, icc: nil)
|
|
69
|
+
Oximg.strip(source, destination, icc: nil, env: nil)
|
|
63
70
|
```
|
|
64
71
|
|
|
65
72
|
Removes EXIF (GPS, camera, timestamps), XMP, IPTC and comments from a
|
|
@@ -71,10 +78,26 @@ still displays upright. `icc: :strip` also drops the colour profile.
|
|
|
71
78
|
The default is `:keep`, or `OXIMG_ICC`. Dropping a CMYK JPEG's profile
|
|
72
79
|
raises `Oximg::ProcessingError`, as do GIF and AVIF sources.
|
|
73
80
|
|
|
81
|
+
## Knobs, per process or per call
|
|
82
|
+
|
|
74
83
|
Everything the server tunes through `OXIMG_*` environment variables
|
|
75
84
|
applies here too, and is validated the same fail-closed way: a typo'd
|
|
76
85
|
knob is a startup error, never a silent default.
|
|
77
86
|
|
|
87
|
+
To set one for a single call, pass `env:` to `resize` or `strip`:
|
|
88
|
+
|
|
89
|
+
```ruby
|
|
90
|
+
Oximg.resize("in.jpg", "out.jpg", width: 750, env: {"OXIMG_JPEG_PROGRESSIVE" => "0"})
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
Each call spawns its own process, and `env:` reaches that process
|
|
94
|
+
only: `ENV` is never touched, so concurrent calls in a threaded job
|
|
95
|
+
runner each get their own settings. Names must be in `Oximg::KNOBS`
|
|
96
|
+
(the pipeline knobs; server settings such as `OXIMG_KEY` are refused),
|
|
97
|
+
values are Strings or Integers, and `nil` unsets a name for that call.
|
|
98
|
+
An unknown name raises `ArgumentError` before anything runs; a bad
|
|
99
|
+
value is refused by the binary (`ProcessingError`, status 2).
|
|
100
|
+
|
|
78
101
|
## Probing
|
|
79
102
|
|
|
80
103
|
```ruby
|
|
@@ -138,8 +161,8 @@ Oximg.in_process_probe? #=> true on a platform gem
|
|
|
138
161
|
|
|
139
162
|
```ruby
|
|
140
163
|
Oximg.available? #=> true
|
|
141
|
-
Oximg.executable #=> "/…/gems/oximg-0.18.
|
|
142
|
-
Oximg.version #=> "0.18.
|
|
164
|
+
Oximg.executable #=> "/…/gems/oximg-0.18.1-arm64-darwin/exe/oximg"
|
|
165
|
+
Oximg.version #=> "0.18.1" # the binary's version, not the gem's
|
|
143
166
|
```
|
|
144
167
|
|
|
145
168
|
`resize` shells out to that binary — one process per image, which is
|
data/exe/oximg
CHANGED
|
Binary file
|
data/lib/oximg/binary.rb
CHANGED
|
@@ -60,8 +60,14 @@ module Oximg
|
|
|
60
60
|
# nothing in a filename can be interpreted as syntax. Returns
|
|
61
61
|
# [stdout, stderr]; a non-zero exit raises with the binary's own
|
|
62
62
|
# stderr, which already names what it refused.
|
|
63
|
-
|
|
64
|
-
|
|
63
|
+
#
|
|
64
|
+
# +env+ is merged into the child's environment only (a nil value
|
|
65
|
+
# unsets that name there): one process per call means one call's
|
|
66
|
+
# knobs never reach another's, even across threads, and the
|
|
67
|
+
# parent's ENV is never touched. Validate it first; Oximg.resize
|
|
68
|
+
# and Oximg.strip do.
|
|
69
|
+
def run(*args, env: {})
|
|
70
|
+
out, err, status = Open3.capture3(env, path, *args)
|
|
65
71
|
unless status.success?
|
|
66
72
|
message = err.strip
|
|
67
73
|
message = "oximg exited #{status.exitstatus}" if message.empty?
|
|
Binary file
|
data/lib/oximg/version.rb
CHANGED
data/lib/oximg.rb
CHANGED
|
@@ -45,9 +45,52 @@ module Oximg
|
|
|
45
45
|
# mozjpeg's fast/small trade differently.
|
|
46
46
|
PRESETS = %i[jpegli fast small].freeze
|
|
47
47
|
|
|
48
|
-
# What `strip` may do with an embedded colour profile.
|
|
48
|
+
# What `resize` and `strip` may do with an embedded colour profile.
|
|
49
49
|
ICC_MODES = %i[keep strip].freeze
|
|
50
50
|
|
|
51
|
+
# The OXIMG_* pipeline knobs an +env:+ may set for one call. Pinned to
|
|
52
|
+
# the binary's own inventory (KNOBS in src/config.rs) by a test there,
|
|
53
|
+
# so a knob the binary gains or drops cannot drift from this list.
|
|
54
|
+
# Server-startup settings (OXIMG_KEY, OXIMG_BIND, ...) are not here:
|
|
55
|
+
# a one-shot never reads them.
|
|
56
|
+
KNOBS = %w[
|
|
57
|
+
OXIMG_TIMING
|
|
58
|
+
OXIMG_RESIZE
|
|
59
|
+
OXIMG_RESIZE_BACKEND
|
|
60
|
+
OXIMG_AUTO_ROTATE
|
|
61
|
+
OXIMG_ICC
|
|
62
|
+
OXIMG_DCT_MARGIN
|
|
63
|
+
OXIMG_LINEAR_SHRINK
|
|
64
|
+
OXIMG_JPEG_PROGRESSIVE
|
|
65
|
+
OXIMG_JPEG_SEQUENTIAL_PIXELS
|
|
66
|
+
OXIMG_JPEG_STREAMING_PIXELS
|
|
67
|
+
OXIMG_FLATTEN_BG
|
|
68
|
+
OXIMG_PNG_EFFORT
|
|
69
|
+
OXIMG_PNG_QUANTIZE
|
|
70
|
+
OXIMG_PNG_QUANTIZE_COLORS
|
|
71
|
+
OXIMG_WEBP_QUALITY
|
|
72
|
+
OXIMG_WEBP_EFFORT
|
|
73
|
+
OXIMG_WEBP_DECODE_THREADS
|
|
74
|
+
OXIMG_AVIF_QUALITY
|
|
75
|
+
OXIMG_AVIF_ALPHA_QUALITY
|
|
76
|
+
OXIMG_AVIF_SPEED
|
|
77
|
+
OXIMG_AVIF_DECODE_THREADS
|
|
78
|
+
OXIMG_MAX_SOURCE_BYTES
|
|
79
|
+
OXIMG_MAX_SRC_PIXELS
|
|
80
|
+
OXIMG_GIF_ANIMATION
|
|
81
|
+
OXIMG_MAX_ANIM_FRAMES
|
|
82
|
+
OXIMG_MAX_ANIM_WORK
|
|
83
|
+
OXIMG_ANIM_FRAME_STEP
|
|
84
|
+
OXIMG_MAX_DECODED_BYTES
|
|
85
|
+
OXIMG_LOG_DECODED_BYTES_ABOVE
|
|
86
|
+
OXIMG_UPSTREAM_CONNECT_TIMEOUT
|
|
87
|
+
OXIMG_UPSTREAM_TIMEOUT
|
|
88
|
+
OXIMG_GCS_ENDPOINT
|
|
89
|
+
OXIMG_S3_ENDPOINT
|
|
90
|
+
OXIMG_S3_PATH_STYLE
|
|
91
|
+
OXIMG_OVERLAP
|
|
92
|
+
].freeze
|
|
93
|
+
|
|
51
94
|
CONTENT_TYPE_FORMATS = {
|
|
52
95
|
"image/jpeg" => :jpeg,
|
|
53
96
|
"image/png" => :png,
|
|
@@ -106,10 +149,24 @@ module Oximg
|
|
|
106
149
|
# The output format follows +format:+, else +destination+'s
|
|
107
150
|
# extension, else the source's own format. Returns the destination
|
|
108
151
|
# path.
|
|
109
|
-
|
|
152
|
+
#
|
|
153
|
+
# +icc:+ (:keep or :strip) and +auto_rotate:+ (true or false)
|
|
154
|
+
# override the binary's OXIMG_ICC and OXIMG_AUTO_ROTATE for this
|
|
155
|
+
# call only; nil leaves them to the environment (default: keep the
|
|
156
|
+
# profile, apply the EXIF orientation).
|
|
157
|
+
#
|
|
158
|
+
# +env:+ sets any other pipeline knob for this call only, e.g.
|
|
159
|
+
# <tt>env: {"OXIMG_JPEG_PROGRESSIVE" => "0"}</tt>: it reaches the
|
|
160
|
+
# one child process this call spawns, never ENV, so it is safe in a
|
|
161
|
+
# threaded job runner. Names must be in KNOBS; nil unsets a name
|
|
162
|
+
# for the call. The binary validates the values, fail-closed.
|
|
163
|
+
def resize(source, destination, width: 0, height: 0, quality: nil, format: nil, preset: nil,
|
|
164
|
+
icc: nil, auto_rotate: nil, env: nil)
|
|
110
165
|
output = expand(destination, "destination")
|
|
111
|
-
|
|
112
|
-
width: width, height: height, quality: quality, format: format, preset: preset
|
|
166
|
+
argv = resize_argv(source, output,
|
|
167
|
+
width: width, height: height, quality: quality, format: format, preset: preset,
|
|
168
|
+
icc: icc, auto_rotate: auto_rotate)
|
|
169
|
+
Binary.run(*argv, env: knob_env(env))
|
|
113
170
|
output
|
|
114
171
|
end
|
|
115
172
|
|
|
@@ -123,12 +180,37 @@ module Oximg
|
|
|
123
180
|
#
|
|
124
181
|
# This is what <tt>saver(strip: true)</tt> / <tt>-strip</tt> did
|
|
125
182
|
# under libvips or ImageMagick, minus the re-encode.
|
|
126
|
-
|
|
183
|
+
#
|
|
184
|
+
# +env:+ is per-call knobs, as for resize.
|
|
185
|
+
def strip(source, destination, icc: nil, env: nil)
|
|
127
186
|
output = expand(destination, "destination")
|
|
128
|
-
|
|
187
|
+
argv = strip_argv(source, output, icc: icc)
|
|
188
|
+
Binary.run(*argv, env: knob_env(env))
|
|
129
189
|
output
|
|
130
190
|
end
|
|
131
191
|
|
|
192
|
+
# The child environment an +env:+ turns into: String names and
|
|
193
|
+
# values, each name a known knob. A typo raises here rather than
|
|
194
|
+
# being passed along and ignored, which is the same fail-closed
|
|
195
|
+
# promise the binary makes about the values. Public for the same
|
|
196
|
+
# reason as resize_argv.
|
|
197
|
+
def knob_env(env)
|
|
198
|
+
return {} if env.nil?
|
|
199
|
+
raise ArgumentError, "env must be a Hash, got #{env.inspect}" unless env.is_a?(Hash)
|
|
200
|
+
|
|
201
|
+
env.each_with_object({}) do |(name, value), out|
|
|
202
|
+
key = name.to_s
|
|
203
|
+
unless KNOBS.include?(key)
|
|
204
|
+
raise ArgumentError, "unknown knob #{name.inspect} in env (one of Oximg::KNOBS)"
|
|
205
|
+
end
|
|
206
|
+
unless value.nil? || value.is_a?(String) || value.is_a?(Integer)
|
|
207
|
+
raise ArgumentError, "#{key} must be a String, an Integer or nil, got #{value.inspect}"
|
|
208
|
+
end
|
|
209
|
+
|
|
210
|
+
out[key] = value&.to_s
|
|
211
|
+
end
|
|
212
|
+
end
|
|
213
|
+
|
|
132
214
|
# The argv `strip` would run, minus the executable; public for the
|
|
133
215
|
# same reason as resize_argv.
|
|
134
216
|
def strip_argv(source, destination, icc: nil)
|
|
@@ -180,7 +262,8 @@ module Oximg
|
|
|
180
262
|
# The argv `resize` would run, minus the executable. Public because
|
|
181
263
|
# it is the honest way to see what a call turns into — and the way
|
|
182
264
|
# to test that without a binary present.
|
|
183
|
-
def resize_argv(source, destination, width: 0, height: 0, quality: nil, format: nil, preset: nil
|
|
265
|
+
def resize_argv(source, destination, width: 0, height: 0, quality: nil, format: nil, preset: nil,
|
|
266
|
+
icc: nil, auto_rotate: nil)
|
|
184
267
|
argv = [
|
|
185
268
|
"resize",
|
|
186
269
|
expand(source, "source"),
|
|
@@ -191,6 +274,8 @@ module Oximg
|
|
|
191
274
|
argv.push("-q", bounded(quality, "quality", 1, 100).to_s) unless quality.nil?
|
|
192
275
|
argv.push("-f", token(format, FORMATS, "format")) unless format.nil?
|
|
193
276
|
argv.push("--preset", token(preset, PRESETS, "preset")) unless preset.nil?
|
|
277
|
+
argv.push("--icc", token(icc, ICC_MODES, "icc")) unless icc.nil?
|
|
278
|
+
argv.push(boolean(auto_rotate, "auto_rotate") ? "--auto-rotate" : "--no-auto-rotate") unless auto_rotate.nil?
|
|
194
279
|
argv
|
|
195
280
|
end
|
|
196
281
|
|
|
@@ -319,6 +404,16 @@ module Oximg
|
|
|
319
404
|
value
|
|
320
405
|
end
|
|
321
406
|
|
|
407
|
+
# Strictly true or false: a truthy "0" or "false" read as true would
|
|
408
|
+
# rotate exactly the images the caller asked not to.
|
|
409
|
+
def boolean(value, name)
|
|
410
|
+
unless value == true || value == false
|
|
411
|
+
raise ArgumentError, "#{name} must be true or false, got #{value.inspect}"
|
|
412
|
+
end
|
|
413
|
+
|
|
414
|
+
value
|
|
415
|
+
end
|
|
416
|
+
|
|
322
417
|
def token(value, allowed, name)
|
|
323
418
|
token = value.to_s.downcase
|
|
324
419
|
unless allowed.include?(token.to_sym)
|