diff --git a/.changeset/pink-tips-unite.md b/.changeset/pink-tips-unite.md
new file mode 100644
index 00000000..16cf192b
--- /dev/null
+++ b/.changeset/pink-tips-unite.md
@@ -0,0 +1,5 @@
+---
+"zxing-wasm": minor
+---
+
+Support WeChat Mini Program.
diff --git a/.changeset/pretty-ravens-send.md b/.changeset/pretty-ravens-send.md
new file mode 100644
index 00000000..ce5c50e7
--- /dev/null
+++ b/.changeset/pretty-ravens-send.md
@@ -0,0 +1,5 @@
+---
+"zxing-wasm": minor
+---
+
+Accept `ArrayBuffer` and `Uint8Array` as input types in `readBarcodes`.
diff --git a/README.md b/README.md
index f0c05819..8d2eba52 100644
--- a/README.md
+++ b/README.md
@@ -130,7 +130,7 @@ Apart from ES and CJS modules, this package also ships IIFE scripts. The registe
### [`readBarcodes`](https://zxing-wasm.deno.dev/functions/full.readBarcodes.html)
-[`readBarcodes`](https://zxing-wasm.deno.dev/functions/full.readBarcodes.html) accepts an image [`Blob`](https://developer.mozilla.org/docs/Web/API/Blob), image [`File`](https://developer.mozilla.org/docs/Web/API/File), or an [`ImageData`](https://developer.mozilla.org/docs/Web/API/ImageData) as its first argument, and various options are supported in [`ReaderOptions`](https://zxing-wasm.deno.dev/interfaces/full.ReaderOptions.html) as an optional second argument.
+[`readBarcodes`](https://zxing-wasm.deno.dev/functions/full.readBarcodes.html) accepts an image [`Blob`](https://developer.mozilla.org/docs/Web/API/Blob), image [`File`](https://developer.mozilla.org/docs/Web/API/File), [`ArrayBuffer`](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/ArrayBuffer), [`Uint8Array`](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Uint8Array), or an [`ImageData`](https://developer.mozilla.org/docs/Web/API/ImageData) as its first argument, and various options are supported in [`ReaderOptions`](https://zxing-wasm.deno.dev/interfaces/full.ReaderOptions.html) as an optional second argument.
The return result of this function is a `Promise` of an array of [`ReadResult`](https://zxing-wasm.deno.dev/interfaces/full.ReadResult.html)s.
@@ -336,6 +336,30 @@ If you want to use this library in non-web runtimes (such as Node.js, Bun, Deno,
});
```
+> [!NOTE]
+> To use this library in a WeChat mini program
, there are several things to keep in mind:
+>
+> 1. Only the `zxing-wasm` import path is supported; `zxing-wasm/reader` or `zxing-wasm/writer` is not supported.
+> 2. Before using the library, you need to copy/move the `node_modules/zxing-wasm/dist/full/zxing_full.wasm` file into your project directory.
+> 3. You must use `prepareZXingModule` to configure how the `.wasm` file will be fetched, loaded, and compiled before calling `readBarcodes` or `writeBarcode`. This is mandatory, and you can do so with the following code:
+>
+> ```typescript
+> prepareZXingModule({
+> overrides: {
+> instantiateWasm(imports, successCallback) {
+> WXWebAssembly.instantiate("path/to/zxing_full.wasm", imports).then(
+> ({ instance }) => successCallback(instance),
+> );
+> return {};
+> },
+> },
+> });
+> ```
+>
+> Note that WeChat mini programs use `WXWebAssembly` instead of the standard `WebAssembly`, and the first argument in `WXWebAssembly.instantiate` should point to the location where the `zxing_full.wasm` file was moved earlier.
+>
+> 4. This library uses a bare minimum `Blob` polyfill in the mini program environment so that no errors will be thrown if you call `writeBarcode`. However, it's recommended to use a full-fledged `Blob` polyfill for not breaking other parts of your program.
+
> [!IMPORTANT]
>
> Each version of this library has a unique corresponding `.wasm` file. If you choose to serve it yourself, please ensure that the `.wasm` file matches the version of the `zxing-wasm` library you are using. Otherwise, you may encounter unexpected errors.
diff --git a/package.json b/package.json
index 945c3c02..c4a90414 100644
--- a/package.json
+++ b/package.json
@@ -9,6 +9,7 @@
],
"main": "./dist/cjs/full/index.js",
"module": "./dist/es/full/index.js",
+ "miniprogram": "./dist/miniprogram",
"exports": {
".": {
"import": "./dist/es/full/index.js",
@@ -171,7 +172,8 @@
"build:es": "vite build",
"build:cjs": "tsx ./scripts/build-cjs.ts",
"build:iife": "tsx ./scripts/build-iife.ts",
- "build": "conc \"pnpm:build:es\" \"pnpm:build:cjs\" \"pnpm:build:iife\"",
+ "build:miniprogram": "tsx ./scripts/build-miniprogram.ts",
+ "build": "conc \"pnpm:build:es\" \"pnpm:build:cjs\" \"pnpm:build:iife\" \"pnpm:build:miniprogram\"",
"postbuild:es": "tsc -p ./tsconfig.pkg.json --declarationDir ./dist/es",
"postbuild:cjs": "tsc -p ./tsconfig.pkg.json --declarationDir ./dist/cjs",
"postbuild": "conc \"pnpm:copy:wasm\" \"pnpm:docs:build\"",
@@ -189,6 +191,7 @@
"@babel/types": "^7.26.9",
"@biomejs/biome": "1.9.4",
"@changesets/cli": "^2.28.1",
+ "@napi-rs/canvas": "^0.1.67",
"@types/babel__core": "^7.20.5",
"@types/node": "^22.13.5",
"@vitest/ui": "^3.0.6",
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index c1f72d58..e2a74387 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -27,6 +27,9 @@ importers:
'@changesets/cli':
specifier: ^2.28.1
version: 2.28.1
+ '@napi-rs/canvas':
+ specifier: ^0.1.67
+ version: 0.1.67
'@types/babel__core':
specifier: ^7.20.5
version: 7.20.5
@@ -717,6 +720,70 @@ packages:
'@manypkg/get-packages@1.1.3':
resolution: {integrity: sha512-fo+QhuU3qE/2TQMQmbVMqaQ6EWbMhi4ABWP+O4AM1NqPBuy0OrApV5LO6BrrgnhtAHS2NH6RrVk9OL181tTi8A==}
+ '@napi-rs/canvas-android-arm64@0.1.67':
+ resolution: {integrity: sha512-W+3DFG5h0WU8Vqqb3W5fNmm5/TPH5ECZRinQDK4CAKFSUkc4iZcDwrmyFG9sB4KdHazf1mFVHCpEeVMO6Mk6Zg==}
+ engines: {node: '>= 10'}
+ cpu: [arm64]
+ os: [android]
+
+ '@napi-rs/canvas-darwin-arm64@0.1.67':
+ resolution: {integrity: sha512-xzrv7QboI47yhIHR5P5u/9KGswokuOKLiKSukr1Ku03RRJxP6lGuVtrAZAgdRg7F9FsuF2REf2yK53YVb6pMlA==}
+ engines: {node: '>= 10'}
+ cpu: [arm64]
+ os: [darwin]
+
+ '@napi-rs/canvas-darwin-x64@0.1.67':
+ resolution: {integrity: sha512-SNk9lYBr84N0gW8MZ2IrjygFtbFBILr3SEqMdHzHHuph20SQmssFvJGPZwSSCMEyKAvyqhogbmlew0te5Z4w9Q==}
+ engines: {node: '>= 10'}
+ cpu: [x64]
+ os: [darwin]
+
+ '@napi-rs/canvas-linux-arm-gnueabihf@0.1.67':
+ resolution: {integrity: sha512-qmBlSvUpl567bzH8tNXi82u5FrL4d0qINqd6K9O7GWGGGFmKMJdrgi2/SW3wwCTxqHBasIDdVWc4KSJfwyaoDQ==}
+ engines: {node: '>= 10'}
+ cpu: [arm]
+ os: [linux]
+
+ '@napi-rs/canvas-linux-arm64-gnu@0.1.67':
+ resolution: {integrity: sha512-k3nAPQefkMeFuJ65Rqdnx92KX1JXQhEKjjWeKsCJB+7sIBgQUWtHo9c3etfVLv5pkWJJDFi/Zc2soNkH3E8dRA==}
+ engines: {node: '>= 10'}
+ cpu: [arm64]
+ os: [linux]
+
+ '@napi-rs/canvas-linux-arm64-musl@0.1.67':
+ resolution: {integrity: sha512-lZwHWR1cCP408l86n3Qbs3X1oFeAYMjJIQvQl1VMZh6wo5PfI+jaZSKBUOd8x44TnVllX9yhLY9unNRztk/sUQ==}
+ engines: {node: '>= 10'}
+ cpu: [arm64]
+ os: [linux]
+
+ '@napi-rs/canvas-linux-riscv64-gnu@0.1.67':
+ resolution: {integrity: sha512-PdBC9p6bLHA1W3OdA0vTHj701SB/kioGQ1uCFBRMs5KBCaMLb/H4aNi8uaIUIEvBWnxeAjoNcLU7//q0FxEosw==}
+ engines: {node: '>= 10'}
+ cpu: [riscv64]
+ os: [linux]
+
+ '@napi-rs/canvas-linux-x64-gnu@0.1.67':
+ resolution: {integrity: sha512-kJJX6eWzjipL/LdKOWCJctc88e5yzuXri8+s0V/lN06OwuLGW62TWS3lvi8qlUrGMOfRGabSWWlB4omhASSB8w==}
+ engines: {node: '>= 10'}
+ cpu: [x64]
+ os: [linux]
+
+ '@napi-rs/canvas-linux-x64-musl@0.1.67':
+ resolution: {integrity: sha512-jLKiPWGeN6ZzhnaLG7ex7eexsiHJ1mdtPK1qKvETIcu45dApMXyUIHvdL6XWB5gFFtj5ScHzLUxv1vkfPZsoxA==}
+ engines: {node: '>= 10'}
+ cpu: [x64]
+ os: [linux]
+
+ '@napi-rs/canvas-win32-x64-msvc@0.1.67':
+ resolution: {integrity: sha512-K/JmkOFbc4iRZYUqJhj0jwqfHA/wNQEmTiGNsgZ6d59yF/IBNp5T0D5eg3B8ghjI8GxDYCiSJ6DNX8mC3Oh2EQ==}
+ engines: {node: '>= 10'}
+ cpu: [x64]
+ os: [win32]
+
+ '@napi-rs/canvas@0.1.67':
+ resolution: {integrity: sha512-VA4Khm/5Kg2bQGx3jXotTC4MloOG8b1Ung80exafUK0k5u6yJmIz3Q2iXeeWZs5weV+LQOEB+CPKsYwEYaGAjw==}
+ engines: {node: '>= 10'}
+
'@nodelib/fs.scandir@2.1.5':
resolution: {integrity: sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==}
engines: {node: '>= 8'}
@@ -2872,6 +2939,49 @@ snapshots:
globby: 11.1.0
read-yaml-file: 1.1.0
+ '@napi-rs/canvas-android-arm64@0.1.67':
+ optional: true
+
+ '@napi-rs/canvas-darwin-arm64@0.1.67':
+ optional: true
+
+ '@napi-rs/canvas-darwin-x64@0.1.67':
+ optional: true
+
+ '@napi-rs/canvas-linux-arm-gnueabihf@0.1.67':
+ optional: true
+
+ '@napi-rs/canvas-linux-arm64-gnu@0.1.67':
+ optional: true
+
+ '@napi-rs/canvas-linux-arm64-musl@0.1.67':
+ optional: true
+
+ '@napi-rs/canvas-linux-riscv64-gnu@0.1.67':
+ optional: true
+
+ '@napi-rs/canvas-linux-x64-gnu@0.1.67':
+ optional: true
+
+ '@napi-rs/canvas-linux-x64-musl@0.1.67':
+ optional: true
+
+ '@napi-rs/canvas-win32-x64-msvc@0.1.67':
+ optional: true
+
+ '@napi-rs/canvas@0.1.67':
+ optionalDependencies:
+ '@napi-rs/canvas-android-arm64': 0.1.67
+ '@napi-rs/canvas-darwin-arm64': 0.1.67
+ '@napi-rs/canvas-darwin-x64': 0.1.67
+ '@napi-rs/canvas-linux-arm-gnueabihf': 0.1.67
+ '@napi-rs/canvas-linux-arm64-gnu': 0.1.67
+ '@napi-rs/canvas-linux-arm64-musl': 0.1.67
+ '@napi-rs/canvas-linux-riscv64-gnu': 0.1.67
+ '@napi-rs/canvas-linux-x64-gnu': 0.1.67
+ '@napi-rs/canvas-linux-x64-musl': 0.1.67
+ '@napi-rs/canvas-win32-x64-msvc': 0.1.67
+
'@nodelib/fs.scandir@2.1.5':
dependencies:
'@nodelib/fs.stat': 2.0.5
diff --git a/scripts/build-cjs.ts b/scripts/build-cjs.ts
index c539e885..102011f3 100644
--- a/scripts/build-cjs.ts
+++ b/scripts/build-cjs.ts
@@ -1,8 +1,10 @@
import { writeFile } from "node:fs/promises";
+import { rimraf } from "rimraf";
import { type LibraryOptions, build } from "vite";
import viteConfig from "../vite.config.js";
async function buildCjs() {
+ await rimraf("dist/cjs");
await build({
...viteConfig,
build: {
diff --git a/scripts/build-miniprogram.ts b/scripts/build-miniprogram.ts
new file mode 100644
index 00000000..1b0152b3
--- /dev/null
+++ b/scripts/build-miniprogram.ts
@@ -0,0 +1,42 @@
+import { writeFile } from "node:fs/promises";
+import { rimraf } from "rimraf";
+import { type LibraryOptions, build } from "vite";
+import viteConfig from "../vite.config.js";
+
+async function buildMiniprogram() {
+ await rimraf("dist/miniprogram");
+ await build({
+ ...viteConfig,
+ mode: "miniprogram",
+ build: {
+ ...viteConfig.build,
+ target: ["es2018"],
+ lib: {
+ ...(viteConfig.build?.lib as LibraryOptions),
+ entry: {
+ index: "./src/full/index.ts",
+ },
+ formats: ["cjs"],
+ },
+ outDir: "dist/miniprogram",
+ rollupOptions: {
+ ...viteConfig.build?.rollupOptions,
+ output: {
+ ...viteConfig.build?.rollupOptions?.output,
+ manualChunks: {},
+ },
+ },
+ },
+ configFile: false,
+ define: {
+ ...viteConfig.define,
+ WebAssembly: "WXWebAssembly",
+ },
+ });
+ await writeFile(
+ "dist/miniprogram/package.json",
+ `${JSON.stringify({ type: "commonjs" }, undefined, 2)}\n`,
+ );
+}
+
+buildMiniprogram();
diff --git a/src/full/index.ts b/src/full/index.ts
index 7b756145..5443c4b3 100644
--- a/src/full/index.ts
+++ b/src/full/index.ts
@@ -74,7 +74,7 @@ export function setZXingModuleOverrides(
}
export async function readBarcodes(
- input: Blob | ImageData,
+ input: Blob | ArrayBuffer | Uint8Array | ImageData,
readerOptions?: ReaderOptions,
) {
return readBarcodesWithFactory(zxingModuleFactory, input, readerOptions);
diff --git a/src/reader/index.ts b/src/reader/index.ts
index f5faaf27..b4d01399 100644
--- a/src/reader/index.ts
+++ b/src/reader/index.ts
@@ -73,7 +73,7 @@ export function setZXingModuleOverrides(
}
export async function readBarcodes(
- input: Blob | ImageData,
+ input: Blob | ArrayBuffer | Uint8Array | ImageData,
readerOptions?: ReaderOptions,
) {
return readBarcodesWithFactory(zxingModuleFactory, input, readerOptions);
diff --git a/src/share.ts b/src/share.ts
index 2d0b530d..e7e58ca8 100644
--- a/src/share.ts
+++ b/src/share.ts
@@ -83,25 +83,51 @@ export const ZXING_WASM_VERSION = NPM_PACKAGE_VERSION;
export const ZXING_CPP_COMMIT = SUBMODULE_COMMIT;
-const DEFAULT_MODULE_OVERRIDES: ZXingModuleOverrides = import.meta.env.PROD
- ? {
- locateFile: (path, prefix) => {
- const match = path.match(/_(.+?)\.wasm$/);
- if (match) {
- return `https://fastly.jsdelivr.net/npm/zxing-wasm@${NPM_PACKAGE_VERSION}/dist/${match[1]}/${path}`;
- }
- return prefix + path;
- },
- }
- : {
- locateFile: (path, prefix) => {
- const match = path.match(/_(.+?)\.wasm$/);
- if (match) {
- return `/src/${match[1]}/${path}`;
+const DEFAULT_MODULE_OVERRIDES: ZXingModuleOverrides =
+ import.meta.env.MODE === "miniprogram"
+ ? {
+ instantiateWasm() {
+ throw Error(
+ `To use zxing-wasm in a WeChat Mini Program, you must provide a custom "instantiateWasm" function, e.g.:
+
+prepareZXingModule({
+ overrides: {
+ instantiateWasm(imports, successCallback) {
+ WXWebAssembly.instantiate("path/to/zxing_full.wasm", imports).then(({ instance }) =>
+ successCallback(instance),
+ );
+ return {};
+ },
+ }
+});
+
+Learn more:
+- https://developers.weixin.qq.com/miniprogram/dev/framework/performance/wasm.html
+- https://emscripten.org/docs/api_reference/module.html#Module.instantiateWasm
+- https://github.com/Sec-ant/zxing-wasm#integrating-in-non-web-runtimes
+`,
+ );
+ },
+ }
+ : import.meta.env.PROD
+ ? {
+ locateFile: (path, prefix) => {
+ const match = path.match(/_(.+?)\.wasm$/);
+ if (match) {
+ return `https://fastly.jsdelivr.net/npm/zxing-wasm@${NPM_PACKAGE_VERSION}/dist/${match[1]}/${path}`;
+ }
+ return prefix + path;
+ },
}
- return prefix + path;
- },
- };
+ : {
+ locateFile: (path, prefix) => {
+ const match = path.match(/_(.+?)\.wasm$/);
+ if (match) {
+ return `/src/${match[1]}/${path}`;
+ }
+ return prefix + path;
+ },
+ };
type CachedValue =
| [ZXingModuleOverrides]
@@ -261,7 +287,7 @@ export function purgeZXingModuleWithFactory(
* Reads barcodes from an image using a ZXing module factory.
*
* @param zxingModuleFactory - Factory function to create a ZXing module instance
- * @param input - Source image data as either a Blob or ImageData object
+ * @param input - Source image data as a Blob, ArrayBuffer, Uint8Array, or ImageData
* @param readerOptions - Optional configuration options for barcode reading (defaults to defaultReaderOptions)
* @returns An array of ReadResult objects containing decoded barcode information
*
@@ -271,7 +297,7 @@ export function purgeZXingModuleWithFactory(
*/
export async function readBarcodesWithFactory(
zxingModuleFactory: ZXingModuleFactory,
- input: Blob | ImageData,
+ input: Blob | ArrayBuffer | Uint8Array | ImageData,
readerOptions: ReaderOptions = defaultReaderOptions,
) {
const requiredReaderOptions: Required = {
@@ -283,18 +309,8 @@ export async function readBarcodesWithFactory(
});
let zxingReadResultVector: ZXingVector;
let bufferPtr: number;
- if ("size" in input) {
- /* Blob */
- const { size } = input;
- const buffer = new Uint8Array(await input.arrayBuffer());
- bufferPtr = zxingModule._malloc(size);
- zxingModule.HEAPU8.set(buffer, bufferPtr);
- zxingReadResultVector = zxingModule.readBarcodesFromImage(
- bufferPtr,
- size,
- readerOptionsToZXingReaderOptions(requiredReaderOptions),
- );
- } else {
+
+ if ("width" in input && "height" in input && "data" in input) {
/* ImageData */
const {
data: buffer,
@@ -310,6 +326,28 @@ export async function readBarcodesWithFactory(
height,
readerOptionsToZXingReaderOptions(requiredReaderOptions),
);
+ } else {
+ let size: number;
+ let buffer: Uint8Array;
+ if ("buffer" in input) {
+ /* Uint8Array */
+ [size, buffer] = [input.byteLength, input];
+ } else if ("byteLength" in input) {
+ /* ArrayBuffer */
+ [size, buffer] = [input.byteLength, new Uint8Array(input)];
+ } else if ("size" in input) {
+ /* Blob */
+ [size, buffer] = [input.size, new Uint8Array(await input.arrayBuffer())];
+ } else {
+ throw new TypeError("Invalid input type");
+ }
+ bufferPtr = zxingModule._malloc(size);
+ zxingModule.HEAPU8.set(buffer, bufferPtr);
+ zxingReadResultVector = zxingModule.readBarcodesFromImage(
+ bufferPtr,
+ size,
+ readerOptionsToZXingReaderOptions(requiredReaderOptions),
+ );
}
zxingModule._free(bufferPtr);
const readResults: ReadResult[] = [];
@@ -364,3 +402,46 @@ export async function writeBarcodeWithFactory(
zxingModule._free(bufferPtr);
return zxingWriteResultToWriteResult(zxingWriteResult);
}
+
+if (import.meta.env.MODE === "miniprogram") {
+ /* A bare minimum Blob polyfill */
+ globalThis.Blob ??= class {
+ #blobParts;
+ #options;
+ #zeroUint8Array = new Uint8Array();
+ constructor(blobParts?: BlobPart[], options?: BlobPropertyBag) {
+ console.error(
+ "For the sake of robustness, a properly implemented Blob polyfill is required.",
+ );
+ this.#blobParts = blobParts as Uint8Array[];
+ this.#options = options;
+ }
+ get size() {
+ return this.#blobParts?.[0]?.byteLength ?? 0;
+ }
+ get type() {
+ return this.#options?.type ?? "";
+ }
+ async arrayBuffer() {
+ return (
+ (this.#blobParts?.[0]?.buffer as ArrayBuffer) ??
+ this.#zeroUint8Array.buffer
+ );
+ }
+ async bytes() {
+ return this.#blobParts?.[0] ?? this.#zeroUint8Array;
+ }
+ slice(): ReturnType {
+ throw new Error("Not implemented");
+ }
+ stream(): ReturnType {
+ throw new Error("Not implemented");
+ }
+ text(): ReturnType {
+ throw new Error("Not implemented");
+ }
+ get [Symbol.toStringTag]() {
+ return "Blob";
+ }
+ };
+}
diff --git a/tests/samples/qrcode/wikipedia.png b/tests/samples/qrcode/wikipedia.png
new file mode 100644
index 00000000..6b3a5193
Binary files /dev/null and b/tests/samples/qrcode/wikipedia.png differ
diff --git a/tests/unit.test.ts b/tests/unit.test.ts
index 3d622af9..4cdb7738 100644
--- a/tests/unit.test.ts
+++ b/tests/unit.test.ts
@@ -1,9 +1,16 @@
-import { afterAll, describe, expect, test, vi } from "vitest";
+import { readFile } from "node:fs/promises";
+import { resolve } from "node:path";
+import { fileURLToPath } from "node:url";
+import { createCanvas, loadImage } from "@napi-rs/canvas";
+import { afterAll, beforeAll, describe, expect, test, vi } from "vitest";
import {
prepareZXingModule as prepareZXingFullModule,
purgeZXingModule as purgeZXingFullModule,
} from "../src/full/index.js";
-import { prepareZXingModule as prepareZXingReaderModule } from "../src/reader/index.js";
+import {
+ prepareZXingModule as prepareZXingReaderModule,
+ readBarcodes,
+} from "../src/reader/index.js";
describe("prepare zxing module", () => {
const consoleMock = vi.spyOn(console, "error").mockImplementation(() => {});
@@ -178,3 +185,62 @@ describe("prepare zxing module", () => {
expect(modulePromise2).toBe(modulePromise3);
});
});
+
+describe("readBarcodes input", async () => {
+ const arrayBuffer = await readFile(
+ fileURLToPath(new URL("./samples/qrcode/wikipedia.png", import.meta.url)),
+ );
+
+ beforeAll(async () => {
+ await prepareZXingReaderModule({
+ overrides: {
+ wasmBinary: (
+ await readFile(
+ resolve(import.meta.dirname, "../src/reader/zxing_reader.wasm"),
+ )
+ ).buffer as ArrayBuffer,
+ },
+ fireImmediately: true,
+ });
+ });
+
+ test("readBarcodes accepts ArrayBuffer as input", async () => {
+ const readResult = await readBarcodes(arrayBuffer);
+ expect(readResult).length(1);
+ expect(readResult[0].text).toBe("http://en.m.wikipedia.org");
+ });
+
+ test("readBarcodes accepts Blob as input", async () => {
+ const blob = new Blob([arrayBuffer], { type: "image/png" });
+ const readResult = await readBarcodes(blob);
+ expect(readResult).length(1);
+ expect(readResult[0].text).toBe("http://en.m.wikipedia.org");
+ });
+
+ test("readBarcodes accepts File as input", async () => {
+ const file = new File([arrayBuffer], "wikipedia.png", {
+ type: "image/png",
+ });
+ const readResult = await readBarcodes(file);
+ expect(readResult).length(1);
+ expect(readResult[0].text).toBe("http://en.m.wikipedia.org");
+ });
+
+ test("readBarcodes accepts Uint8Array as input", async () => {
+ const uint8Array = new Uint8Array(arrayBuffer);
+ const readResult = await readBarcodes(uint8Array);
+ expect(readResult).length(1);
+ expect(readResult[0].text).toBe("http://en.m.wikipedia.org");
+ });
+
+ test("readBarcodes accepts ImageData as input", async () => {
+ const image = await loadImage(arrayBuffer);
+ const canvas = createCanvas(image.width, image.height);
+ const context = canvas.getContext("2d");
+ context.drawImage(image, 0, 0, image.width, image.height);
+ const imageData = context.getImageData(0, 0, image.width, image.height);
+ const readResult = await readBarcodes(imageData);
+ expect(readResult).length(1);
+ expect(readResult[0].text).toBe("http://en.m.wikipedia.org");
+ });
+});