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>
This commit is contained in:
parent
03a00ea5cb
commit
1949060709
|
@ -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'}}
|
||||
/>
|
||||
|
|
|
@ -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": "^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",
|
||||
|
|
|
@ -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> {
|
||||
|
|
10
yarn.lock
10
yarn.lock
|
@ -1699,11 +1699,6 @@ jest-worker@^27.0.2:
|
|||
merge-stream "^2.0.0"
|
||||
supports-color "^8.0.0"
|
||||
|
||||
jpeg-js@^0.4.3:
|
||||
version "0.4.3"
|
||||
resolved "https://registry.npmjs.org/jpeg-js/-/jpeg-js-0.4.3.tgz"
|
||||
integrity sha512-ru1HWKek8octvUHFHvE5ZzQ1yAsJmIvRdGWvSoKV52XKyuyYA437QWDttXT8eZXDSbuMpHlLzPDZUPd6idIz+Q==
|
||||
|
||||
"js-tokens@^3.0.0 || ^4.0.0", js-tokens@^4.0.0:
|
||||
version "4.0.0"
|
||||
resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499"
|
||||
|
@ -2227,11 +2222,6 @@ platform@1.3.6:
|
|||
resolved "https://registry.yarnpkg.com/platform/-/platform-1.3.6.tgz#48b4ce983164b209c2d45a107adb31f473a6e7a7"
|
||||
integrity sha512-fnWVljUchTro6RiCFvCXBbNhJc2NijN7oIQxbwsyL0buWJPG85v81ehlHI9fXrJsMNgTofEoWIQeClKpgxFLrg==
|
||||
|
||||
pngjs@^6.0.0:
|
||||
version "6.0.0"
|
||||
resolved "https://registry.npmjs.org/pngjs/-/pngjs-6.0.0.tgz"
|
||||
integrity sha512-TRzzuFRRmEoSW/p1KVAmiOgPco2Irlah+bGFCeNfJXxxYGwSw7YwAOAcd7X28K/m5bjBWKsC29KyoMfHbypayg==
|
||||
|
||||
pnp-webpack-plugin@1.6.4:
|
||||
version "1.6.4"
|
||||
resolved "https://registry.yarnpkg.com/pnp-webpack-plugin/-/pnp-webpack-plugin-1.6.4.tgz#c9711ac4dc48a685dabafc86f8b6dd9f8df84149"
|
||||
|
|
Loading…
Reference in New Issue