Barcode Reader Node
Overview
The Barcode Reader is a multi-decoder node that scans barcodes and QR codes from images using three powerful libraries: ZBar, ZXing, and Quagga2. It features a flexible block-based architecture that allows you to optimize detection for either maximum accuracy or performance.
Key Features
- Multi-decoder support: ZBar, ZXing, and Quagga2
- Flexible preprocessing: Original, Histogram Equalization, Otsu Threshold
- Block-based configuration: Combine decoders and preprocessing methods
- Execution modes: Parallel (maximum detection) or Sequential (optimized performance)
- Batch processing: Process single images or arrays of images
- Smart deduplication: Automatically merges duplicate detections
- Performance tracking: Built-in execution time monitoring
- Rich output format: Includes barcode corners, rotation, and detection metadata
Configuration
Properties
Name
- Type: String
- Optional: Yes
- Description: Custom name for the node instance
Input
- Type: Message property path
- Default:
payload - Description: Message property containing the input image(s)
Output
- Type: Message property path
- Default:
payload - Description: Message property where results will be stored
Execution Mode
- Type: Select
- Options:
- Parallel: Runs all blocks simultaneously and merges results (maximum detection)
- Sequential: Processes blocks in order, stops at first successful detection (optimized performance)
Decoder Blocks
Each block represents a detection attempt with specific configuration. Blocks can be:
- Added with the "Add Block" button
- Reordered by dragging (relevant for Sequential mode)
- Removed individually
- Configured independently
Decoder Options
ZBar
- Fast and reliable
- Good for standard barcodes and QR codes
- Native C++ implementation
- Best overall performance
ZXing
- Comprehensive format support
- "Try Harder" option for difficult codes
- Good for damaged or low-quality barcodes
- Slower but more thorough
Quagga2
- JavaScript-based decoder
- Good for 1D barcodes
- Runs in Node.js without native dependencies
- Moderate performance
Preprocessing Options
Original
- Simple grayscale conversion
- Fastest option
- Use for high-quality images with good contrast
Histogram Equalization
- Enhances contrast across the image
- Good for poor lighting conditions
- Helps with uneven illumination
Otsu Threshold
- Converts to binary (black/white) image
- Best for low-contrast barcodes
- Effective for faded or worn codes
Decoder-Specific Options
ZXing Options:
- Try Harder: Enables more thorough scanning (slower but more accurate)
Input Format
The node accepts images in multiple formats:
Rosepetal Bitmap Format
{
width: 1920,
height: 1080,
data: Buffer,
colorSpace: "rgb" // or "rgba", "gray"
}2
3
4
5
6
Raw Bitmap
{
width: 1920,
height: 1080,
data: Buffer,
channels: 3 // or 1, 4
}2
3
4
5
6
Image Buffers
- JPEG buffer
- PNG buffer
Array Input
Process multiple images at once:
msg.payload = [image1, image2, image3];Output Format
Single Image Input
Returns an array of detected barcodes:
[
{
format: "QR-Code",
value: "decoded_content_here",
box: {
center: { x: 0.5, y: 0.5 }, // Relative coordinates (0-1)
size: { width: 0.2, height: 0.2 }, // Relative to image size
angle: 15 // Rotation in degrees
},
corners: [ // Four corners in relative coordinates
{ x: 0.4, y: 0.4 },
{ x: 0.6, y: 0.4 },
{ x: 0.6, y: 0.6 },
{ x: 0.4, y: 0.6 }
],
detectedBy: ["zbar_original", "zxing_original"] // Which decoder/preprocessing found it
}
]2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
Array Input
Returns nested array structure:
[
[image1_result1, image1_result2], // Results from first image
[image2_result1], // Results from second image
[] // No results from third image
]2
3
4
5
Performance Tracking
The node automatically adds execution time to msg.performance:
msg.performance = {
"barcode-reader": {
startTime: Date,
milliseconds: 245
}
}2
3
4
5
6
The execution time is also displayed under the node in the editor.
Usage Examples
Example 1: Maximum Detection Rate (Parallel Mode)
Use case: Scanning worn, damaged, or low-quality barcodes
Configuration:
- Mode: Parallel
- Block 1: ZBar + Original
- Block 2: ZBar + Histogram Equalization
- Block 3: ZBar + Otsu Threshold
- Block 4: ZXing + Original + Try Harder
- Block 5: ZXing + Histogram + Try Harder
Behavior: All blocks run simultaneously, results are merged and deduplicated
Trade-off: Slower execution, maximum detection rate
Example 2: Fast with Fallback (Sequential Mode)
Use case: High-throughput production with mostly good quality codes
Configuration:
- Mode: Sequential
- Block 1: ZBar + Original (fastest)
- Block 2: ZXing + Original (if Block 1 fails)
- Block 3: ZXing + Histogram + Try Harder (last resort)
Behavior: Stops at first successful detection
Trade-off: Fast for most images, reliable fallback for difficult ones
Example 3: Balanced Approach
Use case: Mixed quality images, moderate performance requirements
Configuration:
- Mode: Parallel
- Block 1: ZBar + Original
- Block 2: ZXing + Histogram
- Block 3: Quagga2 + Otsu
Behavior: Three different approaches run in parallel
Trade-off: Good balance of speed and detection rate
Example 4: Processing Multiple Images
// Input node
msg.payload = [
imageBuffer1,
imageBuffer2,
imageBuffer3
];
// After barcode reader
msg.payload = [
[{ format: "QR-Code", value: "ABC123", ... }], // Results from image 1
[{ format: "CODE-128", value: "XYZ789", ... }], // Results from image 2
[] // No barcodes in image 3
];2
3
4
5
6
7
8
9
10
11
12
13
Example 5: Custom Input/Output Paths
// Configuration:
// - Input: "image.data"
// - Output: "barcodes"
msg.image = {
data: imageBuffer,
width: 1920,
height: 1080
};
// After processing:
msg.barcodes = [
{ format: "QR-Code", value: "scanned_data", ... }
];2
3
4
5
6
7
8
9
10
11
12
13
14
Supported Barcode Formats
1D Barcodes
- CODE-128 (logistics, shipping)
- CODE-39 (automotive, DoD)
- CODE-93 (Canada Post)
- EAN-13 (retail products worldwide)
- EAN-8 (small retail items)
- UPC-A (North America retail)
- UPC-E (small packages)
- CODABAR (libraries, blood banks, FedEx)
- ITF (Interleaved 2 of 5)
2D Barcodes
- QR Code
- Data Matrix
- PDF417
- Aztec Code
Decoder Format Support
| Format | ZBar | ZXing | Quagga2 |
|---|---|---|---|
| QR Code | ✓ | ✓ | ✗ |
| CODE-128 | ✓ | ✓ | ✓ |
| CODE-39 | ✓ | ✓ | ✓ |
| EAN-13 | ✓ | ✓ | ✓ |
| EAN-8 | ✓ | ✓ | ✓ |
| UPC-A | ✓ | ✓ | ✓ |
| UPC-E | ✓ | ✓ | ✓ |
| Data Matrix | ✓ | ✓ | ✗ |
| PDF417 | ✓ | ✓ | ✗ |
| CODABAR | ✓ | ✓ | ✓ |
Performance Considerations
Execution Time Factors
- Number of blocks: More blocks = longer execution (in Parallel mode)
- Preprocessing method: Original < Histogram < Otsu
- Decoder choice: Quagga2 < ZBar < ZXing (approximate)
- Image size: Larger images take longer
- Try Harder option: Significantly increases ZXing processing time
Optimization Strategies
For Speed
- Use Sequential mode
- Start with Original preprocessing
- Place fastest blocks first (ZBar + Original)
- Reduce image resolution before processing
- Use single decoder only
For Accuracy
- Use Parallel mode
- Include multiple preprocessing options
- Enable "Try Harder" on ZXing blocks
- Use multiple decoders
- Ensure good image quality (1500px max on long side recommended)
Typical Performance
Sequential mode (fast path):
- High-quality barcode: 20-50ms (Block 1 success)
- Medium quality: 100-200ms (falls to Block 2-3)
- Low quality: 300-500ms (exhausts all blocks)
Parallel mode (maximum detection):
- 3 blocks: 150-300ms
- 5 blocks: 300-600ms
- 8 blocks: 500-1000ms
Times vary based on image size, hardware, and complexity
Deduplication Logic
When multiple blocks detect the same barcode:
- Barcodes are considered duplicates if they have the same value (data)
- The detection from the lowest block index is kept as the primary result
- All detection methods are tracked in the
detectedByarray - Position data (corners, box) comes from the primary detection
Example:
// Block 0: ZBar + Original detects "ABC123"
// Block 2: ZXing + Histogram also detects "ABC123"
// Result:
{
format: "CODE-128",
value: "ABC123",
box: { /* from Block 0 */ },
corners: [ /* from Block 0 */ ],
detectedBy: ["zbar_original", "zxing_histogram"]
}2
3
4
5
6
7
8
9
10
11
Troubleshooting
No Barcodes Detected
Possible causes:
- Barcode too small or large in image
- Poor image quality or low contrast
- Barcode damaged or partially obscured
- Unsupported barcode format
Solutions:
- Add blocks with stronger preprocessing (Histogram, Otsu)
- Enable "Try Harder" on ZXing blocks
- Switch to Parallel mode for comprehensive scanning
- Verify barcode format is supported
- Check image quality and resolution
- Ensure proper lighting in source images
Slow Performance
Possible causes:
- Too many blocks in Parallel mode
- Large image resolution
- Multiple "Try Harder" blocks
- Processing arrays of many images
Solutions:
- Switch to Sequential mode
- Reduce number of blocks
- Disable "Try Harder" or use selectively
- Resize images before processing
- Remove blocks with slow preprocessing (Otsu)
Wrong Barcode Values
Possible causes:
- Multiple barcodes in image
- Barcode partially damaged
- Similar patterns confusing decoder
Solutions:
- Crop image to single barcode region
- Use stronger preprocessing
- Enable "Try Harder" on ZXing
- Verify expected barcode format
Missing Quagga2 Warning
Message: Quagga2 not available. Install @ericblade/quagga2 to use Quagga decoder.
Solution:
npm install @ericblade/quagga2Or remove Quagga2 blocks from configuration.
Requirements
System Dependencies
The node requires native libraries to be installed:
Linux (Debian/Ubuntu)
# For ZBar and ZXing
apt-get install libzbar0 libzbar-dev
apt-get install python3-opencv libopencv-dev2
3
Linux (RHEL/CentOS)
# For ZBar and ZXing
yum install zbar zbar-devel
yum install opencv opencv-devel2
3
macOS
# Using Homebrew
brew install zbar opencv2
Node.js Dependencies
The following packages are automatically installed:
- Native barcode decoder addon (ZBar/ZXing)
@ericblade/quagga2(optional, for Quagga2 decoder)jpeg-js(for Quagga2 image conversion)
Best Practices
Image Preparation
- Resolution: Keep images around 1500px on the long side for optimal balance
- Format: Use JPEG for photos, PNG for generated codes
- Lighting: Ensure even lighting across barcode
- Focus: Barcodes must be sharp and in focus
- Orientation: Any orientation works, rotation is detected
Block Configuration
- Start simple: Begin with 1-2 blocks and add more if needed
- Order matters: In Sequential mode, put fastest/most likely blocks first
- Test thoroughly: Verify with representative sample images
- Monitor performance: Watch execution times in production
- Document choices: Note why specific blocks were chosen
Production Deployment
- Test all formats: Verify all expected barcode types are detected
- Benchmark performance: Measure actual execution times
- Handle failures: Implement proper error handling for no-detection cases
- Log statistics: Track detection rates and performance
- Version control: Document block configuration changes
Advanced Usage
Dynamic Block Configuration
You can modify block configuration programmatically before the node:
// In a function node before the barcode reader
msg.barcodeConfig = {
blocks: [
{ decoder: "zbar", preprocessing: "original", options: {} },
{ decoder: "zxing", preprocessing: "histogram", options: { tryHarder: true }}
],
executionMode: "sequential"
};2
3
4
5
6
7
8
Region of Interest Processing
Crop image to barcode region before processing:
// In a function node before the barcode reader
const sharp = require('sharp');
msg.payload = await sharp(msg.payload)
.extract({ left: 100, top: 100, width: 500, height: 200 })
.toBuffer();2
3
4
5
6
Quality Validation
Filter results by confidence or validation:
// In a function node after the barcode reader
msg.payload = msg.payload.filter(result => {
// Only keep results detected by multiple methods
return result.detectedBy.length >= 2;
});2
3
4
5
Performance Monitoring
Track detailed performance metrics:
// In a function node after the barcode reader
const perf = msg.performance["barcode-reader"];
const detectionCount = Array.isArray(msg.payload) ? msg.payload.length : 0;
msg.metrics = {
executionTime: perf.milliseconds,
detectionsFound: detectionCount,
detectionsPerSecond: (detectionCount / perf.milliseconds * 1000).toFixed(2)
};2
3
4
5
6
7
8
9
Migration Guide
From node-zbardecoder
If migrating from the basic node-zbardecoder package:
Old approach:
const bardecoder = require('node-zbardecoder');
const result = JSON.parse(bardecoder.decode('image.jpg'));2
New approach:
- Use the Barcode Reader node in your flow
- Configure with ZBar decoder + Original preprocessing
- Results are automatically parsed and formatted
- Additional decoders and preprocessing available
Key differences:
- Block-based configuration vs. single decoder
- Relative coordinates instead of absolute pixels
- Rich metadata (corners, rotation, detection tracking)
- Built-in performance monitoring
See Also
- ZBar Library - Open source barcode scanner
- ZXing Library - Multi-format 1D/2D barcode library
- Quagga2 - JavaScript barcode decoder
- OpenCV - Computer vision library used for preprocessing