| 56 | |
| 57 | |
| 58 | qrcodegen::QrCode qrcodegen::QrCode::encodeSegments(const std::vector<QrSegment> &segs, const Ecc &ecl, |
| 59 | int minVersion, int maxVersion, int mask, bool boostEcl) { |
| 60 | if (!(1 <= minVersion && minVersion <= maxVersion && maxVersion <= 40) || mask < -1 || mask > 7) |
| 61 | throw "Invalid value"; |
| 62 | |
| 63 | // Find the minimal version number to use |
| 64 | int version, dataUsedBits; |
| 65 | for (version = minVersion; ; version++) { |
| 66 | int dataCapacityBits = getNumDataCodewords(version, ecl) * 8; // Number of data bits available |
| 67 | dataUsedBits = QrSegment::getTotalBits(segs, version); |
| 68 | if (dataUsedBits != -1 && dataUsedBits <= dataCapacityBits) |
| 69 | break; // This version number is found to be suitable |
| 70 | if (version >= maxVersion) // All versions in the range could not fit the given data |
| 71 | throw "Data too long"; |
| 72 | } |
| 73 | if (dataUsedBits == -1) |
| 74 | throw "Assertion error"; |
| 75 | |
| 76 | // Increase the error correction level while the data still fits in the current version number |
| 77 | const Ecc *newEcl = &ecl; |
| 78 | if (boostEcl) { |
| 79 | if (dataUsedBits <= getNumDataCodewords(version, Ecc::MEDIUM ) * 8) newEcl = &Ecc::MEDIUM ; |
| 80 | if (dataUsedBits <= getNumDataCodewords(version, Ecc::QUARTILE) * 8) newEcl = &Ecc::QUARTILE; |
| 81 | if (dataUsedBits <= getNumDataCodewords(version, Ecc::HIGH ) * 8) newEcl = &Ecc::HIGH ; |
| 82 | } |
| 83 | |
| 84 | // Create the data bit string by concatenating all segments |
| 85 | int dataCapacityBits = getNumDataCodewords(version, *newEcl) * 8; |
| 86 | BitBuffer bb; |
| 87 | for (size_t i = 0; i < segs.size(); i++) { |
| 88 | const QrSegment &seg(segs.at(i)); |
| 89 | bb.appendBits(seg.mode.modeBits, 4); |
| 90 | bb.appendBits(seg.numChars, seg.mode.numCharCountBits(version)); |
| 91 | bb.appendData(seg); |
| 92 | } |
| 93 | |
| 94 | // Add terminator and pad up to a byte if applicable |
| 95 | bb.appendBits(0, std::min(4, dataCapacityBits - bb.getBitLength())); |
| 96 | bb.appendBits(0, (8 - bb.getBitLength() % 8) % 8); |
| 97 | |
| 98 | // Pad with alternate bytes until data capacity is reached |
| 99 | for (uint8_t padByte = 0xEC; bb.getBitLength() < dataCapacityBits; padByte ^= 0xEC ^ 0x11) |
| 100 | bb.appendBits(padByte, 8); |
| 101 | if (bb.getBitLength() % 8 != 0) |
| 102 | throw "Assertion error"; |
| 103 | |
| 104 | // Create the QR Code symbol |
| 105 | return QrCode(version, *newEcl, bb.getBytes(), mask); |
| 106 | } |
| 107 | |
| 108 | |
| 109 | qrcodegen::QrCode::QrCode(int ver, const Ecc &ecl, const std::vector<uint8_t> &dataCodewords, int mask) : |
nothing calls this directly
no test coverage detected