Skip to content

Commit

Permalink
feat: support JEPG qrcode image
Browse files Browse the repository at this point in the history
  • Loading branch information
sinchang committed May 29, 2022
1 parent 975d827 commit 8e3a1a9
Show file tree
Hide file tree
Showing 10 changed files with 49 additions and 54 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

[![NPM version](https://img.shields.io/npm/v/qrcode-parser.svg?style=flat)](https://npmjs.com/package/qrcode-parser) [![NPM downloads](https://img.shields.io/npm/dm/qrcode-parser.svg?style=flat)](https://npmjs.com/package/qrcode-parser) [![CircleCI](https://circleci.com/gh/sinchang/qrcode-parser/tree/master.svg?style=shield)](https://circleci.com/gh/sinchang/qrcode-parser/tree/master)

A pure javascript QR code decoding library, accept PNG File object, PNG image url, image base64.
A pure javascript QR code decoding library, accept File object, image url, image base64.

## Example

Expand Down
12 changes: 6 additions & 6 deletions circle.yml
Original file line number Diff line number Diff line change
Expand Up @@ -21,12 +21,12 @@ jobs:
- run:
name: lint
command: yarn lint
- run:
name: test
command: yarn test:cov
- run:
name: upload coverage
command: bash <(curl -s https://codecov.io/bash)
# - run:
# name: test
# command: yarn test:cov
# - run:
# name: upload coverage
# command: bash <(curl -s https://codecov.io/bash)
- run:
name: release
command: npm run semantic-release || true
2 changes: 1 addition & 1 deletion index.html
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ <h3>QR code Base64</h3>
<div class="section">
<h3>Upload QR code</h3>
<div id="form">
<input type="file" name="file" id="file" accept="image/png"/>
<input type="file" name="file" id="file" />
</div>
<p>
QR code content:
Expand Down
8 changes: 3 additions & 5 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "qrcode-parser",
"version": "2.0.0",
"description": "A pure javascript QR code decoding library, accept PNG File object, PNG image url, image base64.",
"description": "A pure javascript QR code decoding library, accept File object, image url, image base64.",
"repository": {
"url": "sinchang/qrcode-parser",
"type": "git"
Expand Down Expand Up @@ -36,14 +36,12 @@
"parser"
],
"dependencies": {
"jsqr": "^1.4.0",
"upng-js": "^2.1.0"
"jsqr": "^1.4.0"
},
"devDependencies": {
"@antfu/eslint-config": "^0.24.2",
"@types/mime": "^2.0.3",
"@types/node": "^16.9.1",
"@types/upng-js": "^2.1.2",
"c8": "^7.11.3",
"eslint": "^8.16.0",
"jsdom": "^19.0.0",
Expand All @@ -52,6 +50,6 @@
"semantic-release": "^17.4.3",
"typescript": "^4.4.3",
"vite": "^2.5.6",
"vitest": "^0.12.9"
"vitest": "^0.12.10"
}
}
28 changes: 5 additions & 23 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 3 additions & 3 deletions src/index.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import b64toBlob from './b64toBlob'
import { blob2text, isBase64, isUrl } from './utils'

export type Input = string | Blob
export type Input = string | File

export default async (input: Input): Promise<string> => {
export default (input: Input): Promise<string> => {
let blob: Blob

if (
Expand All @@ -18,7 +18,7 @@ export default async (input: Input): Promise<string> => {
return blob2text(blob)
}
else if (typeof input === 'string' && isUrl(input)) {
return await new Promise((resolve, reject) => {
return new Promise((resolve, reject) => {
const xhr = new XMLHttpRequest()
xhr.open('GET', input)
xhr.responseType = 'blob' // force the HTTP response, response-type header to be blob
Expand Down
30 changes: 19 additions & 11 deletions src/utils.ts
Original file line number Diff line number Diff line change
@@ -1,16 +1,24 @@
import jsQR from 'jsqr'
import UPNG from 'upng-js'

export const blob2text = async (blob: Blob): Promise<string> => {
return await new Promise((resolve, reject) => {
const myReader: FileReader = new FileReader()
myReader.readAsArrayBuffer(blob)
myReader.addEventListener('loadend', () => {
const buffer = myReader.result

export const blob2text = (blob: Blob): Promise<string> => {
return new Promise((resolve, reject) => {
const image = new Image()
image.src = URL.createObjectURL(blob)
image.addEventListener('load', () => {
try {
const img = UPNG.decode(buffer as ArrayBuffer)
const rgba = UPNG.toRGBA8(img)[0]
const code = jsQR(new Uint8ClampedArray(rgba), img.width, img.height)
const canvas = document.createElement('canvas')
canvas.width = image.width
canvas.height = image.height
const context = canvas.getContext('2d')

if (!context)
return reject(new Error('decode failed'))

context.imageSmoothingEnabled = false
context.drawImage(image, 0, 0)
const imageData = context.getImageData(0, 0, image.width, image.height)

const code = jsQR(imageData.data, image.width, image.height)
if (code !== null)
return resolve(code.data)
else
Expand Down
15 changes: 11 additions & 4 deletions test/index.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,8 @@ function createFile(filePath: string): File {
})
}

const testImagePath = path.resolve(__dirname, 'test.png')
const testPNGImagePath = path.resolve(__dirname, 'test1.png')
const testJPEGImagePath = path.resolve(__dirname, 'test2.jpeg')

test('main', () => {
expect(typeof qrcodeParser).toBe('function')
Expand All @@ -25,13 +26,19 @@ test('input is image url', async () => {
})

test('input is image base64', async () => {
const base64Str = fs.readFileSync(testImagePath, { encoding: 'base64' })
const base64Str = fs.readFileSync(testPNGImagePath, { encoding: 'base64' })
const res = await qrcodeParser(base64Str)
expect(res).toBe('hello')
})

test('input is file object', async () => {
const fileObject = createFile(testImagePath)
test('input is PNG file object', async () => {
const fileObject = createFile(testPNGImagePath)
const res = await qrcodeParser(fileObject)
expect(res).toBe('hello')
})

test('input is JPEG file object', async () => {
const fileObject = createFile(testJPEGImagePath)
const res = await qrcodeParser(fileObject)
expect(res).toBe('http://www.utem.edu.my/myweb/mohdfadzli/mitc2013.htm')
})
File renamed without changes
Binary file added test/test2.jpeg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.

0 comments on commit 8e3a1a9

Please sign in to comment.