Author: | nuintun |
---|---|
Views Total: | 102 views |
Official Page: | Go to website |
Last Update: | April 7, 2025 |
License: | MIT |
Preview:

Description:
QR code encoder and decoder tools that help you quickly generate QR codes from given contents and decode QR codes from images.
How to use it:
Install the package.
# Yarn $ yarn add @nuintun/qrcode # NPM $ npm install @nuintun/qrcode --save
Import modules as per your needs.
// encoder import { Alphanumeric, Byte, Encoder, Hanzi, Kanji, Numeric } from '@nuintun/qrcode'; // decoder import { binarize, Decoder, Detector, grayscale } from '@nuintun/qrcode';
Encoder
Generate a QR code from the content you provide.
const encoder = new Encoder({ hints?: { fnc1?: FNC1 }; version?: 'Auto' | number; level?: 'L' | 'M' | 'Q' | 'H'; encode?: (content: string, charset: Charset) => Uint8Array; }); const qrcode = encoder.encode( // Hanzi new Hanzi('你好世界'), // Byte new Byte('\nhello world\n'), // Kanji new Kanji('こんにちは世界') ); console.log(qrcode.toDataURL());
Encoder Interface:
export class Alphanumeric { public constructor(content: string); } export class Byte { public constructor(content: string, charset?: Charset); } export class Hanzi { public constructor(content: string); } export class Kanji { public constructor(content: string); } export class Numeric { public constructor(content: string); } export interface EncoderOptions { hints?: { fnc1?: FNC1 }; version?: 'Auto' | number; level?: 'L' | 'M' | 'Q' | 'H'; encode?: (content: string, charset: Charset) => Uint8Array; } declare interface DataURLOptions { margin?: number; foreground?: [R: number, G: number, B: number]; background?: [R: number, G: number, B: number]; } export class Encoded { public size: number; public mask: number; public level: string; public version: number; public get(x: number, y: number): number; public toDataURL(moduleSize: number, options?: DataURLOptions): string; } export class Encoder { public constructor(options?: EncoderOptions); public encode(...segments: (Alphanumeric | Byte | Hanzi | Kanji | Numeric)[]): Encoded; }
Decoder:
Decode the QR code data from an image you provide.
const image = new Image(); image.crossOrigin = 'anonymous'; image.addEventListener('error', () => { console.error('image load error'); }); image.addEventListener('load', () => { const { width, height } = image; const canvas = new OffscreenCanvas(width, height); const context = canvas.getContext('2d')!; context.drawImage(image, 0, 0); const luminances = grayscale(context.getImageData(0, 0, width, height)); const binarized = binarize(luminances, width, height); const detector = new Detector(); const detected = detector.detect(binarized); const decoder = new Decoder(); let current = detected.next(); while (!current.done) { let succeed = false; const detect = current.value; try { const { size, finder, alignment } = detect; const decoded = decoder.decode(detect.matrix); // Finder const { topLeft, topRight, bottomLeft } = finder; // Corners const topLeftCorner = detect.mapping(0, 0); const topRightCorner = detect.mapping(size, 0); const bottomRightCorner = detect.mapping(size, size); const bottomLeftCorner = detect.mapping(0, size); // Timing const topLeftTiming = detect.mapping(6.5, 6.5); const topRightTiming = detect.mapping(size - 6.5, 6.5); const bottomLeftTiming = detect.mapping(6.5, size - 6.5); console.log({ content: decoded.content, finder: [topLeft, topRight, bottomLeft], alignment: alignment ? alignment : null, timing: [topLeftTiming, topRightTiming, bottomLeftTiming], corners: [topLeftCorner, topRightCorner, bottomRightCorner, bottomLeftCorner] }); succeed = true; } catch { // Decode failed, skipping... } // Notice: pass succeed to next() is very important, // This can significantly reduce the number of detections. current = detected.next(succeed); } }); image.src = '/path/to/qrcode.jpg';
Decoder Interface:
export class BitMatrix { public constructor(width: number, height: number, bits?: Int32Array); public get width(): number; public get height(): number; public set(x: number, y: number): void; public get(x: number, y: number): number; public flip(): void; public flip(x: number, y: number): void; public clone(): BitMatrix; public setRegion(left: number, top: number, width: number, height: number): void; } export class Point { public get x(): number; public get y(): number; } export class Pattern extends Point { public get moduleSize(): number; } declare class FinderPatternGroup { public get topLeft(): Pattern; public get topRight(): Pattern; public get bottomLeft(): Pattern; } export class Detected { public get matrix(): BitMatrix; public get finder(): FinderPatternGroup; public get alignment(): Pattern | undefined; public get size(): number; public get moduleSize(): number; public mapping(x: number, y: number): Point; } declare interface Structured { readonly index: number; readonly count: number; readonly parity: number; } export class Decoded { public get mask(): number; public get level(): string; public get version(): number; public get mirror(): boolean; public get content(): string; public get corrected(): number; public get symbology(): string; public get fnc1(): FNC1 | false; public get codewords(): Uint8Array; public get structured(): Structured | false; } export function grayscale(imageData: ImageData): Uint8Array; export function binarize(luminances: Uint8Array, width: number, height: number): BitMatrix; export interface DetectorOptions { strict?: boolean; } export class Detector { public constructor(options?: DetectorOptions); public detect(binarized: BitMatrix): Generator<Detected, void, boolean>; } export interface DecoderOptions { decode?: (bytes: Uint8Array, charset: Charset) => string; } export class Decoder { public constructor(options?: DecoderOptions); public decode(matrix: BitMatrix): Decoded; }
Changelog:
v5.0.2 (04/07/2025)
- Update
thank you, it helped me