Added QR Scan with device's camera
- Design changes regarding file selection / camera
This commit is contained in:
parent
98ca5b59bf
commit
57e08bacaf
|
@ -1,9 +1,10 @@
|
||||||
export default Card
|
export default Card
|
||||||
|
|
||||||
function Card({ heading, content, step }) {
|
function Card({heading, content, step}) {
|
||||||
return (
|
return (
|
||||||
<div className="rounded-md p-6 bg-white dark:bg-gray-800 space-y-4">
|
<div className="rounded-md p-6 bg-white dark:bg-gray-800 space-y-4">
|
||||||
{step &&
|
{
|
||||||
|
step &&
|
||||||
<div className="flex flex-row items-center">
|
<div className="flex flex-row items-center">
|
||||||
<div className="rounded-full p-4 bg-green-600 h-5 w-5 flex items-center justify-center">
|
<div className="rounded-full p-4 bg-green-600 h-5 w-5 flex items-center justify-center">
|
||||||
<p className="text-white text-lg font-bold">
|
<p className="text-white text-lg font-bold">
|
||||||
|
@ -13,7 +14,8 @@ function Card({ heading, content, step }) {
|
||||||
<div className="ml-3 font-bold text-xl">
|
<div className="ml-3 font-bold text-xl">
|
||||||
{heading}
|
{heading}
|
||||||
</div>
|
</div>
|
||||||
</div>}
|
</div>
|
||||||
|
}
|
||||||
<div className="text-lg">
|
<div className="text-lg">
|
||||||
{content}
|
{content}
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -1,11 +1,12 @@
|
||||||
import jsQR from "jsqr"
|
|
||||||
import {saveAs} from 'file-saver'
|
import {saveAs} from 'file-saver'
|
||||||
|
import {BrowserQRCodeReader} from '@zxing/browser'
|
||||||
|
import React, {useEffect, useRef, useState} from "react"
|
||||||
import {decodeData} from "../src/decode"
|
import {decodeData} from "../src/decode"
|
||||||
import { processJpeg, processPng, processPdf } from "../src/process"
|
import {processPdf, processPng} from "../src/process"
|
||||||
import {createPass} from "../src/pass"
|
import {createPass} from "../src/pass"
|
||||||
import Card from "../components/Card"
|
import Card from "../components/Card"
|
||||||
import Alert from "../components/Alert"
|
import Alert from "../components/Alert"
|
||||||
|
import jsQR from "jsqr";
|
||||||
|
|
||||||
export default Form
|
export default Form
|
||||||
|
|
||||||
|
@ -25,7 +26,7 @@ function Form() {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
const error = function(heading, message) {
|
const error = function (heading, message) {
|
||||||
const alert = document.getElementById('alert')
|
const alert = document.getElementById('alert')
|
||||||
alert.setAttribute('style', null)
|
alert.setAttribute('style', null)
|
||||||
|
|
||||||
|
@ -35,23 +36,27 @@ function Form() {
|
||||||
document.getElementById('spin').style.display = 'none'
|
document.getElementById('spin').style.display = 'none'
|
||||||
}
|
}
|
||||||
|
|
||||||
const processFile = async function() {
|
const processFile = async function () {
|
||||||
|
console.log(qrCode)
|
||||||
|
console.log(file)
|
||||||
|
if (!qrCode && !file) {
|
||||||
|
error("Error", "Please capture a QR Code or select a file to scan");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
document.getElementById('spin').style.display = 'block'
|
document.getElementById('spin').style.display = 'block'
|
||||||
|
|
||||||
const file = document.getElementById('file').files[0]
|
let rawData;
|
||||||
const fileBuffer = await readFileAsync(file)
|
|
||||||
|
|
||||||
|
if (file) {
|
||||||
let imageData
|
let imageData
|
||||||
|
const fileBuffer = await readFileAsync(file)
|
||||||
|
|
||||||
switch (file.type) {
|
switch (file.type) {
|
||||||
case 'application/pdf':
|
case 'application/pdf':
|
||||||
console.log('pdf')
|
console.log('pdf')
|
||||||
imageData = await processPdf(fileBuffer)
|
imageData = await processPdf(fileBuffer)
|
||||||
break
|
break
|
||||||
case 'image/jpeg':
|
|
||||||
console.log('jpeg')
|
|
||||||
imageData = await processJpeg(fileBuffer)
|
|
||||||
break
|
|
||||||
case 'image/png':
|
case 'image/png':
|
||||||
console.log('png')
|
console.log('png')
|
||||||
imageData = await processPng(fileBuffer)
|
imageData = await processPng(fileBuffer)
|
||||||
|
@ -65,31 +70,37 @@ function Form() {
|
||||||
inversionAttempts: 'dontInvert',
|
inversionAttempts: 'dontInvert',
|
||||||
})
|
})
|
||||||
|
|
||||||
if (code) {
|
rawData = code.data;
|
||||||
const rawData = code.data
|
|
||||||
|
} else {
|
||||||
|
rawData = qrCode.getText()
|
||||||
|
}
|
||||||
|
|
||||||
|
if (rawData) {
|
||||||
let decoded
|
let decoded
|
||||||
|
|
||||||
try {
|
try {
|
||||||
decoded = decodeData(rawData)
|
decoded = decodeData(rawData)
|
||||||
} catch (error) {
|
} catch (e) {
|
||||||
error('Invalid QR code found', 'Make sure that you picked the correct PDF')
|
error('Invalid QR code found', 'Try another method to select your certificate')
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
return {decoded: decoded, raw: rawData}
|
return {decoded: decoded, raw: rawData}
|
||||||
} else {
|
} else {
|
||||||
error('No QR code found', 'Try scanning the PDF again')
|
error('No QR code found', 'Try another method to select your certificate')
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const addToWallet = async function(event) {
|
const addToWallet = async function (event) {
|
||||||
event.preventDefault()
|
event.preventDefault()
|
||||||
|
|
||||||
let result
|
let result
|
||||||
|
|
||||||
try {
|
try {
|
||||||
result = await processFile()
|
result = await processFile()
|
||||||
} catch {
|
} catch (e) {
|
||||||
error('Error:', 'Could not extract QR code data from PDF')
|
error('Error:', 'Could not extract QR code data from certificate')
|
||||||
}
|
}
|
||||||
|
|
||||||
if (typeof result === 'undefined') {
|
if (typeof result === 'undefined') {
|
||||||
|
@ -120,30 +131,123 @@ function Form() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const [isCameraOpen, setIsCameraOpen] = useState(false);
|
||||||
|
const [globalControls, setGlobalControls] = useState(undefined);
|
||||||
|
const [qrCode, setQrCode] = useState(undefined);
|
||||||
|
const [file, setFile] = useState(undefined);
|
||||||
|
|
||||||
|
const inputFile = useRef(undefined)
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (inputFile && inputFile.current) {
|
||||||
|
inputFile.current.addEventListener('input', () => {
|
||||||
|
let selectedFile = inputFile.current.files[0];
|
||||||
|
if (selectedFile !== undefined) {
|
||||||
|
setQrCode(undefined);
|
||||||
|
setFile(selectedFile);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}, [inputFile])
|
||||||
|
|
||||||
|
async function showFileDialog() {
|
||||||
|
inputFile.current.click();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
async function hideCameraView() {
|
||||||
|
if (globalControls !== undefined) {
|
||||||
|
globalControls.stop();
|
||||||
|
}
|
||||||
|
setIsCameraOpen(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
async function showCameraView() {
|
||||||
|
const codeReader = new BrowserQRCodeReader();
|
||||||
|
|
||||||
|
// Needs to be called before any camera can be accessed
|
||||||
|
await BrowserQRCodeReader.listVideoInputDevices();
|
||||||
|
|
||||||
|
// Get preview Element to show camera stream
|
||||||
|
const previewElem = document.querySelector('#cameraPreview');
|
||||||
|
|
||||||
|
setGlobalControls(await codeReader.decodeFromVideoDevice(undefined, previewElem, (result, error, controls) => {
|
||||||
|
|
||||||
|
if (result !== undefined) {
|
||||||
|
setQrCode(result);
|
||||||
|
setFile(undefined);
|
||||||
|
|
||||||
|
controls.stop();
|
||||||
|
|
||||||
|
// Reset
|
||||||
|
setGlobalControls(undefined);
|
||||||
|
setIsCameraOpen(false);
|
||||||
|
}
|
||||||
|
}));
|
||||||
|
|
||||||
|
setIsCameraOpen(true);
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
<form className="space-y-5" id="form" onSubmit={(e) => addToWallet(e)}>
|
<form className="space-y-5" id="form" onSubmit={(e) => addToWallet(e)}>
|
||||||
<Card step={1} heading="Select Certificate" content={
|
<Card step={1} heading="Select Certificate" content={
|
||||||
<div className="space-y-5">
|
<div className="space-y-5">
|
||||||
<p>
|
<p>
|
||||||
Please select the certificate screenshot or (scanned) PDF page, which you received from your doctor, pharmacy, vaccination centre or online. Note that taking a picture does not work on most devices yet.
|
Please select the certificate screenshot or (scanned) PDF page, which you received from your
|
||||||
|
doctor, pharmacy, vaccination centre or online. Note that taking a picture does not work on
|
||||||
|
most devices yet.
|
||||||
</p>
|
</p>
|
||||||
<input
|
<div className="grid grid-cols-1 md:grid-cols-2 gap-5">
|
||||||
className="w-full"
|
<button
|
||||||
type="file"
|
type="button"
|
||||||
id="file"
|
onClick={isCameraOpen ? hideCameraView : showCameraView}
|
||||||
accept="application/pdf,image/jpeg,image/png"
|
className="focus:outline-none h-20 bg-gray-500 hover:bg-gray-700 text-white font-semibold rounded-md">
|
||||||
required
|
{isCameraOpen ? "Stop Camera" : "Start Camera"}
|
||||||
/>
|
</button>
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
onClick={showFileDialog}
|
||||||
|
className="focus:outline-none h-20 bg-gray-500 hover:bg-gray-700 text-white font-semibold rounded-md">
|
||||||
|
Open File (PDF, PNG)
|
||||||
|
</button>
|
||||||
</div>
|
</div>
|
||||||
} />
|
|
||||||
|
<video id="cameraPreview" className={`${isCameraOpen ? undefined : "hidden"} rounded-md w-full`}/>
|
||||||
|
<input type='file'
|
||||||
|
id='file'
|
||||||
|
accept="application/pdf,image/png"
|
||||||
|
ref={inputFile}
|
||||||
|
style={{display: 'none'}}
|
||||||
|
/>
|
||||||
|
|
||||||
|
{(qrCode || file) &&
|
||||||
|
<div className="flex items-center space-x-1">
|
||||||
|
<svg className="h-4 w-4 text-green-600" fill="none" viewBox="0 0 24 24"
|
||||||
|
stroke="currentColor">
|
||||||
|
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth="2" d="M9 5l7 7-7 7"/>
|
||||||
|
</svg>
|
||||||
|
<span className="w-full">
|
||||||
|
{
|
||||||
|
qrCode && 'Found QR Code!'
|
||||||
|
}
|
||||||
|
{
|
||||||
|
file && file.name
|
||||||
|
}
|
||||||
|
</span>
|
||||||
|
</div>}
|
||||||
|
|
||||||
|
</div>
|
||||||
|
}/>
|
||||||
<Card step={2} heading="Pick a Color" content={
|
<Card step={2} heading="Pick a Color" content={
|
||||||
<div className="space-y-5">
|
<div className="space-y-5">
|
||||||
<p>
|
<p>
|
||||||
Pick a background color for your pass.
|
Pick a background color for your pass.
|
||||||
</p>
|
</p>
|
||||||
<div className="relative inline-block w-full">
|
<div className="relative inline-block w-full">
|
||||||
<select name="color" id="color" className="bg-gray-200 dark:bg-gray-900 focus:outline-none w-full h-10 pl-3 pr-6 text-base rounded-md appearance-none cursor-pointer">
|
<select name="color" id="color"
|
||||||
|
className="bg-gray-200 dark:bg-gray-900 focus:outline-none w-full h-10 pl-3 pr-6 text-base rounded-md appearance-none cursor-pointer">
|
||||||
<option value="white">white</option>
|
<option value="white">white</option>
|
||||||
<option value="black">black</option>
|
<option value="black">black</option>
|
||||||
<option value="grey">grey</option>
|
<option value="grey">grey</option>
|
||||||
|
@ -154,39 +258,47 @@ function Form() {
|
||||||
<option value="teal">teal</option>
|
<option value="teal">teal</option>
|
||||||
</select>
|
</select>
|
||||||
<div className="absolute inset-y-0 right-0 flex items-center px-2 pointer-events-none">
|
<div className="absolute inset-y-0 right-0 flex items-center px-2 pointer-events-none">
|
||||||
<svg className="w-5 h-5 fill-current" viewBox="0 0 20 20"><path d="M5.293 7.293a1 1 0 011.414 0L10 10.586l3.293-3.293a1 1 0 111.414 1.414l-4 4a1 1 0 01-1.414 0l-4-4a1 1 0 010-1.414z" clipRule="evenodd" fillRule="evenodd"/></svg>
|
<svg className="w-5 h-5 fill-current" viewBox="0 0 20 20">
|
||||||
|
<path
|
||||||
|
d="M5.293 7.293a1 1 0 011.414 0L10 10.586l3.293-3.293a1 1 0 111.414 1.414l-4 4a1 1 0 01-1.414 0l-4-4a1 1 0 010-1.414z"
|
||||||
|
clipRule="evenodd" fillRule="evenodd"/>
|
||||||
|
</svg>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
} />
|
}/>
|
||||||
<Card step={3} heading="Add to Wallet" content={
|
<Card step={3} heading="Add to Wallet" content={
|
||||||
<div className="space-y-5">
|
<div className="space-y-5">
|
||||||
<p>
|
<p>
|
||||||
Data privacy is of special importance when processing health-related data.
|
Data privacy is of special importance when processing health-related data.
|
||||||
In order for you to make an informed decision, please read the <a href="/privacy">Privacy Policy</a>.
|
In order for you to make an informed decision, please read the <a href="/privacy">Privacy
|
||||||
|
Policy</a>.
|
||||||
</p>
|
</p>
|
||||||
<label htmlFor="privacy" className="flex flex-row space-x-4 items-center">
|
<label htmlFor="privacy" className="flex flex-row space-x-4 items-center">
|
||||||
<input type="checkbox" id="privacy" value="privacy" required className="h-4 w-4" />
|
<input type="checkbox" id="privacy" value="privacy" required className="h-4 w-4"/>
|
||||||
<p>
|
<p>
|
||||||
I accept the <a href="/privacy" className="underline">Privacy Policy</a>
|
I accept the <a href="/privacy" className="underline">Privacy Policy</a>
|
||||||
</p>
|
</p>
|
||||||
</label>
|
</label>
|
||||||
<div className="flex flex-row items-center justify-start">
|
<div className="flex flex-row items-center justify-start">
|
||||||
<button id="download" type="download" className="focus:outline-none bg-green-600 py-2 px-3 text-white font-semibold rounded-md disabled:bg-gray-400">
|
<button id="download" type="download"
|
||||||
|
className="focus:outline-none bg-green-600 py-2 px-3 text-white font-semibold rounded-md disabled:bg-gray-400">
|
||||||
Add to Wallet
|
Add to Wallet
|
||||||
</button>
|
</button>
|
||||||
<div id="spin" style={{ "display": "none" }}>
|
<div id="spin" style={{"display": "none"}}>
|
||||||
<svg className="animate-spin h-5 w-5 ml-2" viewBox="0 0 24 24">
|
<svg className="animate-spin h-5 w-5 ml-2" viewBox="0 0 24 24">
|
||||||
<circle className="opacity-0" cx="12" cy="12" r="10" stroke="currentColor" strokeWidth="4"/>
|
<circle className="opacity-0" cx="12" cy="12" r="10" stroke="currentColor"
|
||||||
<path className="opacity-75" fill="currentColor" d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"/>
|
strokeWidth="4"/>
|
||||||
|
<path className="opacity-75" fill="currentColor"
|
||||||
|
d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"/>
|
||||||
</svg>
|
</svg>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
} />
|
}/>
|
||||||
</form>
|
</form>
|
||||||
<Alert />
|
<Alert/>
|
||||||
<canvas id="canvas" style={{ display: "none" }} />
|
<canvas id="canvas" style={{display: "none"}}/>
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,6 +7,7 @@
|
||||||
"": {
|
"": {
|
||||||
"version": "0.1.0",
|
"version": "0.1.0",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
"@zxing/browser": "^0.0.9",
|
||||||
"base45-js": "^1.0.1",
|
"base45-js": "^1.0.1",
|
||||||
"cbor-js": "^0.1.0",
|
"cbor-js": "^0.1.0",
|
||||||
"do-not-zip": "^1.0.0",
|
"do-not-zip": "^1.0.0",
|
||||||
|
@ -435,6 +436,38 @@
|
||||||
"resolved": "https://registry.npmjs.org/@xtuc/long/-/long-4.2.2.tgz",
|
"resolved": "https://registry.npmjs.org/@xtuc/long/-/long-4.2.2.tgz",
|
||||||
"integrity": "sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ=="
|
"integrity": "sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ=="
|
||||||
},
|
},
|
||||||
|
"node_modules/@zxing/browser": {
|
||||||
|
"version": "0.0.9",
|
||||||
|
"resolved": "https://registry.npmjs.org/@zxing/browser/-/browser-0.0.9.tgz",
|
||||||
|
"integrity": "sha512-yqYz/FHQXbUnfSK+oeDXUa4ezC/qdXkVpqEFAnxM7LqIWvNWEQyUpdaTr0X6MGtIcP0Smakj5D8J7/l276plBw==",
|
||||||
|
"optionalDependencies": {
|
||||||
|
"@zxing/text-encoding": "^0.9.0"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"@zxing/library": "^0.18.5"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@zxing/library": {
|
||||||
|
"version": "0.18.6",
|
||||||
|
"resolved": "https://registry.npmjs.org/@zxing/library/-/library-0.18.6.tgz",
|
||||||
|
"integrity": "sha512-bulZ9JHoLFd9W36pi+7e7DnEYNJhljYjZ1UTsKPOoLMU3qtC+REHITeCRNx40zTRJZx18W5TBRXt5pq2Uopjsw==",
|
||||||
|
"peer": true,
|
||||||
|
"dependencies": {
|
||||||
|
"ts-custom-error": "^3.0.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 10.4.0"
|
||||||
|
},
|
||||||
|
"optionalDependencies": {
|
||||||
|
"@zxing/text-encoding": "~0.9.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@zxing/text-encoding": {
|
||||||
|
"version": "0.9.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@zxing/text-encoding/-/text-encoding-0.9.0.tgz",
|
||||||
|
"integrity": "sha512-U/4aVJ2mxI0aDNI8Uq0wEhMgY+u4CNtEb0om3+y3+niDAsoTCOB33UF0sxpzqzdqXLqmvc+vZyAt4O8pPdfkwA==",
|
||||||
|
"optional": true
|
||||||
|
},
|
||||||
"node_modules/acorn": {
|
"node_modules/acorn": {
|
||||||
"version": "7.4.1",
|
"version": "7.4.1",
|
||||||
"resolved": "https://registry.npmjs.org/acorn/-/acorn-7.4.1.tgz",
|
"resolved": "https://registry.npmjs.org/acorn/-/acorn-7.4.1.tgz",
|
||||||
|
@ -4012,6 +4045,15 @@
|
||||||
"punycode": "^2.1.0"
|
"punycode": "^2.1.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/ts-custom-error": {
|
||||||
|
"version": "3.2.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/ts-custom-error/-/ts-custom-error-3.2.0.tgz",
|
||||||
|
"integrity": "sha512-cBvC2QjtvJ9JfWLvstVnI45Y46Y5dMxIaG1TDMGAD/R87hpvqFL+7LhvUDhnRCfOnx/xitollFWWvUKKKhbN0A==",
|
||||||
|
"peer": true,
|
||||||
|
"engines": {
|
||||||
|
"node": ">=8.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/ts-pnp": {
|
"node_modules/ts-pnp": {
|
||||||
"version": "1.2.0",
|
"version": "1.2.0",
|
||||||
"resolved": "https://registry.npmjs.org/ts-pnp/-/ts-pnp-1.2.0.tgz",
|
"resolved": "https://registry.npmjs.org/ts-pnp/-/ts-pnp-1.2.0.tgz",
|
||||||
|
@ -4730,6 +4772,30 @@
|
||||||
"resolved": "https://registry.npmjs.org/@xtuc/long/-/long-4.2.2.tgz",
|
"resolved": "https://registry.npmjs.org/@xtuc/long/-/long-4.2.2.tgz",
|
||||||
"integrity": "sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ=="
|
"integrity": "sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ=="
|
||||||
},
|
},
|
||||||
|
"@zxing/browser": {
|
||||||
|
"version": "0.0.9",
|
||||||
|
"resolved": "https://registry.npmjs.org/@zxing/browser/-/browser-0.0.9.tgz",
|
||||||
|
"integrity": "sha512-yqYz/FHQXbUnfSK+oeDXUa4ezC/qdXkVpqEFAnxM7LqIWvNWEQyUpdaTr0X6MGtIcP0Smakj5D8J7/l276plBw==",
|
||||||
|
"requires": {
|
||||||
|
"@zxing/text-encoding": "^0.9.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"@zxing/library": {
|
||||||
|
"version": "0.18.6",
|
||||||
|
"resolved": "https://registry.npmjs.org/@zxing/library/-/library-0.18.6.tgz",
|
||||||
|
"integrity": "sha512-bulZ9JHoLFd9W36pi+7e7DnEYNJhljYjZ1UTsKPOoLMU3qtC+REHITeCRNx40zTRJZx18W5TBRXt5pq2Uopjsw==",
|
||||||
|
"peer": true,
|
||||||
|
"requires": {
|
||||||
|
"@zxing/text-encoding": "~0.9.0",
|
||||||
|
"ts-custom-error": "^3.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"@zxing/text-encoding": {
|
||||||
|
"version": "0.9.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@zxing/text-encoding/-/text-encoding-0.9.0.tgz",
|
||||||
|
"integrity": "sha512-U/4aVJ2mxI0aDNI8Uq0wEhMgY+u4CNtEb0om3+y3+niDAsoTCOB33UF0sxpzqzdqXLqmvc+vZyAt4O8pPdfkwA==",
|
||||||
|
"optional": true
|
||||||
|
},
|
||||||
"acorn": {
|
"acorn": {
|
||||||
"version": "7.4.1",
|
"version": "7.4.1",
|
||||||
"resolved": "https://registry.npmjs.org/acorn/-/acorn-7.4.1.tgz",
|
"resolved": "https://registry.npmjs.org/acorn/-/acorn-7.4.1.tgz",
|
||||||
|
@ -7485,6 +7551,12 @@
|
||||||
"punycode": "^2.1.0"
|
"punycode": "^2.1.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"ts-custom-error": {
|
||||||
|
"version": "3.2.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/ts-custom-error/-/ts-custom-error-3.2.0.tgz",
|
||||||
|
"integrity": "sha512-cBvC2QjtvJ9JfWLvstVnI45Y46Y5dMxIaG1TDMGAD/R87hpvqFL+7LhvUDhnRCfOnx/xitollFWWvUKKKhbN0A==",
|
||||||
|
"peer": true
|
||||||
|
},
|
||||||
"ts-pnp": {
|
"ts-pnp": {
|
||||||
"version": "1.2.0",
|
"version": "1.2.0",
|
||||||
"resolved": "https://registry.npmjs.org/ts-pnp/-/ts-pnp-1.2.0.tgz",
|
"resolved": "https://registry.npmjs.org/ts-pnp/-/ts-pnp-1.2.0.tgz",
|
||||||
|
|
|
@ -9,6 +9,7 @@
|
||||||
"start": "next start"
|
"start": "next start"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
"@zxing/browser": "^0.0.9",
|
||||||
"base45-js": "^1.0.1",
|
"base45-js": "^1.0.1",
|
||||||
"cbor-js": "^0.1.0",
|
"cbor-js": "^0.1.0",
|
||||||
"do-not-zip": "^1.0.0",
|
"do-not-zip": "^1.0.0",
|
||||||
|
|
|
@ -1,4 +1,3 @@
|
||||||
import jpeg from 'jpeg-js'
|
|
||||||
import {PNG} from 'pngjs'
|
import {PNG} from 'pngjs'
|
||||||
import * as PdfJS from 'pdfjs-dist'
|
import * as PdfJS from 'pdfjs-dist'
|
||||||
|
|
||||||
|
@ -42,11 +41,6 @@ export async function processPdf(file) {
|
||||||
return ctx.getImageData(0, 0, canvas.width, canvas.height)
|
return ctx.getImageData(0, 0, canvas.width, canvas.height)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Processes a JPEG File and returns it as ImageData
|
|
||||||
export async function processJpeg(file) {
|
|
||||||
return jpeg.decode(file)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Processes a PNG File and returns it as ImageData
|
// Processes a PNG File and returns it as ImageData
|
||||||
export async function processPng(file) {
|
export async function processPng(file) {
|
||||||
return new Promise(async (resolve, reject) => {
|
return new Promise(async (resolve, reject) => {
|
||||||
|
|
Loading…
Reference in New Issue