Skip to content

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

javascript
{
  width: 1920,
  height: 1080,
  data: Buffer,
  colorSpace: "rgb" // or "rgba", "gray"
}

Raw Bitmap

javascript
{
  width: 1920,
  height: 1080,
  data: Buffer,
  channels: 3 // or 1, 4
}

Image Buffers

  • JPEG buffer
  • PNG buffer

Array Input

Process multiple images at once:

javascript
msg.payload = [image1, image2, image3];

Output Format

Single Image Input

Returns an array of detected barcodes:

javascript
[
  {
    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
  }
]

Array Input

Returns nested array structure:

javascript
[
  [image1_result1, image1_result2], // Results from first image
  [image2_result1],                  // Results from second image
  []                                 // No results from third image
]

Performance Tracking

The node automatically adds execution time to msg.performance:

javascript
msg.performance = {
  "barcode-reader": {
    startTime: Date,
    milliseconds: 245
  }
}

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

javascript
// 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
];

Example 5: Custom Input/Output Paths

javascript
// Configuration:
// - Input: "image.data"
// - Output: "barcodes"

msg.image = {
  data: imageBuffer,
  width: 1920,
  height: 1080
};

// After processing:
msg.barcodes = [
  { format: "QR-Code", value: "scanned_data", ... }
];

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

FormatZBarZXingQuagga2
QR Code
CODE-128
CODE-39
EAN-13
EAN-8
UPC-A
UPC-E
Data Matrix
PDF417
CODABAR

Performance Considerations

Execution Time Factors

  1. Number of blocks: More blocks = longer execution (in Parallel mode)
  2. Preprocessing method: Original < Histogram < Otsu
  3. Decoder choice: Quagga2 < ZBar < ZXing (approximate)
  4. Image size: Larger images take longer
  5. 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:

  1. Barcodes are considered duplicates if they have the same value (data)
  2. The detection from the lowest block index is kept as the primary result
  3. All detection methods are tracked in the detectedBy array
  4. Position data (corners, box) comes from the primary detection

Example:

javascript
// 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"]
}

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:

  1. Add blocks with stronger preprocessing (Histogram, Otsu)
  2. Enable "Try Harder" on ZXing blocks
  3. Switch to Parallel mode for comprehensive scanning
  4. Verify barcode format is supported
  5. Check image quality and resolution
  6. 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:

  1. Switch to Sequential mode
  2. Reduce number of blocks
  3. Disable "Try Harder" or use selectively
  4. Resize images before processing
  5. Remove blocks with slow preprocessing (Otsu)

Wrong Barcode Values

Possible causes:

  • Multiple barcodes in image
  • Barcode partially damaged
  • Similar patterns confusing decoder

Solutions:

  1. Crop image to single barcode region
  2. Use stronger preprocessing
  3. Enable "Try Harder" on ZXing
  4. Verify expected barcode format

Missing Quagga2 Warning

Message: Quagga2 not available. Install @ericblade/quagga2 to use Quagga decoder.

Solution:

bash
npm install @ericblade/quagga2

Or remove Quagga2 blocks from configuration.

Requirements

System Dependencies

The node requires native libraries to be installed:

Linux (Debian/Ubuntu)

bash
# For ZBar and ZXing
apt-get install libzbar0 libzbar-dev
apt-get install python3-opencv libopencv-dev

Linux (RHEL/CentOS)

bash
# For ZBar and ZXing
yum install zbar zbar-devel
yum install opencv opencv-devel

macOS

bash
# Using Homebrew
brew install zbar opencv

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

  1. Resolution: Keep images around 1500px on the long side for optimal balance
  2. Format: Use JPEG for photos, PNG for generated codes
  3. Lighting: Ensure even lighting across barcode
  4. Focus: Barcodes must be sharp and in focus
  5. Orientation: Any orientation works, rotation is detected

Block Configuration

  1. Start simple: Begin with 1-2 blocks and add more if needed
  2. Order matters: In Sequential mode, put fastest/most likely blocks first
  3. Test thoroughly: Verify with representative sample images
  4. Monitor performance: Watch execution times in production
  5. Document choices: Note why specific blocks were chosen

Production Deployment

  1. Test all formats: Verify all expected barcode types are detected
  2. Benchmark performance: Measure actual execution times
  3. Handle failures: Implement proper error handling for no-detection cases
  4. Log statistics: Track detection rates and performance
  5. Version control: Document block configuration changes

Advanced Usage

Dynamic Block Configuration

You can modify block configuration programmatically before the node:

javascript
// 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"
};

Region of Interest Processing

Crop image to barcode region before processing:

javascript
// 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();

Quality Validation

Filter results by confidence or validation:

javascript
// 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;
});

Performance Monitoring

Track detailed performance metrics:

javascript
// 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)
};

Migration Guide

From node-zbardecoder

If migrating from the basic node-zbardecoder package:

Old approach:

javascript
const bardecoder = require('node-zbardecoder');
const result = JSON.parse(bardecoder.decode('image.jpg'));

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