@barcodesdk/decoder-zxing 0.1.0
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/LICENSE +9 -0
- package/dist/decoder.d.ts +11 -0
- package/dist/decoder.d.ts.map +1 -0
- package/dist/format-map.d.ts +5 -0
- package/dist/format-map.d.ts.map +1 -0
- package/dist/index.d.ts +6 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +480 -0
- package/dist/index.js.map +1 -0
- package/dist/normalize.d.ts +4 -0
- package/dist/normalize.d.ts.map +1 -0
- package/dist/preprocess.d.ts +20 -0
- package/dist/preprocess.d.ts.map +1 -0
- package/dist/types.d.ts +36 -0
- package/dist/types.d.ts.map +1 -0
- package/package.json +47 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
Copyright (c) 2026 Vijay Reddy
|
|
2
|
+
|
|
3
|
+
All rights reserved.
|
|
4
|
+
|
|
5
|
+
This software is proprietary beta software. Unauthorized copying,
|
|
6
|
+
modification, distribution, or use is prohibited except under a written
|
|
7
|
+
license agreement with the copyright holder.
|
|
8
|
+
|
|
9
|
+
Third-party notices for bundled dependencies are in NOTICES.md.
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { DecodeFrameInput, DecodedBarcode, DecoderConfig } from "./types.js";
|
|
2
|
+
export declare function initializeDecoder(config: DecoderConfig): Promise<void>;
|
|
3
|
+
export declare function resetDecoderForTests(): void;
|
|
4
|
+
export declare function decodeFrame(input: DecodeFrameInput, config: DecoderConfig): Promise<DecodedBarcode[]>;
|
|
5
|
+
/**
|
|
6
|
+
* Static-image decode with EXIF-oriented multi-scale passes.
|
|
7
|
+
* All corner points are mapped back to the oriented original image size
|
|
8
|
+
* so overlays match the preview.
|
|
9
|
+
*/
|
|
10
|
+
export declare function decodeBlob(blob: Blob, config: DecoderConfig, timestampMs?: number): Promise<DecodedBarcode[]>;
|
|
11
|
+
//# sourceMappingURL=decoder.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"decoder.d.ts","sourceRoot":"","sources":["../src/decoder.ts"],"names":[],"mappings":"AAQA,OAAO,KAAK,EACV,gBAAgB,EAChB,cAAc,EACd,aAAa,EAEd,MAAM,YAAY,CAAC;AA0JpB,wBAAsB,iBAAiB,CAAC,MAAM,EAAE,aAAa,GAAG,OAAO,CAAC,IAAI,CAAC,CAiC5E;AAED,wBAAgB,oBAAoB,IAAI,IAAI,CAG3C;AAED,wBAAsB,WAAW,CAC/B,KAAK,EAAE,gBAAgB,EACvB,MAAM,EAAE,aAAa,GACpB,OAAO,CAAC,cAAc,EAAE,CAAC,CAmB3B;AAmDD;;;;GAIG;AACH,wBAAsB,UAAU,CAC9B,IAAI,EAAE,IAAI,EACV,MAAM,EAAE,aAAa,EACrB,WAAW,SAAa,GACvB,OAAO,CAAC,cAAc,EAAE,CAAC,CA2D3B"}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import type { ReadInputBarcodeFormat } from "zxing-wasm/reader";
|
|
2
|
+
import type { SupportedFormat } from "./types.js";
|
|
3
|
+
export declare function toZxingFormats(formats: SupportedFormat[]): ReadInputBarcodeFormat[];
|
|
4
|
+
export declare function fromZxingFormat(format: ReadInputBarcodeFormat | "None"): SupportedFormat | null;
|
|
5
|
+
//# sourceMappingURL=format-map.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"format-map.d.ts","sourceRoot":"","sources":["../src/format-map.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,mBAAmB,CAAC;AAChE,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAmBlD,wBAAgB,cAAc,CAC5B,OAAO,EAAE,eAAe,EAAE,GACzB,sBAAsB,EAAE,CAG1B;AAED,wBAAgB,eAAe,CAC7B,MAAM,EAAE,sBAAsB,GAAG,MAAM,GACtC,eAAe,GAAG,IAAI,CAKxB"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
export { decodeBlob, decodeFrame, initializeDecoder, resetDecoderForTests, } from "./decoder.js";
|
|
2
|
+
export { fromZxingFormat, toZxingFormats } from "./format-map.js";
|
|
3
|
+
export { normalizeReadResult } from "./normalize.js";
|
|
4
|
+
export { applyPreprocess } from "./preprocess.js";
|
|
5
|
+
export type { DecodeFrameInput, DecodedBarcode, DecoderConfig, Point, PreprocessOptions, SupportedFormat, } from "./types.js";
|
|
6
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,UAAU,EACV,WAAW,EACX,iBAAiB,EACjB,oBAAoB,GACrB,MAAM,cAAc,CAAC;AACtB,OAAO,EAAE,eAAe,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;AAClE,OAAO,EAAE,mBAAmB,EAAE,MAAM,gBAAgB,CAAC;AACrD,OAAO,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAC;AAClD,YAAY,EACV,gBAAgB,EAChB,cAAc,EACd,aAAa,EACb,KAAK,EACL,iBAAiB,EACjB,eAAe,GAChB,MAAM,YAAY,CAAC"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,480 @@
|
|
|
1
|
+
import { readBarcodes, prepareZXingModule } from "zxing-wasm/reader";
|
|
2
|
+
const FORMAT_TO_ZXING = {
|
|
3
|
+
qr_code: "QRCode",
|
|
4
|
+
data_matrix: "DataMatrix",
|
|
5
|
+
code_128: "Code128",
|
|
6
|
+
gs1_128: "Code128",
|
|
7
|
+
ean_13: "EAN13"
|
|
8
|
+
};
|
|
9
|
+
const ZXING_TO_FORMAT = {
|
|
10
|
+
QRCode: "qr_code",
|
|
11
|
+
DataMatrix: "data_matrix",
|
|
12
|
+
Code128: "code_128",
|
|
13
|
+
EAN13: "ean_13"
|
|
14
|
+
};
|
|
15
|
+
function toZxingFormats(formats) {
|
|
16
|
+
const mapped = formats.map((format) => FORMAT_TO_ZXING[format]);
|
|
17
|
+
return [...new Set(mapped)];
|
|
18
|
+
}
|
|
19
|
+
function fromZxingFormat(format) {
|
|
20
|
+
if (format === "None") {
|
|
21
|
+
return null;
|
|
22
|
+
}
|
|
23
|
+
return ZXING_TO_FORMAT[format] ?? null;
|
|
24
|
+
}
|
|
25
|
+
function positionToCornerPoints(position) {
|
|
26
|
+
return [
|
|
27
|
+
position.topLeft,
|
|
28
|
+
position.topRight,
|
|
29
|
+
position.bottomRight,
|
|
30
|
+
position.bottomLeft
|
|
31
|
+
];
|
|
32
|
+
}
|
|
33
|
+
function normalizeReadResult(result, sourceWidth, sourceHeight, timestampMs) {
|
|
34
|
+
if (!result.isValid || result.format === "None") {
|
|
35
|
+
return null;
|
|
36
|
+
}
|
|
37
|
+
const format = fromZxingFormat(result.format);
|
|
38
|
+
if (!format) {
|
|
39
|
+
return null;
|
|
40
|
+
}
|
|
41
|
+
return {
|
|
42
|
+
text: result.text,
|
|
43
|
+
rawBytes: result.bytes.length > 0 ? result.bytes : void 0,
|
|
44
|
+
format,
|
|
45
|
+
cornerPoints: positionToCornerPoints(result.position),
|
|
46
|
+
sourceWidth,
|
|
47
|
+
sourceHeight,
|
|
48
|
+
timestampMs
|
|
49
|
+
};
|
|
50
|
+
}
|
|
51
|
+
function identityMap(point) {
|
|
52
|
+
return { x: point.x, y: point.y };
|
|
53
|
+
}
|
|
54
|
+
function hasActivePreprocess(options) {
|
|
55
|
+
if (!options) {
|
|
56
|
+
return false;
|
|
57
|
+
}
|
|
58
|
+
return options.scale !== void 0 && options.scale !== 1 || options.rotationDegrees !== void 0 && options.rotationDegrees !== 0 || options.contrast !== void 0 && options.contrast !== 1 || options.invert === true;
|
|
59
|
+
}
|
|
60
|
+
function applyContrastInvert(imageData, contrast, invert) {
|
|
61
|
+
if (contrast === 1 && !invert) {
|
|
62
|
+
return imageData;
|
|
63
|
+
}
|
|
64
|
+
const next = createImageData(imageData.width, imageData.height);
|
|
65
|
+
const src = imageData.data;
|
|
66
|
+
const dst = next.data;
|
|
67
|
+
const factor = contrast;
|
|
68
|
+
for (let i = 0; i < src.length; i += 4) {
|
|
69
|
+
let r = src[i];
|
|
70
|
+
let g = src[i + 1];
|
|
71
|
+
let b = src[i + 2];
|
|
72
|
+
if (factor !== 1) {
|
|
73
|
+
r = Math.min(255, Math.max(0, (r - 128) * factor + 128));
|
|
74
|
+
g = Math.min(255, Math.max(0, (g - 128) * factor + 128));
|
|
75
|
+
b = Math.min(255, Math.max(0, (b - 128) * factor + 128));
|
|
76
|
+
}
|
|
77
|
+
if (invert) {
|
|
78
|
+
r = 255 - r;
|
|
79
|
+
g = 255 - g;
|
|
80
|
+
b = 255 - b;
|
|
81
|
+
}
|
|
82
|
+
dst[i] = r;
|
|
83
|
+
dst[i + 1] = g;
|
|
84
|
+
dst[i + 2] = b;
|
|
85
|
+
dst[i + 3] = src[i + 3];
|
|
86
|
+
}
|
|
87
|
+
return next;
|
|
88
|
+
}
|
|
89
|
+
function createImageData(width, height) {
|
|
90
|
+
if (typeof ImageData !== "undefined") {
|
|
91
|
+
return new ImageData(width, height);
|
|
92
|
+
}
|
|
93
|
+
return {
|
|
94
|
+
width,
|
|
95
|
+
height,
|
|
96
|
+
data: new Uint8ClampedArray(width * height * 4),
|
|
97
|
+
colorSpace: "srgb"
|
|
98
|
+
};
|
|
99
|
+
}
|
|
100
|
+
function scaleNearest(source, scale) {
|
|
101
|
+
if (scale === 1) {
|
|
102
|
+
return source;
|
|
103
|
+
}
|
|
104
|
+
const width = Math.max(1, Math.round(source.width * scale));
|
|
105
|
+
const height = Math.max(1, Math.round(source.height * scale));
|
|
106
|
+
const next = createImageData(width, height);
|
|
107
|
+
for (let y = 0; y < height; y += 1) {
|
|
108
|
+
const sy = Math.min(source.height - 1, Math.floor(y / scale));
|
|
109
|
+
for (let x = 0; x < width; x += 1) {
|
|
110
|
+
const sx = Math.min(source.width - 1, Math.floor(x / scale));
|
|
111
|
+
const si = (sy * source.width + sx) * 4;
|
|
112
|
+
const di = (y * width + x) * 4;
|
|
113
|
+
next.data[di] = source.data[si];
|
|
114
|
+
next.data[di + 1] = source.data[si + 1];
|
|
115
|
+
next.data[di + 2] = source.data[si + 2];
|
|
116
|
+
next.data[di + 3] = source.data[si + 3];
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
return next;
|
|
120
|
+
}
|
|
121
|
+
function rotateImageData(source, rotation) {
|
|
122
|
+
if (rotation === 0) {
|
|
123
|
+
return source;
|
|
124
|
+
}
|
|
125
|
+
const { width, height, data } = source;
|
|
126
|
+
const rotatedWidth = rotation === 180 ? width : height;
|
|
127
|
+
const rotatedHeight = rotation === 180 ? height : width;
|
|
128
|
+
const next = createImageData(rotatedWidth, rotatedHeight);
|
|
129
|
+
for (let y = 0; y < height; y += 1) {
|
|
130
|
+
for (let x = 0; x < width; x += 1) {
|
|
131
|
+
let dx = x;
|
|
132
|
+
let dy = y;
|
|
133
|
+
if (rotation === 90) {
|
|
134
|
+
dx = height - 1 - y;
|
|
135
|
+
dy = x;
|
|
136
|
+
} else if (rotation === 180) {
|
|
137
|
+
dx = width - 1 - x;
|
|
138
|
+
dy = height - 1 - y;
|
|
139
|
+
} else if (rotation === 270) {
|
|
140
|
+
dx = y;
|
|
141
|
+
dy = width - 1 - x;
|
|
142
|
+
}
|
|
143
|
+
const si = (y * width + x) * 4;
|
|
144
|
+
const di = (dy * rotatedWidth + dx) * 4;
|
|
145
|
+
next.data[di] = data[si];
|
|
146
|
+
next.data[di + 1] = data[si + 1];
|
|
147
|
+
next.data[di + 2] = data[si + 2];
|
|
148
|
+
next.data[di + 3] = data[si + 3];
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
return next;
|
|
152
|
+
}
|
|
153
|
+
function createMapper(scale, rotation, processedWidth, processedHeight) {
|
|
154
|
+
return (point) => {
|
|
155
|
+
let x = point.x;
|
|
156
|
+
let y = point.y;
|
|
157
|
+
if (rotation === 90) {
|
|
158
|
+
const rx = y;
|
|
159
|
+
const ry = processedWidth - 1 - x;
|
|
160
|
+
x = rx;
|
|
161
|
+
y = ry;
|
|
162
|
+
} else if (rotation === 180) {
|
|
163
|
+
x = processedWidth - 1 - x;
|
|
164
|
+
y = processedHeight - 1 - y;
|
|
165
|
+
} else if (rotation === 270) {
|
|
166
|
+
const rx = processedHeight - 1 - y;
|
|
167
|
+
const ry = x;
|
|
168
|
+
x = rx;
|
|
169
|
+
y = ry;
|
|
170
|
+
}
|
|
171
|
+
return {
|
|
172
|
+
x: x / scale,
|
|
173
|
+
y: y / scale
|
|
174
|
+
};
|
|
175
|
+
};
|
|
176
|
+
}
|
|
177
|
+
function applyPreprocess(source, options) {
|
|
178
|
+
const sourceWidth = source.width;
|
|
179
|
+
const sourceHeight = source.height;
|
|
180
|
+
if (!hasActivePreprocess(options)) {
|
|
181
|
+
return {
|
|
182
|
+
imageData: source,
|
|
183
|
+
mapPointToSource: identityMap,
|
|
184
|
+
sourceWidth,
|
|
185
|
+
sourceHeight
|
|
186
|
+
};
|
|
187
|
+
}
|
|
188
|
+
const scale = (options == null ? void 0 : options.scale) ?? 1;
|
|
189
|
+
const rotation = (options == null ? void 0 : options.rotationDegrees) ?? 0;
|
|
190
|
+
const contrast = (options == null ? void 0 : options.contrast) ?? 1;
|
|
191
|
+
const invert = (options == null ? void 0 : options.invert) === true;
|
|
192
|
+
let processed = scaleNearest(source, scale);
|
|
193
|
+
processed = rotateImageData(processed, rotation);
|
|
194
|
+
processed = applyContrastInvert(processed, contrast, invert);
|
|
195
|
+
return {
|
|
196
|
+
imageData: processed,
|
|
197
|
+
mapPointToSource: createMapper(
|
|
198
|
+
scale,
|
|
199
|
+
rotation,
|
|
200
|
+
processed.width,
|
|
201
|
+
processed.height
|
|
202
|
+
),
|
|
203
|
+
sourceWidth,
|
|
204
|
+
sourceHeight
|
|
205
|
+
};
|
|
206
|
+
}
|
|
207
|
+
let initPromise = null;
|
|
208
|
+
let activeWasmUrl = null;
|
|
209
|
+
function resolveWasmUrl(path, prefix) {
|
|
210
|
+
if (path.endsWith(".wasm") && activeWasmUrl) {
|
|
211
|
+
return activeWasmUrl;
|
|
212
|
+
}
|
|
213
|
+
return `${prefix}${path}`;
|
|
214
|
+
}
|
|
215
|
+
function liveReaderOptions(config) {
|
|
216
|
+
return {
|
|
217
|
+
formats: toZxingFormats(config.formats),
|
|
218
|
+
maxNumberOfSymbols: config.maxResultsPerFrame,
|
|
219
|
+
tryHarder: true,
|
|
220
|
+
tryRotate: true,
|
|
221
|
+
tryInvert: true,
|
|
222
|
+
tryDownscale: true
|
|
223
|
+
};
|
|
224
|
+
}
|
|
225
|
+
function imageReaderOptions(config) {
|
|
226
|
+
return {
|
|
227
|
+
formats: toZxingFormats(config.formats),
|
|
228
|
+
// Collect generously during multi-pass, then bound to maxResultsPerFrame.
|
|
229
|
+
maxNumberOfSymbols: Math.max(config.maxResultsPerFrame, 32),
|
|
230
|
+
tryHarder: true,
|
|
231
|
+
tryRotate: true,
|
|
232
|
+
tryInvert: true,
|
|
233
|
+
// We manage scaling ourselves so coordinates stay consistent.
|
|
234
|
+
tryDownscale: false,
|
|
235
|
+
tryDenoise: true,
|
|
236
|
+
minLineCount: 1
|
|
237
|
+
};
|
|
238
|
+
}
|
|
239
|
+
function boundResults(results, maxResultsPerFrame) {
|
|
240
|
+
if (results.length <= maxResultsPerFrame) {
|
|
241
|
+
return results;
|
|
242
|
+
}
|
|
243
|
+
return results.slice(0, maxResultsPerFrame);
|
|
244
|
+
}
|
|
245
|
+
function scalePoints(points, scaleX, scaleY) {
|
|
246
|
+
return points.map((point) => ({
|
|
247
|
+
x: point.x * scaleX,
|
|
248
|
+
y: point.y * scaleY
|
|
249
|
+
}));
|
|
250
|
+
}
|
|
251
|
+
function quadArea(points) {
|
|
252
|
+
if (points.length < 3) {
|
|
253
|
+
return 0;
|
|
254
|
+
}
|
|
255
|
+
let area = 0;
|
|
256
|
+
for (let i = 0; i < points.length; i += 1) {
|
|
257
|
+
const a = points[i];
|
|
258
|
+
const b = points[(i + 1) % points.length];
|
|
259
|
+
area += a.x * b.y - b.x * a.y;
|
|
260
|
+
}
|
|
261
|
+
return Math.abs(area) / 2;
|
|
262
|
+
}
|
|
263
|
+
function isPlausibleGeometry(points, sourceWidth, sourceHeight) {
|
|
264
|
+
if (points.length < 4) {
|
|
265
|
+
return false;
|
|
266
|
+
}
|
|
267
|
+
if (sourceWidth <= 0 || sourceHeight <= 0) {
|
|
268
|
+
return true;
|
|
269
|
+
}
|
|
270
|
+
for (const point of points) {
|
|
271
|
+
if (!Number.isFinite(point.x) || !Number.isFinite(point.y) || point.x < -sourceWidth * 0.05 || point.y < -sourceHeight * 0.05 || point.x > sourceWidth * 1.05 || point.y > sourceHeight * 1.05) {
|
|
272
|
+
return false;
|
|
273
|
+
}
|
|
274
|
+
}
|
|
275
|
+
const area = quadArea(points);
|
|
276
|
+
const imageArea = sourceWidth * sourceHeight;
|
|
277
|
+
if (area < 24 || area < imageArea * 2e-5) {
|
|
278
|
+
return false;
|
|
279
|
+
}
|
|
280
|
+
if (area > imageArea * 0.6) {
|
|
281
|
+
return false;
|
|
282
|
+
}
|
|
283
|
+
return true;
|
|
284
|
+
}
|
|
285
|
+
function normalizeList(rawResults, sourceWidth, sourceHeight, timestampMs, scaleX = 1, scaleY = 1) {
|
|
286
|
+
const decoded = [];
|
|
287
|
+
for (const result of rawResults) {
|
|
288
|
+
const normalized = normalizeReadResult(
|
|
289
|
+
result,
|
|
290
|
+
sourceWidth,
|
|
291
|
+
sourceHeight,
|
|
292
|
+
timestampMs
|
|
293
|
+
);
|
|
294
|
+
if (!normalized) {
|
|
295
|
+
continue;
|
|
296
|
+
}
|
|
297
|
+
const mapped = {
|
|
298
|
+
...normalized,
|
|
299
|
+
cornerPoints: scalePoints(normalized.cornerPoints, scaleX, scaleY),
|
|
300
|
+
sourceWidth,
|
|
301
|
+
sourceHeight
|
|
302
|
+
};
|
|
303
|
+
if (!isPlausibleGeometry(mapped.cornerPoints, sourceWidth, sourceHeight)) {
|
|
304
|
+
continue;
|
|
305
|
+
}
|
|
306
|
+
decoded.push(mapped);
|
|
307
|
+
}
|
|
308
|
+
return decoded;
|
|
309
|
+
}
|
|
310
|
+
function mergeByValue(results) {
|
|
311
|
+
const best = /* @__PURE__ */ new Map();
|
|
312
|
+
for (const result of results) {
|
|
313
|
+
const key = `${result.format}\0${result.text}`;
|
|
314
|
+
const previous = best.get(key);
|
|
315
|
+
if (!previous || quadArea(result.cornerPoints) > quadArea(previous.cornerPoints)) {
|
|
316
|
+
best.set(key, result);
|
|
317
|
+
}
|
|
318
|
+
}
|
|
319
|
+
return [...best.values()];
|
|
320
|
+
}
|
|
321
|
+
async function initializeDecoder(config) {
|
|
322
|
+
if (!config.wasmModuleUrl) {
|
|
323
|
+
throw new Error("wasmModuleUrl is required.");
|
|
324
|
+
}
|
|
325
|
+
activeWasmUrl = config.wasmModuleUrl;
|
|
326
|
+
const nextInit = async () => {
|
|
327
|
+
await prepareZXingModule({
|
|
328
|
+
overrides: {
|
|
329
|
+
...config.wasmBinary ? { wasmBinary: config.wasmBinary } : {},
|
|
330
|
+
locateFile: resolveWasmUrl
|
|
331
|
+
},
|
|
332
|
+
fireImmediately: true
|
|
333
|
+
});
|
|
334
|
+
await readBarcodes(new Uint8Array(8 * 8 * 4), {
|
|
335
|
+
formats: ["QRCode"],
|
|
336
|
+
maxNumberOfSymbols: 1
|
|
337
|
+
});
|
|
338
|
+
};
|
|
339
|
+
if (!initPromise) {
|
|
340
|
+
initPromise = nextInit();
|
|
341
|
+
} else {
|
|
342
|
+
initPromise = initPromise.then(nextInit);
|
|
343
|
+
}
|
|
344
|
+
try {
|
|
345
|
+
await initPromise;
|
|
346
|
+
} catch (error) {
|
|
347
|
+
initPromise = null;
|
|
348
|
+
throw error;
|
|
349
|
+
}
|
|
350
|
+
}
|
|
351
|
+
function resetDecoderForTests() {
|
|
352
|
+
initPromise = null;
|
|
353
|
+
activeWasmUrl = null;
|
|
354
|
+
}
|
|
355
|
+
async function decodeFrame(input, config) {
|
|
356
|
+
await initializeDecoder(config);
|
|
357
|
+
const processed = applyPreprocess(input.imageData, config.preprocess);
|
|
358
|
+
const rawResults = await readBarcodes(
|
|
359
|
+
processed.imageData,
|
|
360
|
+
liveReaderOptions(config)
|
|
361
|
+
);
|
|
362
|
+
const normalized = normalizeList(
|
|
363
|
+
rawResults,
|
|
364
|
+
processed.imageData.width,
|
|
365
|
+
processed.imageData.height,
|
|
366
|
+
input.timestampMs
|
|
367
|
+
).map((result) => ({
|
|
368
|
+
...result,
|
|
369
|
+
cornerPoints: result.cornerPoints.map(processed.mapPointToSource),
|
|
370
|
+
sourceWidth: processed.sourceWidth,
|
|
371
|
+
sourceHeight: processed.sourceHeight
|
|
372
|
+
}));
|
|
373
|
+
return boundResults(normalized, config.maxResultsPerFrame);
|
|
374
|
+
}
|
|
375
|
+
async function createOrientedBitmap(blob) {
|
|
376
|
+
try {
|
|
377
|
+
return await createImageBitmap(blob, {
|
|
378
|
+
imageOrientation: "from-image"
|
|
379
|
+
});
|
|
380
|
+
} catch {
|
|
381
|
+
return createImageBitmap(blob);
|
|
382
|
+
}
|
|
383
|
+
}
|
|
384
|
+
async function bitmapToImageData(bitmap) {
|
|
385
|
+
const canvas = new OffscreenCanvas(bitmap.width, bitmap.height);
|
|
386
|
+
const context = canvas.getContext("2d");
|
|
387
|
+
if (!context) {
|
|
388
|
+
throw new Error("OffscreenCanvas 2D context unavailable.");
|
|
389
|
+
}
|
|
390
|
+
context.drawImage(bitmap, 0, 0);
|
|
391
|
+
return context.getImageData(0, 0, bitmap.width, bitmap.height);
|
|
392
|
+
}
|
|
393
|
+
async function scaleBitmap(bitmap, maxEdge) {
|
|
394
|
+
const longest = Math.max(bitmap.width, bitmap.height);
|
|
395
|
+
if (longest <= maxEdge) {
|
|
396
|
+
return {
|
|
397
|
+
bitmap,
|
|
398
|
+
width: bitmap.width,
|
|
399
|
+
height: bitmap.height,
|
|
400
|
+
owned: false
|
|
401
|
+
};
|
|
402
|
+
}
|
|
403
|
+
const scale = maxEdge / longest;
|
|
404
|
+
const width = Math.max(1, Math.round(bitmap.width * scale));
|
|
405
|
+
const height = Math.max(1, Math.round(bitmap.height * scale));
|
|
406
|
+
const canvas = new OffscreenCanvas(width, height);
|
|
407
|
+
const context = canvas.getContext("2d");
|
|
408
|
+
if (!context) {
|
|
409
|
+
throw new Error("OffscreenCanvas 2D context unavailable.");
|
|
410
|
+
}
|
|
411
|
+
context.imageSmoothingEnabled = true;
|
|
412
|
+
context.imageSmoothingQuality = "high";
|
|
413
|
+
context.drawImage(bitmap, 0, 0, width, height);
|
|
414
|
+
const scaled = await createImageBitmap(canvas);
|
|
415
|
+
return { bitmap: scaled, width, height, owned: true };
|
|
416
|
+
}
|
|
417
|
+
async function decodeBlob(blob, config, timestampMs = Date.now()) {
|
|
418
|
+
await initializeDecoder(config);
|
|
419
|
+
if (typeof createImageBitmap !== "function" || typeof OffscreenCanvas === "undefined") {
|
|
420
|
+
const rawResults = await readBarcodes(blob, imageReaderOptions(config));
|
|
421
|
+
return boundResults(
|
|
422
|
+
normalizeList(rawResults, 0, 0, timestampMs),
|
|
423
|
+
config.maxResultsPerFrame
|
|
424
|
+
);
|
|
425
|
+
}
|
|
426
|
+
const oriented = await createOrientedBitmap(blob);
|
|
427
|
+
const sourceWidth = oriented.width;
|
|
428
|
+
const sourceHeight = oriented.height;
|
|
429
|
+
const options = imageReaderOptions(config);
|
|
430
|
+
const collected = [];
|
|
431
|
+
const scales = [1600, 2200, 1200, 900, sourceWidth];
|
|
432
|
+
try {
|
|
433
|
+
for (const maxEdge of scales) {
|
|
434
|
+
const { bitmap, width, height, owned } = await scaleBitmap(oriented, maxEdge);
|
|
435
|
+
try {
|
|
436
|
+
const baseImage = await bitmapToImageData(bitmap);
|
|
437
|
+
const processed = applyPreprocess(baseImage, config.preprocess);
|
|
438
|
+
const rawResults = await readBarcodes(processed.imageData, options);
|
|
439
|
+
const scaleX = sourceWidth / width;
|
|
440
|
+
const scaleY = sourceHeight / height;
|
|
441
|
+
const pass = normalizeList(
|
|
442
|
+
rawResults,
|
|
443
|
+
processed.imageData.width,
|
|
444
|
+
processed.imageData.height,
|
|
445
|
+
timestampMs
|
|
446
|
+
).map((result) => {
|
|
447
|
+
const inSourcePass = result.cornerPoints.map(processed.mapPointToSource);
|
|
448
|
+
return {
|
|
449
|
+
...result,
|
|
450
|
+
cornerPoints: inSourcePass.map((point) => ({
|
|
451
|
+
x: point.x * scaleX,
|
|
452
|
+
y: point.y * scaleY
|
|
453
|
+
})),
|
|
454
|
+
sourceWidth,
|
|
455
|
+
sourceHeight
|
|
456
|
+
};
|
|
457
|
+
});
|
|
458
|
+
collected.push(...pass);
|
|
459
|
+
} finally {
|
|
460
|
+
if (owned) {
|
|
461
|
+
bitmap.close();
|
|
462
|
+
}
|
|
463
|
+
}
|
|
464
|
+
}
|
|
465
|
+
} finally {
|
|
466
|
+
oriented.close();
|
|
467
|
+
}
|
|
468
|
+
return boundResults(mergeByValue(collected), config.maxResultsPerFrame);
|
|
469
|
+
}
|
|
470
|
+
export {
|
|
471
|
+
applyPreprocess,
|
|
472
|
+
decodeBlob,
|
|
473
|
+
decodeFrame,
|
|
474
|
+
fromZxingFormat,
|
|
475
|
+
initializeDecoder,
|
|
476
|
+
normalizeReadResult,
|
|
477
|
+
resetDecoderForTests,
|
|
478
|
+
toZxingFormats
|
|
479
|
+
};
|
|
480
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sources":["../src/format-map.ts","../src/normalize.ts","../src/preprocess.ts","../src/decoder.ts"],"sourcesContent":["import type { ReadInputBarcodeFormat } from \"zxing-wasm/reader\";\nimport type { SupportedFormat } from \"./types.js\";\n\nconst FORMAT_TO_ZXING: Record<SupportedFormat, ReadInputBarcodeFormat> = {\n qr_code: \"QRCode\",\n data_matrix: \"DataMatrix\",\n code_128: \"Code128\",\n gs1_128: \"Code128\",\n ean_13: \"EAN13\",\n};\n\nconst ZXING_TO_FORMAT: Partial<\n Record<ReadInputBarcodeFormat, SupportedFormat>\n> = {\n QRCode: \"qr_code\",\n DataMatrix: \"data_matrix\",\n Code128: \"code_128\",\n EAN13: \"ean_13\",\n};\n\nexport function toZxingFormats(\n formats: SupportedFormat[],\n): ReadInputBarcodeFormat[] {\n const mapped = formats.map((format) => FORMAT_TO_ZXING[format]);\n return [...new Set(mapped)];\n}\n\nexport function fromZxingFormat(\n format: ReadInputBarcodeFormat | \"None\",\n): SupportedFormat | null {\n if (format === \"None\") {\n return null;\n }\n return ZXING_TO_FORMAT[format] ?? null;\n}\n","import type { ReadResult } from \"zxing-wasm/reader\";\nimport { fromZxingFormat } from \"./format-map.js\";\nimport type { DecodedBarcode, Point } from \"./types.js\";\n\nfunction positionToCornerPoints(position: ReadResult[\"position\"]): Point[] {\n return [\n position.topLeft,\n position.topRight,\n position.bottomRight,\n position.bottomLeft,\n ];\n}\n\nexport function normalizeReadResult(\n result: ReadResult,\n sourceWidth: number,\n sourceHeight: number,\n timestampMs: number,\n): DecodedBarcode | null {\n if (!result.isValid || result.format === \"None\") {\n return null;\n }\n\n const format = fromZxingFormat(result.format);\n if (!format) {\n return null;\n }\n\n return {\n text: result.text,\n rawBytes: result.bytes.length > 0 ? result.bytes : undefined,\n format,\n cornerPoints: positionToCornerPoints(result.position),\n sourceWidth,\n sourceHeight,\n timestampMs,\n };\n}\n","import type { Point } from \"./types.js\";\n\nexport interface PreprocessOptions {\n scale?: number;\n rotationDegrees?: 0 | 90 | 180 | 270;\n contrast?: number;\n invert?: boolean;\n}\n\nexport interface PreprocessResult {\n imageData: ImageData;\n /** Maps a point in processed space back to original source space. */\n mapPointToSource: (point: Point) => Point;\n sourceWidth: number;\n sourceHeight: number;\n}\n\nfunction identityMap(point: Point): Point {\n return { x: point.x, y: point.y };\n}\n\nfunction hasActivePreprocess(options: PreprocessOptions | null | undefined): boolean {\n if (!options) {\n return false;\n }\n return (\n (options.scale !== undefined && options.scale !== 1) ||\n (options.rotationDegrees !== undefined && options.rotationDegrees !== 0) ||\n (options.contrast !== undefined && options.contrast !== 1) ||\n options.invert === true\n );\n}\n\nfunction applyContrastInvert(\n imageData: ImageData,\n contrast: number,\n invert: boolean,\n): ImageData {\n if (contrast === 1 && !invert) {\n return imageData;\n }\n\n const next = createImageData(imageData.width, imageData.height);\n const src = imageData.data;\n const dst = next.data;\n const factor = contrast;\n\n for (let i = 0; i < src.length; i += 4) {\n let r = src[i];\n let g = src[i + 1];\n let b = src[i + 2];\n\n if (factor !== 1) {\n r = Math.min(255, Math.max(0, (r - 128) * factor + 128));\n g = Math.min(255, Math.max(0, (g - 128) * factor + 128));\n b = Math.min(255, Math.max(0, (b - 128) * factor + 128));\n }\n\n if (invert) {\n r = 255 - r;\n g = 255 - g;\n b = 255 - b;\n }\n\n dst[i] = r;\n dst[i + 1] = g;\n dst[i + 2] = b;\n dst[i + 3] = src[i + 3];\n }\n\n return next;\n}\n\nfunction createImageData(width: number, height: number): ImageData {\n if (typeof ImageData !== \"undefined\") {\n return new ImageData(width, height);\n }\n return {\n width,\n height,\n data: new Uint8ClampedArray(width * height * 4),\n colorSpace: \"srgb\",\n } as ImageData;\n}\n\nfunction scaleNearest(source: ImageData, scale: number): ImageData {\n if (scale === 1) {\n return source;\n }\n const width = Math.max(1, Math.round(source.width * scale));\n const height = Math.max(1, Math.round(source.height * scale));\n const next = createImageData(width, height);\n for (let y = 0; y < height; y += 1) {\n const sy = Math.min(source.height - 1, Math.floor(y / scale));\n for (let x = 0; x < width; x += 1) {\n const sx = Math.min(source.width - 1, Math.floor(x / scale));\n const si = (sy * source.width + sx) * 4;\n const di = (y * width + x) * 4;\n next.data[di] = source.data[si];\n next.data[di + 1] = source.data[si + 1];\n next.data[di + 2] = source.data[si + 2];\n next.data[di + 3] = source.data[si + 3];\n }\n }\n return next;\n}\n\nfunction rotateImageData(\n source: ImageData,\n rotation: 0 | 90 | 180 | 270,\n): ImageData {\n if (rotation === 0) {\n return source;\n }\n\n const { width, height, data } = source;\n const rotatedWidth = rotation === 180 ? width : height;\n const rotatedHeight = rotation === 180 ? height : width;\n const next = createImageData(rotatedWidth, rotatedHeight);\n\n for (let y = 0; y < height; y += 1) {\n for (let x = 0; x < width; x += 1) {\n let dx = x;\n let dy = y;\n if (rotation === 90) {\n dx = height - 1 - y;\n dy = x;\n } else if (rotation === 180) {\n dx = width - 1 - x;\n dy = height - 1 - y;\n } else if (rotation === 270) {\n dx = y;\n dy = width - 1 - x;\n }\n const si = (y * width + x) * 4;\n const di = (dy * rotatedWidth + dx) * 4;\n next.data[di] = data[si];\n next.data[di + 1] = data[si + 1];\n next.data[di + 2] = data[si + 2];\n next.data[di + 3] = data[si + 3];\n }\n }\n\n return next;\n}\n\nfunction createMapper(\n scale: number,\n rotation: 0 | 90 | 180 | 270,\n processedWidth: number,\n processedHeight: number,\n): (point: Point) => Point {\n return (point: Point): Point => {\n let x = point.x;\n let y = point.y;\n\n if (rotation === 90) {\n // Inverse of (x,y) → (h-1-y, x)\n const rx = y;\n const ry = processedWidth - 1 - x;\n x = rx;\n y = ry;\n } else if (rotation === 180) {\n x = processedWidth - 1 - x;\n y = processedHeight - 1 - y;\n } else if (rotation === 270) {\n // Inverse of (x,y) → (y, w-1-x)\n const rx = processedHeight - 1 - y;\n const ry = x;\n x = rx;\n y = ry;\n }\n\n return {\n x: x / scale,\n y: y / scale,\n };\n };\n}\n\n/**\n * Apply optional scale / rotation / contrast / invert, returning ImageData\n * plus a geometry mapper back to the original source dimensions (FR-012).\n */\nexport function applyPreprocess(\n source: ImageData,\n options: PreprocessOptions | null | undefined,\n): PreprocessResult {\n const sourceWidth = source.width;\n const sourceHeight = source.height;\n\n if (!hasActivePreprocess(options)) {\n return {\n imageData: source,\n mapPointToSource: identityMap,\n sourceWidth,\n sourceHeight,\n };\n }\n\n const scale = options?.scale ?? 1;\n const rotation = options?.rotationDegrees ?? 0;\n const contrast = options?.contrast ?? 1;\n const invert = options?.invert === true;\n\n let processed = scaleNearest(source, scale);\n processed = rotateImageData(processed, rotation);\n processed = applyContrastInvert(processed, contrast, invert);\n\n return {\n imageData: processed,\n mapPointToSource: createMapper(\n scale,\n rotation,\n processed.width,\n processed.height,\n ),\n sourceWidth,\n sourceHeight,\n };\n}\n","import {\n prepareZXingModule,\n readBarcodes,\n type ReaderOptions,\n} from \"zxing-wasm/reader\";\nimport { toZxingFormats } from \"./format-map.js\";\nimport { normalizeReadResult } from \"./normalize.js\";\nimport { applyPreprocess } from \"./preprocess.js\";\nimport type {\n DecodeFrameInput,\n DecodedBarcode,\n DecoderConfig,\n Point,\n} from \"./types.js\";\n\nlet initPromise: Promise<void> | null = null;\nlet activeWasmUrl: string | null = null;\n\nfunction resolveWasmUrl(path: string, prefix: string): string {\n if (path.endsWith(\".wasm\") && activeWasmUrl) {\n return activeWasmUrl;\n }\n return `${prefix}${path}`;\n}\n\nfunction liveReaderOptions(config: DecoderConfig): ReaderOptions {\n return {\n formats: toZxingFormats(config.formats),\n maxNumberOfSymbols: config.maxResultsPerFrame,\n tryHarder: true,\n tryRotate: true,\n tryInvert: true,\n tryDownscale: true,\n };\n}\n\nfunction imageReaderOptions(config: DecoderConfig): ReaderOptions {\n return {\n formats: toZxingFormats(config.formats),\n // Collect generously during multi-pass, then bound to maxResultsPerFrame.\n maxNumberOfSymbols: Math.max(config.maxResultsPerFrame, 32),\n tryHarder: true,\n tryRotate: true,\n tryInvert: true,\n // We manage scaling ourselves so coordinates stay consistent.\n tryDownscale: false,\n tryDenoise: true,\n minLineCount: 1,\n };\n}\n\nfunction boundResults(\n results: DecodedBarcode[],\n maxResultsPerFrame: number,\n): DecodedBarcode[] {\n if (results.length <= maxResultsPerFrame) {\n return results;\n }\n return results.slice(0, maxResultsPerFrame);\n}\n\nfunction scalePoints(points: Point[], scaleX: number, scaleY: number): Point[] {\n return points.map((point) => ({\n x: point.x * scaleX,\n y: point.y * scaleY,\n }));\n}\n\nfunction quadArea(points: Point[]): number {\n if (points.length < 3) {\n return 0;\n }\n let area = 0;\n for (let i = 0; i < points.length; i += 1) {\n const a = points[i];\n const b = points[(i + 1) % points.length];\n area += a.x * b.y - b.x * a.y;\n }\n return Math.abs(area) / 2;\n}\n\nfunction isPlausibleGeometry(\n points: Point[],\n sourceWidth: number,\n sourceHeight: number,\n): boolean {\n if (points.length < 4) {\n return false;\n }\n\n // Unknown source size (Node blob fallback) — keep decoder results as-is.\n if (sourceWidth <= 0 || sourceHeight <= 0) {\n return true;\n }\n\n for (const point of points) {\n if (\n !Number.isFinite(point.x) ||\n !Number.isFinite(point.y) ||\n point.x < -sourceWidth * 0.05 ||\n point.y < -sourceHeight * 0.05 ||\n point.x > sourceWidth * 1.05 ||\n point.y > sourceHeight * 1.05\n ) {\n return false;\n }\n }\n\n const area = quadArea(points);\n const imageArea = sourceWidth * sourceHeight;\n // Reject pin-sized / degenerate quads and absurdly huge covers.\n if (area < 24 || area < imageArea * 0.00002) {\n return false;\n }\n if (area > imageArea * 0.6) {\n return false;\n }\n return true;\n}\n\nfunction normalizeList(\n rawResults: Awaited<ReturnType<typeof readBarcodes>>,\n sourceWidth: number,\n sourceHeight: number,\n timestampMs: number,\n scaleX = 1,\n scaleY = 1,\n): DecodedBarcode[] {\n const decoded: DecodedBarcode[] = [];\n for (const result of rawResults) {\n const normalized = normalizeReadResult(\n result,\n sourceWidth,\n sourceHeight,\n timestampMs,\n );\n if (!normalized) {\n continue;\n }\n\n const mapped: DecodedBarcode = {\n ...normalized,\n cornerPoints: scalePoints(normalized.cornerPoints, scaleX, scaleY),\n sourceWidth,\n sourceHeight,\n };\n\n if (!isPlausibleGeometry(mapped.cornerPoints, sourceWidth, sourceHeight)) {\n continue;\n }\n decoded.push(mapped);\n }\n return decoded;\n}\n\nfunction mergeByValue(results: DecodedBarcode[]): DecodedBarcode[] {\n const best = new Map<string, DecodedBarcode>();\n for (const result of results) {\n const key = `${result.format}\\u0000${result.text}`;\n const previous = best.get(key);\n if (!previous || quadArea(result.cornerPoints) > quadArea(previous.cornerPoints)) {\n best.set(key, result);\n }\n }\n return [...best.values()];\n}\n\nexport async function initializeDecoder(config: DecoderConfig): Promise<void> {\n if (!config.wasmModuleUrl) {\n throw new Error(\"wasmModuleUrl is required.\");\n }\n\n activeWasmUrl = config.wasmModuleUrl;\n const nextInit = async () => {\n await prepareZXingModule({\n overrides: {\n ...(config.wasmBinary ? { wasmBinary: config.wasmBinary } : {}),\n locateFile: resolveWasmUrl,\n },\n fireImmediately: true,\n });\n // Warm up JIT before the first real frame.\n await readBarcodes(new Uint8Array(8 * 8 * 4), {\n formats: [\"QRCode\"],\n maxNumberOfSymbols: 1,\n });\n };\n\n if (!initPromise) {\n initPromise = nextInit();\n } else {\n initPromise = initPromise.then(nextInit);\n }\n\n try {\n await initPromise;\n } catch (error) {\n initPromise = null;\n throw error;\n }\n}\n\nexport function resetDecoderForTests(): void {\n initPromise = null;\n activeWasmUrl = null;\n}\n\nexport async function decodeFrame(\n input: DecodeFrameInput,\n config: DecoderConfig,\n): Promise<DecodedBarcode[]> {\n await initializeDecoder(config);\n const processed = applyPreprocess(input.imageData, config.preprocess);\n const rawResults = await readBarcodes(\n processed.imageData,\n liveReaderOptions(config),\n );\n const normalized = normalizeList(\n rawResults,\n processed.imageData.width,\n processed.imageData.height,\n input.timestampMs,\n ).map((result) => ({\n ...result,\n cornerPoints: result.cornerPoints.map(processed.mapPointToSource),\n sourceWidth: processed.sourceWidth,\n sourceHeight: processed.sourceHeight,\n }));\n return boundResults(normalized, config.maxResultsPerFrame);\n}\n\nasync function createOrientedBitmap(blob: Blob): Promise<ImageBitmap> {\n try {\n return await createImageBitmap(blob, {\n imageOrientation: \"from-image\",\n } as ImageBitmapOptions);\n } catch {\n return createImageBitmap(blob);\n }\n}\n\nasync function bitmapToImageData(bitmap: ImageBitmap): Promise<ImageData> {\n const canvas = new OffscreenCanvas(bitmap.width, bitmap.height);\n const context = canvas.getContext(\"2d\");\n if (!context) {\n throw new Error(\"OffscreenCanvas 2D context unavailable.\");\n }\n context.drawImage(bitmap, 0, 0);\n return context.getImageData(0, 0, bitmap.width, bitmap.height);\n}\n\nasync function scaleBitmap(\n bitmap: ImageBitmap,\n maxEdge: number,\n): Promise<{ bitmap: ImageBitmap; width: number; height: number; owned: boolean }> {\n const longest = Math.max(bitmap.width, bitmap.height);\n if (longest <= maxEdge) {\n return {\n bitmap,\n width: bitmap.width,\n height: bitmap.height,\n owned: false,\n };\n }\n\n const scale = maxEdge / longest;\n const width = Math.max(1, Math.round(bitmap.width * scale));\n const height = Math.max(1, Math.round(bitmap.height * scale));\n const canvas = new OffscreenCanvas(width, height);\n const context = canvas.getContext(\"2d\");\n if (!context) {\n throw new Error(\"OffscreenCanvas 2D context unavailable.\");\n }\n context.imageSmoothingEnabled = true;\n context.imageSmoothingQuality = \"high\";\n context.drawImage(bitmap, 0, 0, width, height);\n const scaled = await createImageBitmap(canvas);\n return { bitmap: scaled, width, height, owned: true };\n}\n\n/**\n * Static-image decode with EXIF-oriented multi-scale passes.\n * All corner points are mapped back to the oriented original image size\n * so overlays match the preview.\n */\nexport async function decodeBlob(\n blob: Blob,\n config: DecoderConfig,\n timestampMs = Date.now(),\n): Promise<DecodedBarcode[]> {\n await initializeDecoder(config);\n\n if (typeof createImageBitmap !== \"function\" || typeof OffscreenCanvas === \"undefined\") {\n // Node / tests without bitmap: fall back to direct blob decode.\n const rawResults = await readBarcodes(blob, imageReaderOptions(config));\n return boundResults(\n normalizeList(rawResults, 0, 0, timestampMs),\n config.maxResultsPerFrame,\n );\n }\n\n const oriented = await createOrientedBitmap(blob);\n const sourceWidth = oriented.width;\n const sourceHeight = oriented.height;\n const options = imageReaderOptions(config);\n const collected: DecodedBarcode[] = [];\n\n // Prefer mid sizes for dense packs, then full, then smaller.\n const scales = [1600, 2200, 1200, 900, sourceWidth];\n\n try {\n for (const maxEdge of scales) {\n const { bitmap, width, height, owned } = await scaleBitmap(oriented, maxEdge);\n try {\n const baseImage = await bitmapToImageData(bitmap);\n const processed = applyPreprocess(baseImage, config.preprocess);\n const rawResults = await readBarcodes(processed.imageData, options);\n const scaleX = sourceWidth / width;\n const scaleY = sourceHeight / height;\n const pass = normalizeList(\n rawResults,\n processed.imageData.width,\n processed.imageData.height,\n timestampMs,\n ).map((result) => {\n const inSourcePass = result.cornerPoints.map(processed.mapPointToSource);\n return {\n ...result,\n cornerPoints: inSourcePass.map((point) => ({\n x: point.x * scaleX,\n y: point.y * scaleY,\n })),\n sourceWidth,\n sourceHeight,\n };\n });\n collected.push(...pass);\n } finally {\n if (owned) {\n bitmap.close();\n }\n }\n }\n } finally {\n oriented.close();\n }\n\n return boundResults(mergeByValue(collected), config.maxResultsPerFrame);\n}\n"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import type { ReadResult } from "zxing-wasm/reader";
|
|
2
|
+
import type { DecodedBarcode } from "./types.js";
|
|
3
|
+
export declare function normalizeReadResult(result: ReadResult, sourceWidth: number, sourceHeight: number, timestampMs: number): DecodedBarcode | null;
|
|
4
|
+
//# sourceMappingURL=normalize.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"normalize.d.ts","sourceRoot":"","sources":["../src/normalize.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAEpD,OAAO,KAAK,EAAE,cAAc,EAAS,MAAM,YAAY,CAAC;AAWxD,wBAAgB,mBAAmB,CACjC,MAAM,EAAE,UAAU,EAClB,WAAW,EAAE,MAAM,EACnB,YAAY,EAAE,MAAM,EACpB,WAAW,EAAE,MAAM,GAClB,cAAc,GAAG,IAAI,CAmBvB"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import type { Point } from "./types.js";
|
|
2
|
+
export interface PreprocessOptions {
|
|
3
|
+
scale?: number;
|
|
4
|
+
rotationDegrees?: 0 | 90 | 180 | 270;
|
|
5
|
+
contrast?: number;
|
|
6
|
+
invert?: boolean;
|
|
7
|
+
}
|
|
8
|
+
export interface PreprocessResult {
|
|
9
|
+
imageData: ImageData;
|
|
10
|
+
/** Maps a point in processed space back to original source space. */
|
|
11
|
+
mapPointToSource: (point: Point) => Point;
|
|
12
|
+
sourceWidth: number;
|
|
13
|
+
sourceHeight: number;
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* Apply optional scale / rotation / contrast / invert, returning ImageData
|
|
17
|
+
* plus a geometry mapper back to the original source dimensions (FR-012).
|
|
18
|
+
*/
|
|
19
|
+
export declare function applyPreprocess(source: ImageData, options: PreprocessOptions | null | undefined): PreprocessResult;
|
|
20
|
+
//# sourceMappingURL=preprocess.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"preprocess.d.ts","sourceRoot":"","sources":["../src/preprocess.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AAExC,MAAM,WAAW,iBAAiB;IAChC,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,eAAe,CAAC,EAAE,CAAC,GAAG,EAAE,GAAG,GAAG,GAAG,GAAG,CAAC;IACrC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,MAAM,CAAC,EAAE,OAAO,CAAC;CAClB;AAED,MAAM,WAAW,gBAAgB;IAC/B,SAAS,EAAE,SAAS,CAAC;IACrB,qEAAqE;IACrE,gBAAgB,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,KAAK,CAAC;IAC1C,WAAW,EAAE,MAAM,CAAC;IACpB,YAAY,EAAE,MAAM,CAAC;CACtB;AAqKD;;;GAGG;AACH,wBAAgB,eAAe,CAC7B,MAAM,EAAE,SAAS,EACjB,OAAO,EAAE,iBAAiB,GAAG,IAAI,GAAG,SAAS,GAC5C,gBAAgB,CAiClB"}
|
package/dist/types.d.ts
ADDED
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
/** Matches @barcodesdk/core BarcodeFormat — kept local to avoid circular deps. */
|
|
2
|
+
export type SupportedFormat = "qr_code" | "data_matrix" | "code_128" | "gs1_128" | "ean_13";
|
|
3
|
+
export interface Point {
|
|
4
|
+
x: number;
|
|
5
|
+
y: number;
|
|
6
|
+
}
|
|
7
|
+
export interface DecodedBarcode {
|
|
8
|
+
text: string;
|
|
9
|
+
rawBytes?: Uint8Array;
|
|
10
|
+
format: SupportedFormat;
|
|
11
|
+
cornerPoints: Point[];
|
|
12
|
+
sourceWidth: number;
|
|
13
|
+
sourceHeight: number;
|
|
14
|
+
timestampMs: number;
|
|
15
|
+
}
|
|
16
|
+
export interface PreprocessOptions {
|
|
17
|
+
scale?: number;
|
|
18
|
+
rotationDegrees?: 0 | 90 | 180 | 270;
|
|
19
|
+
contrast?: number;
|
|
20
|
+
invert?: boolean;
|
|
21
|
+
}
|
|
22
|
+
export interface DecoderConfig {
|
|
23
|
+
formats: SupportedFormat[];
|
|
24
|
+
maxResultsPerFrame: number;
|
|
25
|
+
/** Resolved URL passed to Emscripten locateFile for the .wasm asset. */
|
|
26
|
+
wasmModuleUrl: string;
|
|
27
|
+
/** Optional preloaded WASM bytes (used in Node tests). */
|
|
28
|
+
wasmBinary?: Uint8Array;
|
|
29
|
+
/** Optional evidence-backed preprocessing (FR-012). */
|
|
30
|
+
preprocess?: PreprocessOptions | null;
|
|
31
|
+
}
|
|
32
|
+
export interface DecodeFrameInput {
|
|
33
|
+
imageData: ImageData;
|
|
34
|
+
timestampMs: number;
|
|
35
|
+
}
|
|
36
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,kFAAkF;AAClF,MAAM,MAAM,eAAe,GACvB,SAAS,GACT,aAAa,GACb,UAAU,GACV,SAAS,GACT,QAAQ,CAAC;AAEb,MAAM,WAAW,KAAK;IACpB,CAAC,EAAE,MAAM,CAAC;IACV,CAAC,EAAE,MAAM,CAAC;CACX;AAED,MAAM,WAAW,cAAc;IAC7B,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,CAAC,EAAE,UAAU,CAAC;IACtB,MAAM,EAAE,eAAe,CAAC;IACxB,YAAY,EAAE,KAAK,EAAE,CAAC;IACtB,WAAW,EAAE,MAAM,CAAC;IACpB,YAAY,EAAE,MAAM,CAAC;IACrB,WAAW,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,iBAAiB;IAChC,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,eAAe,CAAC,EAAE,CAAC,GAAG,EAAE,GAAG,GAAG,GAAG,GAAG,CAAC;IACrC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,MAAM,CAAC,EAAE,OAAO,CAAC;CAClB;AAED,MAAM,WAAW,aAAa;IAC5B,OAAO,EAAE,eAAe,EAAE,CAAC;IAC3B,kBAAkB,EAAE,MAAM,CAAC;IAC3B,wEAAwE;IACxE,aAAa,EAAE,MAAM,CAAC;IACtB,0DAA0D;IAC1D,UAAU,CAAC,EAAE,UAAU,CAAC;IACxB,uDAAuD;IACvD,UAAU,CAAC,EAAE,iBAAiB,GAAG,IAAI,CAAC;CACvC;AAED,MAAM,WAAW,gBAAgB;IAC/B,SAAS,EAAE,SAAS,CAAC;IACrB,WAAW,EAAE,MAAM,CAAC;CACrB"}
|
package/package.json
ADDED
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@barcodesdk/decoder-zxing",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "ZXing-WASM decoder adapter for Barcode WebSDK",
|
|
5
|
+
"license": "SEE LICENSE IN LICENSE",
|
|
6
|
+
"author": "Vijay Reddy",
|
|
7
|
+
"repository": {
|
|
8
|
+
"type": "git",
|
|
9
|
+
"url": "git+https://github.com/vjiayreddy/barcodesdk.git",
|
|
10
|
+
"directory": "packages/decoder-zxing"
|
|
11
|
+
},
|
|
12
|
+
"publishConfig": {
|
|
13
|
+
"access": "public",
|
|
14
|
+
"tag": "beta"
|
|
15
|
+
},
|
|
16
|
+
"type": "module",
|
|
17
|
+
"sideEffects": false,
|
|
18
|
+
"files": [
|
|
19
|
+
"dist"
|
|
20
|
+
],
|
|
21
|
+
"main": "./dist/index.js",
|
|
22
|
+
"module": "./dist/index.js",
|
|
23
|
+
"types": "./dist/index.d.ts",
|
|
24
|
+
"exports": {
|
|
25
|
+
".": {
|
|
26
|
+
"types": "./dist/index.d.ts",
|
|
27
|
+
"import": "./dist/index.js"
|
|
28
|
+
}
|
|
29
|
+
},
|
|
30
|
+
"dependencies": {
|
|
31
|
+
"zxing-wasm": "^3.1.3"
|
|
32
|
+
},
|
|
33
|
+
"devDependencies": {
|
|
34
|
+
"pngjs": "^7.0.0",
|
|
35
|
+
"qrcode": "^1.5.4",
|
|
36
|
+
"typescript": "^5",
|
|
37
|
+
"vite": "^6",
|
|
38
|
+
"vitest": "^3"
|
|
39
|
+
},
|
|
40
|
+
"scripts": {
|
|
41
|
+
"build": "vite build && tsc --emitDeclarationOnly -p tsconfig.build.json",
|
|
42
|
+
"dev": "vite build --watch",
|
|
43
|
+
"typecheck": "tsc --noEmit",
|
|
44
|
+
"test": "vitest run",
|
|
45
|
+
"test:watch": "vitest"
|
|
46
|
+
}
|
|
47
|
+
}
|