zxing-wasm

repository·main·Indexed 42 days ago

https://github.com/sec-ant/zxing-wasm

A WebAssembly port of ZXing-C++ provided as an ES/CJS module with types. It enables reading and writing of various 1D and 2D barcodes across JavaScript runtimes including Web, Node.js, Bun, and Deno. Version 3.1.4 supports a wide range of formats such as QRCode, Code128, DataMatrix, and PDF417. The package offers optimized subpaths for reader-only, writer-only, or full functionality to reduce WASM binary size.

Tokens
11K
Snippets
40
Records
49
Agent score
55%

What's inside zxing-wasm

  1. Trigger immediate `.wasm` instantiation and caching control

    main

    By default, the .wasm binary is only fetched and instantiated when a readBarcodes or writeBarcode function is first called.

    To explicitly trigger the download and instantiation immediately (e.g., during app startup), set fireImmediately: true in prepareZXingModule. When fireImmediately is true, prepareZXingModule returns a Promise that resolves to the underlying Emscripten module.

    To force a re-fetch and re-instantiation (bypassing the default equality check on overrides), provide a custom equalityFn that always returns false.

    prepareZXingModule({
      overrides: {
        /* ... your desired overrides ... */
      },
      fireImmediately: true,
      equalityFn: () => false, // force re-fetch and re-instantiate
    });
  2. Understand barcode formats and symbologies

    main

    The library distinguishes between canonical names (e.g., QRCode, EAN13) and symbologies (e.g., EANUPC or QRCode).

    • Symbology Roots: Represented in bold italic in documentation, these are group identifiers. Passing a symbology root to a reader matches any variant within that group.
    • ReadResult.format: Returns the specific detected format (the variant) or the symbology root if no finer variant was identified.
    • ReadResult.symbology: Always returns the symbology root.

    Linear (1D) Barcodes

    Supported formats include:

    • Codabar
    • Code39 (variants: Code39Std, Code39Ext)
    • Code32
    • PZN
    • Code93
    • Code128 (supports GS1)
    • ITF (variants: ITF14)
    • DataBar (variants: DataBarOmni, DataBarStk, DataBarStkOmni, DataBarLtd, DataBarExp, DataBarExpStk; supports GS1)
    • EANUPC (variants: EAN13, EAN8, EAN5, EAN2; supports Retail)
    • ISBN
    • UPCA, UPCE
    • Telepen (variants: TelepenAlpha, TelepenNumeric)
    • OtherBarcode (variant: DXFilmEdge)

    Matrix (2D) Barcodes

    Supported formats include:

    • PDF417 (variants: CompactPDF417, MicroPDF417)
    • Aztec (variants: AztecCode, AztecRune; supports GS1)
    • QRCode (variants: QRCodeModel1, QRCodeModel2, MicroQRCode, RMQRCode; supports GS1)
    • DataMatrix (supports GS1)
    • MaxiCode (Note: Reading MaxiCode requires a pure monochrome image with an unrotated/unskewed symbol and a sufficient white border).
  3. Choose a package subpath based on your needs

    main

    The zxing-wasm package provides three subpaths to optimize the WebAssembly (WASM) binary size depending on whether you need to read, write, or both barcodes:

    • zxing-wasm or zxing-wasm/full: Provides both readBarcodes and writeBarcode functions. WASM size: ~1.46 MiB.
    • zxing-wasm/reader: Provides only the readBarcodes function. WASM size: ~1.04 MiB.
    • zxing-wasm/writer: Provides only the writeBarcode function. WASM size: ~636 KiB.
    // Full functionality
    import { readBarcodes, writeBarcode } from "zxing-wasm";
    // or
    import { readBarcodes, writeBarcode } from "zxing-wasm/full";
    
    // Reader only
    import { readBarcodes } from "zxing-wasm/reader";
    
    // Writer only
    import { writeBarcode } from "zxing-wasm/writer";
  4. Higher-level libraries using zxing-wasm

    main

    If you prefer a higher-level abstraction rather than using zxing-wasm directly, several libraries use barcode-detector (which uses zxing-wasm under the hood) to simplify barcode detection:

    • barcode-detector: A Barcode Detection API polyfill/ponyfill.
    • vue-qrcode-reader: Vue.js components for detecting QR codes and other formats.
    • @yudiel/react-qr-scanner: A React library for scanning QR Codes.
    • svelte-qrcode-reader: Svelte 5 components for detecting and decoding QR codes.
  5. Integrate zxing-wasm in Node.js (Non-Web Runtimes)

    main

    To use the library in environments like Node.js, Bun, or Deno without a web server, you must manually provide the .wasm binary via prepareZXingModule overrides. Here are the recommended approaches for Node.js:

    1. Using instantiateWasm: Manually call WebAssembly.instantiate with a buffer read from the filesystem.
    2. Using wasmBinary: Pass the file buffer directly as an ArrayBuffer.
    3. Using locateFile with Object URLs: Create a Blob URL from the file buffer and use locateFile to return it. Use the postRun hook to call URL.revokeObjectURL to free memory.
    4. Using locateFile with Base64 Data URLs: (Not recommended) Convert the file to a Base64 string and return a data URL.
    // Example: Using wasmBinary in Node.js
    import { readFileSync } from "node:fs";
    import { prepareZXingModule } from "zxing-wasm/reader";
    
    prepareZXingModule({
      overrides: {
        wasmBinary: readFileSync("/path/to/the/zxing_reader.wasm")
          .buffer as ArrayBuffer,
      },
    });
  6. Configure custom `.wasm` serving paths

    main

    By default, zxing-wasm uses a jsDelivr CDN to fetch the required .wasm binary. To serve the .wasm file from your own server or a different CDN, use prepareZXingModule with an overrides object containing a locateFile function. This is necessary before calling any barcode reading or writing functions.

    Important: Ensure the .wasm file version matches your zxing-wasm library version to avoid errors.

    import {
      prepareZXingModule,
      writeBarcode,
      ZXING_WASM_VERSION,
    } from "zxing-wasm";
    
    // Override the locateFile function
    prepareZXingModule({
      overrides: {
        locateFile: (path, prefix) => {
          if (path.endsWith(".wasm")) {
            return `https://unpkg.com/zxing-wasm@${ZXING_WASM_VERSION}/dist/full/${path}`;
          }
          return prefix + path;
        },
      },
    });
    
    // Call read or write functions afterward
    const writeOutput = await writeBarcode("Hello world!");
  7. Use zxing-wasm via IIFE scripts

    main

    For non-module environments, you can include the package via CDN using IIFE scripts. All exported functions and variables are available under the global ZXingWASM object.

    Replace <version> with the desired version number in the URLs below:

    <!-- full -->
    <script src="https://cdn.jsdelivr.net/npm/zxing-wasm@<version>/dist/iife/full/index.js"></script>
    
    <!-- reader -->
    <script src="https://cdn.jsdelivr.net/npm/zxing-wasm@<version>/dist/iife/reader/index.js"></script>
    
    <!-- writer -->
    <script src="https://cdn.jsdelivr.net/npm/zxing-wasm@<version>/dist/iife/writer/index.js"></script>
  8. Build zxing-wasm from source

    main

    To build the project manually, ensure you have pnpm, CMake, and Emscripten installed. Follow these steps:

    1. Clone the repository with submodules: git clone --recurse-submodules https://github.com/Sec-ant/zxing-wasm
    2. Navigate to the directory: cd zxing-wasm
    3. Install dependencies: pnpm i --frozen-lockfile
    4. Build the WASM component: pnpm build:wasm
    5. Build the project: pnpm build
    git clone --recurse-submodules https://github.com/Sec-ant/zxing-wasm
    cd zxing-wasm
    pnpm i --frozen-lockfile
    pnpm build:wasm
    pnpm build
  9. Use zxing-wasm in WeChat Mini Programs

    main

    Using zxing-wasm in WeChat mini programs requires specific configuration due to environment limitations:

    1. Import Path: Use only the base zxing-wasm import path. zxing-wasm/reader and zxing-wasm/writer are not supported.
    2. File Management: Manually copy node_modules/zxing-wasm/dist/full/zxing_full.wasm into your project directory.
    3. Configuration: You must use prepareZXingModule to configure loading via WXWebAssembly.instantiate (the WeChat-specific WebAssembly API).
    4. Polyfills: The library includes a minimal Blob polyfill, but a full-fledged Blob polyfill is recommended for overall stability.
    // WeChat Mini Program configuration
    prepareZXingModule({
      overrides: {
        instantiateWasm(imports, successCallback) {
          WXWebAssembly.instantiate("path/to/zxing_full.wasm", imports).then(
            ({ instance }) => successCallback(instance),
          );
          return {};
        },
      },
    });
  10. Initialize submodules for zxing-wasm

    main

    This project relies on zxing-cpp and zint as submodules. If you cloned the repository without the --recurse-submodules flag, you must manually initialize them to ensure barcode reading and generation capabilities work correctly.

    git submodule update --init --recursive
  11. Use ImageData in Node.js or non-browser runtimes

    main

    The readBarcodes function accepts an ImageData object. While ImageData is a standard DOM type, the library uses duck-typing. To use it in Node.js or other environments, provide an object that matches the following shape, ensuring the data property is in RGBA format using a Uint8ClampedArray.

    interface ImageData {
      data: Uint8ClampedArray;
      width: number;
      height: number;
    }