{"id":13455025,"url":"https://github.com/nuintun/qrcode","last_synced_at":"2025-05-14T20:06:09.515Z","repository":{"id":21188243,"uuid":"24494844","full_name":"nuintun/qrcode","owner":"nuintun","description":"A pure JavaScript QRCode encode and decode library.","archived":false,"fork":false,"pushed_at":"2025-04-10T01:47:27.000Z","size":56092,"stargazers_count":208,"open_issues_count":4,"forks_count":29,"subscribers_count":7,"default_branch":"main","last_synced_at":"2025-04-10T02:49:15.878Z","etag":null,"topics":["qrcode","qrcode-decoder","qrcode-encoder","qrcode-generator","qrcode-reader","qrcode-scanner"],"latest_commit_sha":null,"homepage":"https://nuintun.github.io/qrcode","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/nuintun.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":".github/FUNDING.yml","license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null},"funding":{"custom":"https://paypal.me/nuintun"}},"created_at":"2014-09-26T09:57:37.000Z","updated_at":"2025-04-10T01:47:30.000Z","dependencies_parsed_at":"2023-02-17T15:45:19.580Z","dependency_job_id":"c414c3a1-af67-4b37-9a4c-483b45d79ec0","html_url":"https://github.com/nuintun/qrcode","commit_stats":{"total_commits":572,"total_committers":8,"mean_commits":71.5,"dds":0.08391608391608396,"last_synced_commit":"14f6cdc483f5a71812552772e940ec857ee87bc9"},"previous_names":[],"tags_count":28,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nuintun%2Fqrcode","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nuintun%2Fqrcode/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nuintun%2Fqrcode/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nuintun%2Fqrcode/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/nuintun","download_url":"https://codeload.github.com/nuintun/qrcode/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248552905,"owners_count":21123333,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["qrcode","qrcode-decoder","qrcode-encoder","qrcode-generator","qrcode-reader","qrcode-scanner"],"created_at":"2024-07-31T08:01:00.430Z","updated_at":"2025-05-14T20:06:09.509Z","avatar_url":"https://github.com/nuintun.png","language":"TypeScript","readme":"# QRCode\n\n\u003c!-- prettier-ignore --\u003e\n\u003e A pure JavaScript QRCode encode and decode library.\n\u003e\n\u003e [![NPM Version][npm-image]][npm-url]\n\u003e [![Download Status][download-image]][npm-url]\n\u003e [![Languages Status][languages-image]][github-url]\n\u003e\n\u003e [![Tree Shakeable][tree-shakeable-image]][bundle-phobia-url]\n\u003e [![Side Effect][side-effect-image]][bundle-phobia-url]\n\u003e [![Minzip][bundle-phobia-minzip]][bundle-phobia-url]\n\u003e [![License][license-image]][license-url]\n\n### QRCode guide and example\n\n\u003c!-- prettier-ignore --\u003e\n\u003e [QRCode guide](https://nuintun.github.io/qrcode/spec/ISO-IEC-18004-2015.pdf)\n\u003e\n\u003e [QRCode encode example](https://nuintun.github.io/qrcode/#/encode)\n\u003e\n\u003e [QRCode decode example](https://nuintun.github.io/qrcode/#/decode)\n\n### Usage\n\n##### Common Interface\n\n```ts\ndeclare type Level = 'L' | 'M' | 'Q' | 'H';\n\nexport class Charset {\n  public static readonly CP437: Charset;\n  public static readonly ISO_8859_1: Charset;\n  public static readonly ISO_8859_2: Charset;\n  public static readonly ISO_8859_3: Charset;\n  public static readonly ISO_8859_4: Charset;\n  public static readonly ISO_8859_5: Charset;\n  public static readonly ISO_8859_6: Charset;\n  public static readonly ISO_8859_7: Charset;\n  public static readonly ISO_8859_8: Charset;\n  public static readonly ISO_8859_9: Charset;\n  public static readonly ISO_8859_10: Charset;\n  public static readonly ISO_8859_11: Charset;\n  public static readonly ISO_8859_13: Charset;\n  public static readonly ISO_8859_14: Charset;\n  public static readonly ISO_8859_15: Charset;\n  public static readonly ISO_8859_16: Charset;\n  public static readonly SHIFT_JIS: Charset;\n  public static readonly CP1250: Charset;\n  public static readonly CP1251: Charset;\n  public static readonly CP1252: Charset;\n  public static readonly CP1256: Charset;\n  public static readonly UTF_16BE: Charset;\n  public static readonly UTF_8: Charset;\n  public static readonly ASCII: Charset;\n  public static readonly BIG5: Charset;\n  public static readonly GB2312: Charset;\n  public static readonly EUC_KR: Charset;\n  public static readonly GBK: Charset;\n  public static readonly GB18030: Charset;\n  public static readonly UTF_16LE: Charset;\n  public static readonly UTF_32BE: Charset;\n  public static readonly UTF_32LE: Charset;\n  public static readonly ISO_646_INV: Charset;\n  public static readonly BINARY: Charset;\n  public constructor(label: string, ...values: number[]);\n}\n\ndeclare type FNC1 = [mode: 'GS1'] | [mode: 'AIM', indicator: number];\n```\n\n##### Encoder Interface\n\n```ts\nexport class Alphanumeric {\n  public constructor(content: string);\n}\n\nexport class Byte {\n  public constructor(content: string, charset?: Charset);\n}\n\nexport class Hanzi {\n  public constructor(content: string);\n}\n\nexport class Kanji {\n  public constructor(content: string);\n}\n\nexport class Numeric {\n  public constructor(content: string);\n}\n\nexport interface EncoderOptions {\n  level?: Level;\n  hints?: { fnc1?: FNC1 };\n  version?: 'Auto' | number;\n  encode?: (content: string, charset: Charset) =\u003e Uint8Array;\n}\n\ndeclare interface DataURLOptions {\n  margin?: number;\n  foreground?: [R: number, G: number, B: number];\n  background?: [R: number, G: number, B: number];\n}\n\nexport class Encoded {\n  public size: number;\n  public mask: number;\n  public level: Level;\n  public version: number;\n  public get(x: number, y: number): 0 | 1;\n  public toDataURL(moduleSize: number, options?: DataURLOptions): string;\n}\n\nexport class Encoder {\n  public constructor(options?: EncoderOptions);\n  public encode(...segments: (Alphanumeric | Byte | Hanzi | Kanji | Numeric)[]): Encoded;\n}\n```\n\n##### Encoder Example\n\n```ts\nimport { Byte, Encoder, Hanzi, Kanji } from '@nuintun/qrcode';\n\nconst encoder = new Encoder({\n  level: 'H'\n});\n\nconst qrcode = encoder.encode(\n  // Hanzi\n  new Hanzi('你好世界'),\n  // Byte\n  new Byte('\\nhello world\\n'),\n  // Kanji\n  new Kanji('こんにちは世界')\n);\n\nconsole.log(qrcode.toDataURL());\n```\n\n##### Decoder Interface\n\n```ts\nexport class BitMatrix {\n  public constructor(size: number);\n  public constructor(width: number, height: number);\n  public get width(): number;\n  public get height(): number;\n  public set(x: number, y: number): void;\n  public get(x: number, y: number): 0 | 1;\n  public flip(): void;\n  public flip(x: number, y: number): void;\n  public clone(): BitMatrix;\n  public setRegion(left: number, top: number, width: number, height: number): void;\n}\n\nexport class Point {\n  public get x(): number;\n  public get y(): number;\n}\n\nexport class Pattern extends Point {\n  public get moduleSize(): number;\n}\n\ndeclare class FinderPatternGroup {\n  public get topLeft(): Pattern;\n  public get topRight(): Pattern;\n  public get bottomLeft(): Pattern;\n}\n\nexport class Detected {\n  public get matrix(): BitMatrix;\n  public get finder(): FinderPatternGroup;\n  public get alignment(): Pattern | undefined;\n  public get size(): number;\n  public get moduleSize(): number;\n  public mapping(x: number, y: number): Point;\n}\n\ndeclare interface Structured {\n  readonly index: number;\n  readonly count: number;\n  readonly parity: number;\n}\n\nexport class Decoded {\n  public get mask(): number;\n  public get level(): Level;\n  public get version(): number;\n  public get mirror(): boolean;\n  public get content(): string;\n  public get corrected(): number;\n  public get symbology(): string;\n  public get fnc1(): FNC1 | false;\n  public get codewords(): Uint8Array;\n  public get structured(): Structured | false;\n}\n\nexport function grayscale(imageData: ImageData): Uint8Array;\n\nexport function binarize(luminances: Uint8Array, width: number, height: number): BitMatrix;\n\nexport interface DetectorOptions {\n  strict?: boolean;\n}\n\nexport class Detector {\n  public constructor(options?: DetectorOptions);\n  public detect(binarized: BitMatrix): Generator\u003cDetected, void, boolean\u003e;\n}\n\nexport interface DecoderOptions {\n  decode?: (bytes: Uint8Array, charset: Charset) =\u003e string;\n}\n\nexport class Decoder {\n  public constructor(options?: DecoderOptions);\n  public decode(matrix: BitMatrix): Decoded;\n}\n```\n\n##### Decoder Example\n\n```ts\nimport { binarize, Decoder, Detector, grayscale } from '@nuintun/qrcode';\n\nconst image = new Image();\n\nimage.crossOrigin = 'anonymous';\n\nimage.addEventListener('error', () =\u003e {\n  console.error('image load error');\n});\n\nimage.addEventListener('load', () =\u003e {\n  const { width, height } = image;\n  const canvas = new OffscreenCanvas(width, height);\n  const context = canvas.getContext('2d')!;\n\n  context.drawImage(image, 0, 0);\n\n  const luminances = grayscale(context.getImageData(0, 0, width, height));\n  const binarized = binarize(luminances, width, height);\n  const detector = new Detector();\n  // Notice: the detect result are possible combinations of QR Code regions,\n  // which may not necessarily be successfully decoded.\n  const detected = detector.detect(binarized);\n  const decoder = new Decoder();\n\n  let current = detected.next();\n\n  while (!current.done) {\n    let succeed = false;\n\n    const detect = current.value;\n\n    try {\n      const { size, finder, alignment } = detect;\n      const decoded = decoder.decode(detect.matrix);\n      // Finder\n      const { topLeft, topRight, bottomLeft } = finder;\n      // Corners\n      const topLeftCorner = detect.mapping(0, 0);\n      const topRightCorner = detect.mapping(size, 0);\n      const bottomRightCorner = detect.mapping(size, size);\n      const bottomLeftCorner = detect.mapping(0, size);\n      // Timing\n      const topLeftTiming = detect.mapping(6.5, 6.5);\n      const topRightTiming = detect.mapping(size - 6.5, 6.5);\n      const bottomLeftTiming = detect.mapping(6.5, size - 6.5);\n\n      console.log({\n        content: decoded.content,\n        finder: [topLeft, topRight, bottomLeft],\n        alignment: alignment ? alignment : null,\n        timing: [topLeftTiming, topRightTiming, bottomLeftTiming],\n        corners: [topLeftCorner, topRightCorner, bottomRightCorner, bottomLeftCorner]\n      });\n\n      succeed = true;\n    } catch {\n      // Decode failed, skipping...\n    }\n\n    // Notice: pass succeed to next() is very important,\n    // this can significantly reduce the number of detections.\n    current = detected.next(succeed);\n  }\n});\n\nimage.src = 'https://nuintun.github.io/qrcode/public/images/qrcode.jpg';\n```\n\n### Links\n\n\u003c!-- prettier-ignore --\u003e\n\u003e [zxing/zxing](https://github.com/zxing/zxing)\n\u003e\n\u003e [zxing-cpp/zxing-cpp](https://github.com/zxing-cpp/zxing-cpp)\n\n[npm-image]: https://img.shields.io/npm/v/@nuintun/qrcode?style=flat-square\n[npm-url]: https://www.npmjs.org/package/@nuintun/qrcode\n[download-image]: https://img.shields.io/npm/dm/@nuintun/qrcode?style=flat-square\n[languages-image]: https://img.shields.io/github/languages/top/nuintun/qrcode?style=flat-square\n[github-url]: https://github.com/nuintun/qrcode\n[tree-shakeable-image]: https://img.shields.io/badge/tree--shakeable-true-brightgreen?style=flat-square\n[side-effect-image]: https://img.shields.io/badge/side--effect-free-brightgreen?style=flat-square\n[bundle-phobia-url]: https://bundlephobia.com/result?p=@nuintun/qrcode\n[bundle-phobia-minzip]: https://img.shields.io/bundlephobia/minzip/%40nuintun/qrcode/latest?style=flat-square\n[license-image]: https://img.shields.io/github/license/nuintun/qrcode?style=flat-square\n[license-url]: https://github.com/nuintun/qrcode/blob/main/packages/core/LICENSE\n","funding_links":["https://paypal.me/nuintun"],"categories":["TypeScript"],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fnuintun%2Fqrcode","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fnuintun%2Fqrcode","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fnuintun%2Fqrcode/lists"}