var Buffer = require('../utils/buffer') var Utils = require('./utils') var ECCode = require('./error-correction-code') var ECLevel = require('./error-correction-level') var ByteData = require('./byte-data') // Generator polynomial used to encode version information var G18 = (1 << 12) | (1 << 11) | (1 << 10) | (1 << 9) | (1 << 8) | (1 << 5) | (1 << 2) | (1 << 0) var G18_BCH = Utils.getBCHDigit(G18) var getBestVersionForDataLength = function getBestVersionForDataLength (length, errorCorrectionLevel) { for (var currentVersion = 1; currentVersion <= 40; currentVersion++) { if (length <= exports.getCapacity(currentVersion, errorCorrectionLevel)) return currentVersion } return undefined } /** * Check if QR Code version is valid * * @param {Number} version QR Code version * @return {Boolean} true if valid version, false otherwise */ exports.isValidVersion = function isValidVersion (version) { return !isNaN(version) && version >= 1 && version <= 40 } /** * Returns how much data can be stored with the specified QR code version * and error correction level * * @param {Number} version QR Code version (1-40) * @param {Number} errorCorrectionLevel Error correction level * @return {Number} Quantity of storable data */ exports.getCapacity = function getCapacity (version, errorCorrectionLevel) { if (!exports.isValidVersion(version)) { throw new Error('Invalid QR Code version') } // Total codewords for this QR code version (Data + Error correction) var totalCodewords = Utils.getSymbolTotalCodewords(version) // Total number of error correction codewords var ecTotalCodewords = ECCode.getTotalCodewordsCount(version, errorCorrectionLevel) // Total number of data codewords var dataTotalCodewordsBits = (totalCodewords - ecTotalCodewords) * 8 // Character count indicator + mode indicator bits var reservedBits = ByteData.getCharCountIndicator(version) + 4 // Return max number of storable codewords return Math.floor((dataTotalCodewordsBits - reservedBits) / 8) } /** * Returns the minimum version needed to contain the amount of data * * @param {Buffer, Array, ByteData} data Data buffer * @param {Number} [errorCorrectionLevel=H] Error correction level * @return {Number} QR Code version */ exports.getBestVersionForData = function getBestVersionForData (data, errorCorrectionLevel) { var dataLength if (data instanceof ByteData) dataLength = data.getLength() else if (Buffer.isBuffer(data)) dataLength = data.length else dataLength = new Buffer(data).length var ecl = errorCorrectionLevel if (typeof ecl === 'undefined') ecl = ECLevel.H return getBestVersionForDataLength(dataLength, ecl) } /** * Returns version information with relative error correction bits * * The version information is included in QR Code symbols of version 7 or larger. * It consists of an 18-bit sequence containing 6 data bits, * with 12 error correction bits calculated using the (18, 6) Golay code. * * @param {Number} version QR Code version * @return {Number} Encoded version info bits */ exports.getEncodedBits = function getEncodedBits (version) { if (!exports.isValidVersion(version) || version < 7) { throw new Error('Invalid QR Code version') } var d = version << 12 while (Utils.getBCHDigit(d) - G18_BCH >= 0) { d ^= (G18 << (Utils.getBCHDigit(d) - G18_BCH)) } return (version << 12) | d }