TypeScript port of ZXing multi-format 1D/2D barcode image processing library
Complete guide to getting started with @zxing/library for barcode reading and writing.
npm install @zxing/libraryFor browser-specific features (camera access):
npm install @zxing/browserimport {
MultiFormatReader,
BinaryBitmap,
HybridBinarizer,
RGBLuminanceSource,
DecodeHintType,
BarcodeFormat
} from '@zxing/library';
// Step 1: Create luminance source from image data
const luminanceSource = new RGBLuminanceSource(
imagePixels, // Uint8ClampedArray of grayscale or ARGB pixels
width, // Image width in pixels
height // Image height in pixels
);
// Step 2: Apply binarization (convert grayscale to black/white)
const binarizer = new HybridBinarizer(luminanceSource);
// Step 3: Create binary bitmap
const binaryBitmap = new BinaryBitmap(binarizer);
// Step 4: Configure reader
const reader = new MultiFormatReader();
const hints = new Map();
hints.set(DecodeHintType.POSSIBLE_FORMATS, [
BarcodeFormat.QR_CODE,
BarcodeFormat.EAN_13,
BarcodeFormat.CODE_128
]);
hints.set(DecodeHintType.TRY_HARDER, true);
// Step 5: Decode
try {
const result = reader.decode(binaryBitmap, hints);
console.log('Text:', result.getText());
console.log('Format:', result.getBarcodeFormat());
console.log('Timestamp:', result.getTimestamp());
} catch (error) {
console.error('Decode failed:', error);
}import {
MultiFormatReader,
BinaryBitmap,
HybridBinarizer,
RGBLuminanceSource
} from '@zxing/library';
function decodeFromImage(imageElement: HTMLImageElement): string | null {
// Extract pixel data from image
const canvas = document.createElement('canvas');
const context = canvas.getContext('2d')!;
canvas.width = imageElement.naturalWidth || imageElement.width;
canvas.height = imageElement.naturalHeight || imageElement.height;
context.drawImage(imageElement, 0, 0);
const imageData = context.getImageData(0, 0, canvas.width, canvas.height);
// Create luminance source
const luminanceSource = new RGBLuminanceSource(
new Uint8ClampedArray(imageData.data),
canvas.width,
canvas.height
);
// Decode
const binaryBitmap = new BinaryBitmap(new HybridBinarizer(luminanceSource));
const reader = new MultiFormatReader();
try {
const result = reader.decode(binaryBitmap);
return result.getText();
} catch (error) {
console.error('Decode failed:', error);
return null;
}
}
// Usage
const img = document.getElementById('barcode-img') as HTMLImageElement;
const text = decodeFromImage(img);
console.log('Decoded:', text);import { BrowserMultiFormatReader } from '@zxing/library';
const codeReader = new BrowserMultiFormatReader();
// Check browser support
if (!BrowserCodeReader.isMediaDevicesSupported()) {
console.error('Camera not supported');
return;
}
// Get available cameras
const devices = await codeReader.listVideoInputDevices();
console.log(`Found ${devices.length} cameras`);
// Decode once from default camera
const videoElement = document.getElementById('video') as HTMLVideoElement;
try {
const result = await codeReader.decodeOnceFromVideoDevice(undefined, videoElement);
console.log('Scanned:', result.getText());
} catch (error) {
console.error('Scan failed:', error);
} finally {
codeReader.reset(); // Always release camera
}import { BrowserMultiFormatReader } from '@zxing/library';
const codeReader = new BrowserMultiFormatReader();
const videoElement = document.getElementById('video') as HTMLVideoElement;
// Start continuous scanning
await codeReader.decodeFromVideoDevice(
null, // null = default camera
videoElement,
(result, error) => {
if (result) {
console.log('Found:', result.getText());
document.getElementById('result')!.textContent = result.getText();
}
if (error && !(error instanceof NotFoundException)) {
console.error('Error:', error);
}
}
);
// Stop scanning later
document.getElementById('stop-btn')!.addEventListener('click', () => {
codeReader.stopContinuousDecode();
codeReader.reset();
});import {
QRCodeWriter,
BarcodeFormat,
EncodeHintType,
QRCodeDecoderErrorCorrectionLevel
} from '@zxing/library';
const writer = new QRCodeWriter();
// Configure hints
const hints = new Map();
hints.set(EncodeHintType.ERROR_CORRECTION, QRCodeDecoderErrorCorrectionLevel.H);
hints.set(EncodeHintType.CHARACTER_SET, 'UTF-8');
hints.set(EncodeHintType.MARGIN, 2);
// Encode
const bitMatrix = writer.encode(
'https://example.com',
BarcodeFormat.QR_CODE,
300, // Width in pixels
300, // Height in pixels
hints
);
// Render to canvas
const canvas = document.getElementById('qr') as HTMLCanvasElement;
const ctx = canvas.getContext('2d')!;
canvas.width = bitMatrix.getWidth();
canvas.height = bitMatrix.getHeight();
for (let y = 0; y < bitMatrix.getHeight(); y++) {
for (let x = 0; x < bitMatrix.getWidth(); x++) {
ctx.fillStyle = bitMatrix.get(x, y) ? '#000000' : '#FFFFFF';
ctx.fillRect(x, y, 1, 1);
}
}import {
DataMatrixWriter,
BarcodeFormat,
EncodeHintType,
SymbolShapeHint
} from '@zxing/library';
const writer = new DataMatrixWriter();
const hints = new Map();
hints.set(EncodeHintType.DATA_MATRIX_SHAPE, SymbolShapeHint.FORCE_SQUARE);
hints.set(EncodeHintType.CHARACTER_SET, 'UTF-8');
const bitMatrix = writer.encode(
'Product: 12345',
BarcodeFormat.DATA_MATRIX,
200,
200,
hints
);
// Render bitMatrix to image...import {
AztecCodeWriter,
BarcodeFormat,
EncodeHintType
} from '@zxing/library';
const writer = new AztecCodeWriter();
const hints = new Map();
hints.set(EncodeHintType.ERROR_CORRECTION, 33); // 33% error correction
hints.set(EncodeHintType.AZTEC_LAYERS, 0); // Auto-select layers
const bitMatrix = writer.encode(
'Aztec data',
BarcodeFormat.AZTEC,
0, // 0 = auto-size
0,
hints
);
console.log('Generated:', bitMatrix.getWidth(), '×', bitMatrix.getHeight());const hints = new Map();
// Limit to expected formats only
hints.set(DecodeHintType.POSSIBLE_FORMATS, [BarcodeFormat.QR_CODE]);
// Don't use TRY_HARDER (faster but less reliable)
// hints.set(DecodeHintType.TRY_HARDER, false); // Default
// Use GlobalHistogramBinarizer (faster)
const binarizer = new GlobalHistogramBinarizer(luminanceSource);const hints = new Map();
// Enable thorough scanning
hints.set(DecodeHintType.TRY_HARDER, true);
// Allow multiple formats
hints.set(DecodeHintType.POSSIBLE_FORMATS, [
BarcodeFormat.QR_CODE,
BarcodeFormat.DATA_MATRIX,
BarcodeFormat.AZTEC
]);
// Use HybridBinarizer (more accurate)
const binarizer = new HybridBinarizer(luminanceSource);import {
NotFoundException,
FormatException,
ChecksumException
} from '@zxing/library';
try {
const result = reader.decode(bitmap);
console.log('Success:', result.getText());
} catch (error) {
if (error instanceof NotFoundException) {
console.error('No barcode found');
} else if (error instanceof ChecksumException) {
console.error('Barcode damaged');
} else if (error instanceof FormatException) {
console.error('Invalid barcode format');
} else {
console.error('Unknown error:', error);
}
}async function decodeWithFallbacks(bitmap: BinaryBitmap): Promise<Result | null> {
const reader = new MultiFormatReader();
// Try normal
try {
return reader.decode(bitmap);
} catch (e1) {}
// Try with TRY_HARDER
try {
const hints = new Map();
hints.set(DecodeHintType.TRY_HARDER, true);
return reader.decode(bitmap, hints);
} catch (e2) {}
return null;
}Install with Tessl CLI
npx tessl i tessl/npm-zxing--library