CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/npm-zxing--library

TypeScript port of ZXing multi-format 1D/2D barcode image processing library

Overview
Eval results
Files

datamatrix.mddocs/reference/

Data Matrix

The Data Matrix module provides comprehensive support for encoding and decoding Data Matrix 2D barcodes, following the ISO/IEC 16022:2000(E) standard. Data Matrix is a two-dimensional barcode format that can encode large amounts of data in a compact space with robust error correction capabilities (ECC200 Reed-Solomon).

Package Information

  • Package Name: @zxing/library
  • Package Type: npm
  • Module: core/datamatrix
  • Language: TypeScript
  • Standard: ISO/IEC 16022:2000(E)
  • Error Correction: ECC200 (Reed-Solomon)
  • Shapes: Square and rectangular symbols

Core Imports

import {
  // Reader/Writer
  DataMatrixReader,
  DataMatrixWriter,
  
  // Symbol information
  SymbolInfo,
  SymbolShapeHint,
  Dimension,
  
  // Encoders
  HighLevelEncoder as DataMatrixHighLevelEncoder,
  MinimalEncoder as DataMatrixMinimalEncoder,
  
  // Placement and error correction
  DefaultPlacement as DataMatrixDefaultPlacement,
  ErrorCorrection as DataMatrixErrorCorrection,
  
  // Decoder components
  Decoder as DataMatrixDecoder,
  Detector as DataMatrixDetector,
  Version as DataMatrixVersion,
  DecodedBitStreamParser as DataMatrixDecodedBitStreamParser,
  
  // Supporting types
  BarcodeFormat,
  EncodeHintType,
  DecodeHintType,
  Result,
  BinaryBitmap,
  BitMatrix
} from "@zxing/library";

Basic Usage

Decoding a Data Matrix Code

import {
  DataMatrixReader,
  BinaryBitmap,
  HybridBinarizer,
  RGBLuminanceSource,
  DecodeHintType,
  Result
} from "@zxing/library";

// Create luminance source from image data
const luminanceSource = new RGBLuminanceSource(
  imageData,  // Uint8ClampedArray: image pixel data
  width,      // number: image width
  height      // number: image height
);

// Create binary bitmap
const binaryBitmap = new BinaryBitmap(
  new HybridBinarizer(luminanceSource)
);

// Decode Data Matrix
const reader = new DataMatrixReader();
try {
  const result: Result = reader.decode(binaryBitmap);

  console.log("Decoded text:", result.getText());
  console.log("Format:", result.getBarcodeFormat()); // BarcodeFormat.DATA_MATRIX
  console.log("Raw bytes:", result.getRawBytes());
  
  // Access result points (corners)
  const points = result.getResultPoints();
  console.log(`Detected at ${points.length} corner points`);
} catch (error) {
  console.error("Data Matrix decode failed:", error);
}

Encoding a Data Matrix Code

import {
  DataMatrixWriter,
  BarcodeFormat,
  EncodeHintType,
  SymbolShapeHint,
  BitMatrix
} from "@zxing/library";

const writer = new DataMatrixWriter();

// Basic encoding with square preference
const hints = new Map<EncodeHintType, any>();
hints.set(EncodeHintType.DATA_MATRIX_SHAPE, SymbolShapeHint.FORCE_SQUARE);
hints.set(EncodeHintType.CHARACTER_SET, "UTF-8");

const bitMatrix: BitMatrix = writer.encode(
  "Hello, Data Matrix!",
  BarcodeFormat.DATA_MATRIX,
  200,  // width: number
  200,  // height: number
  hints // Map<EncodeHintType, any>
);

// Render BitMatrix to canvas/image
const width: number = bitMatrix.getWidth();
const height: number = bitMatrix.getHeight();

for (let y = 0; y < height; y++) {
  for (let x = 0; x < width; x++) {
    const isBlack: boolean = bitMatrix.get(x, y);
    // Draw pixel at (x, y) - black if true, white if false
  }
}

Architecture

The Data Matrix module is organized into several key components:

  • Reader/Writer: High-level interfaces (DataMatrixReader, DataMatrixWriter) for decoding and encoding
  • Decoder: Low-level decoding logic including bit stream parsing and error correction
  • Encoders: Two encoding engines:
    • HighLevelEncoder: Fast greedy algorithm for most use cases
    • MinimalEncoder: Graph-based optimization for minimal encoding length
  • Symbol Info: Symbol size and capacity database for different Data Matrix versions
  • Detector: Pattern detection and corner identification in images
  • Error Correction: Reed-Solomon ECC200 implementation
  • Placement: Bit placement algorithm following ISO/IEC 16022 Annex M.1

Capabilities

DataMatrixReader

Decodes Data Matrix codes from binary bitmap images, with support for both pure barcodes and complex image detection.

/**
 * Data Matrix barcode reader
 * Decodes Data Matrix 2D barcodes from images using pattern detection and error correction
 */
class DataMatrixReader implements Reader {
  /**
   * Locates and decodes a Data Matrix code in an image
   * @param image - BinaryBitmap: binary representation of the image
   * @param hints - Map<DecodeHintType, any>: optional decode hints
   *   - PURE_BARCODE: boolean for pure barcode extraction (faster)
   *   - CHARACTER_SET: string for text encoding
   * @returns Result: decoded text, raw bytes, and metadata
   * @throws NotFoundException if Data Matrix code cannot be found
   * @throws FormatException if Data Matrix code cannot be decoded
   * @throws ChecksumException if error correction fails (too many errors)
   */
  decode(image: BinaryBitmap, hints?: Map<DecodeHintType, any>): Result;

  /**
   * Resets any internal state (currently no-op for Data Matrix)
   */
  reset(): void;
}

Usage Examples:

import {
  DataMatrixReader,
  BinaryBitmap,
  HybridBinarizer,
  RGBLuminanceSource,
  DecodeHintType,
  Result,
  ResultMetadataType,
  BarcodeFormat
} from "@zxing/library";

// Standard decoding with automatic detection
const reader = new DataMatrixReader();
const luminanceSource = new RGBLuminanceSource(imageData, width, height);
const binarizer = new HybridBinarizer(luminanceSource);
const binaryBitmap = new BinaryBitmap(binarizer);

try {
  const result: Result = reader.decode(binaryBitmap);

  console.log("Text:", result.getText());
  console.log("Format:", result.getBarcodeFormat()); // BarcodeFormat.DATA_MATRIX
  console.log("Timestamp:", result.getTimestamp());

  // Access metadata
  const metadata = result.getResultMetadata();
  if (metadata && metadata.has(ResultMetadataType.ERROR_CORRECTION_LEVEL)) {
    const ecLevel = metadata.get(ResultMetadataType.ERROR_CORRECTION_LEVEL);
    console.log("EC Level:", ecLevel);
  }

  // Get detected corner points
  const points = result.getResultPoints();
  points.forEach((point, i) => {
    console.log(`Corner ${i}: (${point.getX()}, ${point.getY()})`);
  });
  
  // Access raw bytes
  const rawBytes = result.getRawBytes();
  if (rawBytes) {
    console.log("Raw bytes length:", rawBytes.length);
  }
} catch (error) {
  console.error("Data Matrix decode failed:", error);
}

// Pure barcode mode (faster, requires clean image with no rotation)
const pureHints = new Map<DecodeHintType, any>();
pureHints.set(DecodeHintType.PURE_BARCODE, true);

try {
  const pureResult: Result = reader.decode(binaryBitmap, pureHints);
  console.log("Pure barcode decode:", pureResult.getText());
} catch (error) {
  console.error("Pure barcode decode failed:", error);
}

// Character set specification
const utf8Hints = new Map<DecodeHintType, any>();
utf8Hints.set(DecodeHintType.CHARACTER_SET, "UTF-8");

try {
  const utf8Result: Result = reader.decode(binaryBitmap, utf8Hints);
  console.log("UTF-8 decoded:", utf8Result.getText());
} catch (error) {
  console.error("UTF-8 decode failed:", error);
}

Decode Hints:

  • DecodeHintType.PURE_BARCODE: Set to true for pure, unrotated barcodes (faster processing, no detection needed)
  • DecodeHintType.CHARACTER_SET: Specify character encoding (e.g., "UTF-8", "ISO-8859-1", "Windows-1252")

DataMatrixWriter

Encodes text and binary data into Data Matrix barcode format with configurable size and shape constraints.

/**
 * Data Matrix barcode writer
 * Encodes text and data into Data Matrix 2D barcode format
 */
class DataMatrixWriter implements Writer {
  /**
   * Encodes content as a Data Matrix barcode
   * @param contents - string: text or data to encode
   * @param format - BarcodeFormat: must be BarcodeFormat.DATA_MATRIX
   * @param width - number: desired width in pixels (minimum enforced by symbol size)
   * @param height - number: desired height in pixels (minimum enforced by symbol size)
   * @param hints - Map<EncodeHintType, unknown>: optional encoding hints
   *   - DATA_MATRIX_SHAPE: SymbolShapeHint (FORCE_NONE|FORCE_SQUARE|FORCE_RECTANGLE)
   *   - MIN_SIZE: Dimension (minimum symbol dimensions)
   *   - MAX_SIZE: Dimension (maximum symbol dimensions)
   *   - DATA_MATRIX_COMPACT: boolean (use MinimalEncoder)
   *   - FORCE_C40: boolean (force C40 encoding mode)
   *   - CHARACTER_SET: string (character encoding)
   *   - GS1_FORMAT: boolean (enable GS1 encoding with FNC1)
   * @returns BitMatrix: encoded barcode as binary matrix
   * @throws Error if contents is empty, format is wrong, or dimensions are negative
   * @throws WriterException if encoding fails
   */
  encode(
    contents: string,
    format: BarcodeFormat,
    width: number,
    height: number,
    hints?: Map<EncodeHintType, unknown>
  ): BitMatrix;
}

Encoding Hints:

  • DATA_MATRIX_SHAPE: Control symbol shape (SymbolShapeHint enum)
  • MIN_SIZE: Minimum symbol size as Dimension object
  • MAX_SIZE: Maximum symbol size as Dimension object
  • DATA_MATRIX_COMPACT: Use MinimalEncoder for optimal compression (boolean)
  • FORCE_C40: Force C40 encoding mode (boolean)
  • CHARACTER_SET: Character set for encoding (string)
  • GS1_FORMAT: Enable GS1 format encoding with FNC1 (boolean)

Usage Examples:

import {
  DataMatrixWriter,
  BarcodeFormat,
  EncodeHintType,
  SymbolShapeHint,
  Dimension,
  BitMatrix
} from "@zxing/library";

const writer = new DataMatrixWriter();

// Square symbol (most common)
const squareHints = new Map<EncodeHintType, any>();
squareHints.set(EncodeHintType.DATA_MATRIX_SHAPE, SymbolShapeHint.FORCE_SQUARE);
squareHints.set(EncodeHintType.CHARACTER_SET, "UTF-8");

const squareMatrix: BitMatrix = writer.encode(
  "https://example.com/product/12345",
  BarcodeFormat.DATA_MATRIX,
  200,
  200,
  squareHints
);

// Rectangular symbol with size constraints
const rectHints = new Map<EncodeHintType, any>();
rectHints.set(EncodeHintType.DATA_MATRIX_SHAPE, SymbolShapeHint.FORCE_RECTANGLE);
rectHints.set(EncodeHintType.MIN_SIZE, new Dimension(10, 10));
rectHints.set(EncodeHintType.MAX_SIZE, new Dimension(48, 48));

const rectMatrix: BitMatrix = writer.encode(
  "Compact data",
  BarcodeFormat.DATA_MATRIX,
  300,
  200,
  rectHints
);

// Minimal encoding for better compression
const compactHints = new Map<EncodeHintType, any>();
compactHints.set(EncodeHintType.DATA_MATRIX_COMPACT, true);

const compactMatrix: BitMatrix = writer.encode(
  "ABCDEF123456",
  BarcodeFormat.DATA_MATRIX,
  150,
  150,
  compactHints
);

// GS1 format encoding with FNC1 character
const gs1Hints = new Map<EncodeHintType, any>();
gs1Hints.set(EncodeHintType.GS1_FORMAT, true);
gs1Hints.set(EncodeHintType.DATA_MATRIX_COMPACT, true);

const gs1Matrix: BitMatrix = writer.encode(
  "01095012345678903310ABC123", // GS1 Application Identifiers
  BarcodeFormat.DATA_MATRIX,
  200,
  200,
  gs1Hints
);

// Force C40 encoding mode for uppercase text
const c40Hints = new Map<EncodeHintType, any>();
c40Hints.set(EncodeHintType.FORCE_C40, true);

const c40Matrix: BitMatrix = writer.encode(
  "UPPER CASE TEXT 123",
  BarcodeFormat.DATA_MATRIX,
  180,
  180,
  c40Hints
);

// Auto-select shape (optimal for data)
const autoHints = new Map<EncodeHintType, any>();
autoHints.set(EncodeHintType.DATA_MATRIX_SHAPE, SymbolShapeHint.FORCE_NONE);

const autoMatrix: BitMatrix = writer.encode(
  "Auto-selected shape",
  BarcodeFormat.DATA_MATRIX,
  200,
  200,
  autoHints
);

// Render BitMatrix to canvas
function renderToCanvas(matrix: BitMatrix, canvas: HTMLCanvasElement): void {
  const ctx = canvas.getContext("2d")!;
  const width = matrix.getWidth();
  const height = matrix.getHeight();

  canvas.width = width;
  canvas.height = height;

  const imageData = ctx.createImageData(width, height);
  
  for (let y = 0; y < height; y++) {
    for (let x = 0; x < width; x++) {
      const offset = (y * width + x) * 4;
      const color = matrix.get(x, y) ? 0 : 255;
      
      imageData.data[offset] = color;     // R
      imageData.data[offset + 1] = color; // G
      imageData.data[offset + 2] = color; // B
      imageData.data[offset + 3] = 255;   // A
    }
  }
  
  ctx.putImageData(imageData, 0, 0);
}

// Error handling
try {
  const matrix: BitMatrix = writer.encode("Data", BarcodeFormat.DATA_MATRIX, 100, 100);
  const canvas = document.getElementById("dm-canvas") as HTMLCanvasElement;
  renderToCanvas(matrix, canvas);
} catch (error) {
  console.error("Encoding or rendering failed:", error);
}

DataMatrixSymbolInfo

Provides symbol size information, capacity, and error correction parameters for Data Matrix codes.

/**
 * Data Matrix symbol information
 * Provides size, capacity, and error correction details for each symbol variant
 */
class SymbolInfo {
  /**
   * Looks up the appropriate symbol info for given data capacity
   * Selects smallest symbol that fits data with specified constraints
   * @param dataCodewords - number: number of data codewords to encode
   * @param shape - SymbolShapeHint: shape preference (FORCE_NONE|FORCE_SQUARE|FORCE_RECTANGLE)
   * @param minSize - Dimension: optional minimum symbol dimensions
   * @param maxSize - Dimension: optional maximum symbol dimensions
   * @param fail - boolean: whether to throw error if no symbol found (default: true)
   * @returns SymbolInfo: appropriate symbol for the data
   * @throws Error if no suitable symbol found and fail=true
   */
  static lookup(
    dataCodewords: number,
    shape?: SymbolShapeHint,
    minSize?: Dimension,
    maxSize?: Dimension,
    fail?: boolean
  ): SymbolInfo;

  /**
   * Gets the width of the data region in modules (excludes borders)
   * @returns number: data region width
   */
  getSymbolDataWidth(): number;

  /**
   * Gets the height of the data region in modules (excludes borders)
   * @returns number: data region height
   */
  getSymbolDataHeight(): number;

  /**
   * Gets the total symbol width including borders in modules
   * @returns number: total width including finder patterns
   */
  getSymbolWidth(): number;

  /**
   * Gets the total symbol height including borders in modules
   * @returns number: total height including finder patterns
   */
  getSymbolHeight(): number;

  /**
   * Gets the total number of codewords (data + error correction)
   * @returns number: total codewords in symbol
   */
  getCodewordCount(): number;

  /**
   * Gets the number of interleaved blocks for this symbol
   * Larger symbols use multiple interleaved blocks
   * @returns number: block count (1 or 2)
   */
  getInterleavedBlockCount(): number;

  /**
   * Gets the data capacity in codewords (excludes error correction)
   * @returns number: data codewords
   */
  getDataCapacity(): number;

  /**
   * Gets the number of error correction codewords
   * @returns number: error correction codewords
   */
  getErrorCodewords(): number;

  /**
   * Gets the data length for a specific interleaved block
   * @param index - number: block index (1-based)
   * @returns number: data codewords in block
   */
  getDataLengthForInterleavedBlock(index: number): number;

  /**
   * Gets the error correction length for a specific interleaved block
   * @param index - number: block index (1-based)
   * @returns number: error correction codewords in block
   */
  getErrorLengthForInterleavedBlock(index: number): number;
}

Usage Examples:

import {
  SymbolInfo,
  SymbolShapeHint,
  Dimension
} from "@zxing/library";

// Find smallest square symbol for 10 data codewords
const squareSymbol: SymbolInfo = SymbolInfo.lookup(10, SymbolShapeHint.FORCE_SQUARE);

console.log(`Symbol size: ${squareSymbol.getSymbolWidth()} × ${squareSymbol.getSymbolHeight()}`);
console.log(`Data region: ${squareSymbol.getSymbolDataWidth()} × ${squareSymbol.getSymbolDataHeight()}`);
console.log(`Data capacity: ${squareSymbol.getDataCapacity()} codewords`);
console.log(`Error correction: ${squareSymbol.getErrorCodewords()} codewords`);
console.log(`Total codewords: ${squareSymbol.getCodewordCount()}`);

// Find rectangular symbol with size constraints
const minSize = new Dimension(10, 10);
const maxSize = new Dimension(24, 24);

const rectSymbol: SymbolInfo = SymbolInfo.lookup(
  15,
  SymbolShapeHint.FORCE_RECTANGLE,
  minSize,
  maxSize
);

console.log(`Rectangle: ${rectSymbol.getSymbolWidth()} × ${rectSymbol.getSymbolHeight()}`);

// Check interleaved blocks
const blockCount: number = rectSymbol.getInterleavedBlockCount();
console.log(`Interleaved blocks: ${blockCount}`);

if (blockCount > 1) {
  for (let i = 1; i <= blockCount; i++) {
    const dataLen: number = rectSymbol.getDataLengthForInterleavedBlock(i);
    const errorLen: number = rectSymbol.getErrorLengthForInterleavedBlock(i);
    console.log(`Block ${i}: ${dataLen} data + ${errorLen} error codewords`);
  }
}

// Check if symbol supports required capacity
function findSymbolForData(requiredDataCodewords: number): SymbolInfo | null {
  try {
    const symbol: SymbolInfo = SymbolInfo.lookup(
      requiredDataCodewords,
      SymbolShapeHint.FORCE_NONE
    );
    console.log(`Found symbol: ${symbol.getSymbolWidth()}×${symbol.getSymbolHeight()}`);
    console.log(`Capacity: ${symbol.getDataCapacity()} codewords`);
    return symbol;
  } catch (e) {
    console.error(`No symbol found for ${requiredDataCodewords} codewords`);
    return null;
  }
}

// Test different capacities
[5, 10, 50, 100, 200].forEach(capacity => {
  const symbol = findSymbolForData(capacity);
  if (symbol) {
    console.log(`${capacity} codewords → ${symbol.getSymbolWidth()}×${symbol.getSymbolHeight()}`);
  }
});

Available Symbol Sizes:

The library supports all standard Data Matrix symbol sizes defined in ISO/IEC 16022:

Square Symbols:

  • 10×10, 12×12, 14×14, 16×16, 18×18, 20×20, 22×22, 24×24, 26×26
  • 32×32, 36×36, 40×40, 44×44, 48×48, 52×52
  • 64×64, 72×72, 80×80, 88×88, 96×96, 104×104, 120×120, 132×132, 144×144

Rectangular Symbols:

  • 8×18, 8×32, 12×26, 12×36, 16×36, 16×48

DataMatrixSymbolShapeHint

Enumeration for controlling Data Matrix symbol shape preference during encoding.

/**
 * Symbol shape hint enumeration
 * Controls whether encoder prefers square or rectangular symbols
 */
enum SymbolShapeHint {
  /**
   * No shape preference - encoder chooses optimal shape for data
   * May select square or rectangular based on data characteristics
   */
  FORCE_NONE = 0,

  /**
   * Force square symbol shape
   * Only considers square symbols (10×10, 12×12, 14×14, etc.)
   */
  FORCE_SQUARE = 1,

  /**
   * Force rectangular symbol shape
   * Only considers rectangular symbols (8×18, 8×32, 12×26, etc.)
   */
  FORCE_RECTANGLE = 2,
}

Usage Examples:

import {
  DataMatrixWriter,
  BarcodeFormat,
  EncodeHintType,
  SymbolShapeHint,
  BitMatrix
} from "@zxing/library";

const writer = new DataMatrixWriter();

// Let encoder choose optimal shape (may be square or rectangular)
const autoHints = new Map<EncodeHintType, any>();
autoHints.set(EncodeHintType.DATA_MATRIX_SHAPE, SymbolShapeHint.FORCE_NONE);

const autoMatrix: BitMatrix = writer.encode(
  "AUTO",
  BarcodeFormat.DATA_MATRIX,
  200,
  200,
  autoHints
);
console.log(`Auto shape: ${autoMatrix.getWidth()}×${autoMatrix.getHeight()}`);

// Force square shape
const squareHints = new Map<EncodeHintType, any>();
squareHints.set(EncodeHintType.DATA_MATRIX_SHAPE, SymbolShapeHint.FORCE_SQUARE);

const squareMatrix: BitMatrix = writer.encode(
  "SQUARE",
  BarcodeFormat.DATA_MATRIX,
  200,
  200,
  squareHints
);
console.log(`Square: ${squareMatrix.getWidth()}×${squareMatrix.getHeight()}`);

// Force rectangular shape
const rectHints = new Map<EncodeHintType, any>();
rectHints.set(EncodeHintType.DATA_MATRIX_SHAPE, SymbolShapeHint.FORCE_RECTANGLE);

const rectMatrix: BitMatrix = writer.encode(
  "RECT",
  BarcodeFormat.DATA_MATRIX,
  200,
  200,
  rectHints
);
console.log(`Rectangle: ${rectMatrix.getWidth()}×${rectMatrix.getHeight()}`);

// Compare encoding efficiency
const testData = "TEST DATA 123456";

const noneMatrix: BitMatrix = writer.encode(
  testData,
  BarcodeFormat.DATA_MATRIX,
  200,
  200,
  new Map([[EncodeHintType.DATA_MATRIX_SHAPE, SymbolShapeHint.FORCE_NONE]])
);

const sqMatrix: BitMatrix = writer.encode(
  testData,
  BarcodeFormat.DATA_MATRIX,
  200,
  200,
  new Map([[EncodeHintType.DATA_MATRIX_SHAPE, SymbolShapeHint.FORCE_SQUARE]])
);

const rectMatrix2: BitMatrix = writer.encode(
  testData,
  BarcodeFormat.DATA_MATRIX,
  200,
  200,
  new Map([[EncodeHintType.DATA_MATRIX_SHAPE, SymbolShapeHint.FORCE_RECTANGLE]])
);

console.log(`Auto: ${noneMatrix.getWidth()}×${noneMatrix.getHeight()}`);
console.log(`Square: ${sqMatrix.getWidth()}×${sqMatrix.getHeight()}`);
console.log(`Rectangle: ${rectMatrix2.getWidth()}×${rectMatrix2.getHeight()}`);

DataMatrixHighLevelEncoder

High-level encoder that converts input text to Data Matrix codewords using optimal encoding modes (ASCII, C40, TEXT, X12, EDIFACT, BASE256).

/**
 * High-level Data Matrix encoder
 * Implements ISO/IEC 16022:2000(E) Annex P encoding algorithm
 * Uses greedy lookahead to select optimal encoding modes
 */
class HighLevelEncoder {
  /**
   * Performs message encoding using the algorithm described in ISO/IEC 16022:2000(E) Annex P
   * Automatically selects between ASCII, C40, TEXT, X12, EDIFACT, and BASE256 modes
   * @param msg - string: message to encode
   * @param shape - SymbolShapeHint: optional shape preference (default: FORCE_NONE)
   * @param minSize - Dimension: optional minimum symbol size (default: null)
   * @param maxSize - Dimension: optional maximum symbol size (default: null)
   * @param forceC40 - boolean: optional force C40 encoding mode (default: false)
   * @returns string: encoded message as codeword string (char values 0-255)
   * @throws WriterException if encoding fails or data doesn't fit constraints
   */
  static encodeHighLevel(
    msg: string,
    shape?: SymbolShapeHint,
    minSize?: Dimension,
    maxSize?: Dimension,
    forceC40?: boolean
  ): string;

  /**
   * Determines the number of consecutive digits in the message
   * @param msg - string: message to analyze
   * @param startpos - number: starting position (default: 0)
   * @returns number: count of consecutive digits from start position
   */
  static determineConsecutiveDigitCount(
    msg: string,
    startpos?: number
  ): number;

  /**
   * Checks if character is a digit (0-9)
   * @param ch - number: character code
   * @returns boolean: true if digit
   */
  static isDigit(ch: number): boolean;

  /**
   * Checks if character is extended ASCII (128-255)
   * @param ch - number: character code
   * @returns boolean: true if extended ASCII
   */
  static isExtendedASCII(ch: number): boolean;

  /**
   * Checks if character is native to C40 encoding
   * C40 native: space, digits 0-9, uppercase A-Z
   * @param ch - number: character code
   * @returns boolean: true if native to C40
   */
  static isNativeC40(ch: number): boolean;

  /**
   * Checks if character is native to Text encoding
   * Text native: space, digits 0-9, lowercase a-z
   * @param ch - number: character code
   * @returns boolean: true if native to Text
   */
  static isNativeText(ch: number): boolean;

  /**
   * Checks if character is native to X12 encoding
   * X12 native: CR, *, >, space, digits 0-9, uppercase A-Z
   * @param ch - number: character code
   * @returns boolean: true if native to X12
   */
  static isNativeX12(ch: number): boolean;

  /**
   * Checks if character is native to EDIFACT encoding
   * EDIFACT native: ASCII 32-94 (space through ^)
   * @param ch - number: character code
   * @returns boolean: true if native to EDIFACT
   */
  static isNativeEDIFACT(ch: number): boolean;
}

Encoding Modes:

The encoder automatically selects between these modes for optimal compression:

ModeCharactersBits per CharBest For
ASCII0-127, digit pairs8 bits, or 4 bits per digit pairMixed content, ASCII text
C40Space, digits, uppercase5.33 bits (3 chars in 2 codewords)Uppercase text
TEXTSpace, digits, lowercase5.33 bits (3 chars in 2 codewords)Lowercase text
X12ANSI X12 EDI subset5.33 bits (3 chars in 2 codewords)EDI data
EDIFACTASCII 32-946 bits (4 chars in 3 codewords)EDI messages
BASE256Binary data (0-255)8 bitsBinary data, non-ASCII

Special ASCII Mode Features:

  • Single ASCII: Characters 0-127 encoded as value + 1 (codewords 1-128)
  • Digit Pairs: Two digits 00-99 encoded as value + 130 (codewords 130-229)
    • Example: "12" → codeword 142 (12 + 130)
    • Saves 1 codeword per 2 digits compared to individual encoding

Usage Examples:

import {
  HighLevelEncoder,
  SymbolShapeHint,
  Dimension
} from "@zxing/library";

// Basic encoding with automatic mode selection
const encoded: string = HighLevelEncoder.encodeHighLevel("Hello123");
console.log(`Encoded to ${encoded.length} codewords`);

// Encoding with shape constraint
const squareEncoded: string = HighLevelEncoder.encodeHighLevel(
  "SQUARE DATA",
  SymbolShapeHint.FORCE_SQUARE
);
console.log(`Square encoding: ${squareEncoded.length} codewords`);

// Encoding with size constraints
const minSize = new Dimension(12, 12);
const maxSize = new Dimension(24, 24);

const constrained: string = HighLevelEncoder.encodeHighLevel(
  "Constrained encoding",
  SymbolShapeHint.FORCE_NONE,
  minSize,
  maxSize
);
console.log(`Constrained: ${constrained.length} codewords`);

// Force C40 encoding for uppercase text
const c40Encoded: string = HighLevelEncoder.encodeHighLevel(
  "UPPERCASE TEXT WITH NUMBERS 12345",
  SymbolShapeHint.FORCE_NONE,
  undefined,
  undefined,
  true // forceC40
);
console.log(`C40 encoding: ${c40Encoded.length} codewords`);

// Analyze character types
const testChars = ["A", "a", "5", " ", "!", "ü"];

testChars.forEach(char => {
  const code = char.charCodeAt(0);
  console.log(`'${char}' (${code}):`);
  console.log(`  Digit: ${HighLevelEncoder.isDigit(code)}`);
  console.log(`  C40 native: ${HighLevelEncoder.isNativeC40(code)}`);
  console.log(`  Text native: ${HighLevelEncoder.isNativeText(code)}`);
  console.log(`  X12 native: ${HighLevelEncoder.isNativeX12(code)}`);
  console.log(`  EDIFACT native: ${HighLevelEncoder.isNativeEDIFACT(code)}`);
  console.log(`  Extended ASCII: ${HighLevelEncoder.isExtendedASCII(code)}`);
});

// Count consecutive digits (for ASCII digit pair optimization)
const msg1 = "ABC12345XYZ";
const digitCount1: number = HighLevelEncoder.determineConsecutiveDigitCount(msg1, 3);
console.log(`Consecutive digits at position 3: ${digitCount1}`); // 5

const msg2 = "12345678";
const digitCount2: number = HighLevelEncoder.determineConsecutiveDigitCount(msg2, 0);
console.log(`Consecutive digits from start: ${digitCount2}`); // 8

// Encoding efficiency comparison
function compareEncodings(text: string): void {
  const encoded = HighLevelEncoder.encodeHighLevel(text);
  const rawBytes = new TextEncoder().encode(text).length;
  const encodedCodewords = encoded.length;
  
  console.log(`Text: "${text}"`);
  console.log(`  Raw bytes: ${rawBytes}`);
  console.log(`  Encoded codewords: ${encodedCodewords}`);
  console.log(`  Efficiency: ${encodedCodewords <= rawBytes ? 'Better' : 'Worse'}`);
}

compareEncodings("123456789012");    // ASCII digit pairs: very efficient
compareEncodings("UPPERCASE TEXT");  // C40 mode: efficient
compareEncodings("lowercase text");  // TEXT mode: efficient
compareEncodings("Mixed Case 123");  // Mixed modes: moderate efficiency

Macro Characters:

Data Matrix supports special macro headers for compact encoding of common message structures:

// Macro 05 format: [)>\u001E05\u001D ... \u001E\u0004
// Macro 06 format: [)>\u001E06\u001D ... \u001E\u0004

// The encoder automatically detects and optimizes these patterns
const macro05 = "[)>\\u001E05\\u001DData\\u001E\\u0004";
const macro06 = "[)>\\u001E06\\u001DData\\u001E\\u0004";

// Macros save several codewords compared to raw encoding

DataMatrixMinimalEncoder

Advanced encoder that produces minimal-length encodings using sophisticated graph-based optimization algorithms.

/**
 * Minimal Data Matrix encoder
 * Uses graph-based optimization to find shortest possible encoding
 * More complex but produces better compression than HighLevelEncoder
 */
class MinimalEncoder {
  /**
   * Performs minimal-length message encoding
   * Uses graph search algorithm to find optimal encoding path
   * @param msg - string: message to encode
   * @param priorityCharset - Charset: optional preferred character set (default: null)
   * @param fnc1 - number: FNC1 character code or -1 for non-GS1 (default: -1)
   * @param shape - SymbolShapeHint: optional shape preference (default: FORCE_NONE)
   * @returns string: encoded message with minimal codeword count
   * @throws WriterException if encoding fails
   */
  static encodeHighLevel(
    msg: string,
    priorityCharset?: Charset,
    fnc1?: number,
    shape?: SymbolShapeHint
  ): string;

  /**
   * Checks if character is extended ASCII
   * @param ch - number: character code
   * @param fnc1 - number: FNC1 character code
   * @returns boolean: true if extended ASCII
   */
  static isExtendedASCII(ch: number, fnc1: number): boolean;

  /**
   * Checks if character is in C40 Shift 1 set
   * @param ch - number: character code
   * @returns boolean: true if in C40 Shift 1
   */
  static isInC40Shift1Set(ch: number): boolean;

  /**
   * Checks if character is in C40 Shift 2 set
   * @param ch - number: character code
   * @param fnc1 - number: FNC1 character code
   * @returns boolean: true if in C40 Shift 2
   */
  static isInC40Shift2Set(ch: number, fnc1: number): boolean;

  /**
   * Checks if character is in Text Shift 1 set
   * @param ch - number: character code
   * @returns boolean: true if in Text Shift 1
   */
  static isInTextShift1Set(ch: number): boolean;

  /**
   * Checks if character is in Text Shift 2 set
   * @param ch - number: character code
   * @param fnc1 - number: FNC1 character code
   * @returns boolean: true if in Text Shift 2
   */
  static isInTextShift2Set(ch: number, fnc1: number): boolean;
}

Usage Examples:

import {
  MinimalEncoder,
  HighLevelEncoder,
  SymbolShapeHint,
  Charset,
  SymbolInfo,
  ErrorCorrection
} from "@zxing/library";

// Minimal encoding with automatic charset selection
const message = "Mixed Content: ABC123abc!@#";
const minimalEncoded: string = MinimalEncoder.encodeHighLevel(message);
console.log(`Minimal encoding: ${minimalEncoded.length} codewords`);

// Compare with standard encoder
const standardEncoded: string = HighLevelEncoder.encodeHighLevel(message);
console.log(`Standard encoding: ${standardEncoded.length} codewords`);
console.log(`Saved: ${standardEncoded.length - minimalEncoded.length} codewords`);

// Encoding with priority charset
const utf8Charset = Charset.forName("UTF-8");
const utf8Encoded: string = MinimalEncoder.encodeHighLevel(
  "Prioritized UTF-8 encoding",
  utf8Charset
);
console.log(`UTF-8 prioritized: ${utf8Encoded.length} codewords`);

// GS1 format encoding with FNC1
const gs1Message = "01095012345678903310ABC123";
const gs1Encoded: string = MinimalEncoder.encodeHighLevel(
  gs1Message,
  undefined,  // No priority charset
  0x1D,       // FNC1 character (ASCII 29)
  SymbolShapeHint.FORCE_SQUARE
);
console.log(`GS1 encoded: ${gs1Encoded.length} codewords`);

// Encoding with shape preference
const rectEncoded: string = MinimalEncoder.encodeHighLevel(
  "Rectangular preference",
  undefined,
  -1,
  SymbolShapeHint.FORCE_RECTANGLE
);
console.log(`Rectangular: ${rectEncoded.length} codewords`);

// Character set analysis
const testChar = "!".charCodeAt(0);
const fnc1 = 0x1D;

console.log(`Character '!' (${testChar}):`);
console.log(`  Extended ASCII: ${MinimalEncoder.isExtendedASCII(testChar, fnc1)}`);
console.log(`  C40 Shift1: ${MinimalEncoder.isInC40Shift1Set(testChar)}`);
console.log(`  C40 Shift2: ${MinimalEncoder.isInC40Shift2Set(testChar, fnc1)}`);
console.log(`  Text Shift1: ${MinimalEncoder.isInTextShift1Set(testChar)}`);
console.log(`  Text Shift2: ${MinimalEncoder.isInTextShift2Set(testChar, fnc1)}`);

// Complete encoding pipeline with MinimalEncoder
function encodeWithMinimal(text: string): string {
  const encoded: string = MinimalEncoder.encodeHighLevel(
    text,
    undefined,
    -1,
    SymbolShapeHint.FORCE_NONE
  );
  
  const symbolInfo: SymbolInfo = SymbolInfo.lookup(encoded.length);
  const withEC: string = ErrorCorrection.encodeECC200(encoded, symbolInfo);
  
  return withEC;
}

const finalCodewords: string = encodeWithMinimal("Optimized encoding!");
console.log(`Final codewords: ${finalCodewords.length}`);

MinimalEncoder vs HighLevelEncoder:

FeatureMinimalEncoderHighLevelEncoder
AlgorithmGraph-based optimizationGreedy lookahead
CompressionBetter (finds optimal path)Good (local optimum)
SpeedSlower (explores multiple paths)Faster (single pass)
ComplexityHigherLower
Charset SupportMultiple charsetsSingle charset
Use CaseMaximum compression neededGeneral purpose, speed priority
ActivationSet DATA_MATRIX_COMPACT hintDefault in DataMatrixWriter

Choose MinimalEncoder by setting EncodeHintType.DATA_MATRIX_COMPACT to true.

DataMatrixErrorCorrection

Implements Reed-Solomon ECC200 error correction for Data Matrix codes.

/**
 * Data Matrix error correction implementation
 * Implements Reed-Solomon ECC200 per ISO/IEC 16022
 */
class ErrorCorrection {
  /**
   * Creates ECC200 error correction codewords for an encoded message
   * Adds Reed-Solomon error correction with proper interleaving
   * @param codewords - string: data codewords to protect (encoded message)
   * @param symbolInfo - SymbolInfo: symbol information with EC parameters
   * @returns string: complete codeword string with interleaved error correction
   * @throws Error if codeword count doesn't match symbol data capacity
   */
  static encodeECC200(codewords: string, symbolInfo: SymbolInfo): string;
}

Usage Examples:

import {
  ErrorCorrection,
  HighLevelEncoder,
  SymbolInfo,
  SymbolShapeHint
} from "@zxing/library";

// Encode message and add error correction
const message = "Data Matrix ECC200";

// Step 1: High-level encoding
const encoded: string = HighLevelEncoder.encodeHighLevel(
  message,
  SymbolShapeHint.FORCE_SQUARE
);
console.log(`Data codewords: ${encoded.length}`);

// Step 2: Get symbol information
const symbolInfo: SymbolInfo = SymbolInfo.lookup(encoded.length);
console.log(`Symbol: ${symbolInfo.getSymbolWidth()}×${symbolInfo.getSymbolHeight()}`);
console.log(`Data capacity: ${symbolInfo.getDataCapacity()} codewords`);
console.log(`EC codewords: ${symbolInfo.getErrorCodewords()}`);

// Step 3: Add error correction
const withEC: string = ErrorCorrection.encodeECC200(encoded, symbolInfo);
console.log(`Total codewords: ${withEC.length}`);
console.log(`Expected total: ${symbolInfo.getCodewordCount()}`);

// Verify correct length
if (withEC.length === symbolInfo.getCodewordCount()) {
  console.log("✓ Error correction added successfully");
  console.log(`Final: ${symbolInfo.getDataCapacity()} data + ${symbolInfo.getErrorCodewords()} EC = ${withEC.length} total`);
} else {
  console.error("✗ Codeword count mismatch");
}

// For interleaved symbols (larger Data Matrix symbols)
const largeMessage = "A".repeat(100);
const largeEncoded: string = HighLevelEncoder.encodeHighLevel(largeMessage);
const largeSymbol: SymbolInfo = SymbolInfo.lookup(largeEncoded.length);

console.log(`Large symbol interleaved blocks: ${largeSymbol.getInterleavedBlockCount()}`);

const largeWithEC: string = ErrorCorrection.encodeECC200(largeEncoded, largeSymbol);

// Extract data and EC portions
const dataLength: number = largeSymbol.getDataCapacity();
const dataPortion: string = largeWithEC.substring(0, dataLength);
const ecPortion: string = largeWithEC.substring(dataLength);

console.log(`Data portion: ${dataPortion.length} codewords`);
console.log(`EC portion: ${ecPortion.length} codewords`);

// Error correction parameters vary by symbol size
// Small symbols: 5, 7, 10, 12, or 14 EC codewords
// Large symbols: 18, 20, 24, 28, 36, 42, 48, 56, 62, or 68 EC codewords

// Interleaving improves error resilience for burst errors
if (largeSymbol.getInterleavedBlockCount() > 1) {
  console.log("Symbol uses interleaving for better error distribution");
}

Error Correction Parameters:

Data Matrix ECC200 uses Reed-Solomon coding with predefined polynomial factors:

Symbol SizeEC CodewordsCan Correct (Symbols)
10×10 to 16×1652
18×18 to 20×2073
22×22105
24×24 to 26×26126
32×32147
36×36 to 40×40189
44×442010
48×48 to 52×522412
64×64 to 72×722814
80×80 to 88×883618
96×96 to 104×1044221
120×1204824
132×1325628
144×1446231

Interleaving:

Larger symbols use 2 interleaved blocks for better burst error resilience:

  • Symbols 36×36 and larger typically use 2 blocks
  • Codewords are alternated between blocks during placement
  • Improves recovery from scratches or damage in localized areas

Related Documentation

  • Core API - Core reader/writer interfaces
  • Image Processing - BinaryBitmap, Binarizer
  • Common Utilities - BitMatrix, BitArray
  • Error Correction - Reed-Solomon details
  • Types and Enums - Hint types and enums

References

  • ISO/IEC 16022:2000(E): Data Matrix bar code symbology specification
  • ECC200: Reed-Solomon error correction standard for Data Matrix
  • Annex M.1: Bit placement algorithm specification
  • Annex P: High-level encoding algorithm specification
  • Section 5.2: Bit stream decoding specification (modes ASCII, C40, TEXT, X12, EDIFACT, BASE256)

Install with Tessl CLI

npx tessl i tessl/npm-zxing--library

docs

index.md

tile.json