partial implementation of bar code parsing from PDF

This commit is contained in:
2024-02-09 16:02:18 +01:00
parent f41124ced7
commit 84332b81af
6 changed files with 238 additions and 2 deletions

59
app/lib/pdf/pdf2png.ts Normal file
View File

@@ -0,0 +1,59 @@
import { PDFPageProxy } from 'pdfjs-dist';
import { BrowserPDF417Reader } from '@zxing/browser';
import * as pdfJSx from 'pdfjs-dist';
/**
* Render the first page of a PDF document onto a new canvas.
* @param {Event} event - The change event from an HTMLInputElement.
* @return {Promise<HTMLCanvasElement | null>} The canvas with the first page of the PDF, or null if the document is not a PDF.
*/
export async function pdf2canvas(event: React.ChangeEvent<HTMLInputElement>): Promise<HTMLCanvasElement | null> {
const file = (event.target as HTMLInputElement).files?.[0];
if(!file) {
console.error('No file was selected.');
return null;
}
if (file.type !== 'application/pdf') {
console.error(file.name, 'is not a .pdf file.');
return null;
}
const reader = new FileReader();
const data = await new Promise<Uint8Array>((resolve, reject) => {
reader.onload = (e) => resolve(new Uint8Array((e.target as FileReader).result as ArrayBuffer));
reader.onerror = (e) => reject(e);
reader.readAsArrayBuffer(file);
});
const pdfJS = await import('pdfjs-dist');
// worker file was manually copied to the `public` folder
pdfJS.GlobalWorkerOptions.workerSrc = window.location.origin + '/pdf.worker.min.mjs';
const pdf = await pdfJS.getDocument(data).promise;
const page: PDFPageProxy = await pdf.getPage(1);
const scale = 1.5;
const viewport = page.getViewport({ scale });
const canvas = document.createElement('canvas');
const context = canvas.getContext('2d');
canvas.height = viewport.height;
canvas.width = viewport.width;
await page.render({ canvasContext: context as CanvasRenderingContext2D, viewport }).promise;
const codeReader = new BrowserPDF417Reader();
const result = await codeReader.decodeFromCanvas(canvas);
console.log(result);
// codeReader.decode(imageData);
return null;
}

9
app/lib/pdf/pdfjs.ts Normal file
View File

@@ -0,0 +1,9 @@
"use client";
import * as pdfjsModule from 'pdfjs-dist';
const pdfjs = (
'default' in pdfjsModule ? pdfjsModule['default'] : pdfjsModule
) as typeof pdfjsModule;
export default pdfjs;

View File

@@ -7,6 +7,7 @@ import { useFormState } from "react-dom";
import { updateOrAddBill } from "../lib/actions/billActions";
import Link from "next/link";
import { formatYearMonth } from "../lib/format";
import { pdf2canvas } from "../lib/pdf/pdf2png";
// Next.js does not encode an utf-8 file name correctly when sending a form with a file attachment
// This is a workaround for that
@@ -34,10 +35,14 @@ export const BillEditForm:FC<BillEditFormProps> = ({ location, bill }) => {
const [ isPaid, setIsPaid ] = React.useState<boolean>(paid);
const billPaid_handleChange = (event: React.ChangeEvent<HTMLInputElement>) => {
const billPaid_handleChange = (event: React.ChangeEvent<HTMLInputElement>) => {
setIsPaid(event.target.checked);
}
const billAttachment_handleChange = (event: React.ChangeEvent<HTMLInputElement>) => {
pdf2canvas(event);
}
return(
<div className="card card-compact card-bordered bg-base-100 shadow-s">
<div className="card-body">
@@ -70,7 +75,7 @@ export const BillEditForm:FC<BillEditFormProps> = ({ location, bill }) => {
</Link>
: null
}
<input id="billAttachment" name="billAttachment" type="file" className="file-input file-input-bordered max-w-sm w-full file-input-xs my-2 block" />
<input id="billAttachment" name="billAttachment" type="file" className="file-input file-input-bordered max-w-sm w-full file-input-xs my-2 block" onChange={billAttachment_handleChange} />
<div id="status-error" aria-live="polite" aria-atomic="true">
{state.errors?.billAttachment &&
state.errors.billAttachment.map((error: string) => (