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:
parent
de82c494ad
commit
cc7fddb2af
|
@ -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'}}
|
||||
/>
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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",
|
||||
|
|
|
@ -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> {
|
||||
|
|
Loading…
Reference in New Issue