@sythos/js_barcode_universal 1.2.5 → 1.4.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/AI_USAGE.md +33 -0
- package/LICENSE +11 -2
- package/NOTICE.md +10 -4
- package/README.md +601 -465
- package/bundle/sythos-barcode.esm.js +4669 -74
- package/bundle/sythos-barcode.js +4575 -72
- package/examples/create.html +1010 -730
- package/examples/read.html +1 -0
- package/licenses/README.md +40 -58
- package/licenses/aztec-code.license +15 -13
- package/licenses/aztec-rune.license +76 -0
- package/licenses/codabar.license +18 -15
- package/licenses/code-11.license +11 -9
- package/licenses/code-128.license +10 -8
- package/licenses/code-39.license +10 -8
- package/licenses/code-93.license +16 -14
- package/licenses/compact-pdf417.license +76 -0
- package/licenses/data-matrix.license +15 -13
- package/licenses/ean-13.license +10 -8
- package/licenses/ean-2.license +74 -0
- package/licenses/ean-5.license +74 -0
- package/licenses/ean-8.license +10 -8
- package/licenses/frameqr.license +84 -0
- package/licenses/gs1-128.license +10 -8
- package/licenses/gs1-databar.license +81 -0
- package/licenses/isbn.license +10 -8
- package/licenses/itf-14.license +10 -8
- package/licenses/itf.license +9 -7
- package/licenses/micro-qr.license +79 -0
- package/licenses/micropdf417.license +52 -67
- package/licenses/msi-plessey.license +13 -11
- package/licenses/pdf417.license +78 -37
- package/licenses/pharmacode.license +14 -12
- package/licenses/qr-code.license +9 -7
- package/licenses/rmqr.license +79 -0
- package/licenses/upc-a.license +12 -10
- package/licenses/upc-e.license +10 -8
- package/package.json +109 -88
- package/src/aztec/decoder.js +1 -0
- package/src/aztec/detector.js +1 -0
- package/src/aztec/encoder.js +1 -0
- package/src/aztec/high-level.js +1 -0
- package/src/aztec/index.js +1 -0
- package/src/aztec/tables.js +1 -0
- package/src/aztecrune/decoder.js +156 -0
- package/src/aztecrune/detector.js +167 -0
- package/src/aztecrune/encoder.js +122 -0
- package/src/aztecrune/index.js +50 -0
- package/src/aztecrune/tables.js +138 -0
- package/src/compactpdf417/decoder.js +129 -0
- package/src/compactpdf417/detector.js +140 -0
- package/src/compactpdf417/encoder.js +141 -0
- package/src/compactpdf417/index.js +22 -0
- package/src/compactpdf417/tables.js +174 -0
- package/src/core/bit-buffer.js +1 -0
- package/src/core/bit-matrix.js +1 -0
- package/src/core/errors.js +1 -0
- package/src/core/galois-field.js +1 -0
- package/src/core/index.js +1 -0
- package/src/core/reed-solomon.js +1 -0
- package/src/databar/codec.js +182 -0
- package/src/databar/decoder.js +115 -0
- package/src/databar/encoder.js +97 -0
- package/src/databar/gs1.js +178 -0
- package/src/databar/index.js +69 -0
- package/src/databar/patterns.js +144 -0
- package/src/databar/tables.js +125 -0
- package/src/datamatrix/decoder.js +263 -262
- package/src/datamatrix/detector.js +226 -225
- package/src/datamatrix/encoder.js +192 -191
- package/src/datamatrix/index.js +43 -42
- package/src/datamatrix/tables.js +124 -123
- package/src/frameqr/decoder.js +240 -0
- package/src/frameqr/detector.js +193 -0
- package/src/frameqr/encoder.js +157 -0
- package/src/frameqr/index.js +43 -0
- package/src/frameqr/tables.js +271 -0
- package/src/image/binarizer.js +1 -0
- package/src/image/grid-sampler.js +1 -0
- package/src/image/index.js +1 -0
- package/src/image/luminance.js +1 -0
- package/src/image/perspective.js +1 -0
- package/src/index.js +155 -2
- package/src/micropdf417/compaction.js +1 -0
- package/src/micropdf417/decoder.js +1 -0
- package/src/micropdf417/detector.js +1 -0
- package/src/micropdf417/encoder.js +1 -0
- package/src/micropdf417/error-correction.js +1 -0
- package/src/micropdf417/index.js +1 -0
- package/src/micropdf417/tables.js +1 -0
- package/src/microqr/decoder.js +246 -0
- package/src/microqr/detector.js +356 -0
- package/src/microqr/encoder.js +270 -0
- package/src/microqr/index.js +37 -0
- package/src/microqr/tables.js +317 -0
- package/src/oned/addons.js +421 -0
- package/src/oned/index.js +77 -59
- package/src/oned/patterns.js +1 -0
- package/src/oned/reader.js +1 -0
- package/src/oned/writers.js +1 -0
- package/src/pdf417/compaction.js +1 -0
- package/src/pdf417/decoder.js +1 -0
- package/src/pdf417/detector.js +1 -0
- package/src/pdf417/encoder.js +1 -0
- package/src/pdf417/error-correction.js +1 -0
- package/src/pdf417/index.js +5 -0
- package/src/pdf417/tables.js +1 -0
- package/src/qr/decoder.js +1 -0
- package/src/qr/detector.js +1 -0
- package/src/qr/encoder.js +1 -0
- package/src/qr/index.js +1 -0
- package/src/qr/tables.js +1 -0
- package/src/render/image-data.js +1 -0
- package/src/render/index.js +1 -0
- package/src/render/options.js +1 -0
- package/src/render/png.js +1 -0
- package/src/render/svg.js +1 -0
- package/src/render/webgl.js +1 -0
- package/src/render/webgpu.js +1 -0
- package/src/rmqr/decoder.js +102 -0
- package/src/rmqr/detector.js +91 -0
- package/src/rmqr/encoder.js +173 -0
- package/src/rmqr/index.js +38 -0
- package/src/rmqr/tables.js +155 -0
package/README.md
CHANGED
|
@@ -1,277 +1,297 @@
|
|
|
1
|
-
# Sythos Barcode Suite
|
|
2
|
-
|
|
3
|
-
Read and write barcodes in JavaScript.
|
|
4
|
-
|
|
5
|
-
[](https://www.npmjs.com/package/@sythos/js_barcode_universal)
|
|
6
|
-
[](LICENSE)
|
|
7
|
-
[](package.json)
|
|
8
|
-
|
|
1
|
+
# Sythos Barcode Suite and SDK
|
|
2
|
+
|
|
3
|
+
Read and write barcodes in JavaScript.
|
|
4
|
+
|
|
5
|
+
[](https://www.npmjs.com/package/@sythos/js_barcode_universal)
|
|
6
|
+
[](LICENSE)
|
|
7
|
+
[](package.json)
|
|
8
|
+
[](https://nodejs.org/api/esm.html)
|
|
9
|
+
[](https://www.npmjs.com/package/@sythos/js_barcode_universal)
|
|
10
|
+
|
|
11
|
+
[](https://www.npmjs.com/package/@sythos/js_barcode_universal)
|
|
12
|
+
[](https://github.com/Sythos/JS_Barcode_Universal/commits/main/)
|
|
13
|
+
[](https://github.com/Sythos/JS_Barcode_Universal/issues)
|
|
14
|
+
|
|
9
15
|
Original Sythos implementation, zero runtime dependencies, MIT. It runs unmodified in Node, in browsers
|
|
10
|
-
(including Safari on iOS) and in web workers. The core requires no canvas, no filesystem and no
|
|
11
|
-
DOM — images go in and come out as plain `{ data, width, height }` RGBA objects, which is exactly
|
|
12
|
-
what an `ImageData` is.
|
|
13
|
-
|
|
14
|
-
**The code is complete and entirely human-readable.** The full source ships. There is no
|
|
15
|
-
WebAssembly, no native addon, no compiled artefact, no binary blob and no minified file anywhere
|
|
16
|
-
in this repository — every tracked file is text you can open and read.
|
|
17
|
-
|
|
18
|
-
That includes the prebuilt bundles. They are *generated*, concatenated and wrapped from `src/` by
|
|
19
|
-
the project's own bundler, but nothing is stripped in the process:
|
|
20
|
-
[`bundle/sythos-barcode.js`](bundle/sythos-barcode.js) runs to roughly 7,900 lines, about a third
|
|
21
|
-
of them comments, averaging a little over 30 characters a line. Open it anywhere and you are
|
|
22
|
-
reading the same annotated code as the source, in the same order — a convenience, not a black box.
|
|
23
|
-
|
|
24
|
-
Don't take that on trust either; it takes one command:
|
|
25
|
-
|
|
26
|
-
```sh
|
|
27
|
-
awk '{ n += length($0) } END { print "lines:", NR, " avg length:", int(n/NR) }' bundle/sythos-barcode.js
|
|
28
|
-
```
|
|
29
|
-
|
|
30
|
-
A minified bundle gives you a handful of lines averaging thousands of characters. This one does
|
|
31
|
-
not, and that is the whole point.
|
|
32
|
-
|
|
33
|
-
This is deliberate. A barcode library decides what a scanner believes a label says, so it belongs
|
|
34
|
-
in the category of code you can audit rather than have to trust. Every constant table, every
|
|
35
|
-
check digit and every error-correction step is here in full, with the reasoning next to it.
|
|
36
|
-
|
|
37
|
-
```js
|
|
38
|
-
import { encode, decode, toSVG, toImageData } from './src/index.js';
|
|
39
|
-
|
|
40
|
-
const matrix = encode('https://example.com', { format: 'qr', ecc: 'M' });
|
|
41
|
-
const svg = toSVG(matrix, { scale: 8 });
|
|
42
|
-
|
|
43
|
-
const found = decode(toImageData(matrix, { scale: 4 }), { formats: ['qr'] });
|
|
44
|
-
console.log(found[0].text); // 'https://example.com'
|
|
45
|
-
```
|
|
46
|
-
|
|
47
|
-
---
|
|
48
|
-
|
|
49
|
-
## Quick start
|
|
50
|
-
|
|
51
|
-
There are four ways in, and none of them needs a build step.
|
|
52
|
-
|
|
53
|
-
### 1. npm
|
|
54
|
-
|
|
55
|
-
```sh
|
|
56
|
-
npm install @sythos/js_barcode_universal
|
|
57
|
-
```
|
|
58
|
-
|
|
59
|
-
`yarn add @sythos/js_barcode_universal` and `pnpm add @sythos/js_barcode_universal` do the same thing. Nothing is installed
|
|
60
|
-
alongside it — there are no runtime dependencies, no postinstall script and no native build. The
|
|
61
|
-
package is plain ESM (`"type": "module"`) and asks for Node 18 or newer.
|
|
62
|
-
|
|
63
|
-
```js
|
|
64
|
-
import { encode, decode, toSVG, toImageData } from '@sythos/js_barcode_universal';
|
|
65
|
-
|
|
66
|
-
const code = encode('SYT-2026-0042', { format: 'code128' });
|
|
67
|
-
|
|
68
|
-
const svg = toSVG(code, { scale: 2, margin: 10, barHeight: 60 });
|
|
69
|
-
// '<svg xmlns="http://www.w3.org/2000/svg" width="374" height="100" …'
|
|
70
|
-
|
|
71
|
-
const found = decode(toImageData(code, { scale: 4, margin: 10 }), { formats: ['code128'] });
|
|
72
|
-
console.log(found[0].text); // 'SYT-2026-0042'
|
|
73
|
-
```
|
|
74
|
-
|
|
75
|
-
**Subpath exports** hand you one layer instead of the whole surface, which is what lets a
|
|
76
|
-
tree-shaking bundler drop everything you did not ask for. Importing only the QR writer and only
|
|
77
|
-
the SVG renderer never pulls in the 1D formats, the PNG encoder or the read pipeline:
|
|
78
|
-
|
|
79
|
-
```js
|
|
80
|
-
import { encodeQR } from '@sythos/js_barcode_universal/qr';
|
|
81
|
-
import { toSVG } from '@sythos/js_barcode_universal/render/svg';
|
|
82
|
-
|
|
83
|
-
const svg = toSVG(encodeQR('https://example.com', { ecc: 'M' }), { scale: 8 });
|
|
84
|
-
// a 25×25 module symbol — 264×264 px at scale 8 with the default 4-module quiet zone
|
|
85
|
-
```
|
|
86
|
-
|
|
87
|
-
| Subpath | What it exports |
|
|
88
|
-
|---|---|
|
|
89
|
-
| `@sythos/js_barcode_universal` | The whole surface: `encode`, `decode`, every renderer, every error type |
|
|
90
|
-
| `@sythos/js_barcode_universal/core` | `BitMatrix`, `GaloisField`, Reed–Solomon, the error classes |
|
|
91
|
-
| `@sythos/js_barcode_universal/image` | `LuminanceSource`, the binarizers, grid sampling, `PerspectiveTransform` |
|
|
92
|
-
| `@sythos/js_barcode_universal/oned` | The per-format 1D writers (`encodeEAN13`, `encodeCode128`, …) and `decodeOneD` |
|
|
93
|
-
| `@sythos/js_barcode_universal/qr` | `encodeQR`, `decodeQR`, `detectQR`, `detectAndDecodeQR` |
|
|
16
|
+
(including Safari on iOS) and in web workers. The core requires no canvas, no filesystem and no
|
|
17
|
+
DOM — images go in and come out as plain `{ data, width, height }` RGBA objects, which is exactly
|
|
18
|
+
what an `ImageData` is.
|
|
19
|
+
|
|
20
|
+
**The code is complete and entirely human-readable.** The full source ships. There is no
|
|
21
|
+
WebAssembly, no native addon, no compiled artefact, no binary blob and no minified file anywhere
|
|
22
|
+
in this repository — every tracked file is text you can open and read.
|
|
23
|
+
|
|
24
|
+
That includes the prebuilt bundles. They are *generated*, concatenated and wrapped from `src/` by
|
|
25
|
+
the project's own bundler, but nothing is stripped in the process:
|
|
26
|
+
[`bundle/sythos-barcode.js`](bundle/sythos-barcode.js) runs to roughly 7,900 lines, about a third
|
|
27
|
+
of them comments, averaging a little over 30 characters a line. Open it anywhere and you are
|
|
28
|
+
reading the same annotated code as the source, in the same order — a convenience, not a black box.
|
|
29
|
+
|
|
30
|
+
Don't take that on trust either; it takes one command:
|
|
31
|
+
|
|
32
|
+
```sh
|
|
33
|
+
awk '{ n += length($0) } END { print "lines:", NR, " avg length:", int(n/NR) }' bundle/sythos-barcode.js
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
A minified bundle gives you a handful of lines averaging thousands of characters. This one does
|
|
37
|
+
not, and that is the whole point.
|
|
38
|
+
|
|
39
|
+
This is deliberate. A barcode library decides what a scanner believes a label says, so it belongs
|
|
40
|
+
in the category of code you can audit rather than have to trust. Every constant table, every
|
|
41
|
+
check digit and every error-correction step is here in full, with the reasoning next to it.
|
|
42
|
+
|
|
43
|
+
```js
|
|
44
|
+
import { encode, decode, toSVG, toImageData } from './src/index.js';
|
|
45
|
+
|
|
46
|
+
const matrix = encode('https://example.com', { format: 'qr', ecc: 'M' });
|
|
47
|
+
const svg = toSVG(matrix, { scale: 8 });
|
|
48
|
+
|
|
49
|
+
const found = decode(toImageData(matrix, { scale: 4 }), { formats: ['qr'] });
|
|
50
|
+
console.log(found[0].text); // 'https://example.com'
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
---
|
|
54
|
+
|
|
55
|
+
## Quick start
|
|
56
|
+
|
|
57
|
+
There are four ways in, and none of them needs a build step.
|
|
58
|
+
|
|
59
|
+
### 1. npm
|
|
60
|
+
|
|
61
|
+
```sh
|
|
62
|
+
npm install @sythos/js_barcode_universal
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
`yarn add @sythos/js_barcode_universal` and `pnpm add @sythos/js_barcode_universal` do the same thing. Nothing is installed
|
|
66
|
+
alongside it — there are no runtime dependencies, no postinstall script and no native build. The
|
|
67
|
+
package is plain ESM (`"type": "module"`) and asks for Node 18 or newer.
|
|
68
|
+
|
|
69
|
+
```js
|
|
70
|
+
import { encode, decode, toSVG, toImageData } from '@sythos/js_barcode_universal';
|
|
71
|
+
|
|
72
|
+
const code = encode('SYT-2026-0042', { format: 'code128' });
|
|
73
|
+
|
|
74
|
+
const svg = toSVG(code, { scale: 2, margin: 10, barHeight: 60 });
|
|
75
|
+
// '<svg xmlns="http://www.w3.org/2000/svg" width="374" height="100" …'
|
|
76
|
+
|
|
77
|
+
const found = decode(toImageData(code, { scale: 4, margin: 10 }), { formats: ['code128'] });
|
|
78
|
+
console.log(found[0].text); // 'SYT-2026-0042'
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
**Subpath exports** hand you one layer instead of the whole surface, which is what lets a
|
|
82
|
+
tree-shaking bundler drop everything you did not ask for. Importing only the QR writer and only
|
|
83
|
+
the SVG renderer never pulls in the 1D formats, the PNG encoder or the read pipeline:
|
|
84
|
+
|
|
85
|
+
```js
|
|
86
|
+
import { encodeQR } from '@sythos/js_barcode_universal/qr';
|
|
87
|
+
import { toSVG } from '@sythos/js_barcode_universal/render/svg';
|
|
88
|
+
|
|
89
|
+
const svg = toSVG(encodeQR('https://example.com', { ecc: 'M' }), { scale: 8 });
|
|
90
|
+
// a 25×25 module symbol — 264×264 px at scale 8 with the default 4-module quiet zone
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
| Subpath | What it exports |
|
|
94
|
+
|---|---|
|
|
95
|
+
| `@sythos/js_barcode_universal` | The whole surface: `encode`, `decode`, every renderer, every error type |
|
|
96
|
+
| `@sythos/js_barcode_universal/core` | `BitMatrix`, `GaloisField`, Reed–Solomon, the error classes |
|
|
97
|
+
| `@sythos/js_barcode_universal/image` | `LuminanceSource`, the binarizers, grid sampling, `PerspectiveTransform` |
|
|
98
|
+
| `@sythos/js_barcode_universal/oned` | The per-format 1D writers (`encodeEAN13`, `encodeCode128`, …) and `decodeOneD` |
|
|
99
|
+
| `@sythos/js_barcode_universal/qr` | `encodeQR`, `decodeQR`, `detectQR`, `detectAndDecodeQR` |
|
|
94
100
|
| `@sythos/js_barcode_universal/datamatrix` | `encodeDataMatrix`, `decodeDataMatrix`, `detectDataMatrix`, `detectAndDecodeDataMatrix` |
|
|
95
101
|
| `@sythos/js_barcode_universal/aztec` | `encodeAztec`, `decodeAztec`, `detectAztec`, `detectAndDecodeAztec` |
|
|
102
|
+
| `@sythos/js_barcode_universal/aztecrune` | `encodeAztecRune`, `decodeAztecRune`, `detectAztecRune`, `detectAndDecodeAztecRune` |
|
|
96
103
|
| `@sythos/js_barcode_universal/pdf417` | `encodePDF417`, `decodePDF417`, `detectPDF417`, `detectAndDecodePDF417` |
|
|
104
|
+
| `@sythos/js_barcode_universal/compactpdf417` | `encodeCompactPDF417`, `decodeCompactPDF417`, `detectCompactPDF417`, `detectAndDecodeCompactPDF417` |
|
|
105
|
+
| `@sythos/js_barcode_universal/databar` | GS1 DataBar GTIN/AI codecs plus Omnidirectional/Truncated physical helpers |
|
|
97
106
|
| `@sythos/js_barcode_universal/micropdf417` | `encodeMicroPDF417`, `decodeMicroPDF417`, `detectMicroPDF417`, `detectAndDecodeMicroPDF417` |
|
|
98
|
-
| `@sythos/js_barcode_universal/
|
|
99
|
-
| `@sythos/js_barcode_universal/
|
|
100
|
-
| `@sythos/js_barcode_universal/
|
|
101
|
-
| `@sythos/js_barcode_universal/render
|
|
102
|
-
| `@sythos/js_barcode_universal/
|
|
103
|
-
| `@sythos/js_barcode_universal/
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
var
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
const
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
|
200
|
-
|
|
201
|
-
|
|
|
202
|
-
|
|
|
203
|
-
|
|
|
204
|
-
|
|
|
205
|
-
|
|
|
206
|
-
| Code
|
|
207
|
-
|
|
|
208
|
-
|
|
|
209
|
-
|
|
|
210
|
-
|
|
|
211
|
-
|
|
|
212
|
-
|
|
|
213
|
-
|
|
|
214
|
-
|
|
|
107
|
+
| `@sythos/js_barcode_universal/microqr` | `encodeMicroQR`, `decodeMicroQR`, `detectMicroQR`, `detectAndDecodeMicroQR` |
|
|
108
|
+
| `@sythos/js_barcode_universal/rmqr` | `encodeRMQR`, `decodeRMQR`, `detectRMQR`, `detectAndDecodeRMQR` |
|
|
109
|
+
| `@sythos/js_barcode_universal/frameqr` | `encodeFrameQR`, `decodeFrameQR`, `detectFrameQR`, `detectAndDecodeFrameQR` |
|
|
110
|
+
| `@sythos/js_barcode_universal/render` | Every renderer plus `isWebGL2Available` / `isWebGPUAvailable` |
|
|
111
|
+
| `@sythos/js_barcode_universal/render/svg` | `toSVG`, `toSVGDataURI` |
|
|
112
|
+
| `@sythos/js_barcode_universal/render/png` | `toPNG`, `toPNGDataURI` |
|
|
113
|
+
| `@sythos/js_barcode_universal/render/image-data` | `toImageData`, `toCanvas` |
|
|
114
|
+
| `@sythos/js_barcode_universal/bundle` | The prebuilt ESM bundle, as one file |
|
|
115
|
+
| `@sythos/js_barcode_universal/bundle/iife` | The prebuilt IIFE bundle, for a `<script>` tag |
|
|
116
|
+
|
|
117
|
+
The `unpkg` and `jsdelivr` fields point at the IIFE bundle, so a CDN needs no install at all:
|
|
118
|
+
|
|
119
|
+
```html
|
|
120
|
+
<script src="https://unpkg.com/@sythos/js_barcode_universal"></script>
|
|
121
|
+
<script src="https://unpkg.com/@sythos/js_barcode_universal@1.4.1"></script>
|
|
122
|
+
<script src="https://cdn.jsdelivr.net/npm/@sythos/js_barcode_universal@1.4.1"></script>
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
Pin the version for anything you ship; the unpinned form resolves to `latest` and will move under
|
|
126
|
+
you.
|
|
127
|
+
|
|
128
|
+
Both CDNs serve the same file the repository ships in
|
|
129
|
+
[`bundle/sythos-barcode.js`](bundle/sythos-barcode.js) — byte for byte, since that is exactly what
|
|
130
|
+
npm publishes.
|
|
131
|
+
|
|
132
|
+
### 2. A `<script>` tag
|
|
133
|
+
|
|
134
|
+
[`bundle/sythos-barcode.js`](bundle/sythos-barcode.js) is a self-contained IIFE that exposes a
|
|
135
|
+
single global, `SythosBarcode`. It works straight from `file://` — open an HTML file off your
|
|
136
|
+
disk and it runs.
|
|
137
|
+
|
|
138
|
+
```html
|
|
139
|
+
<script src="bundle/sythos-barcode.js"></script>
|
|
140
|
+
<script>
|
|
141
|
+
var encode = SythosBarcode.encode;
|
|
142
|
+
var toSVGDataURI = SythosBarcode.toSVGDataURI;
|
|
143
|
+
|
|
144
|
+
var img = new Image();
|
|
145
|
+
img.src = toSVGDataURI(encode('https://example.com', { format: 'qr' }), { scale: 8 });
|
|
146
|
+
document.body.appendChild(img);
|
|
147
|
+
</script>
|
|
148
|
+
```
|
|
149
|
+
|
|
150
|
+
### 3. ESM bundle
|
|
151
|
+
|
|
152
|
+
[`bundle/sythos-barcode.esm.js`](bundle/sythos-barcode.esm.js) is the same code as a single ES
|
|
153
|
+
module, for `<script type="module">`, a bundler, or Node.
|
|
154
|
+
|
|
155
|
+
```js
|
|
156
|
+
import { encode, toSVG, toPNG } from './bundle/sythos-barcode.esm.js';
|
|
157
|
+
|
|
158
|
+
const ean = encode('5901234123457', { format: 'ean13' });
|
|
159
|
+
|
|
160
|
+
const svg = toSVG(ean, { scale: 3, margin: 10, barHeight: 80 });
|
|
161
|
+
// '<svg xmlns="http://www.w3.org/2000/svg" width="345" height="141" …'
|
|
162
|
+
|
|
163
|
+
toPNG(ean, { scale: 3, barHeight: 80 }).then((bytes) => {
|
|
164
|
+
// Uint8Array — a 1-bit palette PNG
|
|
165
|
+
});
|
|
166
|
+
```
|
|
167
|
+
|
|
168
|
+
### 4. The source directly
|
|
169
|
+
|
|
170
|
+
[`src/index.js`](src/index.js) is plain ESM with JSDoc types and no build step of its own. Import
|
|
171
|
+
it and let your bundler tree-shake; the package is marked side-effect free.
|
|
172
|
+
|
|
173
|
+
```js
|
|
174
|
+
import { encode, decode, toImageData, listFormats } from './src/index.js';
|
|
175
|
+
|
|
176
|
+
const matrix = encode('https://example.com', { format: 'qr', ecc: 'M' });
|
|
177
|
+
const image = toImageData(matrix, { scale: 4, margin: 4 });
|
|
178
|
+
|
|
179
|
+
const found = decode(image, { formats: ['qr'] });
|
|
180
|
+
// [ { text: 'https://example.com', format: 'qr', version: 2, ecc: 'M', … } ]
|
|
181
|
+
```
|
|
182
|
+
|
|
183
|
+
Decoding takes anything `ImageData`-shaped, so a canvas, an `OffscreenCanvas`,
|
|
184
|
+
`createImageBitmap`, or an image library's raw buffer all satisfy it without an adapter:
|
|
185
|
+
|
|
186
|
+
```js
|
|
187
|
+
const ctx = canvas.getContext('2d');
|
|
188
|
+
ctx.drawImage(video, 0, 0, canvas.width, canvas.height);
|
|
189
|
+
|
|
190
|
+
for (const hit of decode(ctx.getImageData(0, 0, canvas.width, canvas.height))) {
|
|
191
|
+
console.log(hit.format, hit.text);
|
|
192
|
+
}
|
|
193
|
+
```
|
|
194
|
+
|
|
195
|
+
`decode` returns an array, empty when nothing is found. A frame with no barcode is an ordinary
|
|
196
|
+
outcome for a camera loop, not an error, so the common case needs no `try`/`catch`. Use
|
|
197
|
+
`decodeStrict` when absence really is a failure.
|
|
198
|
+
|
|
199
|
+
---
|
|
200
|
+
|
|
201
|
+
## Supported formats
|
|
202
|
+
|
|
203
|
+
Generated from `listFormats()`, which reports writing and reading as separate capabilities.
|
|
204
|
+
Writing a symbology is a table lookup; reading one needs a detector that finds it in a
|
|
205
|
+
photograph. The two lists legitimately differ, and saying so here is better than failing at call
|
|
206
|
+
time.
|
|
207
|
+
|
|
208
|
+
| Format | `id` | Kind | Write | Read |
|
|
209
|
+
|---|---|:---:|:---:|:---:|
|
|
210
|
+
| EAN-13 | `ean13` | 1D | ✅ | ✅ |
|
|
211
|
+
| EAN-8 | `ean8` | 1D | ✅ | ✅ |
|
|
212
|
+
| UPC-A | `upca` | 1D | ✅ | ✅ |
|
|
213
|
+
| UPC-E | `upce` | 1D | ✅ | ✅ |
|
|
214
|
+
| ISBN (Bookland) | `isbn` | 1D | ✅ | ✅ [^1] |
|
|
215
|
+
| Code 128 | `code128` | 1D | ✅ | ✅ |
|
|
216
|
+
| GS1-128 | `gs1128` | 1D | ✅ | ✅ [^1] |
|
|
217
|
+
| Code 39 | `code39` | 1D | ✅ | ✅ |
|
|
218
|
+
| Code 93 | `code93` | 1D | ✅ | ✅ |
|
|
219
|
+
| ITF (Interleaved 2 of 5) | `itf` | 1D | ✅ | ✅ |
|
|
220
|
+
| ITF-14 | `itf14` | 1D | ✅ | ✅ [^1] |
|
|
221
|
+
| Codabar | `codabar` | 1D | ✅ | ✅ |
|
|
222
|
+
| Code 11 | `code11` | 1D | ✅ | — |
|
|
223
|
+
| MSI Plessey | `msi` | 1D | ✅ | — |
|
|
224
|
+
| Pharmacode | `pharmacode` | 1D | ✅ | — |
|
|
225
|
+
| QR Code | `qr` | 2D | ✅ | ✅ |
|
|
226
|
+
| Data Matrix ECC 200 | `datamatrix` | 2D | ✅ | ✅ |
|
|
215
227
|
| Aztec Code | `aztec` | 2D | ✅ | ✅ |
|
|
216
228
|
| PDF417 | `pdf417` | 2D | ✅ | ✅ |
|
|
217
229
|
| MicroPDF417 | `micropdf417` | 2D | ✅ | ✅ |
|
|
230
|
+
| Micro QR Code | `microqr` | 2D | ✅ | ✅ |
|
|
231
|
+
| rMQR Code | `rmqr` | 2D | ✅ | ✅ |
|
|
232
|
+
| FrameQR Code | `frameqr` | 2D | ✅ | ✅ |
|
|
233
|
+
| Aztec Rune | `aztecrune` | 2D | ✅ | ✅ |
|
|
234
|
+
| Compact PDF417 | `compactpdf417` | 2D | ✅ | ✅ |
|
|
235
|
+
| GS1 DataBar Omnidirectional / Truncated | `gs1databar14` | 1D | ✅ | — |
|
|
236
|
+
| EAN-2 supplement | `ean2` | 1D | ✅ | — |
|
|
237
|
+
| EAN-5 supplement | `ean5` | 1D | ✅ | — |
|
|
218
238
|
|
|
219
|
-
Twenty formats
|
|
220
|
-
write-only in the generic image pipeline.** PDF417 exposes direct matrix decoding, automatic
|
|
239
|
+
Twenty-eight listed formats are writable and twenty-two are readable. **Code 11, MSI Plessey,
|
|
240
|
+
Pharmacode, EAN-2, EAN-5 and GS1 DataBar remain write-only in the generic image pipeline.** PDF417 exposes direct matrix decoding, automatic
|
|
221
241
|
camera localization and an assisted quadrilateral sampler through its subpath. Its detector is
|
|
222
242
|
validated on degraded synthetic photographs and real Pixel 10/Chrome and iPhone 17/Safari camera
|
|
223
243
|
tests; external black-box vectors from ZXing 3.5.3 and bwip-js also pass in both directions.
|
|
224
244
|
Text and Numeric vectors are covered bidirectionally; binary byte-for-byte interop remains
|
|
225
245
|
explicitly unclaimed until a dedicated external byte corpus is added.
|
|
226
|
-
|
|
227
|
-
[^1]: `gs1128`, `itf14` and `isbn` are sub-variants that share a decoder with their base format, so
|
|
228
|
-
they decode under that base id: a GS1-128 comes back as `code128`, an ITF-14 as `itf`, and an ISBN
|
|
229
|
-
as `ean13`. The payload is intact either way — a GS1-128 *is* a Code 128 with a leading FNC1, an
|
|
230
|
-
ITF-14 *is* an ITF fixed at fourteen digits, and an ISBN barcode *is* an EAN-13 with a 978/979
|
|
231
|
-
prefix. Match on `result.format === 'code128'` rather than `'gs1128'`, or a
|
|
232
|
-
condition on the sub-variant id will silently never fire.
|
|
233
|
-
|
|
234
|
-
### Data Matrix ECC 200
|
|
235
|
-
|
|
236
|
-
`datamatrix` writes and reads the 30 classic ECC 200 square and rectangular symbol sizes. The
|
|
237
|
-
encoder supports ASCII compaction (including numeric pairs), Base256 binary payloads, automatic
|
|
238
|
-
or forced square/rectangular shape, Reed–Solomon error correction and GS1 FNC1 in the first
|
|
239
|
-
position. DMRE is not included.
|
|
240
|
-
|
|
241
|
-
```js
|
|
242
|
-
import { encodeDataMatrix, decodeDataMatrix } from '@sythos/js_barcode_universal/datamatrix';
|
|
243
|
-
|
|
244
|
-
const symbol = encodeDataMatrix('0101234567890128', { gs1: true, shape: 'square' });
|
|
245
|
-
const result = decodeDataMatrix(symbol);
|
|
246
|
-
console.log(result.text, result.gs1); // 0101234567890128 true
|
|
247
|
-
```
|
|
248
|
-
|
|
249
|
-
Binary content is accepted as a `Uint8Array` with `encoding: 'base256'`. The current high-level
|
|
250
|
-
decoder handles ASCII and Base256 codewords; C40, Text, X12 and EDIFACT input symbols are not yet
|
|
251
|
-
decoded. The current detector accepts axis-aligned square or rectangular symbols; the normal
|
|
252
|
-
`decode(image, { formats: ['datamatrix'] })` pipeline also retries quarter-turn rotations.
|
|
253
|
-
Arbitrary-angle and perspective-skewed Data Matrix photographs are not yet guaranteed.
|
|
254
|
-
|
|
255
|
-
### Aztec Code
|
|
256
|
-
|
|
257
|
-
`aztec` writes Compact layers 1–4 and Full layers 1–32, selecting a fitting symbol automatically
|
|
258
|
-
unless `layers` and `compact` are forced. It supports the five Aztec text tables and UTF-8 byte
|
|
259
|
-
payloads through Binary Shift, with `eccPercent` (default 23) controlling the requested
|
|
260
|
-
error-correction level.
|
|
261
|
-
ECI is not yet a configurable public option.
|
|
262
|
-
|
|
263
|
-
```js
|
|
264
|
-
import { encodeAztec, decodeAztec } from '@sythos/js_barcode_universal/aztec';
|
|
265
|
-
|
|
266
|
-
const symbol = encodeAztec('Greetings My Lord Sythos 👋', { eccPercent: 23 });
|
|
267
|
-
const result = decodeAztec(symbol);
|
|
268
|
-
console.log(result.text); // Greetings My Lord Sythos 👋
|
|
269
|
-
```
|
|
270
|
-
|
|
271
|
-
The image detector handles rotation, inverted polarity and quadrilateral sampling around the
|
|
272
|
-
central bull’s-eye. Severe photographic perspective remains an interoperability and robustness
|
|
273
|
-
gate rather than a guaranteed capability.
|
|
274
|
-
|
|
246
|
+
|
|
247
|
+
[^1]: `gs1128`, `itf14` and `isbn` are sub-variants that share a decoder with their base format, so
|
|
248
|
+
they decode under that base id: a GS1-128 comes back as `code128`, an ITF-14 as `itf`, and an ISBN
|
|
249
|
+
as `ean13`. The payload is intact either way — a GS1-128 *is* a Code 128 with a leading FNC1, an
|
|
250
|
+
ITF-14 *is* an ITF fixed at fourteen digits, and an ISBN barcode *is* an EAN-13 with a 978/979
|
|
251
|
+
prefix. Match on `result.format === 'code128'` rather than `'gs1128'`, or a
|
|
252
|
+
condition on the sub-variant id will silently never fire.
|
|
253
|
+
|
|
254
|
+
### Data Matrix ECC 200
|
|
255
|
+
|
|
256
|
+
`datamatrix` writes and reads the 30 classic ECC 200 square and rectangular symbol sizes. The
|
|
257
|
+
encoder supports ASCII compaction (including numeric pairs), Base256 binary payloads, automatic
|
|
258
|
+
or forced square/rectangular shape, Reed–Solomon error correction and GS1 FNC1 in the first
|
|
259
|
+
position. DMRE is not included.
|
|
260
|
+
|
|
261
|
+
```js
|
|
262
|
+
import { encodeDataMatrix, decodeDataMatrix } from '@sythos/js_barcode_universal/datamatrix';
|
|
263
|
+
|
|
264
|
+
const symbol = encodeDataMatrix('0101234567890128', { gs1: true, shape: 'square' });
|
|
265
|
+
const result = decodeDataMatrix(symbol);
|
|
266
|
+
console.log(result.text, result.gs1); // 0101234567890128 true
|
|
267
|
+
```
|
|
268
|
+
|
|
269
|
+
Binary content is accepted as a `Uint8Array` with `encoding: 'base256'`. The current high-level
|
|
270
|
+
decoder handles ASCII and Base256 codewords; C40, Text, X12 and EDIFACT input symbols are not yet
|
|
271
|
+
decoded. The current detector accepts axis-aligned square or rectangular symbols; the normal
|
|
272
|
+
`decode(image, { formats: ['datamatrix'] })` pipeline also retries quarter-turn rotations.
|
|
273
|
+
Arbitrary-angle and perspective-skewed Data Matrix photographs are not yet guaranteed.
|
|
274
|
+
|
|
275
|
+
### Aztec Code
|
|
276
|
+
|
|
277
|
+
`aztec` writes Compact layers 1–4 and Full layers 1–32, selecting a fitting symbol automatically
|
|
278
|
+
unless `layers` and `compact` are forced. It supports the five Aztec text tables and UTF-8 byte
|
|
279
|
+
payloads through Binary Shift, with `eccPercent` (default 23) controlling the requested
|
|
280
|
+
error-correction level.
|
|
281
|
+
ECI is not yet a configurable public option.
|
|
282
|
+
|
|
283
|
+
```js
|
|
284
|
+
import { encodeAztec, decodeAztec } from '@sythos/js_barcode_universal/aztec';
|
|
285
|
+
|
|
286
|
+
const symbol = encodeAztec('Greetings My Lord Sythos 👋', { eccPercent: 23 });
|
|
287
|
+
const result = decodeAztec(symbol);
|
|
288
|
+
console.log(result.text); // Greetings My Lord Sythos 👋
|
|
289
|
+
```
|
|
290
|
+
|
|
291
|
+
The image detector handles rotation, inverted polarity and quadrilateral sampling around the
|
|
292
|
+
central bull’s-eye. Severe photographic perspective remains an interoperability and robustness
|
|
293
|
+
gate rather than a guaranteed capability.
|
|
294
|
+
|
|
275
295
|
### PDF417 (writer, matrix decoder and camera reader)
|
|
276
296
|
|
|
277
297
|
`pdf417` supports PDF417 Text, Byte and Numeric compaction, ECI 3 (ISO-8859-1) and ECI 26
|
|
@@ -309,209 +329,302 @@ The detector accepts clean, integer-scaled raster symbols and quarter-turn rotat
|
|
|
309
329
|
perspective, severe photographic degradation and multi-symbol scenes are not yet claimed as
|
|
310
330
|
robust capabilities.
|
|
311
331
|
|
|
332
|
+
### Micro QR Code
|
|
333
|
+
|
|
334
|
+
`microqr` implements the M1–M4 family with Numeric, Alphanumeric, ISO-8859-1 Byte and Kanji
|
|
335
|
+
payloads, BCH format protection, the four Micro QR masks and Reed–Solomon correction. M1 is
|
|
336
|
+
detection-only. ECI, FNC1/GS1 and Structured Append are intentionally outside the current API.
|
|
337
|
+
The detector accepts clean scaled rasters, quarter-turns, inverted polarity and mild projective
|
|
338
|
+
sampling, and rejects normal QR Model 2 symbols.
|
|
339
|
+
|
|
340
|
+
```js
|
|
341
|
+
import { encodeMicroQR, decodeMicroQR } from '@sythos/js_barcode_universal/microqr';
|
|
342
|
+
|
|
343
|
+
const symbol = encodeMicroQR('12345', { version: 'M2', ecc: 'L' });
|
|
344
|
+
console.log(decodeMicroQR(symbol).text);
|
|
345
|
+
```
|
|
346
|
+
|
|
347
|
+
### rMQR Code
|
|
348
|
+
|
|
349
|
+
`rmqr` implements all 32 standard rectangular geometries, M/H ECC, Numeric, Alphanumeric, Byte,
|
|
350
|
+
Kanji and ECI payloads. The detector accepts clean integer-scaled rasters, quiet zones and
|
|
351
|
+
quarter-turns; arbitrary photographic perspective and multi-symbol scenes are not claimed.
|
|
352
|
+
|
|
353
|
+
```js
|
|
354
|
+
import { encodeRMQR, decodeRMQR } from '@sythos/js_barcode_universal/rmqr';
|
|
355
|
+
|
|
356
|
+
const symbol = encodeRMQR('rMQR SAMPLE', { ecc: 'M' });
|
|
357
|
+
console.log(decodeRMQR(symbol).text);
|
|
358
|
+
```
|
|
359
|
+
|
|
360
|
+
### FrameQR Code
|
|
361
|
+
|
|
362
|
+
`frameqr` is an explicitly scoped, non-certified FrameQR Code profile: it reserves a bounded
|
|
363
|
+
square, circle or diamond artwork canvas inside an ECC-H QR Model 2 symbol. It is **not** a native
|
|
364
|
+
DENSO FrameQR encoder or decoder, and the package makes no DENSO interoperability claim. The
|
|
365
|
+
profile can be read from clean rendered rasters and is exposed through the normal `encode`/`decode`
|
|
366
|
+
API and the `frameqr` subpath.
|
|
367
|
+
|
|
368
|
+
```js
|
|
369
|
+
import { encodeFrameQR, decodeFrameQR } from '@sythos/js_barcode_universal/frameqr';
|
|
370
|
+
|
|
371
|
+
const symbol = encodeFrameQR('https://www.sythos.net/', {
|
|
372
|
+
canvas: { shape: 'square', size: 5 },
|
|
373
|
+
});
|
|
374
|
+
console.log(decodeFrameQR(symbol).text);
|
|
375
|
+
```
|
|
376
|
+
|
|
377
|
+
The canonical `examples/create.html` preview loads `https://www.sythos.net/favicon.ico` and
|
|
378
|
+
falls back to `https://www.sythos.net/apple-touch-icon.png`. The image is never copied into the
|
|
379
|
+
repository; if browser CORS prevents safe compositing, the page keeps a preview overlay and
|
|
380
|
+
exports the QR symbol without embedding the remote artwork.
|
|
381
|
+
|
|
382
|
+
### Aztec Rune, Compact PDF417 and EAN supplements
|
|
383
|
+
|
|
384
|
+
`aztecrune` implements the fixed 11×11 Rune values 0–255 with clean raster
|
|
385
|
+
detection, inversion and quarter-turn handling. Its matrices were compared
|
|
386
|
+
exhaustively with ZXing-C++ as an independent black-box runtime; no ZXing
|
|
387
|
+
source or table is shipped.
|
|
388
|
+
|
|
389
|
+
`compactpdf417` implements the truncated PDF417 geometry with Text, Byte and
|
|
390
|
+
Numeric compaction. It has a clean raster detector and direct matrix decoder.
|
|
391
|
+
|
|
392
|
+
EAN-2 and EAN-5 are writable supplements exposed by the `oned` subpath and by
|
|
393
|
+
the generic `ean2` and `ean5` format IDs. They are intentionally not generic
|
|
394
|
+
standalone camera-reader formats; use the composition helpers with an EAN/UPC
|
|
395
|
+
base symbol.
|
|
396
|
+
|
|
397
|
+
### GS1 DataBar
|
|
398
|
+
|
|
399
|
+
The `databar` subpath exposes original GS1 GTIN/AI codecs plus physical
|
|
400
|
+
Omnidirectional and Truncated writers and clean-matrix decoders. Four GTIN
|
|
401
|
+
vectors were compared bit-for-bit with Zint 2.16.0 as a black box. Limited,
|
|
402
|
+
Stacked, Stacked Omnidirectional and Expanded physical layouts remain planned;
|
|
403
|
+
their data-layer helpers do not imply complete scanner support.
|
|
404
|
+
|
|
312
405
|
### Not implemented
|
|
313
|
-
|
|
314
|
-
|
|
406
|
+
|
|
407
|
+
GS1 DataBar physical support currently covers Omnidirectional and Truncated writing plus clean
|
|
408
|
+
matrix decoding; Limited, Stacked and Expanded physical layouts remain planned. MaxiCode is
|
|
409
|
+
not implemented. Data Matrix ECC
|
|
315
410
|
200 is implemented for its classic square and rectangular symbols;
|
|
316
411
|
DMRE remains outside the current scope. See [`PLAN.md`](PLAN.md) for the remaining symbologies.
|
|
317
|
-
|
|
318
|
-
---
|
|
319
|
-
|
|
320
|
-
## Live examples
|
|
321
|
-
|
|
322
|
-
Two self-contained pages, each loading the IIFE bundle with a plain `<script>` tag. **Both open
|
|
323
|
-
directly from disk** — double-click the file, no server and no build. This `examples/` directory is
|
|
324
|
-
the single canonical source; the development workspace references these files instead of keeping
|
|
325
|
-
a second copy.
|
|
326
|
-
|
|
327
|
-
### [`examples/create.html`](examples/create.html)
|
|
328
|
-
|
|
329
|
-
Pick any writable format, type a payload, and watch the symbol redraw as you type; download it as
|
|
330
|
-
PNG or SVG. For QR it adds a **content-type builder** that assembles the payload for you across
|
|
331
|
-
URL, email, phone, SMS, Wi-Fi network, contact card (both vCard and MeCard), geo location and
|
|
332
|
-
calendar event — with correct escaping for each — and shows you the exact string it produced, so
|
|
333
|
-
you can see what a Wi-Fi or vCard QR actually contains. ECC level, version, scale, margin and both
|
|
334
|
-
colours are exposed.
|
|
335
|
-
|
|
336
|
-
### [`examples/read.html`](examples/read.html)
|
|
337
|
-
|
|
338
|
-
Decode from an image: drop one onto the page, or click to choose a file. It then offers a live
|
|
339
|
-
camera loop that decodes continuously from the video stream.
|
|
340
|
-
|
|
341
|
-
> The file and drag-drop path works anywhere, `file://` included. **The camera needs http(s)**,
|
|
342
|
-
> because `getUserMedia` requires a secure context and refuses to run from `file://`. Serve the
|
|
343
|
-
> folder over localhost for that half; the page detects the situation and says so rather than
|
|
344
|
-
> failing silently.
|
|
345
|
-
|
|
346
|
-
---
|
|
347
|
-
|
|
348
|
-
## API summary
|
|
349
|
-
|
|
350
|
-
Two functions carry the whole surface. Everything else is a renderer or a format-specific escape
|
|
351
|
-
hatch.
|
|
352
|
-
|
|
353
|
-
### Encoding and decoding
|
|
354
|
-
|
|
355
|
-
```js
|
|
356
|
-
encode(text, options?) → BitMatrix
|
|
357
|
-
```
|
|
358
|
-
|
|
359
|
-
`options`: `format` (default `'qr'`), `ecc` (`'L'|'M'|'Q'|'H'`), `version` (QR 1–40, auto if
|
|
360
|
-
omitted), `checkDigit`, `fullAscii` (Code 39 extended), `gs1` (emit a leading FNC1). Data Matrix
|
|
361
|
-
ECC 200 accepts `shape: 'any' | 'square' | 'rectangular'` and `encoding: 'ascii' | 'base256'`.
|
|
412
|
+
|
|
413
|
+
---
|
|
414
|
+
|
|
415
|
+
## Live examples
|
|
416
|
+
|
|
417
|
+
Two self-contained pages, each loading the IIFE bundle with a plain `<script>` tag. **Both open
|
|
418
|
+
directly from disk** — double-click the file, no server and no build. This `examples/` directory is
|
|
419
|
+
the single canonical source; the development workspace references these files instead of keeping
|
|
420
|
+
a second copy.
|
|
421
|
+
|
|
422
|
+
### [`examples/create.html`](examples/create.html)
|
|
423
|
+
|
|
424
|
+
Pick any writable format, type a payload, and watch the symbol redraw as you type; download it as
|
|
425
|
+
PNG or SVG. For QR it adds a **content-type builder** that assembles the payload for you across
|
|
426
|
+
URL, email, phone, SMS, Wi-Fi network, contact card (both vCard and MeCard), geo location and
|
|
427
|
+
calendar event — with correct escaping for each — and shows you the exact string it produced, so
|
|
428
|
+
you can see what a Wi-Fi or vCard QR actually contains. ECC level, version, scale, margin and both
|
|
429
|
+
colours are exposed.
|
|
430
|
+
|
|
431
|
+
### [`examples/read.html`](examples/read.html)
|
|
432
|
+
|
|
433
|
+
Decode from an image: drop one onto the page, or click to choose a file. It then offers a live
|
|
434
|
+
camera loop that decodes continuously from the video stream.
|
|
435
|
+
|
|
436
|
+
> The file and drag-drop path works anywhere, `file://` included. **The camera needs http(s)**,
|
|
437
|
+
> because `getUserMedia` requires a secure context and refuses to run from `file://`. Serve the
|
|
438
|
+
> folder over localhost for that half; the page detects the situation and says so rather than
|
|
439
|
+
> failing silently.
|
|
440
|
+
|
|
441
|
+
---
|
|
442
|
+
|
|
443
|
+
## API summary
|
|
444
|
+
|
|
445
|
+
Two functions carry the whole surface. Everything else is a renderer or a format-specific escape
|
|
446
|
+
hatch.
|
|
447
|
+
|
|
448
|
+
### Encoding and decoding
|
|
449
|
+
|
|
450
|
+
```js
|
|
451
|
+
encode(text, options?) → BitMatrix
|
|
452
|
+
```
|
|
453
|
+
|
|
454
|
+
`options`: `format` (default `'qr'`), `ecc` (`'L'|'M'|'Q'|'H'`), `version` (QR 1–40, auto if
|
|
455
|
+
omitted), `checkDigit`, `fullAscii` (Code 39 extended), `gs1` (emit a leading FNC1). Data Matrix
|
|
456
|
+
ECC 200 accepts `shape: 'any' | 'square' | 'rectangular'` and `encoding: 'ascii' | 'base256'`.
|
|
362
457
|
Aztec accepts `layers`, `compact` and `eccPercent`; it transports UTF-8 byte payloads through
|
|
363
458
|
Binary Shift, and it does not expose configurable ECI yet.
|
|
364
459
|
MicroPDF417 accepts `compaction: 'auto' | 'text' | 'byte' | 'numeric'`, ECI 3 or 26 for Byte
|
|
365
460
|
compaction, and optional `columns`, `rowHeight` and `aspectRatio` constraints.
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
461
|
+
Micro QR accepts `version: 'M1' | 'M2' | 'M3' | 'M4'`, its legal ECC level and mask; its
|
|
462
|
+
unsupported ECI, FNC1/GS1 and Structured Append features are rejected explicitly. rMQR accepts
|
|
463
|
+
`ecc: 'M' | 'H'`, optional geometry/version constraints and ECI for byte payloads. The FrameQR
|
|
464
|
+
Code profile accepts `canvas: { shape: 'square' | 'circle' | 'diamond', size, width, height,
|
|
465
|
+
centerX, centerY, angle }`; it is non-certified and separate from DENSO FrameQR.
|
|
466
|
+
|
|
467
|
+
```js
|
|
468
|
+
encode('5901234123457', { format: 'ean13' })
|
|
469
|
+
encode('ABC-123', { format: 'code39', fullAscii: true, checkDigit: true })
|
|
470
|
+
encode('https://example.com', { format: 'qr', ecc: 'H', version: 7 })
|
|
471
|
+
encode('0101234567890128', { format: 'datamatrix', gs1: true })
|
|
372
472
|
encode('Greetings My Lord Sythos 👋', { format: 'aztec', eccPercent: 23 })
|
|
373
473
|
encode('MICRO PDF417', { format: 'micropdf417', compaction: 'text' })
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
(
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
`
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
`
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
GPU
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
474
|
+
encode('12345', { format: 'microqr', version: 'M2', ecc: 'L' })
|
|
475
|
+
encode('rMQR SAMPLE', { format: 'rmqr', ecc: 'M' })
|
|
476
|
+
encode('https://www.sythos.net/', {
|
|
477
|
+
format: 'frameqr',
|
|
478
|
+
canvas: { shape: 'square', size: 5 },
|
|
479
|
+
})
|
|
480
|
+
```
|
|
481
|
+
|
|
482
|
+
```js
|
|
483
|
+
decode(image, options?) → Result[]
|
|
484
|
+
decodeStrict(image, options?) → Result // throws NotFoundError instead of returning []
|
|
485
|
+
```
|
|
486
|
+
|
|
487
|
+
`image` is `{ data, width, height }` with RGBA bytes. `options`: `formats` (restrict the search,
|
|
488
|
+
and go faster), `tryHarder` (retry inverted, default `true`), `binarizer`
|
|
489
|
+
(`'global' | 'hybrid' | 'auto'`). A `Result` carries at least `text` and `format`; QR results also
|
|
490
|
+
carry `bytes`, `version` and `ecc`.
|
|
491
|
+
|
|
492
|
+
```js
|
|
493
|
+
listFormats() → { id, label, canWrite, canRead, kind }[]
|
|
494
|
+
```
|
|
495
|
+
|
|
496
|
+
The table above is this function's output. Read it at runtime rather than hard-coding a format
|
|
497
|
+
list — that is how the demo pages build their dropdowns.
|
|
498
|
+
|
|
499
|
+
### Renderers
|
|
500
|
+
|
|
501
|
+
```js
|
|
502
|
+
toSVG(matrix, options?) → string // one merged <path>, not a rect per module
|
|
503
|
+
toSVGDataURI(matrix, options?) → string // data: URI for an <img src>
|
|
504
|
+
toImageData(matrix, options?) → { data, width, height }
|
|
505
|
+
toPNG(matrix, options?) → Promise<Uint8Array> // 1-bit palette PNG
|
|
506
|
+
toPNGDataURI(matrix, options?) → Promise<string>
|
|
507
|
+
toCanvas(matrix, canvas, options?) → boolean // 2D context
|
|
508
|
+
renderToCanvasAuto(matrix, canvas, options?) → { backend: 'webgl2' | '2d' | 'none' }
|
|
509
|
+
renderToCanvasAutoAsync(matrix, canvas, options?) → Promise<{ backend: 'webgpu' | 'webgl2' | '2d' | 'none' }>
|
|
510
|
+
```
|
|
511
|
+
|
|
512
|
+
The two PNG functions are async because they use the platform's deflate — `node:zlib` or
|
|
513
|
+
`CompressionStream` — and fall back to stored blocks where neither exists.
|
|
514
|
+
|
|
515
|
+
`renderToCanvasAuto` is synchronous and therefore cannot reach WebGPU: acquiring an adapter is
|
|
516
|
+
asynchronous, and a synchronous function can never wait for one. Use `renderToCanvasAutoAsync`
|
|
517
|
+
when you want WebGPU in the chain. Both fall through to the 2D context, which always exists.
|
|
518
|
+
|
|
519
|
+
All renderers share the same options:
|
|
520
|
+
|
|
521
|
+
| Option | Default | Meaning |
|
|
522
|
+
|---|---|---|
|
|
523
|
+
| `scale` | `8` | Pixels per module |
|
|
524
|
+
| `margin` | `4` | Quiet-zone modules on every side |
|
|
525
|
+
| `dark` | `'#000000'` | Colour of set modules |
|
|
526
|
+
| `light` | `'#ffffff'` | Colour of clear modules; `'none'` for transparent |
|
|
527
|
+
| `barHeight` | auto | 1D only: total bar height in pixels |
|
|
528
|
+
|
|
529
|
+
Also exported: `BitMatrix`, the error types (`BarcodeError`, `EncodeError`, `NotFoundError`,
|
|
530
|
+
`FormatError`, `ChecksumError`), the per-format writers (`encodeEAN13`, `encodeCode128`, …), the
|
|
531
|
+
QR entry points (`encodeQR`, `decodeQR`, `detectQR`, `detectAndDecodeQR`), the image primitives
|
|
532
|
+
(`LuminanceSource`, `binarize`, `binarizeGlobal`, `binarizeHybrid`), and the capability probes
|
|
533
|
+
`isWebGL2Available` / `isWebGPUAvailable`.
|
|
534
|
+
|
|
535
|
+
---
|
|
536
|
+
|
|
537
|
+
## How it works
|
|
538
|
+
|
|
539
|
+
**`BitMatrix` is the interchange type.** Every writer produces one, every reader consumes one,
|
|
540
|
+
every renderer draws one. That single currency is what keeps symbologies and output targets
|
|
541
|
+
independent of each other — adding a format touches no renderer, and adding a renderer touches no
|
|
542
|
+
format. Storage is row-packed into a `Uint32Array`: one allocation, cache-friendly row scans, and
|
|
543
|
+
cheap whole-row operations for the 1D readers.
|
|
544
|
+
|
|
545
|
+
**A set bit is a dark module.** This matches how every specification describes its symbols;
|
|
546
|
+
renderers invert where their medium needs it.
|
|
547
|
+
|
|
548
|
+
**`encode` returns no quiet zone.** The margin is a rendering decision, not an encoding one — how
|
|
549
|
+
much white space a symbol needs depends on where it is going — so the renderers add it and the
|
|
550
|
+
matrix stays the pure symbol. For the same reason, **linear symbols come back exactly one module
|
|
551
|
+
tall**: height carries no information in a 1D barcode, so encoding one would be inventing data.
|
|
552
|
+
The renderer stretches the single row to `barHeight` *before* applying the quiet zone, so the
|
|
553
|
+
margin ends up uniform on all four sides.
|
|
554
|
+
|
|
555
|
+
**The read pipeline** is a straight line, each stage a separate module:
|
|
556
|
+
|
|
557
|
+
```
|
|
558
|
+
RGBA bytes → luminance → binarize → detect → sample → error-correct → decode
|
|
559
|
+
```
|
|
560
|
+
|
|
561
|
+
Luminance conversion flattens the image to greyscale. Binarization turns that into a `BitMatrix`,
|
|
562
|
+
either globally or with a hybrid local threshold that survives uneven lighting. Detection locates
|
|
563
|
+
a symbol and its corners in that bit plane. Detectors that recover four perspective-aware corners
|
|
564
|
+
(currently QR) sample the symbol back through a perspective transform. Data Matrix currently uses
|
|
565
|
+
an axis-aligned bounding box plus quarter-turn retries. Error correction repairs what the camera
|
|
566
|
+
lost. Only then is the payload decoded.
|
|
567
|
+
|
|
568
|
+
**Reed–Solomon is generic over the finite field.** The `GaloisField` class is constructed with a
|
|
569
|
+
field order and a primitive polynomial rather than hard-coding GF(256), which is what lets one
|
|
570
|
+
implementation serve QR, and the prime field GF(929) that PDF417 needs. Prime fields are the
|
|
571
|
+
subtle case: in a binary field addition and subtraction are both XOR, so a decoder that inlines
|
|
572
|
+
`^` for field addition passes every binary field and fails only the prime one.
|
|
573
|
+
|
|
574
|
+
---
|
|
575
|
+
|
|
576
|
+
## About the GPU path
|
|
577
|
+
|
|
578
|
+
The WebGL2 and WebGPU backends accelerate **drawing** a barcode, not **computing** one. That is
|
|
579
|
+
worth stating plainly, because "GPU barcode generation" naturally suggests the latter.
|
|
580
|
+
|
|
581
|
+
Encoding is sequential integer work: Reed–Solomon polynomial division, mask penalty scoring, bit
|
|
582
|
+
placement along a zig-zag path. Each step depends on the one before it, which is precisely the
|
|
583
|
+
shape a GPU cannot exploit. A complete QR encode takes well under a millisecond on the CPU — less
|
|
584
|
+
time than dispatching a compute shader and reading the result back would cost. Moving it to the
|
|
585
|
+
GPU would make it slower.
|
|
586
|
+
|
|
587
|
+
So encoding stays on the CPU because that is the correct engineering answer, not because
|
|
588
|
+
something is missing. Where the GPU genuinely earns its place is drawing large symbols, or many
|
|
589
|
+
symbols per frame, straight into a canvas without a CPU-side pixel buffer — and it would earn it
|
|
590
|
+
again on the read side, where per-frame greyscale conversion and block statistics over a 4K camera
|
|
591
|
+
image are both the real bottleneck and embarrassingly parallel.
|
|
592
|
+
|
|
593
|
+
---
|
|
594
|
+
|
|
595
|
+
## Browser support
|
|
596
|
+
|
|
597
|
+
The syntax floor is **iOS Safari 15**. No `Array.prototype.at`, no top-level `await`, no
|
|
598
|
+
`Object.groupBy`.
|
|
599
|
+
|
|
600
|
+
`OffscreenCanvas`, WebGL2 and WebGPU are feature-detected, never assumed. The 2D canvas path
|
|
601
|
+
always exists, so nothing is unreachable on an older device — `renderToCanvasAuto` degrades to it
|
|
602
|
+
and reports which backend actually drew.
|
|
603
|
+
|
|
604
|
+
---
|
|
605
|
+
|
|
606
|
+
## Licence
|
|
607
|
+
|
|
608
|
+
MIT © 2026 Sythos (https://www.sythos.net). Every source file carries the header.
|
|
609
|
+
|
|
504
610
|
**The implementation is original Sythos work.** No third-party barcode source code is copied into
|
|
505
611
|
or shipped by this package. The symbologies are implemented from published descriptions of the
|
|
506
|
-
formats and from original Sythos data structures
|
|
507
|
-
provenance and pending legal review in `NOTICE.md`.
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
612
|
+
formats and from original Sythos data structures. MicroPDF417, Micro QR, rMQR and the FrameQR
|
|
613
|
+
Code carry provenance and pending legal review in `NOTICE.md`. Independent
|
|
614
|
+
implementations and public technical material may be consulted for engineering review or
|
|
615
|
+
black-box verification; no third-party source code is copied or shipped. The distributed package has no runtime third-party
|
|
616
|
+
dependencies. See [`NOTICE.md`](NOTICE.md) and the per-format files in [`licenses/`](licenses/).
|
|
617
|
+
|
|
618
|
+
Public DENSO FrameQR material was consulted only to document the compatibility boundary. ZXing
|
|
619
|
+
was used only as an independent black-box validation tool; no ZXing source code or tables are
|
|
620
|
+
copied or shipped. The FrameQR Code profile does not claim native DENSO FrameQR
|
|
621
|
+
interoperability or co-author attribution.
|
|
622
|
+
|
|
623
|
+
**Trademark is not licence.** QR Code® is a registered trademark of DENSO WAVE; Aztec Code,
|
|
624
|
+
MaxiCode and GS1 DataBar are likewise marks of their owners. A trademark does not restrict
|
|
625
|
+
implementing a symbology, but it does constrain branding — which is why this package is named
|
|
626
|
+
descriptively rather than after any mark.
|
|
627
|
+
|
|
515
628
|
Data Matrix ECC 200 is governed by ISO/IEC 16022:2024; GS1 DataMatrix additionally uses the GS1
|
|
516
629
|
General Specifications and a leading FNC1. Its engineering provenance, patent and trademark
|
|
517
630
|
research notes are recorded in [`licenses/data-matrix.license`](licenses/data-matrix.license),
|
|
@@ -521,22 +634,45 @@ PDF417 and MicroPDF417 provenance and legal review notes are recorded in
|
|
|
521
634
|
[`licenses/pdf417.license`](licenses/pdf417.license),
|
|
522
635
|
[`licenses/micropdf417.license`](licenses/micropdf417.license) and the attribution log in
|
|
523
636
|
[`NOTICE.md`](NOTICE.md).
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
637
|
+
|
|
638
|
+
Micro QR and rMQR provenance and scoped legal-review notes are recorded in
|
|
639
|
+
[`licenses/micro-qr.license`](licenses/micro-qr.license),
|
|
640
|
+
[`licenses/rmqr.license`](licenses/rmqr.license) and [`NOTICE.md`](NOTICE.md).
|
|
641
|
+
|
|
642
|
+
[`LICENSE`](LICENSE) carries the full MIT text plus an informational appendix inventorying the
|
|
643
|
+
specification copyrights, patent history and trademarks that surround these symbologies. None of
|
|
527
644
|
them is resolved by this file; the appendix is an engineering inventory, not legal advice.
|
|
528
|
-
[`NOTICE.md`](NOTICE.md) records the origin of the code and how its correctness is verified.
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
645
|
+
[`NOTICE.md`](NOTICE.md) records the origin of the code and how its correctness is verified.
|
|
646
|
+
|
|
647
|
+
## AI / LLM Usage & Attribution
|
|
648
|
+
|
|
649
|
+
This project may be analyzed, referenced, modified, or integrated by
|
|
650
|
+
AI-assisted development tools, coding agents, and Large Language Models (LLMs).
|
|
651
|
+
|
|
652
|
+
If code from this repository is copied, adapted, incorporated, or otherwise
|
|
653
|
+
used in another project, please preserve the original copyright and license
|
|
654
|
+
information and include attribution to:
|
|
655
|
+
|
|
656
|
+
**Sythos (https://www.sythos.net)**
|
|
657
|
+
|
|
658
|
+
Licensed under the **MIT License**.
|
|
659
|
+
|
|
660
|
+
AI agents and automated coding tools are explicitly requested to preserve
|
|
661
|
+
this attribution and the applicable license when generating derived code,
|
|
662
|
+
documentation, or project files based on this repository.
|
|
663
|
+
|
|
664
|
+
See [`AI_USAGE.md`](./AI_USAGE.md) for additional machine-oriented guidance.
|
|
665
|
+
|
|
666
|
+
---
|
|
667
|
+
|
|
532
668
|
## Contributing and roadmap
|
|
533
669
|
|
|
534
670
|
[`PLAN.md`](PLAN.md) is the live status document: what is shipped, what is next, and the ground
|
|
535
671
|
rules — chief among them that no third-party source code is copied into or shipped by this
|
|
536
672
|
project, while public or normative values remain provenance-tracked and subject to legal review.
|
|
537
|
-
|
|
538
|
-
Issues and pull requests are welcome at
|
|
539
|
-
[Sythos/JS_Barcode_Universal](https://github.com/Sythos/JS_Barcode_Universal). A patch that adds a
|
|
540
|
-
symbology should implement it from the published description of the format, generate its tables
|
|
541
|
-
where they are derivable, and come with a symbol that a scanner this project did not write has
|
|
542
|
-
actually read — that last one is the check that matters.
|
|
673
|
+
|
|
674
|
+
Issues and pull requests are welcome at
|
|
675
|
+
[Sythos/JS_Barcode_Universal](https://github.com/Sythos/JS_Barcode_Universal). A patch that adds a
|
|
676
|
+
symbology should implement it from the published description of the format, generate its tables
|
|
677
|
+
where they are derivable, and come with a symbol that a scanner this project did not write has
|
|
678
|
+
actually read — that last one is the check that matters.
|