|
|
@ -80,7 +80,7 @@ QrSegment QrSegment::makeNumeric(const char *digits) {
|
|
|
|
int accumCount = 0;
|
|
|
|
int accumCount = 0;
|
|
|
|
int charCount = 0;
|
|
|
|
int charCount = 0;
|
|
|
|
for (; *digits != '\0'; digits++, charCount++) {
|
|
|
|
for (; *digits != '\0'; digits++, charCount++) {
|
|
|
|
char c = *digits;
|
|
|
|
const char c = *digits;
|
|
|
|
if (c < '0' || c > '9')
|
|
|
|
if (c < '0' || c > '9')
|
|
|
|
throw std::domain_error("String contains non-numeric characters");
|
|
|
|
throw std::domain_error("String contains non-numeric characters");
|
|
|
|
accumData = accumData * 10 + (c - '0');
|
|
|
|
accumData = accumData * 10 + (c - '0');
|
|
|
@ -177,7 +177,7 @@ QrSegment::QrSegment(Mode md, int numCh, std::vector<bool> &&dt) :
|
|
|
|
int QrSegment::getTotalBits(const vector<QrSegment> &segs, int version) {
|
|
|
|
int QrSegment::getTotalBits(const vector<QrSegment> &segs, int version) {
|
|
|
|
int result = 0;
|
|
|
|
int result = 0;
|
|
|
|
for (const QrSegment &seg : segs) {
|
|
|
|
for (const QrSegment &seg : segs) {
|
|
|
|
int ccbits = seg.mode.numCharCountBits(version);
|
|
|
|
const int ccbits = seg.mode.numCharCountBits(version);
|
|
|
|
if (seg.numChars >= (1L << ccbits))
|
|
|
|
if (seg.numChars >= (1L << ccbits))
|
|
|
|
return -1; // The segment's length doesn't fit the field's bit width
|
|
|
|
return -1; // The segment's length doesn't fit the field's bit width
|
|
|
|
if (4 + ccbits > INT_MAX - result)
|
|
|
|
if (4 + ccbits > INT_MAX - result)
|
|
|
@ -202,7 +202,7 @@ bool QrSegment::isAlphanumeric(const char *text) {
|
|
|
|
|
|
|
|
|
|
|
|
bool QrSegment::isNumeric(const char *text) {
|
|
|
|
bool QrSegment::isNumeric(const char *text) {
|
|
|
|
for (; *text != '\0'; text++) {
|
|
|
|
for (; *text != '\0'; text++) {
|
|
|
|
char c = *text;
|
|
|
|
const char c = *text;
|
|
|
|
if (c < '0' || c > '9')
|
|
|
|
if (c < '0' || c > '9')
|
|
|
|
return false;
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
@ -241,13 +241,13 @@ int QrCode::getFormatBits(Ecc ecl) {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
QrCode QrCode::encodeText(const char *text, Ecc ecl) {
|
|
|
|
QrCode QrCode::encodeText(const char *text, Ecc ecl) {
|
|
|
|
vector<QrSegment> segs = QrSegment::makeSegments(text);
|
|
|
|
const vector<QrSegment> segs = QrSegment::makeSegments(text);
|
|
|
|
return encodeSegments(segs, ecl);
|
|
|
|
return encodeSegments(segs, ecl);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
QrCode QrCode::encodeBinary(const vector<uint8_t> &data, Ecc ecl) {
|
|
|
|
QrCode QrCode::encodeBinary(const vector<uint8_t> &data, Ecc ecl) {
|
|
|
|
vector<QrSegment> segs{QrSegment::makeBytes(data)};
|
|
|
|
const vector<QrSegment> segs{QrSegment::makeBytes(data)};
|
|
|
|
return encodeSegments(segs, ecl);
|
|
|
|
return encodeSegments(segs, ecl);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
@ -260,7 +260,7 @@ QrCode QrCode::encodeSegments(const vector<QrSegment> &segs, Ecc ecl,
|
|
|
|
// Find the minimal version number to use
|
|
|
|
// Find the minimal version number to use
|
|
|
|
int version, dataUsedBits;
|
|
|
|
int version, dataUsedBits;
|
|
|
|
for (version = minVersion; ; version++) {
|
|
|
|
for (version = minVersion; ; version++) {
|
|
|
|
int dataCapacityBits = getNumDataCodewords(version, ecl) * 8; // Number of data bits available
|
|
|
|
const int dataCapacityBits = getNumDataCodewords(version, ecl) * 8; // Number of data bits available
|
|
|
|
dataUsedBits = QrSegment::getTotalBits(segs, version);
|
|
|
|
dataUsedBits = QrSegment::getTotalBits(segs, version);
|
|
|
|
if (dataUsedBits != -1 && dataUsedBits <= dataCapacityBits)
|
|
|
|
if (dataUsedBits != -1 && dataUsedBits <= dataCapacityBits)
|
|
|
|
break; // This version number is found to be suitable
|
|
|
|
break; // This version number is found to be suitable
|
|
|
@ -295,7 +295,7 @@ QrCode QrCode::encodeSegments(const vector<QrSegment> &segs, Ecc ecl,
|
|
|
|
throw std::logic_error("Assertion error");
|
|
|
|
throw std::logic_error("Assertion error");
|
|
|
|
|
|
|
|
|
|
|
|
// Add terminator and pad up to a byte if applicable
|
|
|
|
// Add terminator and pad up to a byte if applicable
|
|
|
|
size_t dataCapacityBits = static_cast<size_t>(getNumDataCodewords(version, ecl)) * 8;
|
|
|
|
const auto dataCapacityBits = static_cast<size_t>(getNumDataCodewords(version, ecl)) * 8;
|
|
|
|
if (bb.size() > dataCapacityBits)
|
|
|
|
if (bb.size() > dataCapacityBits)
|
|
|
|
throw std::logic_error("Assertion error");
|
|
|
|
throw std::logic_error("Assertion error");
|
|
|
|
bb.appendBits(0, std::min(4, static_cast<int>(dataCapacityBits - bb.size())));
|
|
|
|
bb.appendBits(0, std::min(4, static_cast<int>(dataCapacityBits - bb.size())));
|
|
|
@ -326,7 +326,7 @@ QrCode::QrCode(int ver, Ecc ecl, const vector<uint8_t> &dataCodewords, int msk)
|
|
|
|
if (msk < -1 || msk > 7)
|
|
|
|
if (msk < -1 || msk > 7)
|
|
|
|
throw std::domain_error("Mask value out of range");
|
|
|
|
throw std::domain_error("Mask value out of range");
|
|
|
|
size = ver * 4 + 17;
|
|
|
|
size = ver * 4 + 17;
|
|
|
|
size_t sz = static_cast<size_t>(size);
|
|
|
|
const auto sz = static_cast<size_t>(size);
|
|
|
|
modules = vector<vector<bool> >(sz, vector<bool>(sz)); // Initially all white
|
|
|
|
modules = vector<vector<bool> >(sz, vector<bool>(sz)); // Initially all white
|
|
|
|
isFunction = vector<vector<bool> >(sz, vector<bool>(sz));
|
|
|
|
isFunction = vector<vector<bool> >(sz, vector<bool>(sz));
|
|
|
|
|
|
|
|
|
|
|
@ -341,7 +341,7 @@ QrCode::QrCode(int ver, Ecc ecl, const vector<uint8_t> &dataCodewords, int msk)
|
|
|
|
for (int i = 0; i < 8; i++) {
|
|
|
|
for (int i = 0; i < 8; i++) {
|
|
|
|
applyMask(i);
|
|
|
|
applyMask(i);
|
|
|
|
drawFormatBits(i);
|
|
|
|
drawFormatBits(i);
|
|
|
|
long penalty = getPenaltyScore();
|
|
|
|
const long penalty = getPenaltyScore();
|
|
|
|
if (penalty < minPenalty) {
|
|
|
|
if (penalty < minPenalty) {
|
|
|
|
msk = i;
|
|
|
|
msk = i;
|
|
|
|
minPenalty = penalty;
|
|
|
|
minPenalty = penalty;
|
|
|
@ -427,7 +427,7 @@ void QrCode::drawFunctionPatterns() {
|
|
|
|
|
|
|
|
|
|
|
|
// Draw numerous alignment patterns
|
|
|
|
// Draw numerous alignment patterns
|
|
|
|
const vector<int> alignPatPos = getAlignmentPatternPositions();
|
|
|
|
const vector<int> alignPatPos = getAlignmentPatternPositions();
|
|
|
|
size_t numAlign = alignPatPos.size();
|
|
|
|
const size_t numAlign = alignPatPos.size();
|
|
|
|
for (size_t i = 0; i < numAlign; i++) {
|
|
|
|
for (size_t i = 0; i < numAlign; i++) {
|
|
|
|
for (size_t j = 0; j < numAlign; j++) {
|
|
|
|
for (size_t j = 0; j < numAlign; j++) {
|
|
|
|
// Don't draw on the three finder corners
|
|
|
|
// Don't draw on the three finder corners
|
|
|
@ -444,11 +444,11 @@ void QrCode::drawFunctionPatterns() {
|
|
|
|
|
|
|
|
|
|
|
|
void QrCode::drawFormatBits(int msk) {
|
|
|
|
void QrCode::drawFormatBits(int msk) {
|
|
|
|
// Calculate error correction code and pack bits
|
|
|
|
// Calculate error correction code and pack bits
|
|
|
|
int data = getFormatBits(errorCorrectionLevel) << 3 | msk; // errCorrLvl is uint2, msk is uint3
|
|
|
|
const int data = getFormatBits(errorCorrectionLevel) << 3 | msk; // errCorrLvl is uint2, msk is uint3
|
|
|
|
int rem = data;
|
|
|
|
int rem = data;
|
|
|
|
for (int i = 0; i < 10; i++)
|
|
|
|
for (int i = 0; i < 10; i++)
|
|
|
|
rem = (rem << 1) ^ ((rem >> 9) * 0x537);
|
|
|
|
rem = (rem << 1) ^ ((rem >> 9) * 0x537);
|
|
|
|
int bits = (data << 10 | rem) ^ 0x5412; // uint15
|
|
|
|
const int bits = (data << 10 | rem) ^ 0x5412; // uint15
|
|
|
|
if (bits >> 15 != 0)
|
|
|
|
if (bits >> 15 != 0)
|
|
|
|
throw std::logic_error("Assertion error");
|
|
|
|
throw std::logic_error("Assertion error");
|
|
|
|
|
|
|
|
|
|
|
@ -478,15 +478,15 @@ void QrCode::drawVersion() {
|
|
|
|
int rem = version; // version is uint6, in the range [7, 40]
|
|
|
|
int rem = version; // version is uint6, in the range [7, 40]
|
|
|
|
for (int i = 0; i < 12; i++)
|
|
|
|
for (int i = 0; i < 12; i++)
|
|
|
|
rem = (rem << 1) ^ ((rem >> 11) * 0x1F25);
|
|
|
|
rem = (rem << 1) ^ ((rem >> 11) * 0x1F25);
|
|
|
|
long bits = static_cast<long>(version) << 12 | rem; // uint18
|
|
|
|
const auto bits = static_cast<long>(version) << 12 | rem; // uint18
|
|
|
|
if (bits >> 18 != 0)
|
|
|
|
if (bits >> 18 != 0)
|
|
|
|
throw std::logic_error("Assertion error");
|
|
|
|
throw std::logic_error("Assertion error");
|
|
|
|
|
|
|
|
|
|
|
|
// Draw two copies
|
|
|
|
// Draw two copies
|
|
|
|
for (int i = 0; i < 18; i++) {
|
|
|
|
for (int i = 0; i < 18; i++) {
|
|
|
|
bool bit = getBit(bits, i);
|
|
|
|
const bool bit = getBit(bits, i);
|
|
|
|
int a = size - 11 + i % 3;
|
|
|
|
const int a = size - 11 + i % 3;
|
|
|
|
int b = i / 3;
|
|
|
|
const int b = i / 3;
|
|
|
|
setFunctionModule(a, b, bit);
|
|
|
|
setFunctionModule(a, b, bit);
|
|
|
|
setFunctionModule(b, a, bit);
|
|
|
|
setFunctionModule(b, a, bit);
|
|
|
|
}
|
|
|
|
}
|
|
|
@ -496,8 +496,8 @@ void QrCode::drawVersion() {
|
|
|
|
void QrCode::drawFinderPattern(int x, int y) {
|
|
|
|
void QrCode::drawFinderPattern(int x, int y) {
|
|
|
|
for (int dy = -4; dy <= 4; dy++) {
|
|
|
|
for (int dy = -4; dy <= 4; dy++) {
|
|
|
|
for (int dx = -4; dx <= 4; dx++) {
|
|
|
|
for (int dx = -4; dx <= 4; dx++) {
|
|
|
|
int dist = std::max(std::abs(dx), std::abs(dy)); // Chebyshev/infinity norm
|
|
|
|
const int dist = std::max(std::abs(dx), std::abs(dy)); // Chebyshev/infinity norm
|
|
|
|
int xx = x + dx, yy = y + dy;
|
|
|
|
const int xx = x + dx, yy = y + dy;
|
|
|
|
if (0 <= xx && xx < size && 0 <= yy && yy < size)
|
|
|
|
if (0 <= xx && xx < size && 0 <= yy && yy < size)
|
|
|
|
setFunctionModule(xx, yy, dist != 2 && dist != 4);
|
|
|
|
setFunctionModule(xx, yy, dist != 2 && dist != 4);
|
|
|
|
}
|
|
|
|
}
|
|
|
@ -514,8 +514,8 @@ void QrCode::drawAlignmentPattern(int x, int y) {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void QrCode::setFunctionModule(int x, int y, bool isBlack) {
|
|
|
|
void QrCode::setFunctionModule(int x, int y, bool isBlack) {
|
|
|
|
size_t ux = static_cast<size_t>(x);
|
|
|
|
const auto ux = static_cast<size_t>(x);
|
|
|
|
size_t uy = static_cast<size_t>(y);
|
|
|
|
const auto uy = static_cast<size_t>(y);
|
|
|
|
modules .at(uy).at(ux) = isBlack;
|
|
|
|
modules .at(uy).at(ux) = isBlack;
|
|
|
|
isFunction.at(uy).at(ux) = true;
|
|
|
|
isFunction.at(uy).at(ux) = true;
|
|
|
|
}
|
|
|
|
}
|
|
|
@ -531,11 +531,11 @@ vector<uint8_t> QrCode::addEccAndInterleave(const vector<uint8_t> &data) const {
|
|
|
|
throw std::invalid_argument("Invalid argument");
|
|
|
|
throw std::invalid_argument("Invalid argument");
|
|
|
|
|
|
|
|
|
|
|
|
// Calculate parameter numbers
|
|
|
|
// Calculate parameter numbers
|
|
|
|
int numBlocks = NUM_ERROR_CORRECTION_BLOCKS[static_cast<int>(errorCorrectionLevel)][version];
|
|
|
|
const int numBlocks = NUM_ERROR_CORRECTION_BLOCKS[static_cast<int>(errorCorrectionLevel)][version];
|
|
|
|
int blockEccLen = ECC_CODEWORDS_PER_BLOCK [static_cast<int>(errorCorrectionLevel)][version];
|
|
|
|
const int blockEccLen = ECC_CODEWORDS_PER_BLOCK [static_cast<int>(errorCorrectionLevel)][version];
|
|
|
|
int rawCodewords = getNumRawDataModules(version) / 8;
|
|
|
|
const int rawCodewords = getNumRawDataModules(version) / 8;
|
|
|
|
int numShortBlocks = numBlocks - rawCodewords % numBlocks;
|
|
|
|
const int numShortBlocks = numBlocks - rawCodewords % numBlocks;
|
|
|
|
int shortBlockLen = rawCodewords / numBlocks;
|
|
|
|
const int shortBlockLen = rawCodewords / numBlocks;
|
|
|
|
|
|
|
|
|
|
|
|
// Split data into blocks and append ECC to each block
|
|
|
|
// Split data into blocks and append ECC to each block
|
|
|
|
vector<vector<uint8_t> > blocks;
|
|
|
|
vector<vector<uint8_t> > blocks;
|
|
|
@ -576,9 +576,9 @@ void QrCode::drawCodewords(const vector<uint8_t> &data) {
|
|
|
|
right = 5;
|
|
|
|
right = 5;
|
|
|
|
for (int vert = 0; vert < size; vert++) { // Vertical counter
|
|
|
|
for (int vert = 0; vert < size; vert++) { // Vertical counter
|
|
|
|
for (int j = 0; j < 2; j++) {
|
|
|
|
for (int j = 0; j < 2; j++) {
|
|
|
|
size_t x = static_cast<size_t>(right - j); // Actual x coordinate
|
|
|
|
const auto x = static_cast<size_t>(right - j); // Actual x coordinate
|
|
|
|
bool upward = ((right + 1) & 2) == 0;
|
|
|
|
const bool upward = ((right + 1) & 2) == 0;
|
|
|
|
size_t y = static_cast<size_t>(upward ? size - 1 - vert : vert); // Actual y coordinate
|
|
|
|
const auto y = static_cast<size_t>(upward ? size - 1 - vert : vert); // Actual y coordinate
|
|
|
|
if (!isFunction.at(y).at(x) && i < data.size() * 8) {
|
|
|
|
if (!isFunction.at(y).at(x) && i < data.size() * 8) {
|
|
|
|
modules.at(y).at(x) = getBit(data.at(i >> 3), 7 - static_cast<int>(i & 7));
|
|
|
|
modules.at(y).at(x) = getBit(data.at(i >> 3), 7 - static_cast<int>(i & 7));
|
|
|
|
i++;
|
|
|
|
i++;
|
|
|
@ -596,7 +596,7 @@ void QrCode::drawCodewords(const vector<uint8_t> &data) {
|
|
|
|
void QrCode::applyMask(int msk) {
|
|
|
|
void QrCode::applyMask(int msk) {
|
|
|
|
if (msk < 0 || msk > 7)
|
|
|
|
if (msk < 0 || msk > 7)
|
|
|
|
throw std::domain_error("Mask value out of range");
|
|
|
|
throw std::domain_error("Mask value out of range");
|
|
|
|
size_t sz = static_cast<size_t>(size);
|
|
|
|
const auto sz = static_cast<size_t>(size);
|
|
|
|
for (size_t y = 0; y < sz; y++) {
|
|
|
|
for (size_t y = 0; y < sz; y++) {
|
|
|
|
for (size_t x = 0; x < sz; x++) {
|
|
|
|
for (size_t x = 0; x < sz; x++) {
|
|
|
|
bool invert;
|
|
|
|
bool invert;
|
|
|
@ -668,7 +668,7 @@ long QrCode::getPenaltyScore() const {
|
|
|
|
// 2*2 blocks of modules having same color
|
|
|
|
// 2*2 blocks of modules having same color
|
|
|
|
for (int y = 0; y < size - 1; y++) {
|
|
|
|
for (int y = 0; y < size - 1; y++) {
|
|
|
|
for (int x = 0; x < size - 1; x++) {
|
|
|
|
for (int x = 0; x < size - 1; x++) {
|
|
|
|
bool color = module(x, y);
|
|
|
|
const bool color = module(x, y);
|
|
|
|
if ( color == module(x + 1, y) &&
|
|
|
|
if ( color == module(x + 1, y) &&
|
|
|
|
color == module(x, y + 1) &&
|
|
|
|
color == module(x, y + 1) &&
|
|
|
|
color == module(x + 1, y + 1))
|
|
|
|
color == module(x + 1, y + 1))
|
|
|
@ -684,9 +684,9 @@ long QrCode::getPenaltyScore() const {
|
|
|
|
black++;
|
|
|
|
black++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
int total = size * size; // Note that size is odd, so black/total != 1/2
|
|
|
|
const int total = size * size; // Note that size is odd, so black/total != 1/2
|
|
|
|
// Compute the smallest integer k >= 0 such that (45-5k)% <= black/total <= (55+5k)%
|
|
|
|
// Compute the smallest integer k >= 0 such that (45-5k)% <= black/total <= (55+5k)%
|
|
|
|
int k = static_cast<int>((std::abs(black * 20L - total * 10L) + total - 1) / total) - 1;
|
|
|
|
const auto k = static_cast<int>((std::abs(black * 20L - total * 10L) + total - 1) / total) - 1;
|
|
|
|
result += k * PENALTY_N4;
|
|
|
|
result += k * PENALTY_N4;
|
|
|
|
return result;
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
}
|
|
|
@ -696,8 +696,8 @@ vector<int> QrCode::getAlignmentPatternPositions() const {
|
|
|
|
if (version == 1)
|
|
|
|
if (version == 1)
|
|
|
|
return vector<int>();
|
|
|
|
return vector<int>();
|
|
|
|
else {
|
|
|
|
else {
|
|
|
|
int numAlign = version / 7 + 2;
|
|
|
|
const int numAlign = version / 7 + 2;
|
|
|
|
int step = (version == 32) ? 26 :
|
|
|
|
const int step = (version == 32) ? 26 :
|
|
|
|
(version*4 + numAlign*2 + 1) / (numAlign*2 - 2) * 2;
|
|
|
|
(version*4 + numAlign*2 + 1) / (numAlign*2 - 2) * 2;
|
|
|
|
vector<int> result;
|
|
|
|
vector<int> result;
|
|
|
|
for (int i = 0, pos = size - 7; i < numAlign - 1; i++, pos -= step)
|
|
|
|
for (int i = 0, pos = size - 7; i < numAlign - 1; i++, pos -= step)
|
|
|
@ -713,7 +713,7 @@ int QrCode::getNumRawDataModules(int ver) {
|
|
|
|
throw std::domain_error("Version number out of range");
|
|
|
|
throw std::domain_error("Version number out of range");
|
|
|
|
int result = (16 * ver + 128) * ver + 64;
|
|
|
|
int result = (16 * ver + 128) * ver + 64;
|
|
|
|
if (ver >= 2) {
|
|
|
|
if (ver >= 2) {
|
|
|
|
int numAlign = ver / 7 + 2;
|
|
|
|
const int numAlign = ver / 7 + 2;
|
|
|
|
result -= (25 * numAlign - 10) * numAlign - 55;
|
|
|
|
result -= (25 * numAlign - 10) * numAlign - 55;
|
|
|
|
if (ver >= 7)
|
|
|
|
if (ver >= 7)
|
|
|
|
result -= 36;
|
|
|
|
result -= 36;
|
|
|
@ -731,7 +731,7 @@ int QrCode::getNumDataCodewords(int ver, Ecc ecl) {
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
vector<uint8_t> QrCode::reedSolomonComputeDivisor(int degree) {
|
|
|
|
vector<uint8_t> QrCode::reedSolomonComputeDivisor(const int degree) {
|
|
|
|
if (degree < 1 || degree > 255)
|
|
|
|
if (degree < 1 || degree > 255)
|
|
|
|
throw std::domain_error("Degree out of range");
|
|
|
|
throw std::domain_error("Degree out of range");
|
|
|
|
// Polynomial coefficients are stored from highest to lowest power, excluding the leading term which is always 1.
|
|
|
|
// Polynomial coefficients are stored from highest to lowest power, excluding the leading term which is always 1.
|
|
|
@ -759,7 +759,7 @@ vector<uint8_t> QrCode::reedSolomonComputeDivisor(int degree) {
|
|
|
|
vector<uint8_t> QrCode::reedSolomonComputeRemainder(const vector<uint8_t> &data, const vector<uint8_t> &divisor) {
|
|
|
|
vector<uint8_t> QrCode::reedSolomonComputeRemainder(const vector<uint8_t> &data, const vector<uint8_t> &divisor) {
|
|
|
|
vector<uint8_t> result(divisor.size());
|
|
|
|
vector<uint8_t> result(divisor.size());
|
|
|
|
for (uint8_t b : data) { // Polynomial division
|
|
|
|
for (uint8_t b : data) { // Polynomial division
|
|
|
|
uint8_t factor = b ^ result.at(0);
|
|
|
|
const uint8_t factor = b ^ result.at(0);
|
|
|
|
result.erase(result.begin());
|
|
|
|
result.erase(result.begin());
|
|
|
|
result.push_back(0);
|
|
|
|
result.push_back(0);
|
|
|
|
for (size_t i = 0; i < result.size(); i++)
|
|
|
|
for (size_t i = 0; i < result.size(); i++)
|
|
|
@ -783,10 +783,10 @@ uint8_t QrCode::reedSolomonMultiply(uint8_t x, uint8_t y) {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
int QrCode::finderPenaltyCountPatterns(const std::array<int,7> &runHistory) const {
|
|
|
|
int QrCode::finderPenaltyCountPatterns(const std::array<int,7> &runHistory) const {
|
|
|
|
int n = runHistory.at(1);
|
|
|
|
const int n = runHistory.at(1);
|
|
|
|
if (n > size * 3)
|
|
|
|
if (n > size * 3)
|
|
|
|
throw std::logic_error("Assertion error");
|
|
|
|
throw std::logic_error("Assertion error");
|
|
|
|
bool core = n > 0 && runHistory.at(2) == n && runHistory.at(3) == n * 3 && runHistory.at(4) == n && runHistory.at(5) == n;
|
|
|
|
const bool core = n > 0 && runHistory.at(2) == n && runHistory.at(3) == n * 3 && runHistory.at(4) == n && runHistory.at(5) == n;
|
|
|
|
return (core && runHistory.at(0) >= n * 4 && runHistory.at(6) >= n ? 1 : 0)
|
|
|
|
return (core && runHistory.at(0) >= n * 4 && runHistory.at(6) >= n ? 1 : 0)
|
|
|
|
+ (core && runHistory.at(6) >= n * 4 && runHistory.at(0) >= n ? 1 : 0);
|
|
|
|
+ (core && runHistory.at(6) >= n * 4 && runHistory.at(0) >= n ? 1 : 0);
|
|
|
|
}
|
|
|
|
}
|
|
|
|