image-barcode-identifier 0.0.0-stage → 0.1.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/dist/ops.js ADDED
@@ -0,0 +1,203 @@
1
+ /* eslint-disable @typescript-eslint/no-explicit-any */
2
+ // Thin, leak-free wrappers around the OpenCV.js calls the pipeline needs. Images cross this boundary as plain
3
+ // `Gray` buffers, so no OpenCV `Mat` (which must be freed by hand) ever escapes this file.
4
+ import { getCv } from './cv.js';
5
+ class Scope {
6
+ items = [];
7
+ add(item) {
8
+ this.items.push(item);
9
+ return item;
10
+ }
11
+ dispose() {
12
+ for (const item of this.items) {
13
+ try {
14
+ item.delete();
15
+ }
16
+ catch {
17
+ /* already freed */
18
+ }
19
+ }
20
+ this.items.length = 0;
21
+ }
22
+ }
23
+ function toMat(s, g) {
24
+ const cv = getCv();
25
+ const m = s.add(new cv.Mat(g.height, g.width, cv.CV_8UC1));
26
+ m.data.set(g.data);
27
+ return m;
28
+ }
29
+ function fromMat(m) {
30
+ return { data: new Uint8Array(m.data), width: m.cols, height: m.rows };
31
+ }
32
+ function apply(g, fn) {
33
+ const cv = getCv();
34
+ const s = new Scope();
35
+ try {
36
+ const src = toMat(s, g);
37
+ const dst = s.add(new cv.Mat());
38
+ fn(cv, src, dst, s);
39
+ return fromMat(dst);
40
+ }
41
+ finally {
42
+ s.dispose();
43
+ }
44
+ }
45
+ // --------------------------------------------------------------------------- //
46
+ // Preprocessing variants
47
+ // --------------------------------------------------------------------------- //
48
+ export function clahe(g) {
49
+ return apply(g, (cv, src, dst, s) => {
50
+ const c = s.add(new cv.CLAHE(3.0, new cv.Size(8, 8)));
51
+ c.apply(src, dst);
52
+ });
53
+ }
54
+ export function sharpen(g) {
55
+ return apply(g, (cv, src, dst, s) => {
56
+ const blur = s.add(new cv.Mat());
57
+ cv.GaussianBlur(src, blur, new cv.Size(0, 0), 3, 3, cv.BORDER_DEFAULT);
58
+ cv.addWeighted(src, 1.8, blur, -0.8, 0, dst);
59
+ });
60
+ }
61
+ export function otsu(g) {
62
+ return apply(g, (cv, src, dst) => {
63
+ cv.threshold(src, dst, 0, 255, cv.THRESH_BINARY | cv.THRESH_OTSU);
64
+ });
65
+ }
66
+ export function adaptive(g) {
67
+ const k = Math.max(15, (Math.min(g.width, g.height) >> 3) | 1);
68
+ return apply(g, (cv, src, dst) => {
69
+ cv.adaptiveThreshold(src, dst, 255, cv.ADAPTIVE_THRESH_GAUSSIAN_C, cv.THRESH_BINARY, k, 8);
70
+ });
71
+ }
72
+ export function denoiseOtsu(g) {
73
+ return apply(g, (cv, src, dst, s) => {
74
+ const med = s.add(new cv.Mat());
75
+ cv.medianBlur(src, med, 3);
76
+ cv.threshold(med, dst, 0, 255, cv.THRESH_BINARY | cv.THRESH_OTSU);
77
+ });
78
+ }
79
+ /** Horizontal-only blur: suppresses moire / noise inside bars without smearing bar edges vertically. */
80
+ export function hblur(g) {
81
+ return apply(g, (cv, src, dst) => {
82
+ cv.GaussianBlur(src, dst, new cv.Size(0, 0), 1.5, 0.1, cv.BORDER_DEFAULT);
83
+ });
84
+ }
85
+ // --------------------------------------------------------------------------- //
86
+ // Geometry
87
+ // --------------------------------------------------------------------------- //
88
+ export function resize(g, width, height, mode) {
89
+ return apply(g, (cv, src, dst) => {
90
+ cv.resize(src, dst, new cv.Size(width, height), 0, 0, mode === 'cubic' ? cv.INTER_CUBIC : cv.INTER_AREA);
91
+ });
92
+ }
93
+ export function crop(g, x, y, w, h) {
94
+ const out = new Uint8Array(w * h);
95
+ for (let row = 0; row < h; row++) {
96
+ const start = (y + row) * g.width + x;
97
+ out.set(g.data.subarray(start, start + w), row * w);
98
+ }
99
+ return { data: out, width: w, height: h };
100
+ }
101
+ /** `m` is a row-major 3x3 matrix mapping source -> destination (like cv2.warpPerspective). */
102
+ export function warpPerspective(g, m, width, height) {
103
+ return apply(g, (cv, src, dst, s) => {
104
+ const mat = s.add(cv.matFromArray(3, 3, cv.CV_64FC1, m));
105
+ cv.warpPerspective(src, dst, mat, new cv.Size(width, height), cv.INTER_CUBIC, cv.BORDER_REPLICATE, new cv.Scalar());
106
+ });
107
+ }
108
+ /** `m` is a row-major 2x3 matrix mapping source -> destination (like cv2.warpAffine). */
109
+ export function warpAffine(g, m, width, height) {
110
+ return apply(g, (cv, src, dst, s) => {
111
+ const mat = s.add(cv.matFromArray(2, 3, cv.CV_64FC1, m));
112
+ cv.warpAffine(src, dst, mat, new cv.Size(width, height), cv.INTER_CUBIC, cv.BORDER_REPLICATE, new cv.Scalar());
113
+ });
114
+ }
115
+ /** Row-major 3x3 matrix mapping the 4 `src` points onto the 4 `dst` points. */
116
+ export function getPerspectiveTransform(src, dst) {
117
+ const cv = getCv();
118
+ const s = new Scope();
119
+ try {
120
+ const a = s.add(cv.matFromArray(4, 1, cv.CV_32FC2, src.flat()));
121
+ const b = s.add(cv.matFromArray(4, 1, cv.CV_32FC2, dst.flat()));
122
+ const m = s.add(cv.getPerspectiveTransform(a, b));
123
+ return Array.from(m.data64F);
124
+ }
125
+ finally {
126
+ s.dispose();
127
+ }
128
+ }
129
+ // --------------------------------------------------------------------------- //
130
+ // Barcode localisation by gradient: bars have strong gradients in one direction, weak in the other
131
+ // --------------------------------------------------------------------------- //
132
+ export function gradientCandidates(gray, maxCandidates = 8) {
133
+ const cv = getCv();
134
+ const { width: w, height: h } = gray;
135
+ const scale = Math.max(h, w) > 1000 ? 1000 / Math.max(h, w) : 1;
136
+ const small = scale !== 1 ? resize(gray, Math.round(w * scale), Math.round(h * scale), 'area') : gray;
137
+ const sw = small.width;
138
+ const sh = small.height;
139
+ const s = new Scope();
140
+ const boxes = [];
141
+ try {
142
+ const src = toMat(s, small);
143
+ const gx = s.add(new cv.Mat());
144
+ const gy = s.add(new cv.Mat());
145
+ cv.Scharr(src, gx, cv.CV_32F, 1, 0, 1, 0, cv.BORDER_DEFAULT);
146
+ cv.Scharr(src, gy, cv.CV_32F, 0, 1, 1, 0, cv.BORDER_DEFAULT);
147
+ const ax = gx.data32F;
148
+ const ay = gy.data32F;
149
+ const diff = s.add(new cv.Mat(sh, sw, cv.CV_8UC1));
150
+ const d = diff.data;
151
+ // ||gx| - |gy|| saturated to 8 bits
152
+ for (let i = 0; i < d.length; i++)
153
+ d[i] = Math.min(255, Math.round(Math.abs(Math.abs(ax[i]) - Math.abs(ay[i]))));
154
+ const blur = s.add(new cv.Mat());
155
+ cv.blur(diff, blur, new cv.Size(9, 9), new cv.Point(-1, -1), cv.BORDER_DEFAULT);
156
+ const thr = s.add(new cv.Mat());
157
+ cv.threshold(blur, thr, 0, 255, cv.THRESH_BINARY | cv.THRESH_OTSU);
158
+ const k = Math.max(15, Math.floor(sw / 25));
159
+ const ones = s.add(cv.Mat.ones(3, 3, cv.CV_8U));
160
+ const anchor = new cv.Point(-1, -1);
161
+ const perKernel = [];
162
+ for (const [kw, kh] of [[k, 7], [7, k]]) {
163
+ const kernel = s.add(cv.getStructuringElement(cv.MORPH_RECT, new cv.Size(kw, kh)));
164
+ const closed = s.add(new cv.Mat());
165
+ cv.morphologyEx(thr, closed, cv.MORPH_CLOSE, kernel);
166
+ const eroded = s.add(new cv.Mat());
167
+ cv.erode(closed, eroded, ones, anchor, 3, cv.BORDER_CONSTANT, cv.morphologyDefaultBorderValue());
168
+ const dilated = s.add(new cv.Mat());
169
+ cv.dilate(eroded, dilated, ones, anchor, 3, cv.BORDER_CONSTANT, cv.morphologyDefaultBorderValue());
170
+ const contours = s.add(new cv.MatVector());
171
+ const hierarchy = s.add(new cv.Mat());
172
+ cv.findContours(dilated, contours, hierarchy, cv.RETR_EXTERNAL, cv.CHAIN_APPROX_SIMPLE);
173
+ for (let i = 0; i < contours.size(); i++) {
174
+ const c = contours.get(i);
175
+ try {
176
+ const area = cv.contourArea(c);
177
+ if (area < 0.002 * sh * sw)
178
+ continue;
179
+ const rect = cv.minAreaRect(c);
180
+ const rw = rect.size.width;
181
+ const rh = rect.size.height;
182
+ if (Math.min(rw, rh) < 10 || Math.max(rw, rh) / Math.max(1, Math.min(rw, rh)) < 1.5)
183
+ continue;
184
+ const pts = cv.RotatedRect.points(rect);
185
+ perKernel.push({ area, box: pts.map((p) => [p.x / scale, p.y / scale]) });
186
+ }
187
+ finally {
188
+ c.delete();
189
+ }
190
+ }
191
+ }
192
+ // The Python reference loops over two "directional" difference images that are in fact identical (both are
193
+ // ||gx|-|gy|| after convertScaleAbs), so every box is produced twice there. Keeping the duplicates preserves
194
+ // the exact top-N selection behaviour that was validated.
195
+ boxes.push(...perKernel, ...perKernel);
196
+ }
197
+ finally {
198
+ s.dispose();
199
+ }
200
+ boxes.sort((a, b) => b.area - a.area); // Array.sort is stable
201
+ return boxes.slice(0, maxCandidates).map((b) => b.box);
202
+ }
203
+ //# sourceMappingURL=ops.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ops.js","sourceRoot":"","sources":["../src/ops.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,4 @@
1
+ import type { Gray } from './ops.js';
2
+ import type { BarcodeResult, ReadOptions } from './types.js';
3
+ /** Reads barcodes from an already prepared gray image; positions are in that image's coordinates. */
4
+ export declare function readGray(gray: Gray, options?: ReadOptions): Promise<BarcodeResult[]>;
@@ -0,0 +1,234 @@
1
+ // The detection pipeline (port of barcode_reader.py::read_barcodes).
2
+ //
3
+ // Stage order (cheap and most productive first, stops at the first hit unless `all` is set):
4
+ // 1a. ZXing on the full image, plain gray only
5
+ // 2a. Localised + perspective-rectified regions (gradient heuristic), tolerant built-in Code 128 decoder
6
+ // 2b. ZXing on those regions with all preprocessing variants
7
+ // 2c. The same regions at other strip widths
8
+ // 1b. ZXing on the full image with the remaining preprocessing variants (slow on large photos)
9
+ // 3. ZXing on overlapping tiles / bands
10
+ // 4. Rotation sweep
11
+ //
12
+ // The Python version runs all full-image variants before the regions. On a phone photo each full-image ZXing
13
+ // pass is slow, and the stages that rescue difficult labels would only start after most of a time budget was spent.
14
+ import { CONFIDENT_ERROR, MAX_ERROR, decodeRectified } from './code128.js';
15
+ import { affineMap, boundingRect, cropToBars, deskewBars, invertAffine, iou, offsetScale, perspectiveMap, rectify, rotationMatrix, } from './geometry.js';
16
+ import * as ops from './ops.js';
17
+ import { BINARIZERS, zxingDecode } from './zxing.js';
18
+ const VARIANTS = [
19
+ ['gray', (g) => g],
20
+ ['clahe', ops.clahe],
21
+ ['sharpen', ops.sharpen],
22
+ ['otsu', ops.otsu],
23
+ ['adaptive', ops.adaptive],
24
+ ['denoise-otsu', ops.denoiseOtsu],
25
+ ['hblur', ops.hblur],
26
+ ];
27
+ /** Lazily yields preprocessing variants (optionally also upscaled) so an early hit skips the rest. */
28
+ function* variants(gray, name, minWidth = 0) {
29
+ const w = gray.width;
30
+ const scales = [1.0];
31
+ if (minWidth && w < minWidth)
32
+ scales.push(Math.min(4.0, minWidth / w));
33
+ for (const s of scales) {
34
+ const base = s === 1.0 ? gray : ops.resize(gray, Math.round(gray.width * s), Math.round(gray.height * s), 'cubic');
35
+ for (const [vname, fn] of VARIANTS) {
36
+ yield { strategy: `${name}:${vname}${s !== 1.0 ? `@x${s.toFixed(1)}` : ''}`, img: fn(base), scale: s };
37
+ }
38
+ }
39
+ }
40
+ function findCandidates(gray) {
41
+ // The Python version also asks OpenCV's barcode detector (not part of OpenCV.js); the gradient heuristic
42
+ // alone finds the regions in every test image.
43
+ const kept = [];
44
+ for (const b of ops.gradientCandidates(gray)) {
45
+ const r = boundingRect(b);
46
+ if (kept.every((k) => iou(r, boundingRect(k)) < 0.5))
47
+ kept.push(b);
48
+ }
49
+ return kept;
50
+ }
51
+ function dedupe(results) {
52
+ const seen = new Map();
53
+ for (const r of results) {
54
+ const key = `${r.format}\u0000${r.text}`;
55
+ if (!seen.has(key))
56
+ seen.set(key, r);
57
+ }
58
+ return [...seen.values()];
59
+ }
60
+ function rotate(gray, angle) {
61
+ const { width: w, height: h } = gray;
62
+ const m = rotationMatrix(w / 2, h / 2, angle);
63
+ const nw = Math.trunc(h * Math.abs(m[1]) + w * Math.abs(m[0]));
64
+ const nh = Math.trunc(h * Math.abs(m[0]) + w * Math.abs(m[1]));
65
+ m[2] += nw / 2 - w / 2;
66
+ m[5] += nh / 2 - h / 2;
67
+ return { rot: ops.warpAffine(gray, m, nw, nh), inv: invertAffine(m) };
68
+ }
69
+ const toInt = (pts) => pts.map(([x, y]) => [Math.round(x), Math.round(y)]);
70
+ /** Reads barcodes from an already prepared gray image; positions are in that image's coordinates. */
71
+ export async function readGray(gray, options = {}) {
72
+ const findAll = options.all ?? false;
73
+ const thorough = options.thorough ?? false;
74
+ const deadline = options.timeoutMs ? Date.now() + options.timeoutMs : Infinity;
75
+ const expired = () => Date.now() > deadline;
76
+ const results = [];
77
+ const done = () => (results.length > 0 && !findAll) || expired();
78
+ const decode = async (img, strategy, map, binarizers = BINARIZERS) => {
79
+ results.push(...(await zxingDecode(img, strategy, map, binarizers, expired)));
80
+ };
81
+ const fullVariants = variants(gray, 'full', 1600);
82
+ // Stage 1a: full image, plain gray only
83
+ const first = fullVariants.next();
84
+ if (!first.done) {
85
+ await decode(first.value.img, first.value.strategy, offsetScale([0, 0], first.value.scale));
86
+ if (done())
87
+ return dedupe(results);
88
+ }
89
+ // Stage 2: localised + rectified candidates
90
+ const candidates = findCandidates(gray);
91
+ const strips = new Map();
92
+ const getStrip = (i, outWidth, padY) => {
93
+ const key = `${i}/${outWidth}/${padY}`;
94
+ let s = strips.get(key);
95
+ if (!s) {
96
+ const { strip, inv } = rectify(gray, candidates[i], 0.08, padY, outWidth);
97
+ s = { strip, toOrig: perspectiveMap(inv) };
98
+ strips.set(key, s);
99
+ }
100
+ return s;
101
+ };
102
+ const getDeskew = (s) => (s.deskew ??= deskewBars(s.strip));
103
+ const getTight = (s) => (s.tight === undefined ? (s.tight = cropToBars(s.strip)) : s.tight);
104
+ const getTightDeskew = (s, tight) => (s.tightDeskew ??= deskewBars(tight));
105
+ // A tolerant Code 128 decode is accepted at once only when its match error is low (<= CONFIDENT_ERROR).
106
+ // The checksum alone lets about 1 in 103 random misreads through, and on blurry or downscaled photos a
107
+ // misread (typically a mis-sampled start of the symbol) can have an error only slightly above a correct one.
108
+ // So any other decode is kept as a fallback and the lowest-error one over every strip and width wins, once
109
+ // the region stages have found nothing better.
110
+ const fallback = { value: null, error: Infinity };
111
+ const finish = () => {
112
+ if (fallback.value && !results.length)
113
+ results.push(fallback.value);
114
+ return dedupe(results);
115
+ };
116
+ // Tolerant Code 128 decode of a strip, and of its bar rows only: localisation boxes are usually taller than
117
+ // the bars (they include the printed caption), and rows crossing the caption give checksum-valid misreads.
118
+ // Both are tried and the lower-error decode wins.
119
+ const regionBuiltin = (i, outWidth, padY, tag) => {
120
+ const s = getStrip(i, outWidth, padY);
121
+ const attempt = (img, deskew) => {
122
+ const dec = decodeRectified(img);
123
+ return dec ?? (deskew.angle ? decodeRectified(deskew.strip) : null);
124
+ };
125
+ let best = attempt(s.strip, getDeskew(s));
126
+ const tight = getTight(s);
127
+ if (tight) {
128
+ const dec = attempt(tight, getTightDeskew(s, tight));
129
+ if (dec && (!best || dec.error < best.error))
130
+ best = dec;
131
+ }
132
+ if (!best || best.error > MAX_ERROR)
133
+ return;
134
+ const result = {
135
+ text: best.text,
136
+ format: 'Code128',
137
+ strategy: `region${i}${tag}/builtin-code128`,
138
+ position: toInt(candidates[i]),
139
+ };
140
+ if (best.error <= CONFIDENT_ERROR)
141
+ results.push(result);
142
+ else if (best.error < fallback.error) {
143
+ fallback.value = result;
144
+ fallback.error = best.error;
145
+ }
146
+ };
147
+ const regionZxing = async (i, outWidth, padY, variantList, tag) => {
148
+ const s = getStrip(i, outWidth, padY);
149
+ const deskew = getDeskew(s);
150
+ const tight = getTight(s);
151
+ for (const [vname, fn] of variantList) {
152
+ await decode(fn(s.strip), `region${i}${tag}:${vname}`, s.toOrig);
153
+ if (deskew.angle)
154
+ await decode(fn(deskew.strip), `region${i}${tag}:deskew:${vname}`, s.toOrig);
155
+ if (tight && !done())
156
+ await decode(fn(tight), `region${i}${tag}:tight:${vname}`, s.toOrig);
157
+ if (done())
158
+ return;
159
+ }
160
+ };
161
+ // Stage 2a: tolerant Code 128 decoder on every region (no ZXing, so it is cheap)
162
+ for (let i = 0; i < candidates.length; i++) {
163
+ for (const padY of [0.0, -0.25]) {
164
+ regionBuiltin(i, 1600, padY, '');
165
+ if (done())
166
+ return finish();
167
+ }
168
+ }
169
+ // Stage 2b: ZXing on every region, all preprocessing variants
170
+ for (let i = 0; i < candidates.length; i++) {
171
+ for (const padY of [0.0, -0.25]) {
172
+ await regionZxing(i, 1600, padY, VARIANTS, '');
173
+ if (done())
174
+ return finish();
175
+ }
176
+ }
177
+ // Stage 2c: the same regions at other strip widths. ZXing's 1D decoder is sensitive to the exact sampling of
178
+ // blurry bars, so a strip width that fails at 1600 px often decodes at 2400 or 800 px.
179
+ for (let i = 0; i < candidates.length; i++) {
180
+ for (const outWidth of [2400, 800]) {
181
+ for (const padY of [0.0, -0.25]) {
182
+ regionBuiltin(i, outWidth, padY, `@${outWidth}`);
183
+ if (done())
184
+ return finish();
185
+ await regionZxing(i, outWidth, padY, VARIANTS.slice(0, 3), `@${outWidth}`);
186
+ if (done())
187
+ return finish();
188
+ }
189
+ }
190
+ }
191
+ // Only a low-confidence Code 128 read so far: take it rather than spend the time budget on the slow stages
192
+ if (fallback.value && !findAll)
193
+ return finish();
194
+ // Stage 1b: remaining full-image variants (slow on large photos, hence after the region stages)
195
+ for (const v of fullVariants) {
196
+ await decode(v.img, v.strategy, offsetScale([0, 0], v.scale));
197
+ if (done())
198
+ return finish();
199
+ }
200
+ // Stage 3: tiles / bands
201
+ const { width: w, height: h } = gray;
202
+ const regions = [];
203
+ for (const frac of [0.5, 0.33]) {
204
+ const th = Math.trunc(h * frac);
205
+ const tw = Math.trunc(w * frac);
206
+ for (let y = 0; y < Math.max(1, h - th + 1); y += Math.max(1, Math.trunc(th / 2))) {
207
+ regions.push({ name: `band-h${frac}`, x: 0, y, w, h: th });
208
+ }
209
+ for (let x = 0; x < Math.max(1, w - tw + 1); x += Math.max(1, Math.trunc(tw / 2))) {
210
+ regions.push({ name: `band-v${frac}`, x, y: 0, w: tw, h });
211
+ }
212
+ }
213
+ for (const r of regions) {
214
+ const sub = ops.crop(gray, r.x, r.y, Math.min(r.w, w - r.x), Math.min(r.h, h - r.y));
215
+ for (const v of variants(sub, r.name, 1400)) {
216
+ await decode(v.img, v.strategy, offsetScale([r.x, r.y], v.scale));
217
+ if (done())
218
+ return finish();
219
+ }
220
+ }
221
+ // Stage 4: rotation sweep
222
+ if (thorough || !results.length) {
223
+ for (const angle of [-4, 4, -8, 8, -12, 12, -20, 20, -30, 30, -45, 45]) {
224
+ const { rot, inv } = rotate(gray, angle);
225
+ for (const [vname, fn] of VARIANTS.slice(0, 5)) {
226
+ await decode(fn(rot), `rot${angle}:${vname}`, affineMap(inv), BINARIZERS.slice(0, 2));
227
+ if (done())
228
+ return finish();
229
+ }
230
+ }
231
+ }
232
+ return finish();
233
+ }
234
+ //# sourceMappingURL=pipeline.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pipeline.js","sourceRoot":"","sources":["../src/pipeline.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,22 @@
1
+ import type { BarcodeResult, ImageInput, ReadOptions } from './types.js';
2
+ export type WorkerRequest = {
3
+ id: number;
4
+ type: 'read';
5
+ image: ImageInput;
6
+ options?: ReadOptions;
7
+ } | {
8
+ id: number;
9
+ type: 'warmup';
10
+ };
11
+ export type WorkerResponse = {
12
+ id: number;
13
+ type: 'read';
14
+ results: BarcodeResult[];
15
+ } | {
16
+ id: number;
17
+ type: 'warmup';
18
+ } | {
19
+ id: number;
20
+ type: 'error';
21
+ message: string;
22
+ };
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=protocol.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"protocol.js","sourceRoot":"","sources":["../src/protocol.ts"],"names":[],"mappings":""}
@@ -0,0 +1,50 @@
1
+ /** [x, y] in pixels of the input image. */
2
+ export type Point = [number, number];
3
+ export interface BarcodeResult {
4
+ /** The decoded value. */
5
+ text: string;
6
+ /** Barcode format as reported by ZXing, e.g. "Code128", "EAN13", "QRCode". */
7
+ format: string;
8
+ /** Which pipeline stage found it, e.g. "full:gray/local" or "region0/builtin-code128". Useful for tuning. */
9
+ strategy: string;
10
+ /** 4 corners (tl, tr, br, bl) in input image coordinates, when known. */
11
+ position: Point[] | null;
12
+ }
13
+ export interface ReadOptions {
14
+ /** Find every barcode instead of stopping at the first hit. Default false. */
15
+ all?: boolean;
16
+ /** Also run the rotation sweep when something was already found. Default false. */
17
+ thorough?: boolean;
18
+ /**
19
+ * Stop searching after this many milliseconds and return what was found so far. Checked between decode
20
+ * attempts, so it can overrun by one attempt. Default: no limit - set one (8000 is reasonable) for UI use.
21
+ */
22
+ timeoutMs?: number;
23
+ /**
24
+ * Downscale the image so its longest edge is at most this many pixels before decoding. The default (4096)
25
+ * leaves normal phone photos untouched: shrinking a photo can change what a blurry label decodes to.
26
+ */
27
+ maxEdge?: number;
28
+ }
29
+ /** RGBA pixels, the same shape as the DOM `ImageData`. The only input accepted in Node. */
30
+ export interface RawImage {
31
+ data: Uint8ClampedArray | Uint8Array;
32
+ width: number;
33
+ height: number;
34
+ }
35
+ /**
36
+ * Anything that holds an image. Encoded images (Blob, File, bytes) need `createImageBitmap`, i.e. a browser or
37
+ * a Web Worker; in Node pass raw RGBA pixels.
38
+ */
39
+ export type ImageInput = Blob | ArrayBuffer | Uint8Array | ImageBitmap | RawImage | HTMLImageElement | HTMLCanvasElement | OffscreenCanvas;
40
+ export interface BarcodeReaderConfig {
41
+ /**
42
+ * Override how OpenCV.js is loaded. Default: dynamic `import('@techstark/opencv-js')`. Mostly useful in
43
+ * tests and for hosting OpenCV yourself.
44
+ */
45
+ opencvLoader?: () => Promise<unknown>;
46
+ /** URL of `zxing_reader.wasm`. By default the binary embedded in this package is used - no setup needed. */
47
+ zxingWasmUrl?: string;
48
+ /** The wasm bytes themselves. By default the binary embedded in this package is used. */
49
+ zxingWasmBinary?: ArrayBuffer | Uint8Array;
50
+ }
package/dist/types.js ADDED
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":""}
@@ -0,0 +1 @@
1
+ export {};
package/dist/worker.js ADDED
@@ -0,0 +1,24 @@
1
+ // Worker side. Create a worker file in your app that only imports this module:
2
+ //
3
+ // // barcode.worker.ts
4
+ // import 'image-barcode-identifier/worker';
5
+ //
6
+ // and talk to it with `createWorkerReader` from 'image-barcode-identifier/client'.
7
+ import { readBarcodes, warmup } from './index.js';
8
+ const scope = self;
9
+ scope.onmessage = async ({ data }) => {
10
+ try {
11
+ if (data.type === 'warmup') {
12
+ await warmup();
13
+ scope.postMessage({ id: data.id, type: 'warmup' });
14
+ }
15
+ else {
16
+ const results = await readBarcodes(data.image, data.options);
17
+ scope.postMessage({ id: data.id, type: 'read', results });
18
+ }
19
+ }
20
+ catch (error) {
21
+ scope.postMessage({ id: data.id, type: 'error', message: error instanceof Error ? error.message : String(error) });
22
+ }
23
+ };
24
+ //# sourceMappingURL=worker.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"worker.js","sourceRoot":"","sources":["../src/worker.ts"],"names":[],"mappings":"AAAA,+EAA+E;AAC/E,EAAE;AACF,yBAAyB;AACzB,8CAA8C;AAC9C,EAAE;AACF,mFAAmF;AACnF,OAAO,EAAE,YAAY,EAAE,MAAM,EAAE,MAAM,YAAY,CAAC;AAGlD,MAAM,KAAK,GAAG,IAGb,CAAC;AAEF,KAAK,CAAC,SAAS,GAAG,KAAK,EAAE,EAAE,IAAI,EAAE,EAAE,EAAE;IACnC,IAAI,CAAC;QACH,IAAI,IAAI,CAAC,IAAI,KAAK,QAAQ,EAAE,CAAC;YAC3B,MAAM,MAAM,EAAE,CAAC;YACf,KAAK,CAAC,WAAW,CAAC,EAAE,EAAE,EAAE,IAAI,CAAC,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,CAAC,CAAC;QACrD,CAAC;aAAM,CAAC;YACN,MAAM,OAAO,GAAG,MAAM,YAAY,CAAC,IAAI,CAAC,KAAK,EAAE,IAAI,CAAC,OAAO,CAAC,CAAC;YAC7D,KAAK,CAAC,WAAW,CAAC,EAAE,EAAE,EAAE,IAAI,CAAC,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,CAAC,CAAC;QAC5D,CAAC;IACH,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,KAAK,CAAC,WAAW,CAAC,EAAE,EAAE,EAAE,IAAI,CAAC,EAAE,EAAE,IAAI,EAAE,OAAO,EAAE,OAAO,EAAE,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;IACrH,CAAC;AACH,CAAC,CAAC"}
@@ -0,0 +1,16 @@
1
+ import { type Binarizer } from 'zxing-wasm/reader';
2
+ import type { PointMap } from './geometry.js';
3
+ import type { Gray } from './ops.js';
4
+ import type { BarcodeReaderConfig, BarcodeResult } from './types.js';
5
+ export declare const BINARIZERS: {
6
+ name: string;
7
+ value: Binarizer;
8
+ }[];
9
+ export declare function configureZxing(config: BarcodeReaderConfig): void;
10
+ /** Compile the ZXing WASM now instead of on the first decode. */
11
+ export declare function warmupZxing(): Promise<void>;
12
+ /** Decode with ZXing; `toOriginal` maps points of `img` into original image coordinates. */
13
+ export declare function zxingDecode(img: Gray, strategy: string, toOriginal: PointMap, binarizers?: {
14
+ name: string;
15
+ value: Binarizer;
16
+ }[], expired?: () => boolean): Promise<BarcodeResult[]>;