Barcode-Adapter nimmt Codearten entgegen, Adapter-Weiche je Funktion
decodeBarcodes(imageData, formats) bekommt die zu suchenden Codearten uebergeben; ohne Angabe unveraendertes Verhalten (Code128 + DataMatrix). buildRecognitionAdapters() baut daraus und aus dem echten OCR-Adapter die an recognize() (pipeline.js, unveraendert) uebergebenen Adapter: in Strichcode/QR-Code liefert die Texterkennung sofort leeren Text ohne Tesseract anzustossen, in Text-erkennen liefert die Barcode-Dekodierung sofort eine leere Liste ohne zxing-wasm anzustossen.
This commit is contained in:
+11
-3
@@ -25,8 +25,14 @@ async function ensureReady() {
|
|||||||
await readyPromise;
|
await readyPromise;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Bisheriges Verhalten (Code-128 und DataMatrix), falls der Aufrufer keine
|
||||||
|
// eigene Liste von Codearten angibt - main.js reicht seit den Scan-Funktionen
|
||||||
|
// (siehe scan-modes.js) stets eine eigene Liste durch, aber ohne Angabe
|
||||||
|
// bleibt der Adapter unveraendert nutzbar (z. B. fuer kuenftige Aufrufer).
|
||||||
|
const DEFAULT_FORMATS = ['Code128', 'DataMatrix'];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Dekodiert Code-128 und DataMatrix aus einem Einzelbild.
|
* Dekodiert Barcodes aus einem Einzelbild.
|
||||||
* Barcode-Dekodierung ist exakt - deshalb ist sie die bevorzugte Quelle
|
* Barcode-Dekodierung ist exakt - deshalb ist sie die bevorzugte Quelle
|
||||||
* gegenueber der fehleranfaelligen Texterkennung.
|
* gegenueber der fehleranfaelligen Texterkennung.
|
||||||
*
|
*
|
||||||
@@ -35,12 +41,14 @@ async function ensureReady() {
|
|||||||
* Ausgang und kein Fehler.
|
* Ausgang und kein Fehler.
|
||||||
*
|
*
|
||||||
* @param {ImageData} imageData Einzelbild aus der Kamera.
|
* @param {ImageData} imageData Einzelbild aus der Kamera.
|
||||||
|
* @param {string[]} [formats] Zu suchende Codearten (zxing-wasm-Formatnamen,
|
||||||
|
* siehe scan-modes.js). Ohne Angabe wie bisher: Code128 und DataMatrix.
|
||||||
* @returns {Promise<string[]>}
|
* @returns {Promise<string[]>}
|
||||||
*/
|
*/
|
||||||
export async function decodeBarcodes(imageData) {
|
export async function decodeBarcodes(imageData, formats = DEFAULT_FORMATS) {
|
||||||
await ensureReady();
|
await ensureReady();
|
||||||
const results = await readBarcodes(imageData, {
|
const results = await readBarcodes(imageData, {
|
||||||
formats: ['Code128', 'DataMatrix'],
|
formats,
|
||||||
tryHarder: true,
|
tryHarder: true,
|
||||||
maxNumberOfSymbols: 4,
|
maxNumberOfSymbols: 4,
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -0,0 +1,34 @@
|
|||||||
|
// Baut die Adapter fuer recognize() (pipeline.js) anhand der gewaehlten
|
||||||
|
// Scan-Funktion (siehe scan-modes.js). Reines Modul ohne Browser-Zugriff -
|
||||||
|
// direkt unter Node pruefbar. pipeline.js selbst bleibt unveraendert: die
|
||||||
|
// Funktionen unterscheiden sich ausschliesslich darin, welche Adapter
|
||||||
|
// hineingereicht werden.
|
||||||
|
//
|
||||||
|
// Funktionen 1/2 (laufende Codesuche): echte Barcode-Dekodierung mit den zur
|
||||||
|
// Funktion gehoerenden Codearten; die Texterkennung liefert sofort leeren
|
||||||
|
// Text, ohne dass runOcr ueberhaupt aufgerufen wird.
|
||||||
|
// Funktion 3 (Text erkennen): echte Texterkennung; die Barcode-Dekodierung
|
||||||
|
// liefert sofort eine leere Liste, ohne dass decodeBarcodes ueberhaupt
|
||||||
|
// aufgerufen wird.
|
||||||
|
|
||||||
|
import { getScanMode } from './scan-modes.js';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {string} modeId Kennung aus scan-modes.js.
|
||||||
|
* @param {{decodeBarcodes: Function, runOcr: Function}} adapters echte,
|
||||||
|
* browser-gebundene Adapter (aus barcode.js / ocr.js).
|
||||||
|
* @returns {{decodeBarcodes: Function, runOcr: Function}} an recognize()
|
||||||
|
* durchzureichende Adapter, passend zur gewaehlten Funktion.
|
||||||
|
*/
|
||||||
|
export function buildRecognitionAdapters(modeId, adapters) {
|
||||||
|
const mode = getScanMode(modeId);
|
||||||
|
|
||||||
|
return {
|
||||||
|
decodeBarcodes: mode.useOcr
|
||||||
|
? async () => []
|
||||||
|
: (imageData) => adapters.decodeBarcodes(imageData, mode.barcodeFormats),
|
||||||
|
runOcr: mode.useOcr
|
||||||
|
? adapters.runOcr
|
||||||
|
: async () => '',
|
||||||
|
};
|
||||||
|
}
|
||||||
@@ -0,0 +1,79 @@
|
|||||||
|
import { test } from 'node:test';
|
||||||
|
import assert from 'node:assert/strict';
|
||||||
|
import { buildRecognitionAdapters } from '../src/scan-recognition.js';
|
||||||
|
import { recognize } from '../src/pipeline.js';
|
||||||
|
|
||||||
|
test('Funktion 1: Texterkennung wird nicht aufgerufen, auch wenn kein Code gefunden wird', async () => {
|
||||||
|
let ocrCalled = false;
|
||||||
|
const adapters = buildRecognitionAdapters('barcode', {
|
||||||
|
decodeBarcodes: async () => [],
|
||||||
|
runOcr: async () => { ocrCalled = true; return 'irgendein Text'; },
|
||||||
|
});
|
||||||
|
const result = await recognize({}, adapters);
|
||||||
|
assert.equal(ocrCalled, false, 'runOcr darf in Funktion 1 nie aufgerufen werden');
|
||||||
|
assert.equal(result.confidence, 'red');
|
||||||
|
});
|
||||||
|
|
||||||
|
test('Funktion 2: Texterkennung wird nicht aufgerufen, auch wenn kein Code gefunden wird', async () => {
|
||||||
|
let ocrCalled = false;
|
||||||
|
const adapters = buildRecognitionAdapters('qrcode', {
|
||||||
|
decodeBarcodes: async () => [],
|
||||||
|
runOcr: async () => { ocrCalled = true; return 'irgendein Text'; },
|
||||||
|
});
|
||||||
|
const result = await recognize({}, adapters);
|
||||||
|
assert.equal(ocrCalled, false, 'runOcr darf in Funktion 2 nie aufgerufen werden');
|
||||||
|
assert.equal(result.confidence, 'red');
|
||||||
|
});
|
||||||
|
|
||||||
|
test('Funktion 3: Barcode-Dekodierung wird nicht aufgerufen', async () => {
|
||||||
|
let barcodeCalled = false;
|
||||||
|
const adapters = buildRecognitionAdapters('ocr', {
|
||||||
|
decodeBarcodes: async () => { barcodeCalled = true; return []; },
|
||||||
|
runOcr: async () => '64GB 4DRx4 PC4-2400T-LD1-11-MC0 M386A8K40BM1-CRC4Y 1908',
|
||||||
|
});
|
||||||
|
const result = await recognize({}, adapters);
|
||||||
|
assert.equal(barcodeCalled, false, 'decodeBarcodes darf in Funktion 3 nie aufgerufen werden');
|
||||||
|
assert.equal(result.source, 'ocr');
|
||||||
|
assert.equal(result.confidence, 'yellow');
|
||||||
|
});
|
||||||
|
|
||||||
|
test('Funktion 1: ein gelesener Strichcode fuehrt zu Gruen', async () => {
|
||||||
|
const adapters = buildRecognitionAdapters('barcode', {
|
||||||
|
decodeBarcodes: async () => ['M386A8K40BM1-CRC4Y'],
|
||||||
|
runOcr: async () => '',
|
||||||
|
});
|
||||||
|
const result = await recognize({}, adapters);
|
||||||
|
assert.equal(result.source, 'barcode');
|
||||||
|
assert.equal(result.confidence, 'green');
|
||||||
|
});
|
||||||
|
|
||||||
|
test('Funktion 3: kein brauchbarer Text fuehrt zu Rot, nicht zu Gruen', async () => {
|
||||||
|
const adapters = buildRecognitionAdapters('ocr', {
|
||||||
|
decodeBarcodes: async () => { throw new Error('darf nicht aufgerufen werden'); },
|
||||||
|
runOcr: async () => 'Made in Philippines',
|
||||||
|
});
|
||||||
|
const result = await recognize({}, adapters);
|
||||||
|
assert.equal(result.source, 'none');
|
||||||
|
assert.equal(result.confidence, 'red');
|
||||||
|
});
|
||||||
|
|
||||||
|
test('decodeBarcodes bekommt die Codearten der jeweiligen Funktion uebergeben', async () => {
|
||||||
|
let receivedFormats = null;
|
||||||
|
const adapters = buildRecognitionAdapters('qrcode', {
|
||||||
|
decodeBarcodes: async (_imageData, formats) => { receivedFormats = formats; return []; },
|
||||||
|
runOcr: async () => '',
|
||||||
|
});
|
||||||
|
await adapters.decodeBarcodes({});
|
||||||
|
assert.deepEqual(receivedFormats, ['QRCode', 'MicroQRCode', 'RMQRCode']);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('Funktion 3 uebergibt keine Codearten, weil decodeBarcodes gar nicht aufgerufen wird', async () => {
|
||||||
|
let called = false;
|
||||||
|
const adapters = buildRecognitionAdapters('ocr', {
|
||||||
|
decodeBarcodes: async () => { called = true; return []; },
|
||||||
|
runOcr: async () => '',
|
||||||
|
});
|
||||||
|
const codes = await adapters.decodeBarcodes({});
|
||||||
|
assert.deepEqual(codes, []);
|
||||||
|
assert.equal(called, false);
|
||||||
|
});
|
||||||
Reference in New Issue
Block a user