Spaces:
Running
Running
Download BeadQR/miniprogram/utils/qrcore/qrcode.js from Ethscriptions/cut: direct link, hf CLI and curl.
- Browser
- Download file 15.1 kB
-
https://huggingface.co/spaces/Ethscriptions/cut/resolve/main/BeadQR/miniprogram/utils/qrcore/qrcode.js
- Command line
-
hf download hf://spaces/Ethscriptions/cut/BeadQR/miniprogram/utils/qrcore/qrcode.js
-
curl -L -o qrcode.js https://huggingface.co/spaces/Ethscriptions/cut/resolve/main/BeadQR/miniprogram/utils/qrcore/qrcode.js
15.1 kB
| const Utils = require('./utils') | |
| const ECLevel = require('./error-correction-level') | |
| const BitBuffer = require('./bit-buffer') | |
| const BitMatrix = require('./bit-matrix') | |
| const AlignmentPattern = require('./alignment-pattern') | |
| const FinderPattern = require('./finder-pattern') | |
| const MaskPattern = require('./mask-pattern') | |
| const ECCode = require('./error-correction-code') | |
| const ReedSolomonEncoder = require('./reed-solomon-encoder') | |
| const Version = require('./version') | |
| const FormatInfo = require('./format-info') | |
| const Mode = require('./mode') | |
| const Segments = require('./segments') | |
| /** | |
| * QRCode for JavaScript | |
| * | |
| * modified by Ryan Day for nodejs support | |
| * Copyright (c) 2011 Ryan Day | |
| * | |
| * Licensed under the MIT license: | |
| * http://www.opensource.org/licenses/mit-license.php | |
| * | |
| //--------------------------------------------------------------------- | |
| // QRCode for JavaScript | |
| // | |
| // Copyright (c) 2009 Kazuhiko Arase | |
| // | |
| // URL: http://www.d-project.com/ | |
| // | |
| // Licensed under the MIT license: | |
| // http://www.opensource.org/licenses/mit-license.php | |
| // | |
| // The word "QR Code" is registered trademark of | |
| // DENSO WAVE INCORPORATED | |
| // http://www.denso-wave.com/qrcode/faqpatent-e.html | |
| // | |
| //--------------------------------------------------------------------- | |
| */ | |
| /** | |
| * Add finder patterns bits to matrix | |
| * | |
| * @param {BitMatrix} matrix Modules matrix | |
| * @param {Number} version QR Code version | |
| */ | |
| function setupFinderPattern (matrix, version) { | |
| const size = matrix.size | |
| const pos = FinderPattern.getPositions(version) | |
| for (let i = 0; i < pos.length; i++) { | |
| const row = pos[i][0] | |
| const col = pos[i][1] | |
| for (let r = -1; r <= 7; r++) { | |
| if (row + r <= -1 || size <= row + r) continue | |
| for (let c = -1; c <= 7; c++) { | |
| if (col + c <= -1 || size <= col + c) continue | |
| if ((r >= 0 && r <= 6 && (c === 0 || c === 6)) || | |
| (c >= 0 && c <= 6 && (r === 0 || r === 6)) || | |
| (r >= 2 && r <= 4 && c >= 2 && c <= 4)) { | |
| matrix.set(row + r, col + c, true, true) | |
| } else { | |
| matrix.set(row + r, col + c, false, true) | |
| } | |
| } | |
| } | |
| } | |
| } | |
| /** | |
| * Add timing pattern bits to matrix | |
| * | |
| * Note: this function must be called before {@link setupAlignmentPattern} | |
| * | |
| * @param {BitMatrix} matrix Modules matrix | |
| */ | |
| function setupTimingPattern (matrix) { | |
| const size = matrix.size | |
| for (let r = 8; r < size - 8; r++) { | |
| const value = r % 2 === 0 | |
| matrix.set(r, 6, value, true) | |
| matrix.set(6, r, value, true) | |
| } | |
| } | |
| /** | |
| * Add alignment patterns bits to matrix | |
| * | |
| * Note: this function must be called after {@link setupTimingPattern} | |
| * | |
| * @param {BitMatrix} matrix Modules matrix | |
| * @param {Number} version QR Code version | |
| */ | |
| function setupAlignmentPattern (matrix, version) { | |
| const pos = AlignmentPattern.getPositions(version) | |
| for (let i = 0; i < pos.length; i++) { | |
| const row = pos[i][0] | |
| const col = pos[i][1] | |
| for (let r = -2; r <= 2; r++) { | |
| for (let c = -2; c <= 2; c++) { | |
| if (r === -2 || r === 2 || c === -2 || c === 2 || | |
| (r === 0 && c === 0)) { | |
| matrix.set(row + r, col + c, true, true) | |
| } else { | |
| matrix.set(row + r, col + c, false, true) | |
| } | |
| } | |
| } | |
| } | |
| } | |
| /** | |
| * Add version info bits to matrix | |
| * | |
| * @param {BitMatrix} matrix Modules matrix | |
| * @param {Number} version QR Code version | |
| */ | |
| function setupVersionInfo (matrix, version) { | |
| const size = matrix.size | |
| const bits = Version.getEncodedBits(version) | |
| let row, col, mod | |
| for (let i = 0; i < 18; i++) { | |
| row = Math.floor(i / 3) | |
| col = i % 3 + size - 8 - 3 | |
| mod = ((bits >> i) & 1) === 1 | |
| matrix.set(row, col, mod, true) | |
| matrix.set(col, row, mod, true) | |
| } | |
| } | |
| /** | |
| * Add format info bits to matrix | |
| * | |
| * @param {BitMatrix} matrix Modules matrix | |
| * @param {ErrorCorrectionLevel} errorCorrectionLevel Error correction level | |
| * @param {Number} maskPattern Mask pattern reference value | |
| */ | |
| function setupFormatInfo (matrix, errorCorrectionLevel, maskPattern) { | |
| const size = matrix.size | |
| const bits = FormatInfo.getEncodedBits(errorCorrectionLevel, maskPattern) | |
| let i, mod | |
| for (i = 0; i < 15; i++) { | |
| mod = ((bits >> i) & 1) === 1 | |
| // vertical | |
| if (i < 6) { | |
| matrix.set(i, 8, mod, true) | |
| } else if (i < 8) { | |
| matrix.set(i + 1, 8, mod, true) | |
| } else { | |
| matrix.set(size - 15 + i, 8, mod, true) | |
| } | |
| // horizontal | |
| if (i < 8) { | |
| matrix.set(8, size - i - 1, mod, true) | |
| } else if (i < 9) { | |
| matrix.set(8, 15 - i - 1 + 1, mod, true) | |
| } else { | |
| matrix.set(8, 15 - i - 1, mod, true) | |
| } | |
| } | |
| // fixed module | |
| matrix.set(size - 8, 8, 1, true) | |
| } | |
| /** | |
| * Add encoded data bits to matrix | |
| * | |
| * @param {BitMatrix} matrix Modules matrix | |
| * @param {Uint8Array} data Data codewords | |
| */ | |
| function setupData (matrix, data) { | |
| const size = matrix.size | |
| let inc = -1 | |
| let row = size - 1 | |
| let bitIndex = 7 | |
| let byteIndex = 0 | |
| for (let col = size - 1; col > 0; col -= 2) { | |
| if (col === 6) col-- | |
| while (true) { | |
| for (let c = 0; c < 2; c++) { | |
| if (!matrix.isReserved(row, col - c)) { | |
| let dark = false | |
| if (byteIndex < data.length) { | |
| dark = (((data[byteIndex] >>> bitIndex) & 1) === 1) | |
| } | |
| matrix.set(row, col - c, dark) | |
| bitIndex-- | |
| if (bitIndex === -1) { | |
| byteIndex++ | |
| bitIndex = 7 | |
| } | |
| } | |
| } | |
| row += inc | |
| if (row < 0 || size <= row) { | |
| row -= inc | |
| inc = -inc | |
| break | |
| } | |
| } | |
| } | |
| } | |
| /** | |
| * Create encoded codewords from data input | |
| * | |
| * @param {Number} version QR Code version | |
| * @param {ErrorCorrectionLevel} errorCorrectionLevel Error correction level | |
| * @param {ByteData} data Data input | |
| * @return {Uint8Array} Buffer containing encoded codewords | |
| */ | |
| function createData (version, errorCorrectionLevel, segments) { | |
| // Prepare data buffer | |
| const buffer = new BitBuffer() | |
| segments.forEach(function (data) { | |
| // prefix data with mode indicator (4 bits) | |
| buffer.put(data.mode.bit, 4) | |
| // Prefix data with character count indicator. | |
| // The character count indicator is a string of bits that represents the | |
| // number of characters that are being encoded. | |
| // The character count indicator must be placed after the mode indicator | |
| // and must be a certain number of bits long, depending on the QR version | |
| // and data mode | |
| // @see {@link Mode.getCharCountIndicator}. | |
| buffer.put(data.getLength(), Mode.getCharCountIndicator(data.mode, version)) | |
| // add binary data sequence to buffer | |
| data.write(buffer) | |
| }) | |
| // Calculate required number of bits | |
| const totalCodewords = Utils.getSymbolTotalCodewords(version) | |
| const ecTotalCodewords = ECCode.getTotalCodewordsCount(version, errorCorrectionLevel) | |
| const dataTotalCodewordsBits = (totalCodewords - ecTotalCodewords) * 8 | |
| // Add a terminator. | |
| // If the bit string is shorter than the total number of required bits, | |
| // a terminator of up to four 0s must be added to the right side of the string. | |
| // If the bit string is more than four bits shorter than the required number of bits, | |
| // add four 0s to the end. | |
| if (buffer.getLengthInBits() + 4 <= dataTotalCodewordsBits) { | |
| buffer.put(0, 4) | |
| } | |
| // If the bit string is fewer than four bits shorter, add only the number of 0s that | |
| // are needed to reach the required number of bits. | |
| // After adding the terminator, if the number of bits in the string is not a multiple of 8, | |
| // pad the string on the right with 0s to make the string's length a multiple of 8. | |
| while (buffer.getLengthInBits() % 8 !== 0) { | |
| buffer.putBit(0) | |
| } | |
| // Add pad bytes if the string is still shorter than the total number of required bits. | |
| // Extend the buffer to fill the data capacity of the symbol corresponding to | |
| // the Version and Error Correction Level by adding the Pad Codewords 11101100 (0xEC) | |
| // and 00010001 (0x11) alternately. | |
| const remainingByte = (dataTotalCodewordsBits - buffer.getLengthInBits()) / 8 | |
| for (let i = 0; i < remainingByte; i++) { | |
| buffer.put(i % 2 ? 0x11 : 0xEC, 8) | |
| } | |
| return createCodewords(buffer, version, errorCorrectionLevel) | |
| } | |
| /** | |
| * Encode input data with Reed-Solomon and return codewords with | |
| * relative error correction bits | |
| * | |
| * @param {BitBuffer} bitBuffer Data to encode | |
| * @param {Number} version QR Code version | |
| * @param {ErrorCorrectionLevel} errorCorrectionLevel Error correction level | |
| * @return {Uint8Array} Buffer containing encoded codewords | |
| */ | |
| function createCodewords (bitBuffer, version, errorCorrectionLevel) { | |
| // Total codewords for this QR code version (Data + Error correction) | |
| const totalCodewords = Utils.getSymbolTotalCodewords(version) | |
| // Total number of error correction codewords | |
| const ecTotalCodewords = ECCode.getTotalCodewordsCount(version, errorCorrectionLevel) | |
| // Total number of data codewords | |
| const dataTotalCodewords = totalCodewords - ecTotalCodewords | |
| // Total number of blocks | |
| const ecTotalBlocks = ECCode.getBlocksCount(version, errorCorrectionLevel) | |
| // Calculate how many blocks each group should contain | |
| const blocksInGroup2 = totalCodewords % ecTotalBlocks | |
| const blocksInGroup1 = ecTotalBlocks - blocksInGroup2 | |
| const totalCodewordsInGroup1 = Math.floor(totalCodewords / ecTotalBlocks) | |
| const dataCodewordsInGroup1 = Math.floor(dataTotalCodewords / ecTotalBlocks) | |
| const dataCodewordsInGroup2 = dataCodewordsInGroup1 + 1 | |
| // Number of EC codewords is the same for both groups | |
| const ecCount = totalCodewordsInGroup1 - dataCodewordsInGroup1 | |
| // Initialize a Reed-Solomon encoder with a generator polynomial of degree ecCount | |
| const rs = new ReedSolomonEncoder(ecCount) | |
| let offset = 0 | |
| const dcData = new Array(ecTotalBlocks) | |
| const ecData = new Array(ecTotalBlocks) | |
| let maxDataSize = 0 | |
| const buffer = new Uint8Array(bitBuffer.buffer) | |
| // Divide the buffer into the required number of blocks | |
| for (let b = 0; b < ecTotalBlocks; b++) { | |
| const dataSize = b < blocksInGroup1 ? dataCodewordsInGroup1 : dataCodewordsInGroup2 | |
| // extract a block of data from buffer | |
| dcData[b] = buffer.slice(offset, offset + dataSize) | |
| // Calculate EC codewords for this data block | |
| ecData[b] = rs.encode(dcData[b]) | |
| offset += dataSize | |
| maxDataSize = Math.max(maxDataSize, dataSize) | |
| } | |
| // Create final data | |
| // Interleave the data and error correction codewords from each block | |
| const data = new Uint8Array(totalCodewords) | |
| let index = 0 | |
| let i, r | |
| // Add data codewords | |
| for (i = 0; i < maxDataSize; i++) { | |
| for (r = 0; r < ecTotalBlocks; r++) { | |
| if (i < dcData[r].length) { | |
| data[index++] = dcData[r][i] | |
| } | |
| } | |
| } | |
| // Apped EC codewords | |
| for (i = 0; i < ecCount; i++) { | |
| for (r = 0; r < ecTotalBlocks; r++) { | |
| data[index++] = ecData[r][i] | |
| } | |
| } | |
| return data | |
| } | |
| /** | |
| * Build QR Code symbol | |
| * | |
| * @param {String} data Input string | |
| * @param {Number} version QR Code version | |
| * @param {ErrorCorretionLevel} errorCorrectionLevel Error level | |
| * @param {MaskPattern} maskPattern Mask pattern | |
| * @return {Object} Object containing symbol data | |
| */ | |
| function createSymbol (data, version, errorCorrectionLevel, maskPattern) { | |
| let segments | |
| if (Array.isArray(data)) { | |
| segments = Segments.fromArray(data) | |
| } else if (typeof data === 'string') { | |
| let estimatedVersion = version | |
| if (!estimatedVersion) { | |
| const rawSegments = Segments.rawSplit(data) | |
| // Estimate best version that can contain raw splitted segments | |
| estimatedVersion = Version.getBestVersionForData(rawSegments, errorCorrectionLevel) | |
| } | |
| // Build optimized segments | |
| // If estimated version is undefined, try with the highest version | |
| segments = Segments.fromString(data, estimatedVersion || 40) | |
| } else { | |
| throw new Error('Invalid data') | |
| } | |
| // Get the min version that can contain data | |
| const bestVersion = Version.getBestVersionForData(segments, errorCorrectionLevel) | |
| // If no version is found, data cannot be stored | |
| if (!bestVersion) { | |
| throw new Error('The amount of data is too big to be stored in a QR Code') | |
| } | |
| // If not specified, use min version as default | |
| if (!version) { | |
| version = bestVersion | |
| // Check if the specified version can contain the data | |
| } else if (version < bestVersion) { | |
| throw new Error('\n' + | |
| 'The chosen QR Code version cannot contain this amount of data.\n' + | |
| 'Minimum version required to store current data is: ' + bestVersion + '.\n' | |
| ) | |
| } | |
| const dataBits = createData(version, errorCorrectionLevel, segments) | |
| // Allocate matrix buffer | |
| const moduleCount = Utils.getSymbolSize(version) | |
| const modules = new BitMatrix(moduleCount) | |
| // Add function modules | |
| setupFinderPattern(modules, version) | |
| setupTimingPattern(modules) | |
| setupAlignmentPattern(modules, version) | |
| // Add temporary dummy bits for format info just to set them as reserved. | |
| // This is needed to prevent these bits from being masked by {@link MaskPattern.applyMask} | |
| // since the masking operation must be performed only on the encoding region. | |
| // These blocks will be replaced with correct values later in code. | |
| setupFormatInfo(modules, errorCorrectionLevel, 0) | |
| if (version >= 7) { | |
| setupVersionInfo(modules, version) | |
| } | |
| // Add data codewords | |
| setupData(modules, dataBits) | |
| if (isNaN(maskPattern)) { | |
| // Find best mask pattern | |
| maskPattern = MaskPattern.getBestMask(modules, | |
| setupFormatInfo.bind(null, modules, errorCorrectionLevel)) | |
| } | |
| // Apply mask pattern | |
| MaskPattern.applyMask(maskPattern, modules) | |
| // Replace format info bits with correct values | |
| setupFormatInfo(modules, errorCorrectionLevel, maskPattern) | |
| return { | |
| modules: modules, | |
| version: version, | |
| errorCorrectionLevel: errorCorrectionLevel, | |
| maskPattern: maskPattern, | |
| segments: segments | |
| } | |
| } | |
| /** | |
| * QR Code | |
| * | |
| * @param {String | Array} data Input data | |
| * @param {Object} options Optional configurations | |
| * @param {Number} options.version QR Code version | |
| * @param {String} options.errorCorrectionLevel Error correction level | |
| * @param {Function} options.toSJISFunc Helper func to convert utf8 to sjis | |
| */ | |
| exports.create = function create (data, options) { | |
| if (typeof data === 'undefined' || data === '') { | |
| throw new Error('No input text') | |
| } | |
| let errorCorrectionLevel = ECLevel.M | |
| let version | |
| let mask | |
| if (typeof options !== 'undefined') { | |
| // Use higher error correction level as default | |
| errorCorrectionLevel = ECLevel.from(options.errorCorrectionLevel, ECLevel.M) | |
| version = Version.from(options.version) | |
| mask = MaskPattern.from(options.maskPattern) | |
| if (options.toSJISFunc) { | |
| Utils.setToSJISFunction(options.toSJISFunc) | |
| } | |
| } | |
| return createSymbol(data, version, errorCorrectionLevel, mask) | |
| } | |