Support for other image formats (#95)

* Upgrade packages (#86)

Co-authored-by: Marvin Sextro <marvin.sextro@gmail.com>

* Support JPEG and other image formats; remove pngjs dependency (#93)

* Support JPEG and other image formats; remove pngjs

By using native Canvas to render images it was possible to remove
dependency on external libraries to support image formats while
supporting more formats like JPEG, GIF and WEBP for the QR image

* Constrain images to 2 Mpx

Co-authored-by: Marvin Sextro <marvin.sextro@gmail.com>

* Upgrade packages

Co-authored-by: Marvin Sextro <marvin.sextro@gmail.com>
Co-authored-by: iBobo <andrea@bhweb.it>
This commit is contained in:
Hauke Tönjes 2021-09-03 14:34:04 +02:00 committed by GitHub
parent de82c494ad
commit cc7fddb2af
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 925 additions and 852 deletions

View File

@ -186,7 +186,7 @@ function Form(): JSX.Element {
className={`${isCameraOpen ? undefined : "hidden"} rounded-md w-full`}/>
<input type='file'
id='file'
accept="application/pdf,image/png"
accept="application/pdf,image/png,image/jpeg,image/webp,image/gif"
ref={inputFile}
style={{display: 'none'}}
/>

3
next-env.d.ts vendored
View File

@ -1,3 +1,6 @@
/// <reference types="next" />
/// <reference types="next/types/global" />
/// <reference types="next/image-types/global" />
// NOTE: This file should not be edited
// see https://nextjs.org/docs/basic-features/typescript for more information.

View File

@ -16,14 +16,12 @@
"cbor-js": "^0.1.0",
"do-not-zip": "^1.0.0",
"file-saver": "^2.0.5",
"jpeg-js": "^0.4.3",
"jsqr": "^1.4.0",
"next": "latest",
"next": "^11.1.0",
"next-i18next": "^8.5.1",
"next-seo": "^4.26.0",
"node-fetch": "^2.6.1",
"pdfjs-dist": "^2.5.207",
"pngjs": "^6.0.0",
"react": "^17.0.2",
"react-dom": "^17.0.2",
"uuid": "^8.3.2",

View File

@ -1,5 +1,4 @@
import {PayloadBody} from "./payload";
import {PNG} from 'pngjs'
import * as PdfJS from 'pdfjs-dist'
import jsQR, {QRCode} from "jsqr";
import {decodeData} from "./decode";
@ -9,19 +8,21 @@ import {COLORS} from "./colors";
PdfJS.GlobalWorkerOptions.workerSrc = `https://cdnjs.cloudflare.com/ajax/libs/pdf.js/${PdfJS.version}/pdf.worker.js`
export async function getPayloadBodyFromFile(file: File, color: COLORS): Promise<PayloadBody> {
// Read file
const fileBuffer = await file.arrayBuffer();
let imageData: ImageData;
switch (file.type) {
case 'application/pdf':
console.log('pdf')
// Read file
const fileBuffer = await file.arrayBuffer();
imageData = await getImageDataFromPdf(fileBuffer)
break
case 'image/png':
console.log('png')
imageData = await getImageDataFromPng(fileBuffer)
case 'image/jpeg':
case 'image/webp':
case 'image/gif':
console.log(`image ${file.type}`)
imageData = await getImageDataFromImage(file)
break
default:
throw Error('invalidFileType')
@ -81,18 +82,48 @@ export async function getPayloadBodyFromQR(qrCodeResult: Result, color: COLORS):
}
}
async function getImageDataFromPng(fileBuffer: ArrayBuffer): Promise<ImageData> {
return new Promise(async (resolve, reject) => {
let png = new PNG({filterType: 4})
function getImageDataFromImage(file: File): Promise<ImageData> {
return new Promise((resolve, reject) => {
const canvas = <HTMLCanvasElement>document.getElementById('canvas');
const canvasContext = canvas.getContext('2d');
png.parse(fileBuffer, (error, data) => {
if (error) {
reject();
// create Image object
const img = new Image();
img.onload = () => {
// constrain image to 2 Mpx
const maxPx = 2000000;
let width: number;
let height: number;
if (img.naturalWidth * img.naturalHeight > maxPx) {
const ratio = img.naturalHeight / img.naturalWidth;
width = Math.sqrt(maxPx / ratio);
height = Math.floor(width * ratio);
width = Math.floor(width);
} else {
width = img.naturalWidth;
height = img.naturalHeight;
}
resolve(data);
})
})
// Set correct canvas width / height
canvas.width = width;
canvas.height = height;
// draw image into canvas
canvasContext.clearRect(0, 0, width, height);
canvasContext.drawImage(img, 0, 0, width, height);
// Obtain image data
resolve(canvasContext.getImageData(0, 0, width, height));
};
img.onerror = (e) => {
reject(e);
};
// start loading image from file
img.src = URL.createObjectURL(file);
});
}
async function getImageDataFromPdf(fileBuffer: ArrayBuffer): Promise<ImageData> {

1707
yarn.lock

File diff suppressed because it is too large Load Diff