UNPKG

@nuintun/qrcode

Version:

A pure JavaScript QRCode encode and decode library.

78 lines (73 loc) 2.87 kB
/** * @module QRCode * @package @nuintun/qrcode * @license MIT * @version 5.0.2 * @author nuintun <nuintun@qq.com> * @description A pure JavaScript QRCode encode and decode library. * @see https://github.com/nuintun/qrcode#readme */ 'use strict'; const DataBlock = require('../DataBlock.cjs'); const Decoder = require('../../common/reedsolomon/Decoder.cjs'); /** * @module decoder */ function correctErrors(codewords, numDataCodewords) { const buffer = new Int32Array(codewords); const numECCodewords = codewords.length - numDataCodewords; // Reed solomon encode. const errorsCorrected = new Decoder.Decoder().decode(buffer, numECCodewords); return [buffer, errorsCorrected]; } function getDataBlocks(codewords, version, ecLevel) { const { ecBlocks, numTotalCodewords, numECCodewordsPerBlock } = version.getECBlocks(ecLevel); if (codewords.length !== numTotalCodewords) { throw new Error('failed to get data blocks'); } const blocks = []; // Now establish DataBlocks of the appropriate size and number of data codewords. for (const { count, numDataCodewords } of ecBlocks) { for (let i = 0; i < count; i++) { const numBlockCodewords = numECCodewordsPerBlock + numDataCodewords; blocks.push(new DataBlock.DataBlock(new Uint8Array(numBlockCodewords), numDataCodewords)); } } const { length } = blocks; // All blocks have the same amount of data, except that the last n // (where n may be 0) have 1 more byte. Figure out where these start. let longerBlocksStartAt = length - 1; const shorterBlocksTotalCodewords = blocks[0].codewords.length; while (longerBlocksStartAt >= 0) { const numCodewords = blocks[longerBlocksStartAt].codewords.length; if (numCodewords === shorterBlocksTotalCodewords) { break; } longerBlocksStartAt--; } longerBlocksStartAt++; // The last elements of result may be 1 element longer; // first fill out as many elements as all of them have. let codewordsOffset = 0; const shorterBlocksNumDataCodewords = shorterBlocksTotalCodewords - numECCodewordsPerBlock; for (let i = 0; i < shorterBlocksNumDataCodewords; i++) { for (let j = 0; j < length; j++) { blocks[j].codewords[i] = codewords[codewordsOffset++]; } } // Fill out the last data block in the longer ones. for (let j = longerBlocksStartAt; j < length; j++) { blocks[j].codewords[shorterBlocksNumDataCodewords] = codewords[codewordsOffset++]; } // Now add in error correction blocks. const max = blocks[0].codewords.length; for (let i = shorterBlocksNumDataCodewords; i < max; i++) { for (let j = 0; j < length; j++) { const offset = j < longerBlocksStartAt ? i : i + 1; blocks[j].codewords[offset] = codewords[codewordsOffset++]; } } return blocks; } exports.correctErrors = correctErrors; exports.getDataBlocks = getDataBlocks;