Module: Oximg
- Defined in:
- lib/oximg.rb,
lib/oximg/binary.rb,
lib/oximg/version.rb
Overview
Ruby bindings for oximg (https://github.com/oximg/oximg): high-performance image compression and resizing, in-process work for a Ruby app without libvips or ImageMagick on the box.
Oximg.resize("in.jpg", "out.jpg", width: 750)
Oximg.resize("in.jpg", "out.webp", width: 750, height: 500, quality: 80)
Oximg.probe("in.jpg") #=> {content_type: "image/jpeg", format: :jpeg, ...}
Rails/ActiveStorage integration, and URL building for a remote oximg
server, live in the separate oximg-rails gem.
Defined Under Namespace
Modules: Binary Classes: Error, ExecutableNotFound, ProcessingError
Constant Summary collapse
- FORMATS =
Output formats the CLI accepts for -f/--format.
%i[jpg jpeg png webp avif].freeze
- PRESETS =
Encoder profiles: jpegli maximizes quality per byte (the default), mozjpeg's fast/small trade differently.
%i[jpegli fast small].freeze
- CONTENT_TYPE_FORMATS =
{ "image/jpeg" => :jpeg, "image/png" => :png, "image/webp" => :webp, "image/avif" => :avif }.freeze
- PROBE_LINE =
/:\s+(\S+)\s+(\d+)x(\d+)\s+\(\d+\s+stored\s+pixels\)\s*\z/- VERSION =
The gem version is the version of the oximg it bundles — the same convention the npm package uses. A gem-only fix therefore waits for the next oximg release rather than shipping under a version that names a binary it does not carry.
Oximg.versionreports what the resolved executable actually is, which can differ when it comes from PATH. "0.11.0"
Class Method Summary collapse
-
.available? ⇒ Boolean
True when an executable can be found — for a boot-time check, or for code that falls back to another processor.
-
.executable ⇒ Object
Absolute path to the executable in use; raises ExecutableNotFound if there is none.
-
.executable=(path) ⇒ Object
Pins the executable, overriding discovery and OXIMG_BIN.
-
.probe(source) ⇒ Object
Header-only inspection — no pixels are decoded.
-
.resize(source, destination, width: 0, height: 0, quality: nil, format: nil, preset: nil) ⇒ Object
Fits
sourcewithinwidthxheightand writes the re-encoded image todestination. -
.resize_argv(source, destination, width: 0, height: 0, quality: nil, format: nil, preset: nil) ⇒ Object
The argv
resizewould run, minus the executable. -
.version ⇒ Object
Version of the executable, which is not necessarily this gem's VERSION when the binary comes from PATH.
Class Method Details
.available? ⇒ Boolean
True when an executable can be found — for a boot-time check, or for code that falls back to another processor.
68 69 70 |
# File 'lib/oximg.rb', line 68 def available? Binary.available? end |
.executable ⇒ Object
Absolute path to the executable in use; raises ExecutableNotFound if there is none.
56 57 58 |
# File 'lib/oximg.rb', line 56 def executable Binary.path end |
.executable=(path) ⇒ Object
Pins the executable, overriding discovery and OXIMG_BIN.
61 62 63 64 |
# File 'lib/oximg.rb', line 61 def executable=(path) Binary.reset! Binary.path = path end |
.probe(source) ⇒ Object
Header-only inspection — no pixels are decoded. Returns {content_type:, format:, width:, height:}, where the dimensions are the stored ones (an EXIF rotation is not applied).
97 98 99 100 101 102 103 104 105 106 107 108 |
# File 'lib/oximg.rb', line 97 def probe(source) out, = Binary.run("probe", (source, "source")) match = out.match(PROBE_LINE) raise ProcessingError, "unparsable probe output: #{out.inspect}" unless match { content_type: match[1], format: CONTENT_TYPE_FORMATS[match[1]], width: Integer(match[2]), height: Integer(match[3]) } end |
.resize(source, destination, width: 0, height: 0, quality: nil, format: nil, preset: nil) ⇒ Object
Fits source within width x height and writes the re-encoded
image to destination. The source is never enlarged, and a zero
axis is unconstrained — width: 750 alone is width-only,
and the default 0 x 0 re-encodes at the source's own size, which
is how you ask for compression without a resize.
The output format follows format:, else +destination+'s
extension, else the source's own format. Returns the destination
path.
87 88 89 90 91 92 |
# File 'lib/oximg.rb', line 87 def resize(source, destination, width: 0, height: 0, quality: nil, format: nil, preset: nil) output = (destination, "destination") Binary.run(*resize_argv(source, output, width: width, height: height, quality: quality, format: format, preset: preset)) output end |
.resize_argv(source, destination, width: 0, height: 0, quality: nil, format: nil, preset: nil) ⇒ Object
The argv resize would run, minus the executable. Public because
it is the honest way to see what a call turns into — and the way
to test that without a binary present.
113 114 115 116 117 118 119 120 121 122 123 124 125 |
# File 'lib/oximg.rb', line 113 def resize_argv(source, destination, width: 0, height: 0, quality: nil, format: nil, preset: nil) argv = [ "resize", (source, "source"), dimension(width, "width").to_s, dimension(height, "height").to_s, (destination, "destination") ] argv.push("-q", bounded(quality, "quality", 1, 100).to_s) unless quality.nil? argv.push("-f", token(format, FORMATS, "format")) unless format.nil? argv.push("--preset", token(preset, PRESETS, "preset")) unless preset.nil? argv end |