UNPKG

@nuintun/qrcode

Version:

A pure JavaScript QRCode encode and decode library.

98 lines (93 loc) 3.42 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 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;