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,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)