AI Decision System
Replayable, offline-verifiable records for AI-assisted go/no-go decisions: experiment promotions, typed model answers and human-approved actions.
翻譯準備中
Barcode scanning library for browsers and native applications
翻譯準備中
取自儲存庫 README
正在載入完整 README。 以下為已儲存的摘錄。
Find barcodes at their own angle.
Orientation-aware barcode scanning for JavaScript, Python, Rust, C, C++ and Java.
Tapirscan’s AI-developed algorithm finds barcode regions, estimates their orientation,
and samples across the bars, including diagonally. It is built for photos and camera frames where a
clean horizontal or vertical scanline may be hard to find.檢視完整 README ↗Find barcodes at their own angle.
Orientation-aware barcode scanning for JavaScript, Python, Rust, C, C++, Java, Swift, Android and Dart.
Documentation · Try the live demo · npm · PyPI · JavaScript · Python · How it works · Compare scanners
Tapirscan’s AI-developed algorithm finds barcode regions, estimates their orientation, and samples across the bars, including diagonally. It is built for photos and camera frames where a clean horizontal or vertical scanline may be hard to find.
Supports linear and 2D barcodes, including EAN/UPC, Code 128, QR Code, Data Matrix, PDF417 and Aztec. Retail formats (EAN-13, UPC-A, EAN-8 and UPC-E) are enabled by default; select additional formats as needed. See format coverage for all formats and variants.
low, medium (default), high, or very-high.All formats below are supported in every language binding. A ✓ means the format
is included in that keyword group; — means it is not included, not unsupported.
common is the default.
| Format identifier | retail | common1D | common | 1D | 2D | all | Scope |
|---|---|---|---|---|---|---|---|
EAN13 | ✓ | ✓ | ✓ | ✓ | — | ✓ | EAN-13 |
UPCA | ✓ | ✓ | ✓ | ✓ | — | ✓ | UPC-A; normalized from zero-prefixed EAN-13 |
EAN8 | ✓ | ✓ | ✓ | ✓ | — | ✓ | EAN-8 |
UPCE | ✓ | ✓ | ✓ | ✓ | — | ✓ | UPC-E |
Code128 | — | ✓ | ✓ | ✓ | — | ✓ | Includes GS1-128 |
Code39 | — | ✓ | ✓ | ✓ | — | ✓ | Standard characters; full ASCII is Code39Extended |
ITF | — | ✓ | ✓ | ✓ | — | ✓ | Interleaved 2 of 5 |
Codabar | — | — | — | ✓ | — |
Code32, PZN, MSIPlessey, Industrial25, Pharmacode, Code39Extended, IATA25 and
Matrix25 require explicit selection; no group includes them, even all.
Python and JavaScript accept these keywords as strings, for example
formats="common" in Python or { formats: "common" } in JavaScript. Native
bindings provide equivalent constants. See format coverage
for selection syntax, variant details and EAN/UPC supplements.
Open the camera and photo demo →
Start with Pesto, choose another example, load a photo, or scan with your camera. Medium, ZXing and ZBar are enabled initially to compare the same image. Images are processed in your browser. Choose Retail, Common or other format selections to compare the readers.
| Language | Integration | Guide |
|---|---|---|
| JavaScript / TypeScript | Browser and Node, WASM included | JS/TS |
| Python | Native platform wheels; Pillow, NumPy and tensors | Python |
| Java | JDK 22+ JAR with a separate native library | Java |
| C++ | Header-only C++17 wrapper and CMake installation | C++ |
| C | Shared library with typed results and explicit buffers | C |
| Rust | Standalone Cargo package | Rust |
| Swift (iOS, macOS) | Swift package over an XCFramework; camera frames. Preview: the API may change in minor releases | Swift |
| Android (Kotlin, Java) | AAR with a JNI bridge; CameraX frames. Preview: the API may change in minor releases | Android |
| Dart / Flutter | pub.dev package for Flutter and Dart over dart:ffi. Preview: the API may change in minor releases | Dart |
Every binding offers all four effort modes of the same scanner. JavaScript, Python, Rust and Dart install from npm, PyPI, crates.io and pub.dev. Java, C, C++, Swift, Android and Dart use the native library; each GitHub release attaches it prebuilt per platform, with the AAR and the XCFramework, and the guides explain how to build it from source.
Want another language? Bindings build on the C ABI; the binding checklist lists what a new one needs.
Install Tapirscan from npm or PyPI. See the GitHub releases for release notes and downloadable packages, or build locally. Upgrading? See the migration guide.
npm install tapirscan
In a web app, tapirscan/browser/medium scans files, <img>, <video> and
canvases in a worker, with no WASM setup:
import { scan } from "tapirscan/browser/medium";
const result = await scan(file); // e.g. a File from <input type="file">
console.log(result.values); // Decoded strings, e.g. ["4006381333931"]
for (const barcode of result.barcodes) {
console.log(barcode.text, barcode.format, barcode.polygon, barcode.rect);
}
result.values contains decoded strings. result.barcodes pairs each value
with its format, four polygon corners and enclosing rectangle, in input-image
pixels. Both are empty when nothing is decoded. Use inspect instead of scan
for timing, unread regions and diagnostics. The one-shot scan starts a worker for
each call; for more than one image, create a Scanner once and reuse it.
Node and code that already has decoded pixels use the core tapirscan entry.
React, Svelte and Vite setup, camera scanning and Node loading are in the
JavaScript guide.
Install Tapirscan and Pillow to scan a photo:
pip install tapirscan pillow
from PIL import Image
import tapirscan
with Image.open("label.jpg") as image:
result = tapirscan.scan(image)
print(result.values)
for barcode in result.barcodes:
print(barcode.text, barcode.format, barcode.rect)
Defaults are Medium effort and common formats. Select exactly the formats you need,
for example formats=["EAN13", "QRCode"], or "1D", "2D" or "all"; each enabled
2D format adds work to every scan. Set mode="high" for more effort on difficult
images. For many images, create one tapirscan.Scanner(...) and call scanner.scan.
The Python guide covers TIFF images, PyTorch tensors, and array/tensor layouts, value ranges and GPU tensors. Decoding runs on CPU.
For EAN-13, the ZXing-C++ reader used by our demo primarily searches horizontal rows and, with rotation enabled, vertical rows. A tilted barcode can still work if one of those rows crosses the complete pattern.
ZBar can assemble compatible left- and right-half EAN reads from different scanlines. Tapirscan instead explicitly localizes oriented regions and samples along their geometry, with bounded retries and a small-detail recovery pass in the higher effort modes.
These are different ways of spending work on an image—not a universal speed or accuracy ranking. Read the illustrated comparison and its sources.
| Mode | When to use it |
|---|---|
low | Live camera scanning when keeping up with incoming frames matters most. |
medium | Start here: the default for photos and camera frames. |
high | Difficult images when you can spend more time on each scan. |
very-high | The largest effort budget, including subpixel recovery for small EAN-13 symbols. |
Start with medium. Try low if scanning slows down your camera preview, or
high and very-high when an image is difficult to read. Measure on your own
images and devices: higher effort does not guarantee more reads on every image.
Effort modes tune every format; see effort levels.
Speed is mostly decided by four choices: enable only the formats you need (each 2D
format adds a search of the whole image), reuse one scanner, keep medium unless
low reads your camera frames equally well, and pass decoded 8-bit pixels at the size you need (1-2 megapixel camera
frames rather than 12-megapixel stills). On 960×960 photos, Low with retail formats
takes about 5 ms per scan natively, Medium with all formats about 35-58 ms. See
fast end-to-end scanning for measured costs and the fastest
input path in browsers, Node, Python, Java, C, C++, Rust and mobile apps.
JavaScript also offers experimental Turbo presets for faster 1D scanning:
experimentalTurbo: 2 | 4 | 8 | 16. They trade difficult-image recovery for less
work. See usage and stability.
Every binding returns all decoded instances, including separate labels with the
same value, with polygons in source-image coordinates. result.best (every
binding except C) selects the read with the highest reader-specific support. Support is a ranking heuristic,
not a probability; select by format or payload when your application knows what
it expects. Wrong reads, duplicates and missed symbols remain possible.
| I want to… | Start here |
|---|---|
| Integrate in a browser or Node app | JavaScript / TypeScript |
| Deploy on a website | Browser deployment |
| Switch from another scanner | ZXing · ZBar · Quagga · html5-qrcode · flutter_zxing |
| Scan Python images and arrays | Python |
| Use another native language | Rust, C, C++, Java, Swift, Android, |
The demo is a separate application. Its photos, UI, and comparison engines are not included in the npm package or Python wheels.
Tapirscan’s scanner algorithm was written by GPT-6 Astra, guided by my goals, experiments, and hands-on testing. I directed the development, checked results, and refined the evaluation process.
Tapirscan supports the linear and 2D formats listed in format coverage.
Turbo presets, the content kinds marked experimental in
structured content, the JavaScript camera controller
(tapirscan/camera) and the Swift, Android and Dart previews may
change in minor releases. Release artifacts are published only for
platforms whose release workflows pass. No general claim of superiority over
ZXing or ZBar is made without a reproducible paired benchmark. See the
compatibility policy for API stability.
Licensed under either the MIT License or the
Apache License, Version 2.0, at your option
(MIT OR Apache-2.0), copyright © 2026 Florian Nick.
Third-party components retain their own licenses and
notices.
| ✓ |
Code93 | — | — | — | ✓ | — | ✓ |
QRCode | — | — | ✓ | — | ✓ | ✓ | Model 2; no Model 1 or rMQR |
DataMatrix | — | — | ✓ | — | ✓ | ✓ | ECC200 and DMRE |
PDF417 | — | — | — | — | ✓ | ✓ | Normal/Compact and Macro; no Micro PDF417 |
Aztec | — | — | — | — | ✓ | ✓ | Compact/full and Rune |
DataBar | — | — | — | ✓ | — | ✓ | Omnidirectional, Stacked, Stacked Omnidirectional |
DataBarExpanded | — | — | — | ✓ | — | ✓ | Expanded and Expanded Stacked |
MaxiCode | — | — | — | — | ✓ | ✓ | Modes 2–6 |
Code32 | — | — | — | — | — | — | Opt-in: Italian pharmacy number |
PZN | — | — | — | — | — | — | Opt-in: German PZN8/PZN7 |
MSIPlessey | — | — | — | — | — | — | Opt-in: mod-10 check digit required |
Industrial25 | — | — | — | — | — | — | Opt-in: Industrial (Standard) 2 of 5 |
Pharmacode | — | — | — | — | — | — | Opt-in: Laetus one-track Pharmacode |
DataBarLimited | — | — | — | ✓ | — | ✓ |
MicroQRCode | — | — | — | — | ✓ | ✓ | M1–M4 |
Code39Extended | — | — | — | — | — | — | Opt-in: full-ASCII Code 39 |
IATA25 | — | — | — | — | — | — | Opt-in: IATA 2 of 5 |
Matrix25 | — | — | — | — | — | — | Opt-in: Matrix 2 of 5 |
| Choose formats | Format coverage |
| Make scanning fast | Fast end-to-end scanning |
| Understand the scanner | Comparison · Architecture |
| Evaluate performance fairly | Benchmark guide |
| Build or contribute | Development · Contributing |