@nuintun/qrcode
Version:
A pure JavaScript QRCode encode and decode library.
55 lines (51 loc) • 1.83 kB
JavaScript
/**
* @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
*/
import { Polynomial } from './Polynomial.js';
import { QR_CODE_FIELD_256 } from './GaloisField.js';
/**
* @module Encoder
*/
function buildGenerator(field, generators, degree) {
const { length } = generators;
if (degree >= length) {
const { generator } = field;
let lastGenerator = generators[length - 1];
for (let i = length; i <= degree; i++) {
const coefficients = new Int32Array([1, field.exp(i - 1 + generator)]);
const nextGenerator = lastGenerator.multiply(new Polynomial(field, coefficients));
generators.push(nextGenerator);
lastGenerator = nextGenerator;
}
}
return generators[degree];
}
class Encoder {
#field;
#generators;
constructor(field = QR_CODE_FIELD_256) {
this.#field = field;
this.#generators = [new Polynomial(field, new Int32Array([1]))];
}
encode(received, ecLength) {
const dataBytes = received.length - ecLength;
const infoCoefficients = new Int32Array(dataBytes);
const generator = buildGenerator(this.#field, this.#generators, ecLength);
infoCoefficients.set(received.subarray(0, dataBytes));
const base = new Polynomial(this.#field, infoCoefficients);
const info = base.multiplyByMonomial(ecLength, 1);
const [, remainder] = info.divide(generator);
const { coefficients } = remainder;
const numZeroCoefficients = ecLength - coefficients.length;
const zeroCoefficientsOffset = dataBytes + numZeroCoefficients;
received.fill(0, dataBytes, zeroCoefficientsOffset);
received.set(coefficients, zeroCoefficientsOffset);
}
}
export { Encoder };