@nuintun/qrcode
Version:
A pure JavaScript QRCode encode and decode library.
98 lines (93 loc) • 3.42 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
*/
;
const Pattern = require('./Pattern.cjs');
const Point = require('../common/Point.cjs');
const scanline = require('./utils/scanline.cjs');
const constants = require('./utils/constants.cjs');
const PatternFinder = require('./PatternFinder.cjs');
const pattern = require('./utils/pattern.cjs');
const PatternRatios = require('./PatternRatios.cjs');
/**
* @module AlignmentPatternFinder
*/
class AlignmentPatternFinder extends PatternFinder.PatternFinder {
constructor(matrix, strict) {
super(matrix, PatternRatios.ALIGNMENT_PATTERN_RATIOS, strict);
}
filter(expectAlignment, moduleSize) {
const patterns = this.patterns.filter(pattern$1 => {
return (
Pattern.Pattern.noise(pattern$1) <= 2.5 &&
pattern.isEqualsSize(pattern$1.moduleSize, moduleSize, constants.DIFF_MODULE_SIZE_RATIO)
);
});
if (patterns.length > 1) {
patterns.sort((pattern1, pattern2) => {
const noise1 = Pattern.Pattern.noise(pattern1);
const noise2 = Pattern.Pattern.noise(pattern2);
const moduleSizeDiff1 = Math.abs(pattern1.moduleSize - moduleSize);
const moduleSizeDiff2 = Math.abs(pattern2.moduleSize - moduleSize);
const score1 = (Point.distance(pattern1, expectAlignment) + moduleSizeDiff1) * noise1;
const score2 = (Point.distance(pattern2, expectAlignment) + moduleSizeDiff2) * noise2;
return score1 - score2;
});
}
// Only use the first two patterns.
const alignmentPatterns = patterns.slice(0, 2);
// Add expect alignment for fallback.
alignmentPatterns.push(expectAlignment);
return alignmentPatterns;
}
find(left, top, width, height) {
const { matrix } = this;
const right = left + width;
const bottom = top + height;
const match = (x, y, scanline$1, count, scanlineBits, lastBit) => {
scanline.scanlineUpdate(scanline$1, count);
scanline.scanlineUpdate(scanlineBits, lastBit);
// Match pattern when white-black-white.
if (
scanlineBits[0] === 0 &&
scanlineBits[1] === 1 &&
scanlineBits[2] === 0 &&
pattern.isMatchPattern(scanline$1, PatternRatios.ALIGNMENT_PATTERN_LOOSE_MODE_RATIOS)
) {
this.match(x, y, scanline$1, scanline$1[1]);
}
};
for (let y = top; y < bottom; y++) {
let x = left;
// Burn off leading white pixels before anything else; if we start in the middle of
// a white run, it doesn't make sense to count its length, since we don't know if the
// white run continued to the left of the start point.
while (x < right && !matrix.get(x, y)) {
x++;
}
let count = 0;
let lastBit = matrix.get(x, y);
const scanline = [0, 0, 0];
const scanlineBits = [-1, -1, -1];
while (x < right) {
const bit = matrix.get(x, y);
if (bit === lastBit) {
count++;
} else {
match(x, y, scanline, count, scanlineBits, lastBit);
count = 1;
lastBit = bit;
}
x++;
}
match(x, y, scanline, count, scanlineBits, lastBit);
}
}
}
exports.AlignmentPatternFinder = AlignmentPatternFinder;