@nuintun/qrcode
Version:
A pure JavaScript QRCode encode and decode library.
140 lines (137 loc) • 3.86 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
*/
/**
* @module PerspectiveTransform
*/
class PerspectiveTransform {
#a11;
#a12;
#a13;
#a21;
#a22;
#a23;
#a31;
#a32;
#a33;
constructor(a11, a21, a31, a12, a22, a32, a13, a23, a33) {
this.#a11 = a11;
this.#a12 = a12;
this.#a13 = a13;
this.#a21 = a21;
this.#a22 = a22;
this.#a23 = a23;
this.#a31 = a31;
this.#a32 = a32;
this.#a33 = a33;
}
inverse() {
// Adjoint is the transpose of the cofactor matrix.
const a11 = this.#a11;
const a12 = this.#a12;
const a13 = this.#a13;
const a21 = this.#a21;
const a22 = this.#a22;
const a23 = this.#a23;
const a31 = this.#a31;
const a32 = this.#a32;
const a33 = this.#a33;
return new PerspectiveTransform(
a22 * a33 - a23 * a32,
a23 * a31 - a21 * a33,
a21 * a32 - a22 * a31,
a13 * a32 - a12 * a33,
a11 * a33 - a13 * a31,
a12 * a31 - a11 * a32,
a12 * a23 - a13 * a22,
a13 * a21 - a11 * a23,
a11 * a22 - a12 * a21
);
}
times(other) {
const a11 = this.#a11;
const a12 = this.#a12;
const a13 = this.#a13;
const a21 = this.#a21;
const a22 = this.#a22;
const a23 = this.#a23;
const a31 = this.#a31;
const a32 = this.#a32;
const a33 = this.#a33;
const b11 = other.#a11;
const b12 = other.#a12;
const b13 = other.#a13;
const b21 = other.#a21;
const b22 = other.#a22;
const b23 = other.#a23;
const b31 = other.#a31;
const b32 = other.#a32;
const b33 = other.#a33;
return new PerspectiveTransform(
a11 * b11 + a21 * b12 + a31 * b13,
a11 * b21 + a21 * b22 + a31 * b23,
a11 * b31 + a21 * b32 + a31 * b33,
a12 * b11 + a22 * b12 + a32 * b13,
a12 * b21 + a22 * b22 + a32 * b23,
a12 * b31 + a22 * b32 + a32 * b33,
a13 * b11 + a23 * b12 + a33 * b13,
a13 * b21 + a23 * b22 + a33 * b23,
a13 * b31 + a23 * b32 + a33 * b33
);
}
mapping(x, y) {
const a11 = this.#a11;
const a12 = this.#a12;
const a13 = this.#a13;
const a21 = this.#a21;
const a22 = this.#a22;
const a23 = this.#a23;
const a31 = this.#a31;
const a32 = this.#a32;
const a33 = this.#a33;
const denominator = a13 * x + a23 * y + a33;
return [(a11 * x + a21 * y + a31) / denominator, (a12 * x + a22 * y + a32) / denominator];
}
}
function squareToQuadrilateral(x0, y0, x1, y1, x2, y2, x3, y3) {
const dx3 = x0 - x1 + x2 - x3;
const dy3 = y0 - y1 + y2 - y3;
if (dx3 === 0 && dy3 === 0) {
return new PerspectiveTransform(x1 - x0, x2 - x1, x0, y1 - y0, y2 - y1, y0, 0, 0, 1);
} else {
const dx1 = x1 - x2;
const dx2 = x3 - x2;
const dy1 = y1 - y2;
const dy2 = y3 - y2;
const denominator = dx1 * dy2 - dx2 * dy1;
const a13 = (dx3 * dy2 - dx2 * dy3) / denominator;
const a23 = (dx1 * dy3 - dx3 * dy1) / denominator;
return new PerspectiveTransform(
x1 - x0 + a13 * x1,
x3 - x0 + a23 * x3,
x0,
y1 - y0 + a13 * y1,
y3 - y0 + a23 * y3,
y0,
a13,
a23,
1
);
}
}
function quadrilateralToSquare(x0, y0, x1, y1, x2, y2, x3, y3) {
// Here, the adjoint serves as the inverse.
return squareToQuadrilateral(x0, y0, x1, y1, x2, y2, x3, y3).inverse();
}
function quadrilateralToQuadrilateral(x0, y0, x1, y1, x2, y2, x3, y3, x0p, y0p, x1p, y1p, x2p, y2p, x3p, y3p) {
const qToS = quadrilateralToSquare(x0, y0, x1, y1, x2, y2, x3, y3);
const sToQ = squareToQuadrilateral(x0p, y0p, x1p, y1p, x2p, y2p, x3p, y3p);
return sToQ.times(qToS);
}
export { PerspectiveTransform, quadrilateralToQuadrilateral };