covid-green-dcc-file-decoder
Version:
<img alttext="COVID Green Logo" src="https://raw.githubusercontent.com/lfph/artwork/master/projects/covidgreen/stacked/color/covidgreen-stacked-color.png" width="300" />
108 lines (91 loc) • 2.75 kB
text/typescript
// eslint-disable-next-line
import * as pdfjsLib from 'pdfjs-dist/legacy/build/pdf'
// import workerEntry from 'pdfjs-dist/legacy/build/pdf.worker.entry'
import Canvas from 'canvas'
import { qrNotDetected } from '../util'
import { extractQRFromImage } from './'
// Some PDFs need external cmaps.
const CMAP_URL = '../../node_modules/pdfjs-dist/cmaps'
const CMAP_PACKED = true
type CanvasAndContext = {
canvas: Canvas.Canvas
context: Canvas.CanvasRenderingContext2D
}
// pdfjsLib.GlobalWorkerOptions.workerSrc = workerEntry
// eslint-disable-next-line
function NodeCanvasFactory() {}
NodeCanvasFactory.prototype = {
create: function NodeCanvasFactory_create(
width: number,
height: number
): CanvasAndContext {
const canvas = Canvas.createCanvas(width, height)
const context = canvas.getContext('2d')
return {
canvas,
context,
}
},
reset: function NodeCanvasFactory_reset(
canvasAndContext: CanvasAndContext,
width: number,
height: number
) {
canvasAndContext.canvas.width = width
canvasAndContext.canvas.height = height
},
destroy: function NodeCanvasFactory_destroy(
canvasAndContext: CanvasAndContext
) {
// Zeroing the width and height cause Firefox to release graphics
// resources immediately, which can greatly reduce memory consumption.
canvasAndContext.canvas.width = 0
canvasAndContext.canvas.height = 0
canvasAndContext.canvas = null
canvasAndContext.context = null
},
}
export async function extractQRFromPDF(
pdf: Buffer,
scaleFactor: number
): Promise<string[]> {
// convert pdf to image
// eslint-disable-next-line
const pdfDoc = await pdfjsLib.getDocument({
data: pdf,
cMapUrl: CMAP_URL,
cMapPacked: CMAP_PACKED,
}).promise
// we will read max 3 pages from a pdf
const pageMax = Math.min(pdfDoc.numPages, 1)
let pageCount = 1
let qrData
while (!qrData && pageCount <= pageMax) {
const page = await pdfDoc.getPage(pageCount)
// Render the page on a Node canvas with 100% scale.
const viewport = page.getViewport({ scale: scaleFactor })
const canvasFactory = new NodeCanvasFactory()
const canvasAndContext = canvasFactory.create(
viewport.width,
viewport.height
)
const renderContext = {
canvasContext: canvasAndContext.context,
viewport,
canvasFactory,
}
await page.render(renderContext).promise
const image = canvasAndContext.canvas.toBuffer()
try {
qrData = await extractQRFromImage(image)
} catch (e) {
// no image in page
console.log(e, 'Decode Image Exception')
}
pageCount += 1
}
if (!qrData || qrData.length === 0) {
throw qrNotDetected()
}
return qrData
}