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

aztec.mddocs/reference/

Aztec Code API

Comprehensive API documentation for Aztec 2D barcode encoding and decoding in @zxing/library. Aztec Code is a high-capacity 2D matrix barcode symbology that can encode large amounts of data in a compact space with configurable error correction.

Overview

The Aztec module provides complete functionality for:

  • Decoding: Reading Aztec codes from binary bitmap images
  • Encoding: Generating Aztec codes from text or binary data
  • Detection: Locating and extracting Aztec patterns with distinctive bulls-eye center
  • Error Correction: Reed-Solomon error correction with configurable levels (23%-90%)

Aztec codes support both compact (up to 4 layers, 5-ring bulls-eye) and full (up to 32 layers, 7-ring bulls-eye) formats, with automatic format selection based on data size and error correction requirements.

Package Information

  • Package Name: @zxing/library
  • Module: Aztec Code (core/aztec/)
  • Language: TypeScript
  • Standard: ISO/IEC 24778:2008
  • Format Types: Compact (1-4 layers) and Full (1-32 layers)

Core Imports

import {
  // Reader/Writer
  AztecCodeReader,
  AztecCodeWriter,
  
  // Results and detection
  AztecDetectorResult,
  AztecCode,
  
  // Encoder/Decoder
  Encoder as AztecEncoder,
  Decoder as AztecDecoder,
  HighLevelEncoder as AztecHighLevelEncoder,
  
  // Detector
  Detector as AztecDetector,
  Point as AztecPoint,
  
  // Supporting types
  BinaryBitmap,
  BitMatrix,
  BitArray,
  DecodeHintType,
  EncodeHintType,
  BarcodeFormat,
  Result
} from '@zxing/library';

Basic Usage

Decoding an Aztec Code

import {
  AztecCodeReader,
  BinaryBitmap,
  HybridBinarizer,
  RGBLuminanceSource,
  Result
} from '@zxing/library';

// Create luminance source from image data
const luminanceSource = new RGBLuminanceSource(imageData, width, height);
const binarizer = new HybridBinarizer(luminanceSource);
const bitmap = new BinaryBitmap(binarizer);

// Decode the Aztec code
const reader = new AztecCodeReader();
try {
  const result: Result = reader.decode(bitmap);
  
  console.log('Decoded text:', result.getText());
  console.log('Format:', result.getBarcodeFormat()); // BarcodeFormat.AZTEC
  console.log('Result points:', result.getResultPoints());
  
  // Access metadata
  const metadata = result.getResultMetadata();
  if (metadata) {
    const ecLevel = metadata.get(ResultMetadataType.ERROR_CORRECTION_LEVEL);
    console.log('Error correction:', ecLevel);
  }
} catch (error) {
  console.error('Aztec decode failed:', error);
}

Encoding an Aztec Code

import {
  AztecCodeWriter,
  BarcodeFormat,
  EncodeHintType,
  BitMatrix
} from '@zxing/library';

const writer = new AztecCodeWriter();

// Basic encoding (auto-sized)
const matrix: BitMatrix = writer.encode(
  'Hello, Aztec!',
  BarcodeFormat.AZTEC,
  0, // Width: 0 = auto-size based on data
  0  // Height: 0 = auto-size
);

console.log(`Generated ${matrix.getWidth()}×${matrix.getHeight()} Aztec code`);

// Encoding with hints for custom configuration
const hints = new Map<EncodeHintType, any>();
hints.set(EncodeHintType.ERROR_CORRECTION, 33); // 33% error correction
hints.set(EncodeHintType.AZTEC_LAYERS, 5);      // Force 5 layers
hints.set(EncodeHintType.CHARACTER_SET, 'UTF-8');

const matrixWithHints: BitMatrix = writer.encode(
  'Data with hints',
  BarcodeFormat.AZTEC,
  200, // Fixed width
  200, // Fixed height
  hints
);

Capabilities

AztecCodeReader - Aztec Barcode Decoder

The main class for decoding Aztec codes from binary bitmap images. Implements automatic detection of both normal and mirrored codes with comprehensive error recovery.

/**
 * Decodes Aztec codes from binary bitmap images
 * Implements the Reader interface for Aztec barcode decoding
 * Automatically handles normal and mirrored orientations
 */
class AztecCodeReader implements Reader {
  /**
   * Locates and decodes an Aztec code in an image
   * Attempts both normal and mirrored orientations automatically
   * @param image - BinaryBitmap: binary image containing the Aztec code
   * @param hints - Map<DecodeHintType, any>: optional decode hints
   *   - NEED_RESULT_POINT_CALLBACK: ResultPointCallback for detection tracking
   * @returns Result: decoded text, raw bytes, and metadata
   * @throws NotFoundException if no Aztec code is found
   * @throws FormatException if code structure is invalid or cannot be decoded
   */
  decode(image: BinaryBitmap, hints?: Map<DecodeHintType, any>): Result;

  /**
   * Resets any internal state (no-op for Aztec reader)
   */
  reset(): void;
}

Usage Examples:

import {
  AztecCodeReader,
  BinaryBitmap,
  HybridBinarizer,
  RGBLuminanceSource,
  DecodeHintType,
  ResultPointCallback,
  ResultPoint,
  Result,
  ResultMetadataType
} from '@zxing/library';

// Set up image source
const luminanceSource = new RGBLuminanceSource(pixels, width, height);
const binarizer = new HybridBinarizer(luminanceSource);
const bitmap = new BinaryBitmap(binarizer);

// Decode with result point callback to track detection
const hints = new Map<DecodeHintType, any>();
const callback: ResultPointCallback = {
  foundPossibleResultPoint: (point: ResultPoint) => {
    console.log(`Found point at (${point.getX()}, ${point.getY()})`);
    // Could draw marker on canvas to visualize detection
  }
};
hints.set(DecodeHintType.NEED_RESULT_POINT_CALLBACK, callback);

const reader = new AztecCodeReader();
try {
  const result: Result = reader.decode(bitmap, hints);
  console.log('Decoded:', result.getText());

  // Access metadata
  const metadata = result.getResultMetadata();
  if (metadata) {
    const errorLevel = metadata.get(ResultMetadataType.ERROR_CORRECTION_LEVEL);
    const byteSegments = metadata.get(ResultMetadataType.BYTE_SEGMENTS);

    if (errorLevel !== undefined) {
      console.log('Error correction level:', errorLevel);
    }
    
    if (byteSegments) {
      console.log('Byte segments:', byteSegments);
    }
  }

  // Access raw bytes
  const rawBytes: Uint8Array = result.getRawBytes();
  if (rawBytes) {
    console.log('Raw bytes length:', rawBytes.length);
  }
  
  // Access result points (bulls-eye corners)
  const points = result.getResultPoints();
  console.log(`Bulls-eye detected at ${points.length} points`);
} catch (error) {
  if (error instanceof NotFoundException) {
    console.error('No Aztec code found in image');
  } else if (error instanceof FormatException) {
    console.error('Aztec code structure is invalid:', error.message);
  } else {
    console.error('Decoding failed:', error);
  }
}

// Continuous scanning
const reader2 = new AztecCodeReader();
for (const frame of videoFrames) {
  try {
    const result: Result = reader2.decode(frame);
    console.log('Scanned:', result.getText());
    break; // Stop on first success
  } catch (error) {
    // Continue to next frame
  }
}

Key Features:

  • Automatic detection attempts both normal and mirrored orientations
  • Extracts error correction level from mode message
  • Supports result point callbacks for tracking detection process
  • Returns complete result with text, raw bytes, and format information
  • Handles both compact (5-ring bulls-eye) and full (7-ring bulls-eye) formats

AztecCodeWriter - Aztec Barcode Encoder

Generates Aztec codes from text or binary data with configurable error correction and size parameters. Supports both compact and full-size format generation.

/**
 * Encodes data as Aztec 2D barcode
 * Implements the Writer interface for Aztec barcode encoding
 * Automatically selects optimal format (compact/full) unless specified
 */
class AztecCodeWriter implements Writer {
  /**
   * Encodes content as an Aztec barcode
   * @param contents - string: text content to encode
   * @param format - BarcodeFormat: must be BarcodeFormat.AZTEC
   * @param width - number: desired width in pixels (or 0 for auto-size)
   * @param height - number: desired height in pixels (or 0 for auto-size)
   * @returns BitMatrix: encoded Aztec barcode
   * @throws IllegalArgumentException if format is not AZTEC
   * @throws WriterException if encoding fails
   */
  encode(
    contents: string,
    format: BarcodeFormat,
    width: number,
    height: number
  ): BitMatrix;

  /**
   * Encodes content with encoding hints for customization
   * @param contents - string: text content to encode
   * @param format - BarcodeFormat: must be BarcodeFormat.AZTEC
   * @param width - number: desired width (0 for auto-size)
   * @param height - number: desired height (0 for auto-size)
   * @param hints - Map<EncodeHintType, any>: encoding hints
   *   - ERROR_CORRECTION: number (percentage 0-100, default 33)
   *   - AZTEC_LAYERS: number (negative=compact, 0=auto, positive=full)
   *   - CHARACTER_SET: string (e.g., "UTF-8", "ISO-8859-1")
   * @returns BitMatrix: encoded Aztec barcode
   * @throws IllegalArgumentException if parameters invalid
   * @throws WriterException if encoding fails (data too large)
   */
  encode(
    contents: string,
    format: BarcodeFormat,
    width: number,
    height: number,
    hints: Map<EncodeHintType, any>
  ): BitMatrix;
}

Encoding Hints:

HintTypeDescriptionDefaultValid Range
ERROR_CORRECTIONnumberError correction percentage33%0-100% (recommended: 23-50%)
AZTEC_LAYERSnumberNumber of layers0 (auto)-4 to -1 (compact), 0 (auto), 1 to 32 (full)
CHARACTER_SETstringCharacter encoding"ISO-8859-1"Any valid encoding

Usage Examples:

import {
  AztecCodeWriter,
  BarcodeFormat,
  EncodeHintType,
  BitMatrix
} from '@zxing/library';

const writer = new AztecCodeWriter();

// Auto-sized encoding (optimal dimensions)
const matrix1: BitMatrix = writer.encode(
  'Simple text',
  BarcodeFormat.AZTEC,
  0, // Auto-size
  0
);
console.log(`Auto-sized: ${matrix1.getWidth()}×${matrix1.getHeight()} pixels`);

// Fixed-size encoding with scaling
const matrix2: BitMatrix = writer.encode(
  'Fixed size',
  BarcodeFormat.AZTEC,
  300, // Fixed 300×300
  300
);

// High error correction (50%)
const highEccHints = new Map<EncodeHintType, any>();
highEccHints.set(EncodeHintType.ERROR_CORRECTION, 50);

const matrix3: BitMatrix = writer.encode(
  'Critical data requiring high reliability',
  BarcodeFormat.AZTEC,
  0,
  0,
  highEccHints
);

// Force compact format (negative layers: -1 to -4)
const compactHints = new Map<EncodeHintType, any>();
compactHints.set(EncodeHintType.AZTEC_LAYERS, -3); // Compact with 3 layers
compactHints.set(EncodeHintType.ERROR_CORRECTION, 33);

const matrix4: BitMatrix = writer.encode(
  'Compact',
  BarcodeFormat.AZTEC,
  0,
  0,
  compactHints
);

// Force full format with 10 layers
const fullHints = new Map<EncodeHintType, any>();
fullHints.set(EncodeHintType.AZTEC_LAYERS, 10); // Full format, 10 layers
fullHints.set(EncodeHintType.ERROR_CORRECTION, 25);

const matrix5: BitMatrix = writer.encode(
  'Large data requiring full format',
  BarcodeFormat.AZTEC,
  0,
  0,
  fullHints
);

// UTF-8 encoding for international text
const utf8Hints = new Map<EncodeHintType, any>();
utf8Hints.set(EncodeHintType.CHARACTER_SET, 'UTF-8');
utf8Hints.set(EncodeHintType.ERROR_CORRECTION, 33);

const matrix6: BitMatrix = writer.encode(
  'Hello 世界 🌍',
  BarcodeFormat.AZTEC,
  0,
  0,
  utf8Hints
);

// Low error correction for maximum capacity
const maxCapacityHints = new Map<EncodeHintType, any>();
maxCapacityHints.set(EncodeHintType.ERROR_CORRECTION, 23); // ISO minimum

const matrix7: BitMatrix = writer.encode(
  'Maximum data capacity',
  BarcodeFormat.AZTEC,
  0,
  0,
  maxCapacityHints
);

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

  for (let y = 0; y < matrix.getHeight(); y++) {
    for (let x = 0; x < matrix.getWidth(); x++) {
      ctx.fillStyle = matrix.get(x, y) ? '#000000' : '#FFFFFF';
      ctx.fillRect(x, y, 1, 1);
    }
  }
}

// Error handling
try {
  const tooLargeHints = new Map<EncodeHintType, any>();
  tooLargeHints.set(EncodeHintType.AZTEC_LAYERS, 2); // Only 2 layers
  
  const matrix8: BitMatrix = writer.encode(
    'Very large data that won\'t fit in 2 layers'.repeat(10),
    BarcodeFormat.AZTEC,
    0,
    0,
    tooLargeHints
  );
} catch (error) {
  console.error('Data too large for specified layers:', error);
}

Layer Configuration:

  • Compact mode (layers 1-4): Specified with negative values (-1, -2, -3, -4)
    • 5-ring bulls-eye pattern
    • Size: 15×15 to 27×27 modules
    • Capacity: up to ~293 numeric digits or ~178 alphanumeric characters
  • Full mode (layers 1-32): Specified with positive values (1-32)
    • 7-ring bulls-eye pattern
    • Size: 19×19 to 151×151 modules
    • Capacity: up to ~3,832 numeric digits or ~3,067 alphanumeric characters
  • Auto mode (0): Automatically selects optimal format and layer count

AztecDetectorResult - Detection Result Container

Extends DetectorResult with Aztec-specific information about the detected code including format type, layer count, and data block information.

/**
 * Contains results of Aztec code detection with format-specific metadata
 * Extends DetectorResult with compact flag, layer count, and data blocks
 */
class AztecDetectorResult extends DetectorResult {
  /**
   * Creates a new Aztec detection result
   * @param bits - BitMatrix: decoded bit matrix
   * @param points - ResultPoint[]: corner points of detected code (4 corners)
   * @param compact - boolean: true if compact format (5-ring), false if full (7-ring)
   * @param nbDatablocks - number: number of data codewords
   * @param nbLayers - number: number of layers in the code (1-4 compact, 1-32 full)
   */
  constructor(
    bits: BitMatrix,
    points: ResultPoint[],
    compact: boolean,
    nbDatablocks: number,
    nbLayers: number
  );

  /**
   * Get number of layers in the Aztec code
   * @returns number: layer count (1-4 for compact, 1-32 for full)
   */
  getNbLayers(): number;

  /**
   * Get number of data codewords (blocks)
   * @returns number: count of data codewords
   */
  getNbDatablocks(): number;

  /**
   * Check if code uses compact format
   * @returns boolean: true if compact (5-ring bulls-eye), false if full (7-ring)
   */
  isCompact(): boolean;

  // Inherited from DetectorResult
  
  /**
   * Get the decoded bit matrix
   * @returns BitMatrix: extracted Aztec code bits
   */
  getBits(): BitMatrix;

  /**
   * Get corner points of the detected code
   * @returns ResultPoint[]: 4 corner points in order [topRight, bottomRight, bottomLeft, topLeft]
   */
  getPoints(): ResultPoint[];
}

Usage Examples:

import {
  AztecDetector,
  BitMatrix,
  AztecDetectorResult,
  ResultPoint
} from '@zxing/library';

// Detect Aztec code in bit matrix
const detector = new AztecDetector(bitMatrix);
try {
  const detectorResult: AztecDetectorResult = detector.detect();

  // Access detection information
  console.log('Format:', detectorResult.isCompact() ? 'Compact' : 'Full');
  console.log('Layers:', detectorResult.getNbLayers());
  console.log('Data blocks:', detectorResult.getNbDatablocks());

  // Access corner points
  const points: ResultPoint[] = detectorResult.getPoints();
  console.log('Top-right corner:', points[0].getX(), points[0].getY());
  console.log('Bottom-right corner:', points[1].getX(), points[1].getY());
  console.log('Bottom-left corner:', points[2].getX(), points[2].getY());
  console.log('Top-left corner:', points[3].getX(), points[3].getY());

  // Get the decoded bits
  const bits: BitMatrix = detectorResult.getBits();
  console.log(`Bit matrix: ${bits.getWidth()}×${bits.getHeight()}`);

  // Calculate capacity
  const capacity = calculateCapacity(detectorResult);
  console.log('Total capacity:', capacity, 'bits');
} catch (error) {
  console.error('Detection failed:', error);
}

function calculateCapacity(result: AztecDetectorResult): number {
  const layers: number = result.getNbLayers();
  const compact: boolean = result.isCompact();
  
  // Formula for bit capacity:
  // Compact: (88 + 16 * layers) * layers
  // Full: (112 + 16 * layers) * layers
  return ((compact ? 88 : 112) + 16 * layers) * layers;
}

Format Details:

Compact Format:

  • Bulls-eye: 5 layers (1-3-1 pattern of rings)
  • Layers: 1-4
  • Module range: 15×15 (1 layer) to 27×27 (4 layers)
  • No alignment patterns needed
  • Best for: Small data, space-constrained applications

Full Format:

  • Bulls-eye: 7 layers (1-3-1-3-1 pattern of rings)
  • Layers: 1-32
  • Module range: 19×19 (1 layer) to 151×151 (32 layers)
  • Includes alignment patterns for larger codes (8+ layers)
  • Best for: Larger data, high reliability requirements

AztecCode - Aztec Code Representation

Internal representation of an Aztec code containing all metadata and the encoded bit matrix. Used during encoding to track code properties.

/**
 * Represents an Aztec 2D code with metadata
 * Container for encoded data and format information
 */
class AztecCode {
  /**
   * Check if code uses compact format
   * @returns boolean: true if compact (5-ring), false if full (7-ring)
   */
  isCompact(): boolean;

  /**
   * Set the format type
   * @param compact - boolean: true for compact, false for full
   */
  setCompact(compact: boolean): void;

  /**
   * Get size in pixels (width and height are equal for Aztec)
   * @returns number: size in pixels
   */
  getSize(): number;

  /**
   * Set the matrix size
   * @param size - number: size in pixels
   */
  setSize(size: number): void;

  /**
   * Get number of layers
   * @returns number: layer count (1-4 for compact, 1-32 for full)
   */
  getLayers(): number;

  /**
   * Set the number of layers
   * @param layers - number: layer count
   */
  setLayers(layers: number): void;

  /**
   * Get number of data codewords
   * @returns number: data codeword count
   */
  getCodeWords(): number;

  /**
   * Set the number of data codewords
   * @param codeWords - number: data codeword count
   */
  setCodeWords(codeWords: number): void;

  /**
   * Get the encoded symbol as a bit matrix
   * @returns BitMatrix: encoded Aztec code
   */
  getMatrix(): BitMatrix;

  /**
   * Set the encoded matrix
   * @param matrix - BitMatrix: bit matrix containing the encoded symbol
   */
  setMatrix(matrix: BitMatrix): void;
}

Usage Examples:

import {
  AztecEncoder,
  AztecCode,
  BitMatrix
} from '@zxing/library';

// Encode data to get AztecCode object
const data = new TextEncoder().encode('Example data');
const aztecCode: AztecCode = AztecEncoder.encode(data, 33, 0);

// Access code properties
console.log('Format:', aztecCode.isCompact() ? 'Compact (5-ring)' : 'Full (7-ring)');
console.log('Size:', aztecCode.getSize(), 'pixels');
console.log('Layers:', aztecCode.getLayers());
console.log('Data codewords:', aztecCode.getCodeWords());

// Get the bit matrix for rendering
const matrix: BitMatrix = aztecCode.getMatrix();
console.log(`Matrix dimensions: ${matrix.getWidth()}×${matrix.getHeight()}`);

// Calculate total bit capacity
const layers: number = aztecCode.getLayers();
const compact: boolean = aztecCode.isCompact();
const totalBits = ((compact ? 88 : 112) + 16 * layers) * layers;
console.log('Total capacity:', totalBits, 'bits');

// Analyze code structure
interface AztecAnalysis {
  format: string;
  layers: number;
  size: number;
  bullsEyeSize: number;
  hasAlignmentMarks: boolean;
  dataCodewords: number;
  totalCapacityBits: number;
}

function analyzeAztecCode(code: AztecCode): AztecAnalysis {
  const compact = code.isCompact();
  const layers = code.getLayers();
  const size = code.getSize();
  const codeWords = code.getCodeWords();
  const capacity = ((compact ? 88 : 112) + 16 * layers) * layers;

  return {
    format: compact ? 'Compact' : 'Full',
    layers,
    size,
    bullsEyeSize: compact ? 5 : 7,
    hasAlignmentMarks: !compact && layers >= 8,
    dataCodewords: codeWords,
    totalCapacityBits: capacity
  };
}

const analysis: AztecAnalysis = analyzeAztecCode(aztecCode);
console.log('Analysis:', analysis);

// Manually create and configure Aztec code (advanced)
const customCode = new AztecCode();
customCode.setCompact(false);        // Full format
customCode.setLayers(8);             // 8 layers
customCode.setSize(67);              // 67×67 pixels
customCode.setCodeWords(100);        // 100 data codewords

const customMatrix = new BitMatrix(67);
// ... populate matrix with encoded data ...
customCode.setMatrix(customMatrix);

AztecEncoder - Low-Level Encoding Logic

Core encoding engine that converts binary data into Aztec codes with error correction, bit stuffing, and matrix generation.

/**
 * Generates Aztec 2D barcodes from binary data
 * Low-level encoder with complete control over format and error correction
 * Provides static methods for encoding with various configurations
 */
class AztecEncoder {
  /**
   * Default error correction percentage
   * Provides good balance between capacity and error resilience
   */
  static readonly DEFAULT_EC_PERCENT: number = 33;

  /**
   * Default layers value (auto-select optimal size)
   */
  static readonly DEFAULT_AZTEC_LAYERS: number = 0;

  /**
   * Encodes binary data with default settings (33% ECC, auto-size)
   * @param data - Uint8Array: raw byte data to encode
   * @returns AztecCode: encoded Aztec code with default configuration
   * @throws IllegalArgumentException if data is empty or too large
   */
  static encodeBytes(data: Uint8Array): AztecCode;

  /**
   * Encodes binary data with custom error correction and layer specification
   * @param data - Uint8Array: raw byte data to encode
   * @param minECCPercent - number: minimum error correction percentage (recommended: 23% + 3 words)
   * @param userSpecifiedLayers - number: layer count
   *   - 0: auto-select optimal format and layers
   *   - negative (-1 to -4): compact format with specified layers
   *   - positive (1 to 32): full format with specified layers
   * @returns AztecCode: encoded code with specified configuration
   * @throws IllegalArgumentException if parameters are invalid or data too large for layers
   */
  static encode(
    data: Uint8Array,
    minECCPercent: number,
    userSpecifiedLayers: number
  ): AztecCode;
}

Usage Examples:

import { AztecEncoder, AztecCode, BitMatrix } from '@zxing/library';

// Encode with defaults (33% ECC, auto-size)
const data1 = new TextEncoder().encode('Quick data');
const code1: AztecCode = AztecEncoder.encodeBytes(data1);
console.log('Default encoding:', code1.getLayers(), 'layers,', code1.getSize(), 'pixels');

// Encode with high error correction (50%)
const data2 = new TextEncoder().encode('Critical data requiring high reliability');
const code2: AztecCode = AztecEncoder.encode(data2, 50, 0);
console.log('High ECC code:', code2.getLayers(), 'layers');

// Force compact format with 3 layers
const data3 = new TextEncoder().encode('Compact');
const code3: AztecCode = AztecEncoder.encode(data3, 33, -3);
console.log('Compact format:', code3.isCompact());  // true
console.log('Layers:', code3.getLayers());          // 3
console.log('Size:', code3.getSize(), 'pixels');    // 21×21 (15 + 2*3)

// Force full format with 8 layers
const data4 = new TextEncoder().encode('Full format data');
const code4: AztecCode = AztecEncoder.encode(data4, 33, 8);
console.log('Full format:', !code4.isCompact());   // true
console.log('Layers:', code4.getLayers());          // 8
console.log('Size:', code4.getSize(), 'pixels');    // 51×51 (19 + 2*16)

// Auto-select optimal format and layers
const data5 = new TextEncoder().encode('Auto-select optimal format and size based on data length');
const code5: AztecCode = AztecEncoder.encode(data5, 33, 0);
console.log('Auto-selected format:', code5.isCompact() ? 'Compact' : 'Full');
console.log('Auto-selected layers:', code5.getLayers());

// Binary data encoding (non-text)
const binaryData = new Uint8Array([0x01, 0x02, 0x03, 0xFF, 0xFE, 0xFD]);
const binaryCode: AztecCode = AztecEncoder.encode(binaryData, 25, 0);
console.log('Binary data encoded');

// Large data encoding
const largeData = new TextEncoder().encode('A'.repeat(1000));
try {
  const largeCode: AztecCode = AztecEncoder.encode(largeData, 33, 0);
  console.log('Large data encoded with', largeCode.getLayers(), 'layers');
  console.log('Format:', largeCode.isCompact() ? 'Compact' : 'Full');
  console.log('Size:', largeCode.getSize(), '×', largeCode.getSize());
} catch (error) {
  console.error('Data too large even for version 32:', error);
}

// Calculate required layers for data
function calculateRequiredLayers(
  dataLength: number,
  eccPercent: number,
  compact: boolean
): number {
  const maxLayers = compact ? 4 : 32;
  
  for (let layers = 1; layers <= maxLayers; layers++) {
    const capacity = ((compact ? 88 : 112) + 16 * layers) * layers;
    const dataCapacity = Math.floor(capacity * (100 - eccPercent) / 100);
    const requiredBits = dataLength * 8;
    
    if (requiredBits <= dataCapacity) {
      return layers;
    }
  }
  
  return -1; // Data too large
}

// Example: how many layers needed?
const dataBytes = 100;
const compactLayers = calculateRequiredLayers(dataBytes, 33, true);
const fullLayers = calculateRequiredLayers(dataBytes, 33, false);

console.log(`${dataBytes} bytes with 33% ECC requires:`);
console.log(`  Compact: ${compactLayers} layers${compactLayers === -1 ? ' (too large)' : ''}`);
console.log(`  Full: ${fullLayers} layers`);

Error Correction Recommendations:

ECC %Use CaseProsCons
23%Clean environments, maximum capacityMost dataLess damage tolerance
33%General purpose (default)Good balanceStandard capacity
40%Outdoor, moderate damage expectedGood reliabilityReduced capacity
50%High damage, small printHigh reliabilitySignificantly reduced capacity
>50%Critical data, extreme conditionsMaximum reliabilityMinimal capacity

Layer Selection Guide:

Data SizeRecommended LayersFormatApprox. Capacity (33% ECC)
< 20 bytes1-2Compact10-30 bytes
20-50 bytes2-3Compact30-70 bytes
50-100 bytes3-4Compact or Full70-140 bytes
100-500 bytes4-12Full140-700 bytes
500-1500 bytes12-24Full700-2100 bytes
1500+ bytes24-32Full2100-4500 bytes

AztecHighLevelEncoder - High-Level Text Encoder

Optimizes text encoding by automatically selecting the best encoding modes (UPPER, LOWER, MIXED, DIGIT, PUNCT, BINARY) for minimal bit usage.

/**
 * High-level encoder that optimizes text encoding
 * Uses dynamic programming to find near-optimal encoding sequences
 * Minimizes bit count by choosing best mode switches
 */
class HighLevelEncoder {
  /**
   * Creates encoder for the given text data
   * @param text - Uint8Array: raw byte data to encode
   */
  constructor(text: Uint8Array);

  /**
   * Encodes the text using optimal mode switching
   * Uses dynamic programming to minimize total bit count
   * @returns BitArray: encoded data bits
   */
  encode(): BitArray;
}

Encoding Modes:

ModeCharactersBits/CharUsage
UPPERA-Z, space5Uppercase text
LOWERa-z, space5Lowercase text
MIXEDControl chars, punctuation5Special characters
DIGIT0-9, comma, period4Numeric data (most efficient for numbers)
PUNCTPunctuation marks5Punctuation
BINARYAll bytes8Binary data, Unicode, incompatible characters

Special Character Pairs:

The encoder recognizes and optimizes these two-character sequences:

  • \r\n - Carriage return + line feed (single 5-bit PUNCT token)
  • . - Period + space (single 5-bit PUNCT token)
  • , - Comma + space (single 5-bit PUNCT token)
  • : - Colon + space (single 5-bit PUNCT token)

Usage Examples:

import { HighLevelEncoder, BitArray } from '@zxing/library';

// Encode simple uppercase text
const text1 = new TextEncoder().encode('HELLO');
const encoder1 = new HighLevelEncoder(text1);
const bits1: BitArray = encoder1.encode();
console.log('HELLO encoded to', bits1.getSize(), 'bits');
// Efficient: uses UPPER mode (5 bits per character)

// Encode mixed-case text (uses mode switching)
const text2 = new TextEncoder().encode('Hello World');
const encoder2 = new HighLevelEncoder(text2);
const bits2: BitArray = encoder2.encode();
console.log('Hello World encoded to', bits2.getSize(), 'bits');
// Uses UPPER mode for 'H', switches to LOWER for 'ello', etc.

// Encode numeric data (optimized for DIGIT mode)
const text3 = new TextEncoder().encode('1234567890');
const encoder3 = new HighLevelEncoder(text3);
const bits3: BitArray = encoder3.encode();
console.log('1234567890 encoded to', bits3.getSize(), 'bits');
// Most efficient: ~4 bits per digit = ~40 bits for 10 digits

// Encode binary data
const binaryData = new Uint8Array([0xFF, 0xFE, 0xFD, 0xFC]);
const encoder4 = new HighLevelEncoder(binaryData);
const bits4: BitArray = encoder4.encode();
console.log('Binary data encoded to', bits4.getSize(), 'bits');
// Uses BINARY mode: 8 bits per byte

// Compare encoding efficiency
interface EncodingComparison {
  text: string;
  bytes: number;
  rawBits: number;
  encodedBits: number;
  efficiency: number;
}

function compareEncoding(text: string): EncodingComparison {
  const data = new TextEncoder().encode(text);
  const encoder = new HighLevelEncoder(data);
  const bits = encoder.encode();

  const rawBits = data.length * 8;
  const encodedBits = bits.getSize();
  const efficiency = ((rawBits - encodedBits) / rawBits * 100);

  return {
    text,
    bytes: data.length,
    rawBits,
    encodedBits,
    efficiency
  };
}

console.log("Encoding efficiency:");
console.log(compareEncoding('UPPERCASE TEXT'));    // Best with UPPER mode
console.log(compareEncoding('lowercase text'));    // Best with LOWER mode
console.log(compareEncoding('1234567890'));        // Best with DIGIT mode
console.log(compareEncoding('Mix3d T3xt 123'));    // Uses multiple modes
console.log(compareEncoding('Hello, World! 123')); // Mixed modes with optimal switches

Optimization Strategy:

The encoder uses a sophisticated dynamic programming algorithm:

  1. State Graph: For each character position, maintains set of possible encoding states
  2. State Tracking: Each state tracks current mode, binary shift bytes, and total bit count
  3. Mode Evaluation: At each position, evaluates all possible:
    • Mode latches (permanent mode change)
    • Mode shifts (temporary mode change for 1 character)
    • Binary shifts (for incompatible characters)
  4. Pruning: Keeps only optimal states (lowest bit count) at each position
  5. Solution: Selects minimum bit count state at end and traces back to reconstruct encoding

Example Encoding Strategy:

Text: "Hello123"

Position | Char | Best Mode | Action         | Cumulative Bits
---------|------|-----------|----------------|----------------
0        | H    | UPPER     | Start UPPER    | 5
1        | e    | LOWER     | Latch→LOWER    | 10 (5+5)
2        | l    | LOWER     | Stay in LOWER  | 15 (10+5)
3        | l    | LOWER     | Stay in LOWER  | 20 (15+5)
4        | o    | LOWER     | Stay in LOWER  | 25 (20+5)
5        | 1    | DIGIT     | Latch→DIGIT    | 34 (25+5+4)
6        | 2    | DIGIT     | Stay in DIGIT  | 38 (34+4)
7        | 3    | DIGIT     | Stay in DIGIT  | 42 (38+4)

Total: 42 bits (vs 64 bits for pure binary = 34% savings)

AztecDecoder - Decoding Logic

Internal decoder that extracts data from detected Aztec codes, performs error correction, and decodes the bit stream into text.

/**
 * Decodes the data content from Aztec detection results
 * Handles bit extraction, Reed-Solomon error correction, and character decoding
 */
class Decoder {
  /**
   * Decodes an Aztec code from detection result
   * @param detectorResult - AztecDetectorResult: result from Aztec detector with bits and metadata
   * @returns DecoderResult: decoded text, raw bytes, and metadata
   * @throws FormatException if decoding fails or too many errors detected
   */
  decode(detectorResult: AztecDetectorResult): DecoderResult;

  /**
   * High-level decode from error-corrected bits (testing utility)
   * @param correctedBits - boolean[]: error-corrected boolean bit array
   * @returns string: decoded text
   * @throws FormatException if bit stream cannot be decoded
   */
  static highLevelDecode(correctedBits: boolean[]): string;

  /**
   * Converts boolean bit array to byte array
   * @param boolArr - boolean[]: boolean array (bits)
   * @returns Uint8Array: packed bytes (8 bits per byte)
   */
  static convertBoolArrayToByteArray(boolArr: boolean[]): Uint8Array;
}

Usage Examples:

import {
  Decoder as AztecDecoder,
  AztecDetector,
  AztecDetectorResult,
  DecoderResult,
  BitMatrix
} from '@zxing/library';

// Detect and decode Aztec code (complete pipeline)
const detector = new AztecDetector(bitMatrix);
try {
  const detectorResult: AztecDetectorResult = detector.detect();
  
  console.log('Detected:', detectorResult.isCompact() ? 'Compact' : 'Full');
  console.log('Layers:', detectorResult.getNbLayers());
  console.log('Data blocks:', detectorResult.getNbDatablocks());

  const decoder = new AztecDecoder();
  const decoderResult: DecoderResult = decoder.decode(detectorResult);

  // Access decoded data
  console.log('Decoded text:', decoderResult.getText());
  console.log('Raw bytes length:', decoderResult.getRawBytes()?.length);
  console.log('Num bits:', decoderResult.getNumBits());
  console.log('EC level:', decoderResult.getECLevel());

  // Check for byte segments (binary data)
  const byteSegments: Uint8Array[] | null = decoderResult.getByteSegments();
  if (byteSegments && byteSegments.length > 0) {
    console.log('Has byte segments:', byteSegments.length);
    byteSegments.forEach((segment, i) => {
      console.log(`Segment ${i}: ${segment.length} bytes`);
    });
  }

  // Error correction statistics
  const errorsCorrected = decoderResult.getErrorsCorrected();
  if (errorsCorrected !== undefined && errorsCorrected !== null) {
    console.log('Errors corrected:', errorsCorrected);
  }

  const erasures = decoderResult.getErasures();
  if (erasures !== undefined && erasures !== null) {
    console.log('Erasures:', erasures);
  }
} catch (error) {
  console.error('Aztec decode failed:', error);
}

// Direct high-level decoding from corrected bits (advanced/testing)
const correctedBits: boolean[] = [
  true, false, true, true, false, // ... bit sequence ...
];

try {
  const decoded: string = AztecDecoder.highLevelDecode(correctedBits);
  console.log('Decoded from bits:', decoded);
} catch (error) {
  console.error('High-level decode failed:', error);
}

// Convert boolean array to bytes
const boolArray: boolean[] = [
  true, false, true, false, true, false, true, false, // Byte 1: 0xAA
  true, true, false, false, true, true, false, false  // Byte 2: 0xCC
];

const bytes: Uint8Array = AztecDecoder.convertBoolArrayToByteArray(boolArray);
console.log('Converted bytes:', Array.from(bytes)); // [170, 204] (0xAA, 0xCC)

Decoding Process:

  1. Bit Extraction: Reads bits from the matrix in spiral order starting from bulls-eye
  2. Error Correction: Applies Reed-Solomon error correction using appropriate Galois Field
  3. Bit Unstuffing: Removes bit-stuffing bits inserted during encoding
  4. Mode Decoding: Interprets mode switches (UPPER, LOWER, MIXED, DIGIT, PUNCT, BINARY)
  5. Text Assembly: Builds final decoded string according to detected modes

AztecDetector - Pattern Detection

Locates and extracts Aztec codes from binary bitmap images by identifying the distinctive bulls-eye center pattern and computing corner positions.

/**
 * Detects Aztec codes in binary bitmap images
 * Locates bulls-eye pattern (5 or 7 concentric rings) and determines code boundaries
 */
class Detector {
  /**
   * Creates detector for the given image
   * @param image - BitMatrix: binary bit matrix to scan
   */
  constructor(image: BitMatrix);

  /**
   * Detects an Aztec code in the image
   * Attempts both normal and mirrored orientations automatically
   * @returns AztecDetectorResult: detected code with position and format info
   * @throws NotFoundException if no valid Aztec code found
   */
  detect(): AztecDetectorResult;

  /**
   * Detects with explicit mirror handling
   * @param isMirror - boolean: true to detect mirrored code, false for normal
   * @returns AztecDetectorResult: detected code with position and format info
   * @throws NotFoundException if no valid Aztec code found in specified orientation
   */
  detectMirror(isMirror: boolean): AztecDetectorResult;
}

Usage Examples:

import {
  AztecDetector,
  BitMatrix,
  AztecDetectorResult,
  NotFoundException,
  ResultPoint
} from '@zxing/library';

// Create detector
const detector = new AztecDetector(bitMatrix);

// Automatic detection (tries both orientations)
try {
  const result: AztecDetectorResult = detector.detect();

  console.log('Detected:', result.isCompact() ? 'Compact (5-ring)' : 'Full (7-ring)');
  console.log('Layers:', result.getNbLayers());
  console.log('Data blocks:', result.getNbDatablocks());

  // Get corner points
  const points: ResultPoint[] = result.getPoints();
  console.log('Corner points:');
  points.forEach((p, i) => {
    console.log(`  Point ${i}: (${p.getX()}, ${p.getY()})`);
  });

  // Get extracted bits
  const bits: BitMatrix = result.getBits();
  console.log('Extracted matrix:', bits.getWidth(), '×', bits.getHeight());
  
  // Calculate capacity
  const layers = result.getNbLayers();
  const compact = result.isCompact();
  const capacity = ((compact ? 88 : 112) + 16 * layers) * layers;
  console.log('Total capacity:', capacity, 'bits');
  console.log('Data blocks:', result.getNbDatablocks(), 'codewords');
} catch (error) {
  if (error instanceof NotFoundException) {
    console.log('No Aztec code found in image');
  } else {
    console.error('Detection error:', error);
    throw error;
  }
}

// Manual mirror detection (explicit orientation)
try {
  // Try normal orientation first
  const normalResult: AztecDetectorResult = detector.detectMirror(false);
  console.log('Found in normal orientation');
  console.log('Compact:', normalResult.isCompact());
  console.log('Layers:', normalResult.getNbLayers());
} catch (normalError) {
  try {
    // Fall back to mirrored orientation
    const mirrorResult: AztecDetectorResult = detector.detectMirror(true);
    console.log('Found in mirrored orientation');
    console.log('Compact:', mirrorResult.isCompact());
    console.log('Layers:', mirrorResult.getNbLayers());
  } catch (mirrorError) {
    console.log('No Aztec code found in either orientation');
  }
}

Detection Algorithm:

  1. Matrix Center: Locates the center of the bulls-eye pattern by scanning from image center
  2. Bulls-eye Detection: Identifies concentric rings pattern (5 or 7 layers)
  3. Compact vs Full: Determines format by counting bulls-eye layers
  4. Parameter Extraction: Reads mode message from orientation rings around bulls-eye
  5. Grid Sampling: Samples the code matrix from detected corners with perspective correction
  6. Corner Calculation: Computes outer corners of the code for result points

The bulls-eye pattern structure:

  • Compact (5 rings): Center dot + alternating white/black rings (1-3-1 pattern from center)
  • Full (7 rings): Center dot + alternating white/black rings (1-3-1-3-1 pattern from center)

Point - Detection Point Helper

Exported as: AztecPoint

Simple coordinate point class used during Aztec code detection for tracking positions and performing geometric calculations.

/**
 * Represents a coordinate point in Aztec detection
 * Simple helper class for geometric calculations during detection
 */
class Point {
  /**
   * Creates a new point
   * @param x - number: x coordinate
   * @param y - number: y coordinate
   */
  constructor(x: number, y: number);

  /**
   * Get X coordinate
   * @returns number: x position
   */
  getX(): number;

  /**
   * Get Y coordinate
   * @returns number: y position
   */
  getY(): number;

  /**
   * Converts to ResultPoint for result reporting
   * @returns ResultPoint: result point with same coordinates
   */
  toResultPoint(): ResultPoint;
}

Advanced Topics

Custom Error Correction Strategies

import { AztecEncoder, AztecCode } from '@zxing/library';

// Strategy 1: Minimum viable ECC (maximum capacity)
function encodeMinimalECC(data: Uint8Array): AztecCode {
  return AztecEncoder.encode(data, 23, 0); // ISO minimum 23%
}

// Strategy 2: Balanced for typical use
function encodeBalanced(data: Uint8Array): AztecCode {
  return AztecEncoder.encode(data, 33, 0); // Default 33%
}

// Strategy 3: Maximum reliability (reduced capacity)
function encodeMaxReliability(data: Uint8Array): AztecCode {
  return AztecEncoder.encode(data, 50, 0); // High 50% ECC
}

// Strategy 4: Size-constrained encoding
function encodeConstrained(data: Uint8Array, maxSize: number): AztecCode | null {
  // Try increasing ECC until size limit reached
  for (let ecc = 23; ecc <= 50; ecc += 5) {
    try {
      const code: AztecCode = AztecEncoder.encode(data, ecc, 0);
      if (code.getSize() <= maxSize) {
        console.log(`Encoded with ${ecc}% ECC, size: ${code.getSize()}`);
        return code;
      }
    } catch (error) {
      // Data too large even with lower ECC
    }
  }
  
  // Fall back to minimum ECC
  try {
    return AztecEncoder.encode(data, 23, 0);
  } catch (error) {
    console.error('Data too large even with minimum ECC');
    return null;
  }
}

// Usage
const testData = new TextEncoder().encode('Test data for encoding');
const minimalCode = encodeMinimalECC(testData);
const balancedCode = encodeBalanced(testData);
const reliableCode = encodeMaxReliability(testData);

console.log('Minimal ECC size:', minimalCode.getSize());
console.log('Balanced size:', balancedCode.getSize());
console.log('Reliable size:', reliableCode.getSize());

const constrainedCode = encodeConstrained(testData, 50);
if (constrainedCode) {
  console.log('Constrained encoding successful');
}

Format Selection Logic

import { AztecEncoder, AztecCode } from '@zxing/library';

interface FormatSelection {
  format: 'compact' | 'full';
  layers: number;
  totalCapacityBits: number;
  dataCapacityBits: number;
  size: number;
}

function selectOptimalFormat(
  dataLengthBytes: number,
  eccPercent: number
): FormatSelection | null {
  const requiredDataBits = dataLengthBytes * 8;
  const minTotalBits = Math.ceil(requiredDataBits / (1 - eccPercent / 100));

  // Try compact first (more efficient for small data)
  for (let layers = 1; layers <= 4; layers++) {
    const totalCapacity = (88 + 16 * layers) * layers;
    const dataCapacity = Math.floor(totalCapacity * (100 - eccPercent) / 100);
    
    if (dataCapacity >= requiredDataBits) {
      return {
        format: 'compact',
        layers,
        totalCapacityBits: totalCapacity,
        dataCapacityBits: dataCapacity,
        size: 15 + 2 * layers // Compact: 15 + 2n
      };
    }
  }

  // Try full format
  for (let layers = 1; layers <= 32; layers++) {
    const totalCapacity = (112 + 16 * layers) * layers;
    const dataCapacity = Math.floor(totalCapacity * (100 - eccPercent) / 100);
    
    if (dataCapacity >= requiredDataBits) {
      return {
        format: 'full',
        layers,
        totalCapacityBits: totalCapacity,
        dataCapacityBits: dataCapacity,
        size: 19 + 4 * layers - 2 // Full: 19 + 4n - 2
      };
    }
  }

  return null; // Data too large for Aztec code
}

// Usage examples
console.log('Format selection for 100 bytes with 33% ECC:');
const selection = selectOptimalFormat(100, 33);
if (selection) {
  console.log(`Use ${selection.format} format with ${selection.layers} layers`);
  console.log(`Size: ${selection.size}×${selection.size} modules`);
  console.log(`Data capacity: ${selection.dataCapacityBits} bits (${Math.floor(selection.dataCapacityBits / 8)} bytes)`);
}

// Compare formats for various data sizes
const dataSizes = [20, 50, 100, 200, 500, 1000];
dataSizes.forEach(size => {
  const sel = selectOptimalFormat(size, 33);
  if (sel) {
    console.log(`${size} bytes: ${sel.format} ${sel.layers} layers, ${sel.size}×${sel.size} modules`);
  } else {
    console.log(`${size} bytes: too large for Aztec`);
  }
});

Binary Data Encoding

import { AztecEncoder, AztecCode, AztecCodeWriter, BarcodeFormat, BitMatrix } from '@zxing/library';

// Encode binary data directly
function encodeBinaryData(data: Uint8Array): AztecCode {
  return AztecEncoder.encode(data, 33, 0);
}

// Example: Encode image thumbnail
const imageThumbnail = new Uint8Array([/* JPEG bytes */]);
const imageCode: AztecCode = encodeBinaryData(imageThumbnail);
console.log('Encoded', imageThumbnail.length, 'bytes in', imageCode.getSize(), '×', imageCode.getSize(), 'matrix');

// Encode structured binary data
interface BinaryPacket {
  type: number;
  length: number;
  data: Uint8Array;
}

function encodeBinaryPacket(packet: BinaryPacket): AztecCode {
  // Serialize packet
  const serialized = new Uint8Array(2 + packet.data.length);
  serialized[0] = packet.type;
  serialized[1] = packet.length;
  serialized.set(packet.data, 2);
  
  return AztecEncoder.encode(serialized, 33, 0);
}

const packet: BinaryPacket = {
  type: 1,
  length: 10,
  data: new Uint8Array([1, 2, 3, 4, 5, 6, 7, 8, 9, 10])
};

const packetCode: AztecCode = encodeBinaryPacket(packet);

// Decode and parse binary packet
function decodeBinaryPacket(result: Result): BinaryPacket | null {
  const rawBytes = result.getRawBytes();
  if (!rawBytes || rawBytes.length < 2) return null;
  
  return {
    type: rawBytes[0],
    length: rawBytes[1],
    data: rawBytes.slice(2)
  };
}

Performance Optimization

import {
  AztecCodeReader,
  AztecCodeWriter,
  BinaryBitmap,
  HybridBinarizer,
  RGBLuminanceSource,
  Result,
  BarcodeFormat,
  BitMatrix
} from '@zxing/library';

// Reuse reader instances for continuous scanning
class AztecScanner {
  private reader: AztecCodeReader = new AztecCodeReader();

  decode(bitmap: BinaryBitmap): Result | null {
    try {
      return this.reader.decode(bitmap);
    } catch (error) {
      return null;
    }
  }

  // Reset not strictly needed for Aztec, but good practice
  reset(): void {
    this.reader.reset();
  }
}

// Batch encoding with shared writer instance
class AztecBatchEncoder {
  private writer: AztecCodeWriter = new AztecCodeWriter();

  encodeMultiple(contents: string[]): BitMatrix[] {
    return contents.map(content => {
      try {
        return this.writer.encode(content, BarcodeFormat.AZTEC, 0, 0);
      } catch (error) {
        console.error(`Failed to encode "${content}":`, error);
        return null;
      }
    }).filter((m): m is BitMatrix => m !== null);
  }
}

// Optimized binarization for Aztec
function optimizedBinarize(
  imageData: Uint8ClampedArray,
  width: number,
  height: number
): BinaryBitmap {
  const source = new RGBLuminanceSource(imageData, width, height);
  
  // HybridBinarizer works better than GlobalHistogramBinarizer for Aztec
  // due to the bulls-eye pattern requiring good local contrast
  const binarizer = new HybridBinarizer(source);
  
  return new BinaryBitmap(binarizer);
}

// Adaptive encoding based on data size
function adaptiveEncode(data: string): BitMatrix {
  const writer = new AztecCodeWriter();
  const bytes = new TextEncoder().encode(data);
  
  // Select ECC based on data size
  const hints = new Map<EncodeHintType, any>();
  
  if (bytes.length < 50) {
    hints.set(EncodeHintType.ERROR_CORRECTION, 40); // High ECC for small data
  } else if (bytes.length < 200) {
    hints.set(EncodeHintType.ERROR_CORRECTION, 33); // Balanced
  } else {
    hints.set(EncodeHintType.ERROR_CORRECTION, 25); // Lower ECC for large data
  }
  
  return writer.encode(data, BarcodeFormat.AZTEC, 0, 0, hints);
}

Error Handling

import {
  AztecCodeReader,
  AztecCodeWriter,
  NotFoundException,
  FormatException,
  WriterException,
  IllegalArgumentException,
  BinaryBitmap,
  BarcodeFormat
} from '@zxing/library';

// Comprehensive error handling for reading
function safeAztecDecode(bitmap: BinaryBitmap): string | null {
  const reader = new AztecCodeReader();

  try {
    const result = reader.decode(bitmap);
    return result.getText();
  } catch (error) {
    if (error instanceof NotFoundException) {
      console.error('No Aztec code found in image');
      // Image may not contain Aztec code, or bulls-eye is obscured
    } else if (error instanceof FormatException) {
      console.error('Aztec code structure is invalid');
      // Code is damaged or not a valid Aztec code
    } else {
      console.error('Unknown decode error:', error);
    }
    return null;
  }
}

// Comprehensive error handling for writing
function safeAztecEncode(
  contents: string,
  errorCorrection?: number,
  layers?: number
): BitMatrix | null {
  const writer = new AztecCodeWriter();

  try {
    const hints = new Map<EncodeHintType, any>();
    
    if (errorCorrection !== undefined) {
      if (errorCorrection < 0 || errorCorrection > 100) {
        throw new IllegalArgumentException('Error correction must be 0-100%');
      }
      hints.set(EncodeHintType.ERROR_CORRECTION, errorCorrection);
    }
    
    if (layers !== undefined) {
      if (layers < -4 || layers > 32 || layers === 0) {
        // layers can be -4 to -1, 0 (auto), or 1 to 32
        // Note: 0 is valid (auto-select)
      }
      hints.set(EncodeHintType.AZTEC_LAYERS, layers);
    }

    return writer.encode(contents, BarcodeFormat.AZTEC, 0, 0, hints);
  } catch (error) {
    if (error instanceof WriterException) {
      console.error('Aztec encoding failed:', error.message);
      // Data may be too large for specified layers
    } else if (error instanceof IllegalArgumentException) {
      console.error('Invalid parameters:', error.message);
      // Check error correction percentage, layers, or format
    } else {
      console.error('Unknown encode error:', error);
    }
    return null;
  }
}

// Retry with fallback options
function encodeWithFallback(contents: string): BitMatrix | null {
  const writer = new AztecCodeWriter();
  const strategies = [
    { ecc: 33, layers: 0 },   // Balanced auto
    { ecc: 25, layers: 0 },   // Lower ECC
    { ecc: 33, layers: -4 },  // Compact mode
    { ecc: 23, layers: 0 },   // Minimum ECC
  ];

  for (const strategy of strategies) {
    try {
      const hints = new Map<EncodeHintType, any>();
      hints.set(EncodeHintType.ERROR_CORRECTION, strategy.ecc);
      hints.set(EncodeHintType.AZTEC_LAYERS, strategy.layers);

      return writer.encode(contents, BarcodeFormat.AZTEC, 0, 0, hints);
    } catch (error) {
      console.debug(`Strategy ${strategy.ecc}% ECC, layers ${strategy.layers} failed`);
    }
  }

  console.error('All encoding strategies failed');
  return null;
}

Capacity and Size Reference

Capacity Tables

Compact Format (5-ring bulls-eye):

LayersSizeTotal BitsData Bits (33% ECC)Approx Bytes (33% ECC)
115×1588597
217×1724016120
319×1945630538
421×2173649361

Full Format (7-ring bulls-eye):

LayersSizeTotal BitsData Bits (33% ECC)Approx Bytes (33% ECC)
119×191288610
223×2328819324
431×3167245056
847×4715681051131
1263×6327361833229
1679×7941762798349
2095×9558883945493
24111×11178725274659
28127×127101286786848
32143×1431265684801060

Capacity Calculation Formula:

function calculateAztecCapacity(layers: number, compact: boolean, eccPercent: number): {
  totalBits: number;
  dataBits: number;
  dataBytes: number;
} {
  const totalBits = ((compact ? 88 : 112) + 16 * layers) * layers;
  const dataBits = Math.floor(totalBits * (100 - eccPercent) / 100);
  const dataBytes = Math.floor(dataBits / 8);

  return { totalBits, dataBits, dataBytes };
}

// Examples
console.log('Compact 2 layers, 33% ECC:', calculateAztecCapacity(2, true, 33));
console.log('Full 8 layers, 33% ECC:', calculateAztecCapacity(8, false, 33));
console.log('Full 32 layers, 25% ECC:', calculateAztecCapacity(32, false, 25));

Related APIs

  • Core API - Core Reader/Writer interfaces and Result classes
  • Image Processing - BinaryBitmap, LuminanceSource, Binarizer
  • Common Utilities - BitMatrix, BitArray, error correction
  • Types and Enums - BarcodeFormat, hint types

References

  • ISO/IEC 24778:2008: Aztec Code bar code symbology specification
  • Error Correction: Reed-Solomon over multiple Galois Fields (GF(16), GF(64), GF(256), GF(1024), GF(4096))
  • Encoding Modes: UPPER, LOWER, MIXED, DIGIT, PUNCT, BINARY
  • Format Types: Compact (1-4 layers, 5-ring bulls-eye) and Full (1-32 layers, 7-ring bulls-eye)
  • Minimum ECC: 23% per ISO standard, plus 3 codeword overhead
  • Typical ECC: 33% provides good balance between capacity and reliability

Install with Tessl CLI

npx tessl i tessl/npm-zxing--library@0.21.14

docs

index.md

tile.json