Current section
Files
Jump to
Current section
Files
README.md
# Rxing
[](https://github.com/ivan-podgurskiy/rxing/actions/workflows/ci.yml)
[](https://hex.pm/packages/rxing)
[](https://hexdocs.pm/rxing)
[](LICENSE)
`rxing` decodes barcodes from image binaries using a source-built Rustler NIF
powered by the Rust `rxing` crate.
## Installation
```elixir
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)
```elixir
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:
- `Rxing.decode/2` decodes every supported barcode in an image binary.
- `Rxing.decode_one/2` decodes the first supported barcode or returns `{:error, :not_found}`.
- `Rxing.decode_file/2` reads an image from a path and decodes it.
All APIs share the same option vocabulary and stable error vocabulary.
## Decoding Binaries, One Result, and Files
```elixir
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:
```console
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](LICENSE).