Added scanning barcodes with a camera

This commit is contained in:
2026-03-08 16:59:33 +00:00
parent b4f8489834
commit 5a37e5dd5f
404 changed files with 224181 additions and 0 deletions

View File

@@ -0,0 +1,79 @@
# Configure Barcode Readers {#configure-readers}
This guide explains how to configure which barcode formats Quagga2 will detect.
## Basic Configuration {#basic-configuration}
Specify readers in the `decoder.readers` array:
```javascript
Quagga.init({
decoder: {
readers: ["code_128_reader", "ean_reader"]
}
});
```
## Available Readers {#available-readers}
| Reader | Format | Common Uses |
|--------|--------|-------------|
| `code_128_reader` | Code 128 | Shipping, packaging |
| `ean_reader` | EAN-13 | Retail products |
| `ean_8_reader` | EAN-8 | Small products |
| `upc_reader` | UPC-A | North American retail |
| `upc_e_reader` | UPC-E | Small products |
| `code_39_reader` | Code 39 | Industrial |
| `code_39_vin_reader` | Code 39 VIN | Vehicle identification |
| `codabar_reader` | Codabar | Libraries, blood banks |
| `i2of5_reader` | Interleaved 2 of 5 | Warehouse |
| `2of5_reader` | Standard 2 of 5 | Industrial |
| `code_93_reader` | Code 93 | Logistics |
| `code_32_reader` | Code 32 | Italian pharmaceuticals |
## Reader Priority {#reader-priority}
Readers are processed in order. Put most likely formats first:
```javascript
decoder: {
readers: [
"ean_reader", // Most common - checked first
"upc_reader", // Second most common
"code_128_reader" // Fallback
]
}
```
## EAN Supplements {#ean-supplements}
To read EAN-2 or EAN-5 extension supplements:
```javascript
decoder: {
readers: [
"ean_reader", // Regular EAN without supplements
{
format: "ean_reader",
config: {
supplements: ["ean_5_reader", "ean_2_reader"]
}
}
]
}
```
## Best Practices {#best-practices}
1. **Only enable needed readers** - More readers = slower performance
2. **Order by frequency** - Put most common formats first
3. **Test thoroughly** - Some formats can conflict
## Related {#related}
- [Supported Barcode Types](../reference/readers.md) - Complete reader documentation
- [Configuration Reference](../reference/configuration.md) - All configuration options
---
[← Back to How-To Guides](index.md)

View File

@@ -0,0 +1,234 @@
# How-To: Create and Use External Readers {#create-and-use-external-readers}
This guide explains how to create custom barcode reader plugins and integrate them into Quagga2.
## Using Existing External Readers {#using-existing-external-readers}
### QR Code Reader {#qr-code-reader}
The most common external reader is [quagga2-reader-qr](https://github.com/ericblade/quagga2-reader-qr) for QR code support:
```javascript
import Quagga from '@ericblade/quagga2';
import QRReader from 'quagga2-reader-qr';
// Register the external reader
Quagga.registerReader('qr', QRReader);
// Use it in your config
Quagga.init({
decoder: {
readers: ['qr']
}
});
```
## External Reader Priority {#external-reader-priority}
External readers follow the **same priority rules** as built-in readers:
1. **Registration first**: Call `Quagga.registerReader(name, ReaderClass)` before using the reader
2. **Position determines priority**: The reader's position in the `readers` array determines when it attempts to decode
3. **First success wins**: The first reader to return a valid result is used
### Example: Prioritizing External Readers {#prioritizing-external-readers}
```javascript
// Register external reader
Quagga.registerReader('my_custom_reader', MyCustomReader);
// External reader tried first, then built-in readers
Quagga.init({
decoder: {
readers: ['my_custom_reader', 'ean_reader', 'code_128_reader']
}
});
```
### Example: External Reader as Fallback {#external-reader-fallback}
```javascript
// Register external reader
Quagga.registerReader('my_fallback_reader', MyFallbackReader);
// Built-in readers tried first, external as fallback
Quagga.init({
decoder: {
readers: ['ean_reader', 'code_128_reader', 'my_fallback_reader']
}
});
```
## Creating Custom Readers {#creating-custom-readers}
Quagga2 exports the `BarcodeReader` prototype that you can extend to create custom readers.
### Basic Reader Structure {#basic-reader-structure}
```javascript
import { Readers } from '@ericblade/quagga2';
const { BarcodeReader } = Readers;
class MyCustomReader extends BarcodeReader {
FORMAT = 'my_custom_format';
constructor(config, supplements) {
super(config, supplements);
// Custom initialization
}
decode(row, start) {
// Implement barcode decoding logic
// row: Array<number> - binary line data
// start: number - starting position
// Return null if no barcode found
// Return Barcode object if successful
return null;
}
}
export default MyCustomReader;
```
### Reader Return Format {#reader-return-format}
Your `decode()` method should return either `null` (no match) or a result object:
```javascript
{
code: '1234567890', // The decoded barcode value
start: 0, // Start position in the row
end: 100, // End position in the row
startInfo: { start: 0, end: 10 }, // Start pattern info
format: 'my_custom_format', // Your reader's format name
decodedCodes: [...] // Optional: decoded character info
}
```
### Pattern Matching Utilities {#pattern-matching-utilities}
BarcodeReader provides useful methods for pattern matching:
- `_nextSet(line, offset)` - Find next set (1) bit
- `_nextUnset(line, offset)` - Find next unset (0) bit
- `_matchPattern(counter, code, maxSingleError)` - Match bar patterns
- `_fillCounters(offset, end, isWhite)` - Count consecutive bars/spaces
### Example: Simple Pattern Reader {#simple-pattern-reader}
```javascript
class SimpleBarReader extends BarcodeReader {
FORMAT = 'simple_bar';
START_PATTERN = [1, 1, 1]; // Three bars pattern
decode(row, start) {
if (row) {
this._row = row;
}
// Find start pattern
const startInfo = this._findPattern(this.START_PATTERN, 0, false);
if (!startInfo) {
return null;
}
// Decode the barcode content
const result = this._decodeContent(startInfo.end);
if (!result) {
return null;
}
return {
code: result.code,
start: startInfo.start,
end: result.end,
startInfo: startInfo,
format: this.FORMAT
};
}
_decodeContent(offset) {
// Implement your decoding logic
return null;
}
}
```
## Image-Based Readers {#image-based-readers}
For non-linear barcodes (like QR codes), implement `decodeImage()` instead:
```javascript
class MyImageReader extends BarcodeReader {
FORMAT = 'my_image_format';
// Override decode to return null (not a linear barcode)
decode() {
return null;
}
// Implement image-based decoding
async decodeImage(imageWrapper) {
// imageWrapper.data - pixel data
// imageWrapper.size - { x, y } dimensions
// Process the image and decode
const result = await this.processImage(imageWrapper);
if (!result) {
return null;
}
return {
codeResult: {
code: result.data,
format: this.FORMAT
}
};
}
}
```
## Testing Your Reader {#testing-your-reader}
1. **Unit tests**: Test pattern matching and decoding logic in isolation
2. **Integration tests**: Use `Quagga.decodeSingle()` with test images
3. **Live testing**: Test with real camera input
### Example Test {#example-test}
```javascript
import Quagga from '@ericblade/quagga2';
import MyCustomReader from './my-custom-reader';
Quagga.registerReader('my_custom', MyCustomReader);
const result = await Quagga.decodeSingle({
src: './test-image.jpg',
decoder: {
readers: ['my_custom']
}
});
console.log('Result:', result?.codeResult?.code);
```
## Best Practices {#best-practices}
1. **Set unique FORMAT**: Use a distinctive format name to identify your reader
2. **Handle edge cases**: Return `null` gracefully when patterns don't match
3. **Validate checksums**: Implement checksum validation when the format supports it
4. **Consider performance**: Optimize pattern matching for real-time scanning
5. **Test thoroughly**: Test with various image qualities and conditions
## Related {#related}
- [Supported Barcode Types](../reference/readers.md) - Built-in readers
- [Configuration Reference](../reference/configuration.md) - Full config options
- [quagga2-reader-qr](https://github.com/ericblade/quagga2-reader-qr) - Example external reader
---
[← Back to How-To Guides](index.md)

View File

@@ -0,0 +1,127 @@
# Handle Difficult Barcodes {#handle-difficult-barcodes}
This guide provides techniques for improving barcode detection in challenging conditions.
## Common Challenges {#common-challenges}
- Poor lighting or shadows
- Blurry or out-of-focus images
- Small or distant barcodes
- Damaged or partially obscured barcodes
- Low contrast between bars and background
## Improving Detection {#improving-detection}
### Adjust Patch Size {#adjust-patch-size}
For small or distant barcodes, use a smaller patch size:
```javascript
locator: {
patchSize: "small" // or "x-small" for very small barcodes
}
```
### Increase Resolution {#increase-resolution}
Higher resolution provides more detail:
```javascript
inputStream: {
size: 1280, // Larger processing size
constraints: {
width: { ideal: 1920 },
height: { ideal: 1080 }
}
}
```
### Disable Half Sampling {#disable-half-sampling}
For fine details, process at full resolution:
```javascript
locator: {
halfSample: false
}
```
## Handling False Positives {#handling-false-positives}
### Validate Results {#validate-results}
Check result confidence and format:
```javascript
Quagga.onDetected(function(result) {
// Check if result has expected format
if (result.codeResult.format !== 'ean_13') {
return; // Ignore unexpected formats
}
// Validate checksum externally if needed
if (!validateBarcode(result.codeResult.code)) {
return;
}
processBarcode(result.codeResult.code);
});
```
### Require Multiple Reads {#require-multiple-reads}
Confirm detection across multiple frames:
```javascript
let lastCode = null;
let readCount = 0;
Quagga.onDetected(function(result) {
const code = result.codeResult.code;
if (code === lastCode) {
readCount++;
if (readCount >= 3) {
// Confirmed detection
processBarcode(code);
readCount = 0;
}
} else {
lastCode = code;
readCount = 1;
}
});
```
## Using Debug Flags {#using-debug-flags}
Enable visual debugging to understand detection issues:
```javascript
Quagga.init({
debug: true,
decoder: {
debug: {
drawBoundingBox: true,
drawScanline: true
}
},
locator: {
debug: {
showFoundPatches: true
}
}
});
```
See [Use Debug Flags](use-debug-flags.md) for complete details.
## Related {#related}
- [Configuration Reference](../reference/configuration.md) - All configuration options
- [Optimize Performance](optimize-performance.md) - Balance accuracy vs speed
- [Use Debug Flags](use-debug-flags.md) - Diagnostic tools
---
[← Back to How-To Guides](index.md)

View File

@@ -0,0 +1,77 @@
# How-To Guides
Task-oriented guides for solving specific problems with Quagga2. These assume you have basic familiarity with the library and focus on getting things done.
## Configuration & Setup
### [Configure Barcode Readers](configure-readers.md)
Select which barcode formats to scan (EAN, CODE 128, UPC, etc.) and understand the trade-offs.
### [Use Debug Flags](use-debug-flags.md) 🆕
Enable diagnostic output to troubleshoot issues with localization, decoding, or camera setup.
## Performance & Quality
### [Optimize Performance](optimize-performance.md)
Improve scanning speed and reduce CPU usage through configuration tuning.
### [Handle Difficult Barcodes](handle-difficult-barcodes.md)
Techniques for decoding barcodes with poor lighting, damage, rotation, or small size.
## Advanced Features
### [Create External Readers](external-readers.md)
Build custom barcode decoder plugins to support additional formats.
## Camera & Input
### [Select Specific Camera](select-camera.md) *(Coming Soon)*
Choose between front/back cameras on mobile devices or select from multiple USB cameras.
### [Adjust Camera Settings](camera-settings.md) *(Coming Soon)*
Control focus, zoom, flash/torch, and other camera parameters.
## Drawing & Visualization
### [Working with Box Coordinates](working-with-coordinates.md) 🆕
Understand how `box`, `boxes`, and `line` coordinates relate to processed vs. original image dimensions, and how to properly scale coordinates for overlay rendering on video elements.
## Tips & Best Practices
### [Tips and Tricks](tips-and-tricks.md)
Practical advice for getting the best results with Quagga2, including camera setup, user experience, and handling results.
## Integration
### [Handle Multiple Barcodes](multiple-barcodes.md) *(Coming Soon)*
Detect and decode several barcodes in a single frame simultaneously.
### [Scan in Background](background-scanning.md) *(Coming Soon)*
Continue scanning while users interact with other UI elements.
## Differences from Tutorials
**Tutorials** are for learning - they're comprehensive, beginner-friendly, and explain *why* you're doing each step.
**How-To Guides** are for doing - they're focused, assume knowledge, and show *how* to accomplish specific goals.
If you're new to Quagga2, start with [Tutorials](../tutorials/) instead.
## Contributing
Have a useful technique or solution to share? We welcome contributions! See the [Contributing Guide](../contributing.md).
---
[← Back to Documentation Home](../index.md)

View File

@@ -0,0 +1,114 @@
# Optimize Performance {#optimize-performance}
This guide covers techniques to improve Quagga2's barcode scanning performance.
## Overview {#overview}
Performance optimization in Quagga2 involves balancing accuracy against speed. The key areas to optimize are:
- Input resolution and scaling
- Locator configuration
- Reader selection
- Processing frequency
## Input Resolution {#input-resolution}
### Using `inputStream.size` {#inputstream-size}
Reducing the processing resolution is the most effective way to improve performance:
```javascript
Quagga.init({
inputStream: {
size: 640 // Process at 640px max dimension instead of full resolution
}
});
```
**Recommended values:**
- **1280px** - High quality, slower (good for static images)
- **800px** - Balanced (default for `decodeSingle`)
- **640px** - Fast (recommended for live scanning)
- **480px** - Very fast (may reduce accuracy)
### Camera Constraints {#camera-constraints}
Request only the resolution you need:
```javascript
inputStream: {
constraints: {
width: { ideal: 1280 },
height: { ideal: 720 }
}
}
```
## Locator Configuration {#locator-configuration}
### Half Sampling {#half-sampling}
Keep `halfSample: true` (default) for faster localization:
```javascript
locator: {
halfSample: true // Processes at half resolution
}
```
### Patch Size {#patch-size}
Larger patch sizes are faster but may miss small barcodes:
```javascript
locator: {
patchSize: "large" // Options: x-small, small, medium, large, x-large
}
```
## Reader Selection {#reader-selection}
Only enable the barcode formats you need:
```javascript
decoder: {
readers: ["code_128_reader"] // Don't enable all readers
}
```
## Processing Frequency {#processing-frequency}
Limit scan rate to reduce CPU usage:
```javascript
Quagga.init({
frequency: 10 // Max 10 scans per second
});
```
## Disable Localization {#disable-localization}
If barcode position is fixed, disable localization entirely:
```javascript
Quagga.init({
locate: false,
inputStream: {
area: {
top: "25%",
right: "25%",
bottom: "25%",
left: "25%"
}
}
});
```
## Related {#related}
- [Configuration Reference](../reference/configuration.md) - All configuration options
- [How Barcode Localization Works](../explanation/how-barcode-localization-works.md) - Understanding the algorithm
---
[← Back to How-To Guides](index.md)

View File

@@ -0,0 +1,115 @@
# Tips and Tricks {#tips-and-tricks}
Practical advice for getting the best results with Quagga2.
## Camera Setup {#camera-setup}
### Choosing the Right Camera {#choosing-camera}
- Use the **back camera** on mobile devices (higher resolution, autofocus)
- Request environment-facing camera: `facingMode: "environment"`
- Avoid wide-angle cameras for barcode scanning
### Optimal Distance {#optimal-distance}
- Barcode should fill 50-80% of the frame width
- Too close: barcode may be out of focus
- Too far: insufficient resolution for small bars
## Lighting {#lighting}
- Ensure even lighting across the barcode
- Avoid harsh shadows or reflections
- Enable torch/flash for dark environments:
```javascript
await Quagga.CameraAccess.enableTorch();
```
## User Experience {#user-experience}
### Visual Feedback {#visual-feedback}
Show users the scan area:
```javascript
inputStream: {
area: {
top: "25%",
right: "10%",
bottom: "25%",
left: "10%",
borderColor: "rgba(0, 255, 0, 0.7)",
borderWidth: 2
}
}
```
### Audio Feedback {#audio-feedback}
Play a sound on successful scan:
```javascript
Quagga.onDetected(function(result) {
new Audio('/beep.mp3').play();
processBarcode(result.codeResult.code);
});
```
## Performance {#performance}
### Reduce CPU Usage {#reduce-cpu-usage}
```javascript
Quagga.init({
frequency: 10, // Limit to 10 scans/second
inputStream: {
size: 640 // Reduce processing resolution
}
});
```
### Stop When Not Needed {#stop-when-not-needed}
```javascript
// Stop scanning when modal closes
Quagga.stop();
// Remove event handlers
Quagga.offDetected();
Quagga.offProcessed();
```
## Handling Results {#handling-results}
### Debounce Detections {#debounce-detections}
Avoid processing the same barcode multiple times:
```javascript
let lastScanned = '';
let lastTime = 0;
Quagga.onDetected(function(result) {
const code = result.codeResult.code;
const now = Date.now();
if (code === lastScanned && now - lastTime < 2000) {
return; // Same barcode within 2 seconds
}
lastScanned = code;
lastTime = now;
processBarcode(code);
});
```
## Related {#related}
- [Optimize Performance](optimize-performance.md) - Detailed performance guide
- [Handle Difficult Barcodes](handle-difficult-barcodes.md) - Improve detection
- [Camera Access API](../reference/camera-access.md) - Camera control
---
[← Back to How-To Guides](index.md)

View File

@@ -0,0 +1,776 @@
# How to Use Debug Flags {#how-to-use-debug-flags}
Quagga2 includes several debug flags that enable diagnostic console output to help troubleshoot issues with barcode detection and decoding. This guide explains when and how to use them.
## Overview {#overview}
Debug flags control what information Quagga2 logs to the browser console. By default, **all debug output is suppressed** to keep your console clean. Enable specific flags when you need to diagnose problems.
## Important Note {#important-note}
Debug flags only work when `ENV.development` is `true` (development builds). Production builds strip out all debug code to minimize bundle size.
## Available Debug Flags {#available-debug-flags}
Debug flags are organized into three categories:
1. **Console logging flags** - Print diagnostic information to the console
2. **Visual canvas overlays** - Draw debugging information on the canvas
3. **Performance analysis** - Display frequency and pattern data
### Console Logging Flags {#console-logging-flags}
#### `inputStream.debug.showImageDetails` {#inputstream-debug-showimagedetails}
**What it shows**: Image loading and frame grabber operations
**Console output example**:
```text
*** frame_grabber_browser: willReadFrequency=undefined canvas=<canvas>
Image Loader: Loaded 3 images from /path/to/image.jpg
```
**When to use**:
- Camera feed not showing
- Images not loading from file input
- Canvas-related issues
**How to enable**:
```javascript
Quagga.init({
inputStream: {
// ... your input config
debug: {
showImageDetails: true
}
},
// ... rest of config
});
```
#### `decoder.debug.printReaderInfo` {#decoder-debug-printreaderinfo}
**What it shows**: Barcode reader registration and initialization
**Console output example**:
```text
* ImageWrapper getCanvasAndContext
Registering reader: code_128_reader
Before registering reader: EANReader
Registered Readers: code_128, ean
```
**When to use**:
- Verifying which readers are active
- Reader not detecting expected barcode type
- Multiple reader configuration issues
**How to enable**:
```javascript
Quagga.init({
decoder: {
readers: ["code_128_reader", "ean_reader"],
debug: {
printReaderInfo: true
}
},
// ... rest of config
});
```
#### `locator.debug.showPatchSize` {#locator-debug-showpatchsize}
**What it shows**: Patch dimensions during barcode localization
**Console output example**:
```text
Patch-Size: 320x240
```
**When to use**:
- Barcode locator not finding barcodes
- Understanding what image size the locator is processing
- Performance optimization (smaller patches = faster)
**How to enable**:
```javascript
Quagga.init({
locator: {
patchSize: "medium",
debug: {
showPatchSize: true
}
},
// ... rest of config
});
```
#### `locator.debug.showImageDetails` {#locator-debug-showimagedetails}
**What it shows**: Canvas and image wrapper initialization for locator
**Console output example**:
```text
* initCanvas getCanvasAndContext
* ImageWrapper getCanvasAndContext
```
**When to use**:
- Locator canvas not rendering
- Debugging locator initialization failures
- Understanding when canvas contexts are created
**How to enable**:
```javascript
Quagga.init({
locator: {
// ... your locator config
debug: {
showImageDetails: true
}
},
// ... rest of config
});
```
### Visual Canvas Overlay Flags {#visual-canvas-overlay-flags}
These flags draw debugging information directly on the canvas, allowing you to visualize the barcode detection algorithm's internal state.
Note: The scan area overlay (defined via `inputStream.area`) is not a debug flag. When `locate: false`, Quagga draws the scan area on the overlay canvas each processed frame. You can also draw it manually using `Quagga.drawScannerArea()`. See the [Configuration Reference](../reference/configuration.md#inputstream-area-drawing) and [API](../reference/api.md#quagga-drawscannerarea).
#### `decoder.debug.drawBoundingBox` {#decoder-debug-drawboundingbox}
**What it shows**: Draws a box around the detected barcode location
**When to use**:
- Verify barcode is being located correctly
- Debug positioning issues
- Understand where the decoder thinks the barcode is
**How to enable**:
```javascript
Quagga.init({
decoder: {
debug: {
drawBoundingBox: true
}
},
// ... rest of config
});
```
#### `decoder.debug.drawScanline` {#decoder-debug-drawscanline}
**What it shows**: Draws the scanline path used for decoding
**When to use**:
- Verify scanner is reading through the barcode correctly
- Debug angle/orientation issues
- Understand why certain barcodes fail to decode
**How to enable**:
```javascript
Quagga.init({
decoder: {
debug: {
drawScanline: true
}
},
// ... rest of config
});
```
#### `locator.debug.showCanvas` {#locator-debug-showcanvas}
**What it shows**: Displays the locator's internal canvas used for image processing
**When to use**:
- Debug localization algorithm
- Verify image preprocessing is working
- Understand what the locator "sees"
**How to enable**:
```javascript
Quagga.init({
locator: {
debug: {
showCanvas: true
}
},
// ... rest of config
});
```
#### `locator.debug.showPatches` {#locator-debug-showpatches}
**What it shows**: Draws all patches extracted during the localization phase
**When to use**:
- Debug patch extraction issues
- Verify patch size is appropriate
- Understand what regions are being analyzed
**How to enable**:
```javascript
Quagga.init({
locator: {
debug: {
showPatches: true
}
},
// ... rest of config
});
```
#### `locator.debug.showFoundPatches` {#locator-debug-showfoundpatches}
**What it shows**: Highlights patches where potential barcodes were found
**When to use**:
- Verify barcode candidates are being identified
- Debug false positives/negatives in patch detection
- Optimize patch threshold settings
**How to enable**:
```javascript
Quagga.init({
locator: {
debug: {
showFoundPatches: true
}
},
// ... rest of config
});
```
#### `locator.debug.showSkeleton` {#locator-debug-showskeleton}
**What it shows**: Displays the skeleton structure extracted from patches
**When to use**:
- Debug advanced localization algorithm
- Understand structure detection
- Verify skeleton extraction is working
**How to enable**:
```javascript
Quagga.init({
locator: {
debug: {
showSkeleton: true
}
},
// ... rest of config
});
```
#### `locator.debug.showLabels` {#locator-debug-showlabels}
**What it shows**: Displays component labels during connected component analysis
**When to use**:
- Debug component labeling phase
- Verify components are being identified correctly
- Understand clustering behavior
**How to enable**:
```javascript
Quagga.init({
locator: {
debug: {
showLabels: true
}
},
// ... rest of config
});
```
#### `locator.debug.showPatchLabels` {#locator-debug-showpatchlabels}
**What it shows**: Shows labels assigned to individual patches
**When to use**:
- Debug patch classification
- Verify patches are being labeled correctly
- Understand patch grouping
**How to enable**:
```javascript
Quagga.init({
locator: {
debug: {
showPatchLabels: true
}
},
// ... rest of config
});
```
#### `locator.debug.showRemainingPatchLabels` {#locator-debug-showremainingpatchlabels}
**What it shows**: Displays labels for patches remaining after filtering
**When to use**:
- Debug patch filtering logic
- Verify correct patches survive filtering
- Optimize filter thresholds
**How to enable**:
```javascript
Quagga.init({
locator: {
debug: {
showRemainingPatchLabels: true
}
},
// ... rest of config
});
```
#### `locator.debug.boxFromPatches.showTransformed` {#locator-debug-boxfrompatches-showtransformed}
**What it shows**: Shows transformed patch coordinates during box calculation
**When to use**:
- Debug coordinate transformation
- Verify spatial transformations are correct
- Understand box calculation from patches
**How to enable**:
```javascript
Quagga.init({
locator: {
debug: {
boxFromPatches: {
showTransformed: true
}
}
},
// ... rest of config
});
```
#### `locator.debug.boxFromPatches.showTransformedBox` {#locator-debug-boxfrompatches-showtransformedbox}
**What it shows**: Displays the bounding box after transformation
**When to use**:
- Debug box transformation
- Verify box coordinates after spatial transform
- Understand final box positioning
**How to enable**:
```javascript
Quagga.init({
locator: {
debug: {
boxFromPatches: {
showTransformedBox: true
}
}
},
// ... rest of config
});
```
#### `locator.debug.boxFromPatches.showBB` {#locator-debug-boxfrompatches-showbb}
**What it shows**: Displays the final bounding box around detected barcode region
**When to use**:
- Verify final bounding box is correct
- Debug box calculation from patches
- Optimize localization accuracy
**How to enable**:
```javascript
Quagga.init({
locator: {
debug: {
boxFromPatches: {
showBB: true
}
}
},
// ... rest of config
});
```
### Performance Analysis Flags {#performance-analysis-flags}
#### `decoder.debug.showFrequency` {#decoder-debug-showfrequency}
**What it shows**: Displays frequency data from the barcode scanline
**When to use**:
- Analyze barcode signal quality
- Debug decoding issues at the signal level
- Understand why certain barcodes fail to decode
**How to enable**:
```javascript
Quagga.init({
decoder: {
debug: {
showFrequency: true
}
},
// ... rest of config
});
```
#### `decoder.debug.showPattern` {#decoder-debug-showpattern}
**What it shows**: Displays the pattern data extracted from the barcode
**When to use**:
- Analyze pattern recognition issues
- Debug specific barcode format problems
- Understand pattern extraction process
**How to enable**:
```javascript
Quagga.init({
decoder: {
debug: {
showPattern: true
}
},
// ... rest of config
});
```
## Common Debugging Scenarios {#common-debugging-scenarios}
### "No barcodes detected" {#no-barcodes-detected}
Enable console logging first, then add visual overlays if needed:
```javascript
Quagga.init({
inputStream: {
target: document.querySelector('#scanner'),
debug: {
showImageDetails: true
}
},
decoder: {
readers: ["code_128_reader"],
debug: {
printReaderInfo: true,
drawBoundingBox: true, // Visual: see if barcode is located
drawScanline: true // Visual: see scan path
}
},
locator: {
debug: {
showPatchSize: true,
showImageDetails: true,
showFoundPatches: true // Visual: see candidate patches
}
}
}, function(err) {
if (err) {
console.error("Init error:", err);
return;
}
console.log("Starting Quagga...");
Quagga.start();
});
```
Check console for:
- ✅ Readers registered correctly?
- ✅ Images loading?
- ✅ Patch size reasonable (not 0x0)?
- ✅ Canvas contexts created?
Check canvas overlay for:
- ✅ Are patches being detected? (green highlights)
- ✅ Is a bounding box drawn?
- ✅ Is the scanline visible and passing through the barcode?
### "Camera not working" {#camera-not-working}
Enable input stream debugging:
```javascript
Quagga.init({
inputStream: {
type: "LiveStream",
debug: {
showImageDetails: true // Shows camera/canvas setup
}
},
// ... rest of config
});
```
### "Wrong barcode type detected" {#wrong-barcode-type}
Enable reader info to verify configuration:
```javascript
Quagga.init({
decoder: {
readers: [
"code_128_reader", // Did you enable the right readers?
"ean_reader"
],
debug: {
printReaderInfo: true // Shows which readers are active
}
},
// ... rest of config
});
```
### "Deep-dive localization debugging" {#deep-dive-debugging}
For advanced debugging of the localization algorithm, enable all visual overlays:
```javascript
Quagga.init({
locator: {
debug: {
showCanvas: true,
showPatches: true,
showFoundPatches: true,
showSkeleton: true,
showLabels: true,
showPatchLabels: true,
showRemainingPatchLabels: true,
boxFromPatches: {
showTransformed: true,
showTransformedBox: true,
showBB: true
}
}
}
}, function(err) {
if (err) {
console.error(err);
return;
}
Quagga.start();
});
```
This will display every step of the localization process visually on the canvas. Use this to:
- Understand the complete localization pipeline
- Optimize patch size and thresholds
- Debug complex barcode positioning issues
- Learn how the algorithm works
**Warning**: Enabling all visual overlays may impact performance and make the canvas cluttered. Enable only what you need.
## Performance Impact {#performance-impact}
Debug flags have varying performance impacts:
**Console logging flags** (minimal impact):
- `showImageDetails`, `printReaderInfo`, `showPatchSize` - negligible overhead
- Only execute when enabled and only in development builds
**Visual canvas overlays** (moderate to high impact):
- Drawing operations on canvas can slow down real-time detection
- More overlays = more draw calls = slower performance
- Consider disabling in production or using only for development/debugging
**Performance analysis flags** (high impact):
- `showFrequency`, `showPattern` - can generate large amounts of data
- Best used sparingly when diagnosing specific decoding issues
**Recommendation**: Enable only the flags you need. Disable all visual overlays for production.
## Disabling Debug Output {#disabling-debug-output}
To turn off all debug output, either:
**Option 1**: Remove debug properties entirely
```javascript
Quagga.init({
inputStream: {
// debug property removed
},
// ...
});
```
**Option 2**: Set flags to `false`
```javascript
Quagga.init({
inputStream: {
debug: {
showImageDetails: false
}
},
decoder: {
debug: {
printReaderInfo: false,
drawBoundingBox: false,
drawScanline: false,
showFrequency: false,
showPattern: false
}
},
locator: {
debug: {
showCanvas: false,
showPatches: false,
showFoundPatches: false,
showSkeleton: false,
showLabels: false,
showPatchLabels: false,
showRemainingPatchLabels: false,
showPatchSize: false,
showImageDetails: false,
boxFromPatches: {
showTransformed: false,
showTransformedBox: false,
showBB: false
}
}
}
});
```
## Using in Node.js {#using-in-nodejs}
Debug flags work in Node.js too! Output goes to `console.log`:
```javascript
const Quagga = require('@ericblade/quagga2').default;
Quagga.decodeSingle({
src: './barcode.jpg',
decoder: {
readers: ['code_128_reader'],
debug: {
printReaderInfo: true // Shows reader registration
}
}
}, (result) => {
// Check console for debug output
if (result) {
console.log('Decoded:', result.codeResult.code);
}
});
```
## Development vs Production {#development-vs-production}
**Development builds** (`dist/quagga.js` or when using webpack dev server):
- Debug flags work
- Console output visible
- Larger file size
**Production builds** (`dist/quagga.min.js`):
- Debug flags are stripped out (no-op)
- No console output
- Smaller file size
To enable debug output in production:
1. Use the development build (`quagga.js` instead of `quagga.min.js`)
2. Set `ENV.development = true` before importing Quagga
## Summary {#summary}
Quagga2 provides **19 debug flags** organized into three categories:
**Console logging** (4 flags) - Minimal performance impact:
- `inputStream.debug.showImageDetails` - Frame grabber and image loading
- `decoder.debug.printReaderInfo` - Reader registration
- `locator.debug.showPatchSize` - Patch dimensions
- `locator.debug.showImageDetails` - Canvas initialization
**Visual canvas overlays** (13 flags) - Moderate to high performance impact:
- `decoder.debug.drawBoundingBox` - Barcode location box
- `decoder.debug.drawScanline` - Scan path
- `locator.debug.showCanvas` - Locator's internal canvas
- `locator.debug.showPatches` - All extracted patches
- `locator.debug.showFoundPatches` - Candidate patches
- `locator.debug.showSkeleton` - Skeleton structure
- `locator.debug.showLabels` - Component labels
- `locator.debug.showPatchLabels` - Patch labels
- `locator.debug.showRemainingPatchLabels` - Post-filter labels
- `locator.debug.boxFromPatches.showTransformed` - Transformed coordinates
- `locator.debug.boxFromPatches.showTransformedBox` - Transformed box
- `locator.debug.boxFromPatches.showBB` - Final bounding box
**Performance analysis** (2 flags) - High impact:
- `decoder.debug.showFrequency` - Signal frequency data
- `decoder.debug.showPattern` - Pattern extraction data
**Debugging strategy**: Start with console logging flags, then add visual overlays as needed. Disable all flags in production.
## Related {#related}
- [Configuration Reference](../reference/configuration.md) - Complete config documentation
- [Optimize Performance](optimize-performance.md) - Speed up barcode detection
- [Handle Difficult Barcodes](handle-difficult-barcodes.md) - Improve detection accuracy
## Changelog {#changelog}
**v1.8.4+** (November 2025): Debug flags introduced to replace always-on console spam
Prior versions logged debug information unconditionally, making it difficult to debug application code. The new flag system provides fine-grained control over diagnostic output.
---
**Questions?** Ask in [Gitter Chat](https://gitter.im/quaggaJS/Lobby) or [open an issue](https://github.com/ericblade/quagga2/issues).

View File

@@ -0,0 +1,254 @@
# Working with Box Coordinates {#working-with-box-coordinates}
This guide explains how Quagga2's coordinate system works and how to properly use `box`, `boxes`, and `line` coordinates for overlay rendering, especially when using `inputStream.size` to scale processing.
## Understanding the Coordinate System {#understanding-coordinate-system}
Quagga2 returns `box`, `boxes`, and `line` coordinates in **processed canvas coordinates**, not original image/video coordinates. This is important to understand when:
- Drawing overlay boxes on a video element
- Using `inputStream.size` to reduce processing resolution
- Cropping detected barcode regions from the original image
### Key Concepts {#key-concepts}
| Term | Description |
|------|-------------|
| **Real Size** | The actual dimensions of the source image/video |
| **Processed Size** | The scaled dimensions used for barcode detection (controlled by `inputStream.size`) |
| **Canvas Size** | The dimensions of the processing canvas (typically matches processed size) |
### How Coordinates are Generated {#how-coordinates-generated}
1. **Image Scaling**: When `inputStream.size` is set, the image is scaled so the longest side equals that value
2. **Localization**: Barcode regions are found in the scaled image
3. **Box Coordinates**: Returned coordinates are relative to the scaled/processed image
4. **halfSample Adjustment**: If `halfSample: true`, coordinates are automatically scaled 2x
## Converting Coordinates to Original Image Space {#converting-coordinates}
When you need to draw boxes on the original video/image (not the processed canvas), you must scale the coordinates.
### For Live Video Streams {#live-video-streams}
```javascript
Quagga.onDetected(function(result) {
if (!result.box) return;
// Get the video element
const video = document.querySelector('video');
const videoWidth = video.videoWidth; // Real video dimensions
const videoHeight = video.videoHeight;
// Get processed dimensions from Quagga
const canvas = Quagga.canvas.dom.image;
const processedWidth = canvas.width;
const processedHeight = canvas.height;
// Calculate scale factors
const scaleX = videoWidth / processedWidth;
const scaleY = videoHeight / processedHeight;
// Convert box coordinates to video space
const scaledBox = result.box.map(function(point) {
return [
point[0] * scaleX,
point[1] * scaleY
];
});
// Now use scaledBox for drawing on video overlay
drawBoxOnVideo(scaledBox);
});
```
### For Static Images with decodeSingle {#static-images-decodesingle}
```javascript
Quagga.decodeSingle({
src: './barcode.jpg',
inputStream: {
size: 800 // Process at 800px max dimension
},
// ... other config
}, function(result) {
if (!result || !result.box) return;
// Load original image to get real dimensions
const img = new Image();
img.onload = function() {
const realWidth = img.naturalWidth;
const realHeight = img.naturalHeight;
// Calculate what the processed size was
const aspectRatio = realWidth / realHeight;
let processedWidth, processedHeight;
if (aspectRatio > 1) {
// Landscape: width is the longest side
processedWidth = 800;
processedHeight = Math.floor(800 / aspectRatio);
} else {
// Portrait: height is the longest side
processedHeight = 800;
processedWidth = Math.floor(800 * aspectRatio);
}
// Calculate scale factors
const scaleX = realWidth / processedWidth;
const scaleY = realHeight / processedHeight;
// Convert coordinates
const scaledBox = result.box.map(function(point) {
return [
point[0] * scaleX,
point[1] * scaleY
];
});
// Use scaledBox for original image operations
cropBarcodeFromOriginal(scaledBox);
};
img.src = './barcode.jpg';
});
```
## Complete Example: Drawing Boxes on Live Video {#complete-example}
Here's a complete example showing how to draw accurate bounding boxes on a live video stream:
```javascript
// Initialize Quagga with reduced processing size for performance
Quagga.init({
inputStream: {
name: "Live",
type: "LiveStream",
target: document.querySelector('#scanner-container'),
constraints: {
width: 1280,
height: 720,
facingMode: "environment"
},
size: 640 // Process at 640px for better performance
},
locator: {
patchSize: "medium",
halfSample: true
},
decoder: {
readers: ["code_128_reader", "ean_reader"]
}
}, function(err) {
if (err) {
console.error(err);
return;
}
Quagga.start();
});
// Handle detections with coordinate scaling
Quagga.onDetected(function(result) {
const video = document.querySelector('video');
const overlay = document.querySelector('#overlay-canvas');
const ctx = overlay.getContext('2d');
// Match overlay to video size
overlay.width = video.videoWidth;
overlay.height = video.videoHeight;
// Get processed canvas size
const processedCanvas = Quagga.canvas.dom.image;
// Calculate scale factors
const scaleX = video.videoWidth / processedCanvas.width;
const scaleY = video.videoHeight / processedCanvas.height;
// Clear previous drawings
ctx.clearRect(0, 0, overlay.width, overlay.height);
// Draw all detected boxes
if (result.boxes) {
result.boxes.forEach(function(box) {
drawScaledBox(ctx, box, scaleX, scaleY, '#00ff00');
});
}
// Highlight the successfully decoded box
if (result.box) {
drawScaledBox(ctx, result.box, scaleX, scaleY, '#ff0000');
}
});
function drawScaledBox(ctx, box, scaleX, scaleY, color) {
ctx.strokeStyle = color;
ctx.lineWidth = 2;
ctx.beginPath();
// Scale and draw each point
const scaledPoints = box.map(p => [p[0] * scaleX, p[1] * scaleY]);
ctx.moveTo(scaledPoints[0][0], scaledPoints[0][1]);
for (let i = 1; i < scaledPoints.length; i++) {
ctx.lineTo(scaledPoints[i][0], scaledPoints[i][1]);
}
ctx.closePath();
ctx.stroke();
}
```
## When Coordinates Don't Need Scaling {#no-scaling-needed}
If you're drawing on Quagga's own overlay canvas (`Quagga.canvas.dom.overlay`), coordinates are already in the correct space:
```javascript
Quagga.onDetected(function(result) {
const ctx = Quagga.canvas.ctx.overlay;
const canvas = Quagga.canvas.dom.overlay;
ctx.clearRect(0, 0, canvas.width, canvas.height);
// No scaling needed - coordinates match the overlay canvas
if (result.box) {
Quagga.ImageDebug.drawPath(result.box, { x: 0, y: 1 }, ctx, {
color: "#00ff00",
lineWidth: 2
});
}
});
```
## Common Pitfalls {#common-pitfalls}
### 1. Forgetting halfSample Adjustment {#forgetting-halfsample}
If you're manually calculating processed size, remember that `halfSample: true` doesn't affect the returned coordinates (they're already adjusted).
### 2. Using Wrong Canvas Reference {#wrong-canvas-reference}
```javascript
// ❌ Wrong - using overlay canvas for scale calculation
const wrongWidth = Quagga.canvas.dom.overlay.width;
// ✅ Correct - using image canvas for scale calculation
const correctWidth = Quagga.canvas.dom.image.width;
```
### 3. Assuming Square Pixels {#assuming-square-pixels}
Always calculate scaleX and scaleY separately, as aspect ratios may differ:
```javascript
// ❌ Wrong - using single scale factor
const scale = videoWidth / canvasWidth;
// ✅ Correct - separate scale factors
const scaleX = videoWidth / canvasWidth;
const scaleY = videoHeight / canvasHeight;
```
## Performance Tips {#performance-tips}
1. **Use smaller `inputStream.size`** (e.g., 640-800) for live video to reduce CPU usage
2. **Cache scale factors** - recalculate only when video dimensions change
3. **Use requestAnimationFrame** for smooth overlay rendering
4. **Consider using Quagga's built-in overlay** when possible to avoid manual scaling