CI Hex.pm HexDocs License: MIT

rxing decodes barcodes from image binaries using a source-built Rustler NIF powered by the Rust rxing crate.

Installation

def deps do
  [
    {:rxing, "~> 0.1.0"}
  ]
end

rxing compiles its native library from source when the dependency is compiled. Install Rust 1.91 or newer (rustc and cargo) before running mix compile.

Immediate Example (binary input)

image = File.read!("path/to/barcode.png")

{:ok, [%Rxing.Result{format: :qr_code} | _results]} =
  Rxing.decode(image, formats: [:qr_code])

Public APIs

Rxing exposes three decoding entry points:

All APIs share the same option vocabulary and stable error vocabulary.

Decoding Binaries, One Result, and Files

image = File.read!("path/to/barcodes.png")

# Decode every result up to the configured bound.
{:ok, results} =
  Rxing.decode(image, formats: [:qr_code, :data_matrix], max_results: 32)

# Decode only the first result.
{:ok, first} = Rxing.decode_one(image, formats: [:qr_code, :data_matrix])
%Rxing.Result{} = first

# Let Rxing read a regular file after applying the input-size pre-check.
{:ok, file_results} =
  Rxing.decode_file("path/to/barcodes.png", formats: [:qr_code, :data_matrix])

results and file_results are lists of %Rxing.Result{} values in upstream detection order. When no barcode is recognized, decoding returns {:ok, []}.

Supported Barcode Formats

Rxing.formats/0 returns the guaranteed format set in stable order:

  • :qr_code
  • :data_matrix
  • :code_128
  • :ean_13

Supported Image Encodings

The binary API accepts these content-detectable formats from image 0.25:

  • BMP
  • DDS
  • OpenEXR
  • farbfeld
  • GIF
  • HDR
  • ICO
  • JPEG
  • PNG
  • PNM
  • QOI
  • TIFF
  • WebP

Committed integration fixtures guarantee representative decoding coverage for PNG, JPEG, GIF, BMP, and WebP. Other enabled encodings use the same content-based classification and decoding pipeline.

AVIF and TGA are not accepted by the current binary-only pipeline: AVIF decoding requires the separate image/avif-native feature, while image::guess_format cannot identify TGA without a filename extension.

Options, Filtering, and Defaults

Public options:

  • :formats (default: [:qr_code, :data_matrix, :code_128, :ean_13])
  • :try_harder (default: false)
  • :try_inverted (default: false)
  • :max_results (default: 32, allowed range 1..256)
  • :max_input_bytes (default: 20 * 1024 * 1024)
  • :max_width (default: 10_000)
  • :max_height (default: 10_000)
  • :max_pixels (default: 40_000_000)
  • :max_alloc_bytes (default: 256 * 1024 * 1024)

Filtering examples:

  • Restrict formats: formats: [:qr_code]
  • Enable rotated scan retries: try_harder: true
  • Enable inverted scan retries: try_inverted: true
  • Raise result bound for dense images: max_results: 64

Stable Errors

Decode operations return:

  • {:error, :invalid_image}
  • {:error, :internal_error}
  • {:error, {:unsupported_format, format}}
  • {:error, {:invalid_option, key}}
  • {:error, {:limit_exceeded, limit}}
  • {:error, {:file, reason}} (decode_file/2)
  • {:error, :not_found} (decode_one/2)

Result Payload, Raw Bytes, and Metadata

Every successful decode returns %Rxing.Result{} values:

  • :format - one of the supported barcode format atoms.
  • :text - decoded UTF-8 text when available, else nil.
  • :raw_bytes - raw decoded bytes when available, else nil.
  • :points - list of %{x: float(), y: float()} result points.
  • :metadata - decoder metadata map. Supported keys include: :orientation, :byte_segments, :error_correction_level, :structured_append_sequence, :structured_append_parity, :symbology_identifier, :is_inverted, and :is_mirrored.

Runtime and Concurrency Notes

  • Native decoding runs on dirty CPU schedulers to avoid monopolizing normal BEAM schedulers.
  • Callers remain responsible for choosing safe request-level concurrency and backpressure limits.

Source Build Requirements and Platforms

  • Elixir: ~> 1.15.
  • Tested runtime pairs: Elixir 1.15.8 / OTP 26 and Elixir 1.20 / OTP 29.
  • Rust toolchain: rustc/cargo 1.91 or newer.
  • The native crate is built from source during dependency compilation.
  • Supported CI platforms: Linux and macOS.

Benchmarks

From a repository checkout with development dependencies installed, run:

mix run bench/rxing_bench.exs

The non-gating Benchee report includes throughput, median, p95, and p99 latency, BEAM memory, scheduler counts, run-queue snapshots, and heartbeat observations. It covers the guaranteed barcode formats, clean/rotated/inverted/damaged/multiple and no-code scenarios, an image-size sweep, and concurrency levels 1 through 32.

Treat the output as a baseline for comparisons made on the same host and toolchain. It deliberately contains no pass/fail latency thresholds or portable speed claims.

Non-goals (0.1.0)

  • Barcode encoding/generation APIs.
  • Precompiled NIF artifacts in Hex packages.
  • Alternative native backends beyond Rust rxing.

License

MIT. See LICENSE.