Butteraugli perceptual image-difference metric for Elixir, backed by the
butteraugli Rust crate.
Butteraugli is a distance: lower is better. A score below 1.0 means the
images are perceptually identical, 1.0–2.0 is a subtle/borderline
difference, and above 2.0 is a clearly visible difference. (This is the
opposite orientation from quality metrics like SSIMULACRA2.)
Inputs are packed binaries whose layout is chosen with the :format option
(default :rgb888):
| format | element | channels | bytes/pixel | color space |
|---|---|---|---|---|
:rgb888 (default) | u8 | 3 | 3 | sRGB (gamma) |
:linear_rgb | f32 | 3 | 12 | linear RGB |
Multi-byte elements (f32) are native-endian (<<v::native-float-32>>).
A binary's size must equal width * height * channels * bytes_per_element.
Comparisons return a Butteraugli.Result.
Cancellation
compare/5 and Butteraugli.Reference.compare/3 accept cancel: (a
Butteraugli.CancelRef) and timeout: (milliseconds); aborted calls return
{:error, :cancelled} or {:error, :timeout}. Create a ref with
Butteraugli.CancelRef.new/0 and trip it with cancel/1.
The granularity differs by path, because the binding polls the ref at different points:
compare/5on images ≥ 8×8 (either format) checks the ref between strips, so it aborts mid-computation — a ref cancelled, or a timeout firing, partway through a long compare stops it promptly.- Sub-8×8 images, and
Butteraugli.Reference.compare/3with the defaultprefer: :speedcheck the ref once, at the start of the computation. (Sub-8×8 inputs are padded onto the non-strip path;prefer: :speeduses the precomputed reference for the ~2× speedup, which has no strip-wise stop.) These honor a ref that is already cancelled when the call begins — including batch cancellation, where cancelling one ref aborts every subsequent compare that uses it — but a cancel/timeout arriving after the computation is underway will not interrupt it; that call runs to completion. Butteraugli.Reference.compare/3withprefer: :memoryopts into the strip-bounded walker: bounded peak memory and per-strip mid-computation cancellation, trading away the precompute speedup.
If you must bound the wall-clock of an individual long compare, use compare/5
on a ≥ 8×8 image, or Butteraugli.Reference.compare/3 with prefer: :memory.
Summary
Functions
Trip a Butteraugli.CancelRef, aborting any comparison that uses it.
Compare a reference and distorted image of the same dimensions.
Like compare/5 but returns the bare Butteraugli.Result and raises
Butteraugli.Error on failure. Accepts the same options.
Types
Functions
@spec cancel(Butteraugli.CancelRef.t()) :: :ok
Trip a Butteraugli.CancelRef, aborting any comparison that uses it.
Call from any process to cancel an in-flight compare/5 or
Butteraugli.Reference.compare/3 that was passed this ref as cancel:.
Returns :ok and is safe to call more than once.
@spec compare(image_data(), image_data(), pos_integer(), pos_integer(), keyword()) :: {:ok, Butteraugli.Result.t()} | {:error, reason()}
Compare a reference and distorted image of the same dimensions.
Options:
:format—:rgb888(default) or:linear_rgb.:compute_diffmap— whentrue, theResultincludes a per-pixeldiffmapbinary (defaultfalse).:intensity_target— display brightness in nits (crate default if omitted).:hf_asymmetry— high-frequency penalty asymmetry (crate default if omitted).:cancel— aButteraugli.CancelRef; cancelling it from another process aborts the call with{:error, :cancelled}.:timeout— positive integer milliseconds; the call returns{:error, :timeout}if it exceeds that.
Returns {:ok, %Butteraugli.Result{}} or {:error, reason}.
@spec compare!(image_data(), image_data(), pos_integer(), pos_integer(), keyword()) :: Butteraugli.Result.t()
Like compare/5 but returns the bare Butteraugli.Result and raises
Butteraugli.Error on failure. Accepts the same options.