TypeScript port of ZXing multi-format 1D/2D barcode image processing library
Core type definitions and enumerations used throughout @zxing/library for barcode format identification, decoder/encoder configuration, result metadata, and error handling.
npm install @zxing/libraryimport {
// Format identification
BarcodeFormat,
// Configuration hints
DecodeHintType,
EncodeHintType,
// Result metadata
ResultMetadataType,
// Exceptions
Exception,
ReaderException,
NotFoundException,
FormatException,
ChecksumException,
WriterException,
IllegalArgumentException,
IllegalStateException,
ArgumentException,
ArithmeticException,
ReedSolomonException,
UnsupportedOperationException,
} from "@zxing/library";Enumerates all barcode formats supported by the library. Used to specify which format to encode or to identify the format of a decoded barcode.
/**
* Barcode format enumeration
* Identifies specific barcode symbology types
*/
enum BarcodeFormat {
/** Aztec 2D barcode format */
AZTEC = 0,
/** CODABAR 1D format */
CODABAR = 1,
/** Code 39 1D format */
CODE_39 = 2,
/** Code 93 1D format */
CODE_93 = 3,
/** Code 128 1D format */
CODE_128 = 4,
/** Data Matrix 2D barcode format */
DATA_MATRIX = 5,
/** EAN-8 1D format (8 digits) */
EAN_8 = 6,
/** EAN-13 1D format (13 digits) */
EAN_13 = 7,
/** ITF (Interleaved Two of Five) 1D format */
ITF = 8,
/** MaxiCode 2D barcode format (not implemented) */
MAXICODE = 9,
/** PDF417 2D format */
PDF_417 = 10,
/** QR Code 2D barcode format */
QR_CODE = 11,
/** RSS 14 (GS1 DataBar) */
RSS_14 = 12,
/** RSS EXPANDED (experimental) */
RSS_EXPANDED = 13,
/** UPC-A 1D format (12 digits) */
UPC_A = 14,
/** UPC-E 1D format (8 digits, zero-suppressed) */
UPC_E = 15,
/** UPC/EAN extension format (not a stand-alone format) */
UPC_EAN_EXTENSION = 16,
}1D Barcodes (Linear):
CODABAR: Self-checking numeric barcode
CODE_39: Alphanumeric barcode
CODE_93: High-density alphanumeric barcode
CODE_128: High-density ASCII barcode
EAN_8: 8-digit product code
EAN_13: 13-digit product code
ITF: Interleaved Two of Five
RSS_14: Reduced Space Symbology (GS1 DataBar)
RSS_EXPANDED: Variable-length RSS
UPC_A: 12-digit North American product code
UPC_E: 8-digit compressed UPC code
UPC_EAN_EXTENSION: 2 or 5 digit supplement
2D Barcodes (Matrix):
AZTEC: 2D matrix with bulls-eye finder
DATA_MATRIX: 2D matrix barcode
MAXICODE: Fixed-size 2D with circular finder
PDF_417: Stacked linear barcode
QR_CODE: Quick Response code
Usage Examples:
import {
BarcodeFormat,
MultiFormatWriter,
MultiFormatReader,
DecodeHintType,
BitMatrix,
Result
} from "@zxing/library";
// Encode a QR code
const writer = new MultiFormatWriter();
const qrMatrix: BitMatrix = writer.encode(
"Hello World",
BarcodeFormat.QR_CODE,
200,
200,
new Map()
);
// Specify multiple formats for decoding
const hints = new Map<DecodeHintType, any>();
hints.set(DecodeHintType.POSSIBLE_FORMATS, [
BarcodeFormat.QR_CODE,
BarcodeFormat.DATA_MATRIX,
BarcodeFormat.AZTEC,
BarcodeFormat.EAN_13,
BarcodeFormat.CODE_128,
]);
const reader = new MultiFormatReader();
reader.setHints(hints);
// Check decoded format
const result: Result = reader.decode(binaryBitmap);
const format: BarcodeFormat = result.getBarcodeFormat();
console.log("Decoded format:", format);
if (format === BarcodeFormat.QR_CODE) {
console.log("Decoded QR Code:", result.getText());
} else if (format === BarcodeFormat.EAN_13) {
console.log("Decoded EAN-13:", result.getText());
} else if (format === BarcodeFormat.CODE_128) {
console.log("Decoded Code 128:", result.getText());
}
// Format grouping
const formats2D = [
BarcodeFormat.QR_CODE,
BarcodeFormat.DATA_MATRIX,
BarcodeFormat.AZTEC,
BarcodeFormat.PDF_417
];
const formats1D = [
BarcodeFormat.EAN_13,
BarcodeFormat.EAN_8,
BarcodeFormat.UPC_A,
BarcodeFormat.UPC_E,
BarcodeFormat.CODE_128,
BarcodeFormat.CODE_39,
BarcodeFormat.CODE_93,
BarcodeFormat.ITF,
BarcodeFormat.CODABAR,
BarcodeFormat.RSS_14
];
function is2DFormat(format: BarcodeFormat): boolean {
return formats2D.includes(format);
}
function is1DFormat(format: BarcodeFormat): boolean {
return formats1D.includes(format);
}
console.log("QR_CODE is 2D:", is2DFormat(BarcodeFormat.QR_CODE)); // true
console.log("EAN_13 is 1D:", is1DFormat(BarcodeFormat.EAN_13)); // trueConfiguration hints passed to barcode readers to optimize decoding behavior. These hints help readers decode faster or more accurately by providing context about the image or expected barcode format.
/**
* Decode hint type enumeration
* Used as keys in hints Map<DecodeHintType, any> passed to decode() methods
* Allows fine-tuning of decoder behavior for specific scenarios
*/
enum DecodeHintType {
/**
* OTHER: any
* Unspecified, application-specific hint
*/
OTHER = 0,
/**
* PURE_BARCODE: boolean
* Image is a pure monochrome image of a barcode (no borders, no rotation)
* Enables faster extraction without detection phase
* Set to true for images containing only the barcode with no surrounding content
*/
PURE_BARCODE = 1,
/**
* POSSIBLE_FORMATS: BarcodeFormat[]
* Image is known to be of one of a few possible formats
* Limits decoder attempts to specified formats (improves performance)
* Example: [BarcodeFormat.QR_CODE, BarcodeFormat.EAN_13]
*/
POSSIBLE_FORMATS = 2,
/**
* TRY_HARDER: boolean
* Spend more time to try to find a barcode
* Optimize for accuracy, not speed
* Enables: more thorough scanning, rotation attempts, extended search patterns
*/
TRY_HARDER = 3,
/**
* CHARACTER_SET: string
* Specifies what character encoding to use when decoding
* Examples: "UTF-8", "ISO-8859-1", "Shift_JIS", "GB2312", "Windows-1252"
* Applies where applicable (QR Code, Data Matrix, etc.)
*/
CHARACTER_SET = 4,
/**
* ALLOWED_LENGTHS: Int32Array
* Allowed lengths of encoded data -- reject anything else
* Primarily for ITF barcodes
* Example: new Int32Array([14, 16]) for ITF-14 and ITF-16
*/
ALLOWED_LENGTHS = 5,
/**
* ASSUME_CODE_39_CHECK_DIGIT: boolean
* Assume Code 39 codes employ a check digit
* If true, validates and removes check digit from result
*/
ASSUME_CODE_39_CHECK_DIGIT = 6,
/**
* ENABLE_CODE_39_EXTENDED_MODE: boolean
* Enable extended mode for Code 39 codes (supports full ASCII)
* Decodes special character pairs like "+A" as lowercase 'a'
*/
ENABLE_CODE_39_EXTENDED_MODE = 7,
/**
* ASSUME_GS1: boolean
* Assume the barcode is being processed as a GS1 barcode
* Modifies behavior as needed (e.g., FNC1 handling for Code 128 / GS1-128)
*/
ASSUME_GS1 = 8,
/**
* RETURN_CODABAR_START_END: boolean
* Return the start and end digits in a Codabar barcode
* If false (default), strips start/stop characters (A/B/C/D)
* If true, includes them in result
*/
RETURN_CODABAR_START_END = 9,
/**
* NEED_RESULT_POINT_CALLBACK: ResultPointCallback
* Caller needs to be notified via callback when a possible ResultPoint is found
* Used for tracking detection progress (finder patterns, corners, etc.)
*/
NEED_RESULT_POINT_CALLBACK = 10,
/**
* ALLOWED_EAN_EXTENSIONS: Int32Array
* Allowed extension lengths for EAN or UPC barcodes
* Other formats will ignore this hint
* Values: new Int32Array([2]), new Int32Array([5]), or new Int32Array([2, 5])
* If set and no extension found, no result will be returned
*/
ALLOWED_EAN_EXTENSIONS = 11,
}Usage Examples:
import {
MultiFormatReader,
DecodeHintType,
BarcodeFormat,
ResultPointCallback,
ResultPoint,
Result,
BinaryBitmap
} from "@zxing/library";
// Basic hints for faster decoding
const hints = new Map<DecodeHintType, any>();
hints.set(DecodeHintType.POSSIBLE_FORMATS, [
BarcodeFormat.QR_CODE,
BarcodeFormat.EAN_13,
]);
const reader = new MultiFormatReader();
reader.setHints(hints);
const result: Result = reader.decode(binaryBitmap);
// Pure barcode image (faster, no detection needed)
const pureHints = new Map<DecodeHintType, any>();
pureHints.set(DecodeHintType.PURE_BARCODE, true);
const pureResult: Result = reader.decode(pureBitmap, pureHints);
// Maximum accuracy mode (slower)
const accuracyHints = new Map<DecodeHintType, any>();
accuracyHints.set(DecodeHintType.TRY_HARDER, true);
accuracyHints.set(DecodeHintType.POSSIBLE_FORMATS, [BarcodeFormat.QR_CODE]);
const accurateResult: Result = reader.decode(binaryBitmap, accuracyHints);
// Character encoding specification
const encodingHints = new Map<DecodeHintType, any>();
encodingHints.set(DecodeHintType.CHARACTER_SET, "UTF-8");
const encodedResult: Result = reader.decode(binaryBitmap, encodingHints);
// Code 39 with extended mode and check digit
const code39Hints = new Map<DecodeHintType, any>();
code39Hints.set(DecodeHintType.ASSUME_CODE_39_CHECK_DIGIT, true);
code39Hints.set(DecodeHintType.ENABLE_CODE_39_EXTENDED_MODE, true);
code39Hints.set(DecodeHintType.POSSIBLE_FORMATS, [BarcodeFormat.CODE_39]);
const code39Result: Result = reader.decode(binaryBitmap, code39Hints);
// GS1 format handling (Code 128 as GS1-128)
const gs1Hints = new Map<DecodeHintType, any>();
gs1Hints.set(DecodeHintType.ASSUME_GS1, true);
gs1Hints.set(DecodeHintType.POSSIBLE_FORMATS, [BarcodeFormat.CODE_128]);
const gs1Result: Result = reader.decode(binaryBitmap, gs1Hints);
// Result point callback for tracking finder patterns
const callback: ResultPointCallback = {
foundPossibleResultPoint: (point: ResultPoint) => {
console.log(`Found point at (${point.getX()}, ${point.getY()})`);
// Could draw marker on canvas or update UI
},
};
const callbackHints = new Map<DecodeHintType, any>();
callbackHints.set(DecodeHintType.NEED_RESULT_POINT_CALLBACK, callback);
const trackedResult: Result = reader.decode(binaryBitmap, callbackHints);
// UPC/EAN with specific extension requirements
const extensionHints = new Map<DecodeHintType, any>();
extensionHints.set(DecodeHintType.ALLOWED_EAN_EXTENSIONS, new Int32Array([2, 5]));
extensionHints.set(DecodeHintType.POSSIBLE_FORMATS, [
BarcodeFormat.EAN_13,
BarcodeFormat.UPC_A
]);
const extendedResult: Result = reader.decode(binaryBitmap, extensionHints);
// ITF with allowed lengths (e.g., ITF-14 only)
const itfHints = new Map<DecodeHintType, any>();
itfHints.set(DecodeHintType.ALLOWED_LENGTHS, new Int32Array([14]));
itfHints.set(DecodeHintType.POSSIBLE_FORMATS, [BarcodeFormat.ITF]);
const itfResult: Result = reader.decode(binaryBitmap, itfHints);
// Codabar with start/stop characters
const codabarHints = new Map<DecodeHintType, any>();
codabarHints.set(DecodeHintType.RETURN_CODABAR_START_END, true);
codabarHints.set(DecodeHintType.POSSIBLE_FORMATS, [BarcodeFormat.CODABAR]);
const codabarResult: Result = reader.decode(binaryBitmap, codabarHints);Configuration hints passed to barcode writers to control encoding behavior. These hints specify error correction levels, character encoding, dimensions, and format-specific options.
/**
* Encode hint type enumeration
* Used as keys in hints Map<EncodeHintType, any> passed to encode() methods
* Controls encoding behavior and barcode properties
*/
enum EncodeHintType {
/**
* ERROR_CORRECTION: varies by format
* Specifies degree of error correction to use
* Type varies by format:
* - QR Code: ErrorCorrectionLevel (L, M, Q, H) or string ("L"|"M"|"Q"|"H")
* - Aztec: number (percentage 0-100, recommended 23-50)
* - PDF417: number (0-8, where higher = more correction)
* - Data Matrix: not applicable (uses ECC200 automatically)
*/
ERROR_CORRECTION = 0,
/**
* CHARACTER_SET: string
* Specifies character encoding to use where applicable
* Examples: "UTF-8", "ISO-8859-1", "Shift_JIS", "GB2312", "Windows-1252"
* Affects text encoding in QR Code, Data Matrix, Aztec
*/
CHARACTER_SET = 1,
/**
* DATA_MATRIX_SHAPE: SymbolShapeHint
* Specifies the matrix shape for Data Matrix
* Values: FORCE_NONE (auto), FORCE_SQUARE, FORCE_RECTANGLE
*/
DATA_MATRIX_SHAPE = 2,
/**
* DATA_MATRIX_COMPACT: boolean
* Whether to use compact mode for Data Matrix
* true: Use MinimalEncoder for better compression
* false: Use HighLevelEncoder (default, faster)
* Compact mode supports non-ISO-8859-1 characters via ECIs and GS1-FNC1
* Mutually exclusive with FORCE_C40
*/
DATA_MATRIX_COMPACT = 3,
/**
* MIN_SIZE: Dimension
* Specifies a minimum barcode size
* @deprecated Use width/height parameters in encode() instead
*/
MIN_SIZE = 4,
/**
* MAX_SIZE: Dimension
* Specifies a maximum barcode size
* @deprecated No replacement - use symbol size constraints per format
*/
MAX_SIZE = 5,
/**
* MARGIN: number
* Specifies margin (quiet zone) in pixels to use when generating barcode
* Meaning varies by format:
* - QR Code: margin in modules (default: 4)
* - Data Matrix: border width in modules
* - 1D barcodes: horizontal margin in modules
*/
MARGIN = 6,
/**
* PDF417_COMPACT: boolean
* Whether to use compact mode for PDF417
* Compact mode reduces size slightly but may affect scanning reliability
*/
PDF417_COMPACT = 7,
/**
* PDF417_COMPACTION: Compaction
* Specifies what compaction mode to use for PDF417
* Values: AUTO, TEXT, BYTE, NUMERIC
*/
PDF417_COMPACTION = 8,
/**
* PDF417_DIMENSIONS: Dimensions
* Specifies the minimum and maximum number of rows and columns for PDF417
*/
PDF417_DIMENSIONS = 9,
/**
* AZTEC_LAYERS: number
* Specifies the required number of layers for an Aztec code
* Values:
* - Negative (-1, -2, -3, -4): compact Aztec with specified layers
* - 0: minimum layers / auto-select (default)
* - Positive (1, 2, ..., 32): normal Aztec with specified layers
*/
AZTEC_LAYERS = 10,
/**
* QR_VERSION: number
* Specifies the exact version of QR code to be encoded
* Values: 1-40
* Version N has dimensions (17 + 4*N) × (17 + 4*N) modules
* If data doesn't fit, encoding fails
*/
QR_VERSION = 11,
/**
* GS1_FORMAT: boolean
* Whether data should be encoded to the GS1 standard
* Adds FNC1 character for Application Identifier format
* Supported by: Code 128 (GS1-128), Data Matrix
*/
GS1_FORMAT = 12,
/**
* FORCE_C40: boolean
* Forces C40 encoding for Data Matrix
* C40 optimized for uppercase text and numbers
* Mutually exclusive with DATA_MATRIX_COMPACT
*/
FORCE_C40 = 13,
}Usage Examples:
import {
MultiFormatWriter,
BarcodeFormat,
EncodeHintType,
QRCodeDecoderErrorCorrectionLevel,
SymbolShapeHint,
BitMatrix
} from "@zxing/library";
const writer = new MultiFormatWriter();
// QR Code with high error correction and UTF-8 encoding
const qrHints = new Map<EncodeHintType, any>();
qrHints.set(EncodeHintType.ERROR_CORRECTION, QRCodeDecoderErrorCorrectionLevel.H);
qrHints.set(EncodeHintType.CHARACTER_SET, "UTF-8");
qrHints.set(EncodeHintType.MARGIN, 2);
const qrMatrix: BitMatrix = writer.encode(
"Hello 世界",
BarcodeFormat.QR_CODE,
200,
200,
qrHints
);
// QR Code with specific version
const versionHints = new Map<EncodeHintType, any>();
versionHints.set(EncodeHintType.QR_VERSION, 10); // Version 10 (57×57 modules)
versionHints.set(EncodeHintType.ERROR_CORRECTION, "M");
try {
const versionMatrix: BitMatrix = writer.encode(
"Data for version 10",
BarcodeFormat.QR_CODE,
300,
300,
versionHints
);
} catch (error) {
console.error("Data too large for version 10:", error);
}
// Data Matrix with square shape
const dmHints = new Map<EncodeHintType, any>();
dmHints.set(EncodeHintType.DATA_MATRIX_SHAPE, SymbolShapeHint.FORCE_SQUARE);
dmHints.set(EncodeHintType.CHARACTER_SET, "ISO-8859-1");
const dmMatrix: BitMatrix = writer.encode(
"12345",
BarcodeFormat.DATA_MATRIX,
100,
100,
dmHints
);
// Data Matrix in compact mode (MinimalEncoder)
const compactHints = new Map<EncodeHintType, any>();
compactHints.set(EncodeHintType.DATA_MATRIX_COMPACT, true);
const compactMatrix: BitMatrix = writer.encode(
"Compact encoding",
BarcodeFormat.DATA_MATRIX,
100,
100,
compactHints
);
// Data Matrix with GS1 format
const gs1Hints = new Map<EncodeHintType, any>();
gs1Hints.set(EncodeHintType.GS1_FORMAT, true);
gs1Hints.set(EncodeHintType.DATA_MATRIX_COMPACT, true);
const gs1Matrix: BitMatrix = writer.encode(
"01034531200000111719112510ABCD1234",
BarcodeFormat.DATA_MATRIX,
150,
150,
gs1Hints
);
// Data Matrix with forced C40 encoding
const c40Hints = new Map<EncodeHintType, any>();
c40Hints.set(EncodeHintType.FORCE_C40, true);
const c40Matrix: BitMatrix = writer.encode(
"UPPERCASE TEXT 123",
BarcodeFormat.DATA_MATRIX,
120,
120,
c40Hints
);
// Aztec with specific layer count
const aztecHints = new Map<EncodeHintType, any>();
aztecHints.set(EncodeHintType.AZTEC_LAYERS, -3); // Compact, 3 layers
aztecHints.set(EncodeHintType.ERROR_CORRECTION, 33); // 33% error correction
const aztecMatrix: BitMatrix = writer.encode(
"Aztec compact",
BarcodeFormat.AZTEC,
150,
150,
aztecHints
);
// Code 128 with custom margin
const code128Hints = new Map<EncodeHintType, any>();
code128Hints.set(EncodeHintType.MARGIN, 20); // 20-pixel horizontal margin
code128Hints.set(EncodeHintType.CHARACTER_SET, "UTF-8");
const code128Matrix: BitMatrix = writer.encode(
"CODE128",
BarcodeFormat.CODE_128,
250,
80,
code128Hints
);
// GS1-128 (Code 128 with GS1 format)
const gs1_128Hints = new Map<EncodeHintType, any>();
gs1_128Hints.set(EncodeHintType.GS1_FORMAT, true);
const gs1_128Matrix: BitMatrix = writer.encode(
"01034531200000111719112510ABC",
BarcodeFormat.CODE_128,
300,
100,
gs1_128Hints
);Metadata types that can be attached to decode results. Provides additional information about the decoded barcode beyond the text content.
/**
* Result metadata type enumeration
* Used as keys in result.getResultMetadata() map
* Provides supplementary information about decoded barcodes
*/
enum ResultMetadataType {
/**
* OTHER: Object
* Unspecified, application-specific metadata
*/
OTHER = 0,
/**
* ORIENTATION: number
* Likely approximate orientation of barcode in the image
* Given as degrees rotated clockwise from normal, upright orientation
* Range: 0-360
* Example: 1D barcode read top-to-bottom would have orientation 90
*/
ORIENTATION = 1,
/**
* BYTE_SEGMENTS: Uint8Array[]
* Raw bytes from the byte segments in the barcode
* 2D barcodes can encode binary data in byte mode segments
* List of byte arrays in order they appear
*/
BYTE_SEGMENTS = 2,
/**
* ERROR_CORRECTION_LEVEL: string
* Error correction level used, if applicable
* Format-specific values:
* - QR Code: "L", "M", "Q", or "H"
* - Aztec: percentage as string
* - PDF417: "0" through "8"
*/
ERROR_CORRECTION_LEVEL = 3,
/**
* ISSUE_NUMBER: number
* Issue number for periodicals (from UPC/EAN extension)
* Typically from 2-digit extension
*/
ISSUE_NUMBER = 4,
/**
* SUGGESTED_PRICE: string
* Suggested retail price in the barcode
* Typically from 5-digit UPC/EAN extension
* Format varies by country
*/
SUGGESTED_PRICE = 5,
/**
* POSSIBLE_COUNTRY: string
* Possible country of manufacture or origin
* From EAN/UPC country prefix
* May be multiple countries: "US/CA"
*/
POSSIBLE_COUNTRY = 6,
/**
* UPC_EAN_EXTENSION: string
* Extension text for UPC/EAN products
* 2 or 5 digit extension value
*/
UPC_EAN_EXTENSION = 7,
/**
* PDF417_EXTRA_METADATA: PDF417ResultMetadata
* PDF417-specific metadata object
* Contains: segment info, file transfer data, structured append details
*/
PDF417_EXTRA_METADATA = 8,
/**
* STRUCTURED_APPEND_SEQUENCE: number
* Sequence number if code is part of a structured append
* Zero-based index of this symbol in the sequence
*/
STRUCTURED_APPEND_SEQUENCE = 9,
/**
* STRUCTURED_APPEND_PARITY: number
* Parity data if code is part of a structured append
* Used to verify all symbols belong to same message
*/
STRUCTURED_APPEND_PARITY = 10,
}Usage Examples:
import {
MultiFormatReader,
ResultMetadataType,
PDF417ResultMetadata,
Result,
BarcodeFormat
} from "@zxing/library";
const reader = new MultiFormatReader();
const result: Result = reader.decode(binaryBitmap);
// Access metadata
const metadata = result.getResultMetadata();
// Check barcode orientation
if (metadata && metadata.has(ResultMetadataType.ORIENTATION)) {
const orientation: number = metadata.get(ResultMetadataType.ORIENTATION) as number;
console.log(`Barcode rotated ${orientation}° clockwise`);
if (orientation === 0) console.log("Normal orientation");
else if (orientation === 90) console.log("Rotated 90° (vertical)");
else if (orientation === 180) console.log("Upside down");
else if (orientation === 270) console.log("Rotated 270°");
}
// Access error correction level
if (metadata && metadata.has(ResultMetadataType.ERROR_CORRECTION_LEVEL)) {
const ecLevel: string = metadata.get(ResultMetadataType.ERROR_CORRECTION_LEVEL) as string;
console.log(`Error correction level: ${ecLevel}`);
if (result.getBarcodeFormat() === BarcodeFormat.QR_CODE) {
console.log("QR Code EC level:", ecLevel); // "L", "M", "Q", or "H"
}
}
// Access byte segments (binary data from barcode)
if (metadata && metadata.has(ResultMetadataType.BYTE_SEGMENTS)) {
const byteSegments: Uint8Array[] = metadata.get(ResultMetadataType.BYTE_SEGMENTS) as Uint8Array[];
console.log(`Found ${byteSegments.length} byte segments`);
byteSegments.forEach((segment, index) => {
console.log(`Segment ${index}: ${segment.length} bytes`);
console.log(` First bytes: ${Array.from(segment.slice(0, 10))}`);
});
}
// Check for UPC/EAN extension
if (metadata && metadata.has(ResultMetadataType.UPC_EAN_EXTENSION)) {
const extension: string = metadata.get(ResultMetadataType.UPC_EAN_EXTENSION) as string;
console.log(`Extension: ${extension}`);
if (extension.length === 2) {
console.log("2-digit extension (issue number):", extension);
} else if (extension.length === 5) {
console.log("5-digit extension (price):", extension);
// Parse price (US format)
const firstDigit = extension.charAt(0);
if (firstDigit === '0') {
console.log(`Price: $${extension.substring(1, 3)}.${extension.substring(3)}`);
}
}
}
// Check for suggested retail price
if (metadata && metadata.has(ResultMetadataType.SUGGESTED_PRICE)) {
const price: string = metadata.get(ResultMetadataType.SUGGESTED_PRICE) as string;
console.log(`Suggested price: ${price}`);
}
// Check for country of origin
if (metadata && metadata.has(ResultMetadataType.POSSIBLE_COUNTRY)) {
const country: string = metadata.get(ResultMetadataType.POSSIBLE_COUNTRY) as string;
console.log(`Possible country: ${country}`);
}
// Handle structured append (multi-part barcodes)
if (metadata && metadata.has(ResultMetadataType.STRUCTURED_APPEND_SEQUENCE)) {
const sequence: number = metadata.get(ResultMetadataType.STRUCTURED_APPEND_SEQUENCE) as number;
const parity: number = metadata.get(ResultMetadataType.STRUCTURED_APPEND_PARITY) as number;
console.log(`Part ${sequence + 1} of structured append`);
console.log(`Parity: ${parity}`);
// Collect all parts with same parity to reconstruct complete message
}
// PDF417-specific metadata
if (metadata && metadata.has(ResultMetadataType.PDF417_EXTRA_METADATA)) {
const pdf417Meta = metadata.get(ResultMetadataType.PDF417_EXTRA_METADATA);
if (pdf417Meta instanceof PDF417ResultMetadata) {
console.log("PDF417 segment index:", pdf417Meta.getSegmentIndex());
console.log("PDF417 segment count:", pdf417Meta.getSegmentCount());
console.log("PDF417 file ID:", pdf417Meta.getFileId());
console.log("PDF417 is last:", pdf417Meta.isLastSegment());
const fileName = pdf417Meta.getFileName();
if (fileName) {
console.log("File name:", fileName);
console.log("File size:", pdf417Meta.getFileSize(), "bytes");
}
}
}
// Extract issue number from periodical
if (metadata && metadata.has(ResultMetadataType.ISSUE_NUMBER)) {
const issueNumber: number = metadata.get(ResultMetadataType.ISSUE_NUMBER) as number;
console.log("Magazine issue:", issueNumber);
}All exception classes extend from the base Exception class and are used throughout the library to signal specific error conditions during barcode reading and writing operations.
/**
* Complete exception hierarchy
*/
/**
* Base exception class that all other exceptions extend
*/
class Exception extends CustomError {
static readonly kind: string = "Exception";
/**
* Create exception with optional message
* @param message - string: optional error message
*/
constructor(message?: string);
/**
* Get the kind/type of this exception
* @returns string: exception kind identifier
*/
getKind(): string;
}
/**
* Base exception for all barcode reading errors
*/
class ReaderException extends Exception {
static readonly kind: string = "ReaderException";
}
/**
* Thrown when no barcode is found in the provided image
* Most common exception when scanning images without barcodes or with poor quality
*/
class NotFoundException extends ReaderException {
static readonly kind: string = "NotFoundException";
/**
* Get singleton instance (optimization to avoid allocation)
* @returns NotFoundException: shared instance
*/
static getNotFoundInstance(): NotFoundException;
}
/**
* Thrown when barcode is found but cannot be decoded due to format violations
* Indicates the barcode structure is invalid, corrupted, or unsupported
*/
class FormatException extends ReaderException {
static readonly kind: string = "FormatException";
/**
* Get singleton instance (optimization)
* @returns FormatException: shared instance
*/
static getFormatInstance(): FormatException;
}
/**
* Thrown when barcode checksum validation fails
* Indicates the barcode was read but contains errors that couldn't be corrected
*/
class ChecksumException extends ReaderException {
static readonly kind: string = "ChecksumException";
/**
* Get singleton instance (optimization)
* @returns ChecksumException: shared instance
*/
static getChecksumInstance(): ChecksumException;
}
/**
* Base exception for all barcode writing/encoding errors
*/
class WriterException extends Exception {
static readonly kind: string = "WriterException";
}
/**
* Thrown when an illegal or inappropriate argument is passed to a method
*/
class IllegalArgumentException extends Exception {
static readonly kind: string = "IllegalArgumentException";
}
/**
* Thrown when a method is called at an inappropriate time
* or when an object is in an invalid state for the requested operation
*/
class IllegalStateException extends Exception {
static readonly kind: string = "IllegalStateException";
}
/**
* General exception for argument-related errors
* Similar to IllegalArgumentException but more general purpose
*/
class ArgumentException extends Exception {
static readonly kind: string = "ArgumentException";
}
/**
* Thrown when an arithmetic operation fails or produces invalid result
* Rare in normal usage, typically indicates mathematical computation errors
*/
class ArithmeticException extends Exception {
static readonly kind: string = "ArithmeticException";
}
/**
* Thrown when Reed-Solomon error correction fails
* Indicates the barcode has too many errors to be corrected
*/
class ReedSolomonException extends Exception {
static readonly kind: string = "ReedSolomonException";
}
/**
* Thrown when an operation is not supported or not yet implemented
* Indicates the requested functionality is not available
*/
class UnsupportedOperationException extends Exception {
static readonly kind: string = "UnsupportedOperationException";
}Complete Exception Hierarchy:
Exception (base)
├── ReaderException (reading errors)
│ ├── NotFoundException (no barcode found)
│ ├── FormatException (invalid format)
│ └── ChecksumException (checksum validation failed)
├── WriterException (encoding errors)
├── IllegalArgumentException (invalid arguments)
├── IllegalStateException (invalid state)
├── ArgumentException (general argument errors)
├── ArithmeticException (math errors)
├── ReedSolomonException (error correction failed)
└── UnsupportedOperationException (unsupported operation)Usage Examples:
import {
MultiFormatReader,
MultiFormatWriter,
BarcodeFormat,
NotFoundException,
FormatException,
ChecksumException,
ReaderException,
WriterException,
IllegalArgumentException,
UnsupportedOperationException,
ReedSolomonException,
BinaryBitmap,
BitMatrix
} from "@zxing/library";
// Reading error handling
function safeDecode(binaryBitmap: BinaryBitmap): string | null {
const reader = new MultiFormatReader();
try {
const result = reader.decode(binaryBitmap);
return result.getText();
} catch (e) {
// Handle specific exceptions from most specific to least specific
if (e instanceof NotFoundException) {
console.log("No barcode detected in image");
// Image may not contain a barcode, or barcode is too damaged/small
// Action: Check image quality, try different preprocessing
return null;
} else if (e instanceof ChecksumException) {
console.log("Barcode detected but validation failed");
// Barcode found but contains uncorrectable errors
// Action: Retry with TRY_HARDER, improve image quality
return null;
} else if (e instanceof FormatException) {
console.log("Barcode format is invalid or corrupted");
// Barcode structure doesn't match expected format
// Action: Check if barcode is partially obscured
return null;
} else if (e instanceof ReaderException) {
console.log("General reading error:", e.message);
// Catch-all for other reading errors
return null;
} else {
// Unexpected error - re-throw
console.error("Unexpected error:", e);
throw e;
}
}
}
// Writing error handling
function safeEncode(contents: string, format: BarcodeFormat): BitMatrix | null {
const writer = new MultiFormatWriter();
try {
const matrix: BitMatrix = writer.encode(
contents,
format,
200,
200,
new Map()
);
return matrix;
} catch (e) {
if (e instanceof WriterException) {
console.error("Encoding failed:", e.message);
// Data may be incompatible with format or too large
return null;
} else if (e instanceof IllegalArgumentException) {
console.error("Invalid parameters:", e.message);
// Check dimensions, format, or hint values
return null;
} else if (e instanceof UnsupportedOperationException) {
console.error("Format not supported for encoding:", e.message);
// Some formats don't have writers (MaxiCode, RSS_EXPANDED)
return null;
} else {
console.error("Unexpected error:", e);
throw e;
}
}
}
// Advanced error handling with retry logic
async function decodeWithRetry(
binaryBitmap: BinaryBitmap,
maxRetries: number = 3
): Promise<string | null> {
const reader = new MultiFormatReader();
let lastError: Error | null = null;
for (let attempt = 0; attempt < maxRetries; attempt++) {
try {
// Increase aggressiveness with each retry
const hints = new Map<DecodeHintType, any>();
if (attempt > 0) {
hints.set(DecodeHintType.TRY_HARDER, true);
}
const result = reader.decode(binaryBitmap, hints);
console.log(`Success on attempt ${attempt + 1}`);
return result.getText();
} catch (e) {
lastError = e as Error;
if (e instanceof NotFoundException) {
// No point retrying if no barcode found
console.error("No barcode found, aborting retries");
return null;
} else if (e instanceof ChecksumException || e instanceof FormatException) {
// These might succeed with TRY_HARDER, so retry
console.log(`Attempt ${attempt + 1} failed, retrying...`);
continue;
} else {
// Unexpected error, don't retry
throw e;
}
}
}
console.error("All retry attempts failed:", lastError);
return null;
}
// Exception type checking
function classifyError(error: Error): string {
if (error instanceof NotFoundException) {
return "No barcode found";
} else if (error instanceof ChecksumException) {
return "Checksum validation failed";
} else if (error instanceof FormatException) {
return "Invalid barcode format";
} else if (error instanceof WriterException) {
return "Encoding failed";
} else if (error instanceof ReedSolomonException) {
return "Error correction failed";
} else if (error instanceof IllegalArgumentException) {
return "Invalid argument";
} else if (error instanceof UnsupportedOperationException) {
return "Operation not supported";
} else {
return "Unknown error";
}
}
// Using singleton instances (optimization)
throw NotFoundException.getNotFoundInstance();
throw FormatException.getFormatInstance();
throw ChecksumException.getChecksumInstance();import {
MultiFormatReader,
NotFoundException,
FormatException,
ChecksumException,
ReaderException,
DecodeHintType,
BarcodeFormat,
BinaryBitmap,
Result
} from "@zxing/library";
/**
* Production-ready decoder with comprehensive error handling
*/
function productionDecode(binaryBitmap: BinaryBitmap): {
success: boolean;
text?: string;
format?: BarcodeFormat;
error?: string;
errorType?: string;
} {
const reader = new MultiFormatReader();
try {
const result: Result = reader.decode(binaryBitmap);
return {
success: true,
text: result.getText(),
format: result.getBarcodeFormat()
};
} catch (e) {
let errorType: string;
let errorMessage: string;
if (e instanceof NotFoundException) {
errorType = "NOT_FOUND";
errorMessage = "No barcode detected in image";
} else if (e instanceof ChecksumException) {
errorType = "CHECKSUM_FAILED";
errorMessage = "Barcode checksum validation failed";
} else if (e instanceof FormatException) {
errorType = "INVALID_FORMAT";
errorMessage = "Barcode format is invalid or corrupted";
} else if (e instanceof ReaderException) {
errorType = "READER_ERROR";
errorMessage = "General barcode reading error";
} else {
errorType = "UNKNOWN";
errorMessage = "Unexpected error occurred";
}
return {
success: false,
error: errorMessage,
errorType
};
}
}
// Usage
const decodeResult = productionDecode(bitmap);
if (decodeResult.success) {
console.log("Success:", decodeResult.text);
console.log("Format:", decodeResult.format);
} else {
console.error("Failed:", decodeResult.error);
console.error("Type:", decodeResult.errorType);
// Take action based on error type
switch (decodeResult.errorType) {
case "NOT_FOUND":
// Try different image preprocessing or inform user
break;
case "CHECKSUM_FAILED":
// Retry with TRY_HARDER or improve image quality
break;
case "INVALID_FORMAT":
// Barcode is damaged, try different region
break;
}
}/**
* Dimension type for specifying width and height
* Used in size constraints for encoding
*/
interface Dimension {
/**
* Width in pixels or modules
*/
width: number;
/**
* Height in pixels or modules
*/
height: number;
}Usage:
import { Dimension, EncodeHintType, DataMatrixWriter, BarcodeFormat } from "@zxing/library";
const minSize: Dimension = { width: 10, height: 10 };
const maxSize: Dimension = { width: 48, height: 48 };
const hints = new Map<EncodeHintType, any>();
hints.set(EncodeHintType.MIN_SIZE, minSize);
hints.set(EncodeHintType.MAX_SIZE, maxSize);
const writer = new DataMatrixWriter();
const matrix = writer.encode("Data", BarcodeFormat.DATA_MATRIX, 200, 200, hints);| Format | Read | Write | Error Correction | Max Capacity | Typical Use |
|---|---|---|---|---|---|
| QR_CODE | ✓ | ✓ | L/M/Q/H (~7-30%) | 2,953 bytes | General purpose, mobile |
| DATA_MATRIX | ✓ | ✓ | ECC200 | 2,335 chars | Manufacturing, healthcare |
| AZTEC | ✓ | ✓ | 23-90% configurable | 3,832 digits | Transport, ID documents |
| PDF_417 | ✓ | ✗ | 9 levels (0-8) | 1,850 chars | ID cards, transport |
| EAN_13 | ✓ | ✓ | Check digit | 13 digits | Retail products |
| EAN_8 | ✓ | ✓ | Check digit | 8 digits | Small packages |
| UPC_A | ✓ | ✓ | Check digit | 12 digits | North American retail |
| UPC_E | ✓ | ✓ | Check digit | 8 digits | Small packages (compressed) |
| CODE_128 | ✓ | ✓ | Check digit | Variable | Shipping, logistics |
| CODE_39 | ✓ | ✓ | Optional check | Variable | Industrial, automotive |
| CODE_93 | ✓ | ✗ | 2 check digits | Variable | Postal, logistics |
| ITF | ✓ | ✓ | Optional check | Even length | Distribution, ITF-14 |
| CODABAR | ✓ | ✓ | Self-checking | Variable | Libraries, blood banks |
| RSS_14 | ✓ | ✗ | Check digit | 14 digits | Small items, fresh food |
| RSS_EXPANDED | ✓ | ✗ | Check digit | Variable | Variable data (experimental) |
| MAXICODE | ✗ | ✗ | Built-in | Fixed | UPS (not implemented) |
| UPC_EAN_EXTENSION | ✓ | ✗ | N/A | 2 or 5 digits | Supplement only |
Legend:
// Optimize for speed
const fastHints = new Map<DecodeHintType, any>();
fastHints.set(DecodeHintType.POSSIBLE_FORMATS, [BarcodeFormat.QR_CODE]);
// Optimize for accuracy
const accurateHints = new Map<DecodeHintType, any>();
accurateHints.set(DecodeHintType.TRY_HARDER, true);
// Pure barcode (fastest)
const pureHints = new Map<DecodeHintType, any>();
pureHints.set(DecodeHintType.PURE_BARCODE, true);
// International text
const intlHints = new Map<DecodeHintType, any>();
intlHints.set(DecodeHintType.CHARACTER_SET, "UTF-8");// Maximum error correction (QR Code)
const maxECHints = new Map<EncodeHintType, any>();
maxECHints.set(EncodeHintType.ERROR_CORRECTION, "H");
// UTF-8 encoding
const utf8Hints = new Map<EncodeHintType, any>();
utf8Hints.set(EncodeHintType.CHARACTER_SET, "UTF-8");
// Minimal margin
const minMarginHints = new Map<EncodeHintType, any>();
minMarginHints.set(EncodeHintType.MARGIN, 1);
// Auto-size Aztec
const aztecHints = new Map<EncodeHintType, any>();
aztecHints.set(EncodeHintType.AZTEC_LAYERS, 0);
aztecHints.set(EncodeHintType.ERROR_CORRECTION, 33);
// Square Data Matrix
const squareDMHints = new Map<EncodeHintType, any>();
squareDMHints.set(EncodeHintType.DATA_MATRIX_SHAPE, SymbolShapeHint.FORCE_SQUARE);Install with Tessl CLI
npx tessl i tessl/npm-zxing--library