Skip to content

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

2 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

barq

Generate and scan barcodes — as a desktop app, a command-line tool, and a JSON API on localhost. Same engine behind all three.

payload ──encode──▶ Symbol ──layout──▶ Scene ──render──▶ bytes
                 (modules)         (geometry)      (svg / pdf / eps / png / …)

What it does

Encodes 14 symbologies

Matrix QR Code, Data Matrix, Aztec
Stacked PDF417
Retail EAN-13, EAN-8, UPC-A, UPC-E
Logistics & general Code 128, Code 39, Code 93, Interleaved 2 of 5, Codabar, Telepen

Data Matrix is the small square-or-rectangular block code with the solid L-shaped edge — the one on circuit boards and pharmaceutical packaging.

Decodes those plus MaxiCode, Micro QR, Rectangular Micro QR, GS1 DataBar, GS1 DataBar Expanded and DX Film Edge.

Outputs SVG, PDF, EPS, PNG, WebP, GIF, JPEG, BMP, TIFF, the raw module matrix as JSON, and three terminal renderings (ASCII, Unicode half-blocks, and 24-bit ANSI colour).

Reads from PNG, JPEG, GIF, WebP, BMP, TIFF, raw camera frames, drag-and-drop, and the clipboard.

Install

cargo build --release            # CLI at target/release/barq
cargo tauri build                # desktop app
cargo tauri dev                  # desktop app, live-reloading

Linux needs the usual WebKitGTK development packages for the desktop app (webkit2gtk-4.1, libsoup-3.0, gtk3). The CLI and the API need none of them.

Command line

# straight into your terminal
barq encode "https://example.com"

# a styled PNG
barq encode "https://example.com" -o code.png --preset ocean --scale 12

# a retail barcode; the check digit is calculated for you
barq encode 590123412345 -s ean13 -o label.svg

# Data Matrix for a small part, forced square
barq encode "PART-40219-REV-C" -s data_matrix --dm-shape square -o part.eps

# print-ready vector with a caption
barq encode "SHIP-1029384" -s code128 -o ship.pdf --frame 3 --caption "Crate 12 of 40"

# read one back
barq decode code.png
barq decode photo.jpg --json | jq -r '.results[].text'
cat screenshot.png | barq decode -

# what's supported
barq formats
barq formats data_matrix
barq presets

The output format is taken from the flag, or the file extension, or — when writing to a terminal — Unicode blocks. - means stdin/stdout.

Styling flags
--preset classic|soft|dots|fluid|midnight|sunset|ocean|thermal
--fg COLOR --bg COLOR              # hex, rgb(), CSS name, or `transparent`
--gradient A,B[,ANGLE]
--shape square|rounded|circle|dot|diamond|squircle|cross|star|fluid|horizontal|vertical
--gap 0.05 --radius 0.3            # fractions of a module
--finder-shape match|square|rounded|circle|leaf
--finder-ring COLOR --finder-center COLOR
--logo logo.png --logo-scale 0.2
--scale 12 --quiet-zone 4 --bar-height 60
--rotate 90|180|270 --invert
--no-hri --hri-size 7 --hri-font Courier
--frame 3 --caption "Product name"
--style-json '{"module_gap":0.08}'  # or @file.json — everything the API takes

Style flags merge over the preset, so --preset ocean --gap 0.1 keeps Ocean's gradient and squircles and changes only the gap.

JSON API

Runs on 127.0.0.1:8731 — started by the desktop app automatically, or by barq serve from the command line.

barq serve
barq serve --port 9000 --token "$(openssl rand -hex 16)"
Route Purpose
GET /healthz liveness; never requires a token
GET /v1/capabilities every symbology, format, preset and shape this build supports
GET /v1/symbologies just the symbology catalogue
GET /v1/encode?data=… an image straight from a URL
POST /v1/encode full request → JSON with metrics, warnings and a data URL
POST /v1/encode/raw full request → the image bytes
POST /v1/decode {"image": "<base64 or data URL>"} or a raw frame
POST /v1/decode/raw an image as the request body
# quick
curl "http://127.0.0.1:8731/v1/encode?data=hello&format=png&scale=8&fg=%230e6ba8" -o code.png

# full
curl -X POST http://127.0.0.1:8731/v1/encode \
  -H 'content-type: application/json' \
  -d '{
        "data": "https://example.com",
        "symbology": "qr",
        "options": { "ecc": "H" },
        "preset": "ocean",
        "style": { "scale": 12, "module_gap": 0.06 },
        "output": { "format": "svg" }
      }'

# read
curl -X POST --data-binary @photo.jpg http://127.0.0.1:8731/v1/decode/raw

The desktop app's Request panel shows the exact JSON behind whatever is on screen — paste it into curl and you get the same bytes.

Security posture

  • Binds loopback only by default. --host can change that, and warns when you do.
  • No path parameter anywhere: encode returns bytes, decode accepts bytes. Path traversal and arbitrary file reads are not filtered for — they are absent.
  • --token requires Authorization: Bearer … on every route except /healthz, compared in constant time. Worth setting on a shared machine: loopback is not a trust boundary, and a browser page can reach it cross-origin.
  • Request bodies are capped at 48 MB; output is capped at 20 000 px per side and 64 Mpx.

Desktop app

Two modes, Create and Scan.

Create gives you live preview, every styling control the engine has, a scannability readout, and export to any format. Scan takes a dropped file, a pasted image, a file picker, or the camera — with continuous decoding of the video stream.

Camera capture needs getUserMedia, which is reliable on macOS and Windows; on Linux it depends on how your WebKitGTK was built. Drop, paste and file picking always work.

Design notes

One geometry, four backends. layout turns a symbol and a style into a Scene — a small vector scene of filled paths, images and text. SVG, PDF and EPS are written directly from it, and the rasterisers go through the SVG writer and resvg. That is why a PNG matches its SVG exactly, and why the test suite can assert that all four agree on the page size.

Gradients resolve per module. Rather than emitting gradient definitions each backend implements differently, the layout stage samples the paint at each module's centre. Every backend then only has to fill a shape with one solid colour. At module scale the result is indistinguishable from a continuous gradient, and all four outputs agree.

Styling is bounded by what still scans. Module shapes never leave their cell, so a decoder sampling the centre always hits ink. Options that a symbology cannot survive are dropped rather than honoured: reshaped modules on a linear barcode, a logo on Aztec, gaps on PDF417. What remains is checked and reported — contrast below 3:1, inverted polarity, an undersized quiet zone, a logo too large for the error-correction level.

No embedded fonts. Human-readable text uses the base-14 fonts, which PDF and PostScript already have. The width tables in text.rs are what let those two backends centre a string themselves, and what lets the layout widen a quiet zone when EAN's outset digits would not otherwise fit.

Layout

crates/barq-core/     the engine — encode, style, layout, render, decode
crates/barq-api/      axum router for the JSON API
crates/barq-cli/      the `barq` binary
src-tauri/            desktop app: Tauri commands + the bundled API server
ui/                   the window (no framework, no build step)

barq-core has no async, no HTTP and no GUI dependency; it is usable as a library on its own.

Continuous integration

.github/workflows/ci.yml runs on every push and pull request:

  • core / api / cli on Linux, macOS and Windows — build, test, and a smoke test that encodes a code with the real binary and decodes it back.
  • vector cross-check — installs Ghostscript and librsvg so the cross-renderer tests actually execute rather than skipping themselves.
  • desktop app on all three platforms, with the WebKitGTK toolchain on Linux.

.github/workflows/release.yml fires on a v* tag: it builds the CLI for four targets, verifies each binary encodes and decodes before upload, bundles the desktop app, and publishes everything with checksums. Anything tagged alpha, beta or rc is marked as a pre-release.

Design language

The interface follows the RAGBAZ design system tokens verbatim: a warm solarized-dark ground (#0f0f10 through #1a1a1a with a warm-tinted elevated surface), orange ember as the primary (#ff9900 hot, #f3c46c signature), cyan-blue as the secondary, and gruvbox semantics for success, warning and error. Radii are square-leaning — 0px is the default and rounding is reserved for buttons and pills. Borders carry the structure; shadows are kept minimal.

The system is dark-first and defines no light palette, so the app follows suit rather than inventing one.

Type roles come from the same tokens:

Role Family Used for
mono Intel One Mono labels, eyebrows, data, numerics, controls, code
sans Noto Sans structure and UI copy
serif Noto Serif prose — descriptions, notes, explanations

All three are bundled as Latin-subset variable WOFF2, 91 KB for the set. See ui/fonts/.

Note that the generated symbols still default to black on white regardless of the interface theme: a barcode's job is to scan, and dark-on-light is what scanners want. The ragbaz preset puts the brand into the finder eyes while keeping the data modules at full contrast.

Tests

cargo test --workspace

The suite renders every symbology through every output format and scans the result back, including through third-party renderers (Ghostscript for PDF and EPS, librsvg for SVG) — so a geometry bug in a backend fails the build rather than shipping as an unreadable label.

Licence

GPL-2.0-or-later — GNU General Public License version 2, or (at your option) any later version. The v2 text is in COPYING.

Why "or later" specifically

barq links rxing, a Rust port of ZXing, which is Apache-2.0 only. The FSF considers Apache-2.0 incompatible with GPL-2.0-only: its patent-termination clause is an additional restriction that GPLv2 section 6 does not permit.

The "or later" option resolves it. Apache-2.0 is GPLv3-compatible, so anyone distributing a combined binary can take the v3 option and the conflict does not arise. This is the same reason most GPL projects with modern dependencies are "or later" rather than version-locked.

Every other dependency offers an MIT or BSD option and is GPLv2-compatible:

Crate Licence
rxing, rxing-one-d-proc-derive Apache-2.0 — GPLv3-compatible, hence "or later"
image, resvg, usvg, tauri, clap, serde, flate2, base64 MIT OR Apache-2.0
axum, tokio, tower-http MIT
tiny-skia BSD-3-Clause
encoding_rs (Apache-2.0 OR MIT) AND BSD-3-Clause

The bundled Montserrat and Merriweather typefaces are SIL Open Font License 1.1; see ui/fonts/. The OFL permits redistribution alongside software of any licence and does not affect barq's terms.

About

Generate and scan QR, Data Matrix, Aztec, PDF417 and EAN/UPC barcodes — desktop app, CLI and localhost JSON API. SVG, PDF, EPS, PNG, WebP, GIF and terminal output.

Topics

Resources

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Used by

Contributors

Languages