51 lines
1.4 KiB
TypeScript
51 lines
1.4 KiB
TypeScript
import { isSupported, recognizeText } from "expo-mlkit-ocr";
|
|
|
|
import { parseReceiptText, type ReceiptParseResult } from "@/lib/receipt-parse";
|
|
|
|
export type ReceiptOcrResult = ReceiptParseResult & {
|
|
rawText: string;
|
|
};
|
|
|
|
export function mlKitOcrAvailable(): boolean {
|
|
try {
|
|
return isSupported();
|
|
} catch {
|
|
return false;
|
|
}
|
|
}
|
|
|
|
function normalizeImageUri(uri: string): string {
|
|
if (uri.startsWith("file://") || uri.startsWith("content://")) {
|
|
return uri;
|
|
}
|
|
return `file://${uri}`;
|
|
}
|
|
|
|
/** Run on-device ML Kit OCR and parse receipt fields from recognized text. */
|
|
export async function recognizeReceiptFromImage(uri: string): Promise<ReceiptOcrResult> {
|
|
if (!mlKitOcrAvailable()) {
|
|
throw new Error("On-device OCR is not supported on this device.");
|
|
}
|
|
|
|
const result = await recognizeText(normalizeImageUri(uri));
|
|
const rawText = result.text?.trim() ?? "";
|
|
const parsed = parseReceiptText(rawText);
|
|
|
|
return {
|
|
...parsed,
|
|
rawText,
|
|
};
|
|
}
|
|
|
|
export function applyReceiptOcrToForm(
|
|
ocr: ReceiptParseResult,
|
|
current: { description: string; amountText: string; date: Date },
|
|
): { description: string; amountText: string; date: Date; ocrText: string } {
|
|
return {
|
|
description: ocr.vendor?.trim() || current.description,
|
|
amountText: ocr.amount != null ? String(ocr.amount) : current.amountText,
|
|
date: ocr.date ?? current.date,
|
|
ocrText: ocr.rawLines.join("\n"),
|
|
};
|
|
}
|