echos-ocr/src/lib/pdf.ts

81 lines
2.3 KiB
TypeScript
Raw Normal View History

import { fromBuffer } from "pdf2pic";
import sharp from "sharp";
export interface PageImage {
page: number;
buffer: Buffer;
width: number;
height: number;
}
export async function pdfToImages(pdfBuffer: Buffer): Promise<PageImage[]> {
const converter = fromBuffer(pdfBuffer, {
density: 200,
format: "jpeg",
width: 2200,
height: 2200,
quality: 90,
preserveAspectRatio: true,
});
const pageCount = await getPdfPageCount(pdfBuffer);
const images: PageImage[] = [];
for (let i = 1; i <= pageCount; i++) {
const result = await converter(i, { responseType: "buffer" });
if (result.buffer) {
let buf = result.buffer as Buffer;
let meta = await sharp(buf).metadata();
const w = meta.width || 0;
const h = meta.height || 0;
// Duplex scanners flip the sheet between sides, so odd pages
// (back/response card) are 180° rotated relative to even pages
// (front/survey). Landscape pages need rotation to portrait;
// the direction depends on which side of the sheet was scanned.
const isBackSide = i % 2 === 1;
if (w > h) {
const angle = isBackSide ? -90 : 90;
buf = await sharp(buf).rotate(angle).jpeg({ quality: 90 }).toBuffer();
meta = await sharp(buf).metadata();
} else if (isBackSide) {
buf = await sharp(buf).rotate(180).jpeg({ quality: 90 }).toBuffer();
meta = await sharp(buf).metadata();
}
images.push({
page: i,
buffer: buf,
width: meta.width || 1600,
height: meta.height || 2200,
});
}
}
return images;
}
async function getPdfPageCount(pdfBuffer: Buffer): Promise<number> {
const text = pdfBuffer.toString("latin1");
const matches = text.match(/\/Type\s*\/Page(?!s)/g);
return matches ? matches.length : 2;
}
export async function imageToBase64(buffer: Buffer): Promise<string> {
const processed = await sharp(buffer)
.resize(1200, undefined, { withoutEnlargement: true })
.jpeg({ quality: 85 })
.toBuffer();
return processed.toString("base64");
}
export async function processUploadedImage(buffer: Buffer): Promise<Buffer> {
return sharp(buffer)
.resize(1600, undefined, { withoutEnlargement: true })
.normalize()
.sharpen()
.jpeg({ quality: 90 })
.toBuffer();
}