port to wince

pull/162/head
hwenb 3 years ago
parent 9ca3dd36aa
commit 3f8bb419d4

@ -1,4 +1,4 @@
/*
/*
* QR Code generator demo (C++)
*
* Run this command-line program with no arguments. The program computes a bunch of demonstration
@ -24,8 +24,9 @@
* Software.
*/
#define _CRT_SECURE_NO_DEPRECATE
#include <climits>
#include <cstdint>
#include <cstdlib>
#include <cstring>
#include <iostream>
@ -33,12 +34,16 @@
#include <string>
#include <vector>
#include "qrcodegen.hpp"
#include <fstream>
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
using std::uint8_t;
using qrcodegen::QrCode;
using qrcodegen::QrSegment;
#pragma pack(2)// need this, otherwise cant get correct result of sizeof
#pragma pack(2)//必须得写否则sizeof得不到正确的结果
typedef unsigned char BYTE;
typedef unsigned short WORD;
@ -66,6 +71,84 @@ typedef struct {
DWORD biClrImportant;
} BITMAPINFOHEADER;
int SaveToBMP(const QrCode& qrCode) // to 145*145
{
//将要生成的二维码保存为BMP真彩色图片文件
FILE* pf = fopen("qrcode.bmp", "wb");
if (NULL == pf)
{
printf("file open fail.\n");
fclose(pf);
return -1;
}
int width = qrCode.getSize();
int height = qrCode.getSize();
int biCount = 24;//真彩色
int lineByte = (width * biCount / 8 + 3) / 4 * 4; //每line字节数必须为4的倍数
//位图文件头
BITMAPFILEHEADER bitMapFileHeader;
bitMapFileHeader.bfType = 0x4D42;
bitMapFileHeader.bfSize = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER) + lineByte * height;
bitMapFileHeader.bfReserved1 = 0;
bitMapFileHeader.bfReserved2 = 0;
bitMapFileHeader.bfOffBits = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER);
//位图信息头
BITMAPINFOHEADER bitMapInfoHeader;
bitMapInfoHeader.biBitCount = biCount;
bitMapInfoHeader.biClrImportant = 0;
bitMapInfoHeader.biClrUsed = 0;
bitMapInfoHeader.biCompression = 0;
bitMapInfoHeader.biHeight = height;
bitMapInfoHeader.biPlanes = 1;
bitMapInfoHeader.biSize = 40;
bitMapInfoHeader.biSizeImage = lineByte * height;
bitMapInfoHeader.biWidth = width;
bitMapInfoHeader.biXPelsPerMeter = 0;
bitMapInfoHeader.biYPelsPerMeter = 0;
//写文件头进文件
fwrite(&bitMapFileHeader, sizeof(BITMAPFILEHEADER), 1, pf);
//写位图信息头进文件
fwrite(&bitMapInfoHeader, sizeof(BITMAPINFOHEADER), 1, pf);
unsigned char* pBMPData = new unsigned char[lineByte * height];
memset(pBMPData, 255, lineByte * height);
for (int y = 0; y < height; y++)
{
for (int x = 0; x < height; x++)
{
//qrCode.getModule(x, y) ? printf("##") : printf(" ");
qrCode.getModule(x, y) ? printf("%c%c", 219, 219) : printf(" ");
}
std::cout << std::endl;
}
std::cout << std::endl;
for (int i = 0; i < height; i++)
{
for (int j = 0; j < lineByte / 3; j++)
{
if (qrCode.getModule(j, i))
{
//设置rgb颜色可自定义设置这里设为黑色。
*(pBMPData + lineByte * i + 3 * j) = 0;
*(pBMPData + lineByte * i + 3 * j + 1) = 0;
*(pBMPData + lineByte * i + 3 * j + 2) = 0;
}
}
}
//写数据进文件
fwrite(pBMPData, sizeof(unsigned char), lineByte * height, pf);
fclose(pf);
delete[] pBMPData;
pBMPData = NULL;
return 0;
}
// Function prototypes
static void doBasicDemo();
@ -79,41 +162,40 @@ static void printQr(const QrCode &qr);
// The main application program.
int main() {
doBasicDemo();
doVarietyDemo();
doSegmentDemo();
doMaskDemo();
//doVarietyDemo();
//doSegmentDemo();
//doMaskDemo();
return EXIT_SUCCESS;
}
/*---- Demo suite ----*/
// Creates a single QR Code, then prints it to the console.
static void doBasicDemo() {
const char *text = "Hello, world!"; // User-supplied text
const QrCode::Ecc errCorLvl = QrCode::Ecc::LOW; // Error correction level
const char *text = "https://www.baidu.com/"; // User-supplied text
const QrCode::Ecc errCorLvl = QrCode::LOW; // Error correction level
// Make and print the QR Code symbol
const QrCode qr = QrCode::encodeText(text, errCorLvl);
printQr(qr);
std::cout << toSvgString(qr, 4) << std::endl;
//printQr(qr);
SaveToBMP(qr);
}
// Creates a variety of QR Codes that exercise different features of the library, and prints each one to the console.
static void doVarietyDemo() {
// Numeric mode encoding (3.33 bits per digit)
const QrCode qr0 = QrCode::encodeText("314159265358979323846264338327950288419716939937510", QrCode::Ecc::MEDIUM);
const QrCode qr0 = QrCode::encodeText("314159265358979323846264338327950288419716939937510", QrCode::MEDIUM);
printQr(qr0);
// Alphanumeric mode encoding (5.5 bits per character)
const QrCode qr1 = QrCode::encodeText("DOLLAR-AMOUNT:$39.87 PERCENTAGE:100.00% OPERATIONS:+-*/", QrCode::Ecc::HIGH);
const QrCode qr1 = QrCode::encodeText("DOLLAR-AMOUNT:$39.87 PERCENTAGE:100.00% OPERATIONS:+-*/", QrCode::HIGH);
printQr(qr1);
// Unicode text as UTF-8
const QrCode qr2 = QrCode::encodeText("\xE3\x81\x93\xE3\x82\x93\xE3\x81\xAB\xE3\x81\xA1wa\xE3\x80\x81"
"\xE4\xB8\x96\xE7\x95\x8C\xEF\xBC\x81\x20\xCE\xB1\xCE\xB2\xCE\xB3\xCE\xB4", QrCode::Ecc::QUARTILE);
"\xE4\xB8\x96\xE7\x95\x8C\xEF\xBC\x81\x20\xCE\xB1\xCE\xB2\xCE\xB3\xCE\xB4", QrCode::QUARTILE);
printQr(qr2);
// Moderately large QR Code using longer text (from Lewis Carroll's Alice in Wonderland)
@ -124,7 +206,7 @@ static void doVarietyDemo() {
"'without pictures or conversations?' So she was considering in her own mind (as well as she could, "
"for the hot day made her feel very sleepy and stupid), whether the pleasure of making a "
"daisy-chain would be worth the trouble of getting up and picking the daisies, when suddenly "
"a White Rabbit with pink eyes ran close by her.", QrCode::Ecc::HIGH);
"a White Rabbit with pink eyes ran close by her.", QrCode::HIGH);
printQr(qr3);
}
@ -136,12 +218,13 @@ static void doSegmentDemo() {
const char *silver1 = "41421356237309504880168872420969807856967187537694807317667973799";
const QrCode qr0 = QrCode::encodeText(
(std::string(silver0) + silver1).c_str(),
QrCode::Ecc::LOW);
QrCode::LOW);
printQr(qr0);
const QrCode qr1 = QrCode::encodeSegments(
{QrSegment::makeAlphanumeric(silver0), QrSegment::makeNumeric(silver1)},
QrCode::Ecc::LOW);
std::vector<QrSegment> segs;
segs.push_back(QrSegment::makeAlphanumeric(silver0));
segs.push_back(QrSegment::makeAlphanumeric(silver1));
const QrCode qr1 = QrCode::encodeSegments(segs, QrCode::LOW);
printQr(qr1);
// Illustration "golden"
@ -150,13 +233,15 @@ static void doSegmentDemo() {
const char *golden2 = "......";
const QrCode qr2 = QrCode::encodeText(
(std::string(golden0) + golden1 + golden2).c_str(),
QrCode::Ecc::LOW);
QrCode::LOW);
printQr(qr2);
std::vector<uint8_t> bytes(golden0, golden0 + std::strlen(golden0));
const QrCode qr3 = QrCode::encodeSegments(
{QrSegment::makeBytes(bytes), QrSegment::makeNumeric(golden1), QrSegment::makeAlphanumeric(golden2)},
QrCode::Ecc::LOW);
std::vector<QrSegment> segs3;
segs3.push_back(QrSegment::makeBytes(bytes));
segs3.push_back(QrSegment::makeNumeric(golden1));
segs3.push_back(QrSegment::makeAlphanumeric(golden2));
const QrCode qr3 = QrCode::encodeSegments(segs3, QrCode::LOW);
printQr(qr3);
// Illustration "Madoka": kanji, kana, Cyrillic, full-width Latin, Greek characters
@ -170,24 +255,24 @@ static void doSegmentDemo() {
"\xEF\xBD\x84\xEF\xBD\x85\xEF\xBD\x93\xEF"
"\xBD\x95\xE3\x80\x80\xCE\xBA\xCE\xB1\xEF"
"\xBC\x9F";
const QrCode qr4 = QrCode::encodeText(madoka, QrCode::Ecc::LOW);
const QrCode qr4 = QrCode::encodeText(madoka, QrCode::LOW);
printQr(qr4);
const std::vector<int> kanjiChars{ // Kanji mode encoding (13 bits per character)
0x0035, 0x1002, 0x0FC0, 0x0AED, 0x0AD7,
0x015C, 0x0147, 0x0129, 0x0059, 0x01BD,
0x018D, 0x018A, 0x0036, 0x0141, 0x0144,
0x0001, 0x0000, 0x0249, 0x0240, 0x0249,
0x0000, 0x0104, 0x0105, 0x0113, 0x0115,
0x0000, 0x0208, 0x01FF, 0x0008,
};
qrcodegen::BitBuffer bb;
for (int c : kanjiChars)
bb.appendBits(static_cast<std::uint32_t>(c), 13);
const QrCode qr5 = QrCode::encodeSegments(
{QrSegment(QrSegment::Mode::KANJI, static_cast<int>(kanjiChars.size()), bb)},
QrCode::Ecc::LOW);
printQr(qr5);
//const std::vector<int> kanjiChars{ // Kanji mode encoding (13 bits per character)
// 0x0035, 0x1002, 0x0FC0, 0x0AED, 0x0AD7,
// 0x015C, 0x0147, 0x0129, 0x0059, 0x01BD,
// 0x018D, 0x018A, 0x0036, 0x0141, 0x0144,
// 0x0001, 0x0000, 0x0249, 0x0240, 0x0249,
// 0x0000, 0x0104, 0x0105, 0x0113, 0x0115,
// 0x0000, 0x0208, 0x01FF, 0x0008,
//};
//qrcodegen::BitBuffer bb;
//for (int c : kanjiChars)
// bb.appendBits(static_cast<std::uint32_t>(c), 13);
//const QrCode qr5 = QrCode::encodeSegments(
// {QrSegment(QrSegment::Mode::KANJI, static_cast<int>(kanjiChars.size()), bb)},
// QrCode::LOW);
//printQr(qr5);
}
@ -195,8 +280,8 @@ static void doSegmentDemo() {
static void doMaskDemo() {
// Project Nayuki URL
std::vector<QrSegment> segs0 = QrSegment::makeSegments("https://www.nayuki.io/");
printQr(QrCode::encodeSegments(segs0, QrCode::Ecc::HIGH, QrCode::MIN_VERSION, QrCode::MAX_VERSION, -1, true)); // Automatic mask
printQr(QrCode::encodeSegments(segs0, QrCode::Ecc::HIGH, QrCode::MIN_VERSION, QrCode::MAX_VERSION, 3, true)); // Force mask 3
printQr(QrCode::encodeSegments(segs0, QrCode::HIGH, QrCode::MIN_VERSION, QrCode::MAX_VERSION, -1, true)); // Automatic mask
printQr(QrCode::encodeSegments(segs0, QrCode::HIGH, QrCode::MIN_VERSION, QrCode::MAX_VERSION, 3, true)); // Force mask 3
// Chinese text as UTF-8
std::vector<QrSegment> segs1 = QrSegment::makeSegments(
@ -207,10 +292,10 @@ static void doMaskDemo() {
"\xE3\x80\x81\xE5\x85\xAC\xE9\x96\x8B\xE7\xB7\xA8\xE8\xBC\xAF\xE4\xB8\x94\xE5\xA4"
"\x9A\xE8\xAA\x9E\xE8\xA8\x80\xE7\x9A\x84\xE7\xB6\xB2\xE8\xB7\xAF\xE7\x99\xBE\xE7"
"\xA7\x91\xE5\x85\xA8\xE6\x9B\xB8\xE5\x8D\x94\xE4\xBD\x9C\xE8\xA8\x88\xE7\x95\xAB");
printQr(QrCode::encodeSegments(segs1, QrCode::Ecc::MEDIUM, QrCode::MIN_VERSION, QrCode::MAX_VERSION, 0, true)); // Force mask 0
printQr(QrCode::encodeSegments(segs1, QrCode::Ecc::MEDIUM, QrCode::MIN_VERSION, QrCode::MAX_VERSION, 1, true)); // Force mask 1
printQr(QrCode::encodeSegments(segs1, QrCode::Ecc::MEDIUM, QrCode::MIN_VERSION, QrCode::MAX_VERSION, 5, true)); // Force mask 5
printQr(QrCode::encodeSegments(segs1, QrCode::Ecc::MEDIUM, QrCode::MIN_VERSION, QrCode::MAX_VERSION, 7, true)); // Force mask 7
printQr(QrCode::encodeSegments(segs1, QrCode::MEDIUM, QrCode::MIN_VERSION, QrCode::MAX_VERSION, 0, true)); // Force mask 0
printQr(QrCode::encodeSegments(segs1, QrCode::MEDIUM, QrCode::MIN_VERSION, QrCode::MAX_VERSION, 1, true)); // Force mask 1
printQr(QrCode::encodeSegments(segs1, QrCode::MEDIUM, QrCode::MIN_VERSION, QrCode::MAX_VERSION, 5, true)); // Force mask 5
printQr(QrCode::encodeSegments(segs1, QrCode::MEDIUM, QrCode::MIN_VERSION, QrCode::MAX_VERSION, 7, true)); // Force mask 7
}
@ -246,15 +331,18 @@ static std::string toSvgString(const QrCode &qr, int border) {
return sb.str();
}
// Prints the given QrCode object to the console.
static void printQr(const QrCode &qr) {
int border = 4;
for (int y = -border; y < qr.getSize() + border; y++) {
for (int x = -border; x < qr.getSize() + border; x++) {
std::cout << (qr.getModule(x, y) ? "##" : " ");
qr.getModule(x, y) ? printf("%c%c", 219, 219) : printf(" ");
}
std::cout << std::endl;
}
std::cout << std::endl;
}

@ -31,9 +31,7 @@
#include <utility>
#include "qrcodegen.hpp"
using std::int8_t;
using std::uint8_t;
using std::size_t;
using std::vector;
@ -70,9 +68,9 @@ QrSegment QrSegment::makeBytes(const vector<uint8_t> &data) {
if (data.size() > static_cast<unsigned int>(INT_MAX))
throw std::length_error("Data too long");
BitBuffer bb;
for (uint8_t b : data)
bb.appendBits(b, 8);
return QrSegment(Mode::BYTE, static_cast<int>(data.size()), std::move(bb));
for (vector<uint8_t>::size_type i = 0; i < data.size(); i++)
bb.appendBits(data[i], 8);
return QrSegment(Mode::BYTE, static_cast<int>(data.size()), bb);
}
@ -95,7 +93,7 @@ QrSegment QrSegment::makeNumeric(const char *digits) {
}
if (accumCount > 0) // 1 or 2 digits remaining
bb.appendBits(static_cast<uint32_t>(accumData), accumCount * 3 + 1);
return QrSegment(Mode::NUMERIC, charCount, std::move(bb));
return QrSegment(Mode::NUMERIC, charCount, bb);
}
@ -106,7 +104,7 @@ QrSegment QrSegment::makeAlphanumeric(const char *text) {
int charCount = 0;
for (; *text != '\0'; text++, charCount++) {
const char *temp = std::strchr(ALPHANUMERIC_CHARSET, *text);
if (temp == nullptr)
if (temp == NULL)
throw std::domain_error("String contains unencodable characters in alphanumeric mode");
accumData = accumData * 45 + static_cast<int>(temp - ALPHANUMERIC_CHARSET);
accumCount++;
@ -118,7 +116,7 @@ QrSegment QrSegment::makeAlphanumeric(const char *text) {
}
if (accumCount > 0) // 1 character remaining
bb.appendBits(static_cast<uint32_t>(accumData), 6);
return QrSegment(Mode::ALPHANUMERIC, charCount, std::move(bb));
return QrSegment(Mode::ALPHANUMERIC, charCount, bb);
}
@ -154,7 +152,7 @@ QrSegment QrSegment::makeEci(long assignVal) {
bb.appendBits(static_cast<uint32_t>(assignVal), 21);
} else
throw std::domain_error("ECI assignment value out of range");
return QrSegment(Mode::ECI, 0, std::move(bb));
return QrSegment(Mode::ECI, 0, bb);
}
@ -167,10 +165,10 @@ QrSegment::QrSegment(const Mode &md, int numCh, const std::vector<bool> &dt) :
}
QrSegment::QrSegment(const Mode &md, int numCh, std::vector<bool> &&dt) :
QrSegment::QrSegment(const Mode &md, int numCh, std::vector<bool> &dt) :
mode(&md),
numChars(numCh),
data(std::move(dt)) {
data(dt) {
if (numCh < 0)
throw std::domain_error("Invalid value");
}
@ -178,16 +176,16 @@ QrSegment::QrSegment(const Mode &md, int numCh, std::vector<bool> &&dt) :
int QrSegment::getTotalBits(const vector<QrSegment> &segs, int version) {
int result = 0;
for (const QrSegment &seg : segs) {
int ccbits = seg.mode->numCharCountBits(version);
if (seg.numChars >= (1L << ccbits))
for (vector<QrSegment>::size_type i = 0; i <segs.size(); i++) {
int ccbits = segs[i].mode->numCharCountBits(version);
if (segs[i].numChars >= (1L << ccbits))
return -1; // The segment's length doesn't fit the field's bit width
if (4 + ccbits > INT_MAX - result)
return -1; // The sum will overflow an int type
result += 4 + ccbits;
if (seg.data.size() > static_cast<unsigned int>(INT_MAX - result))
if (segs[i].data.size() > static_cast<unsigned int>(INT_MAX - result))
return -1; // The sum will overflow an int type
result += static_cast<int>(seg.data.size());
result += static_cast<int>(segs[i].data.size());
}
return result;
}
@ -205,7 +203,7 @@ bool QrSegment::isNumeric(const char *text) {
bool QrSegment::isAlphanumeric(const char *text) {
for (; *text != '\0'; text++) {
if (std::strchr(ALPHANUMERIC_CHARSET, *text) == nullptr)
if (std::strchr(ALPHANUMERIC_CHARSET, *text) == NULL)
return false;
}
return true;
@ -235,10 +233,10 @@ const char *QrSegment::ALPHANUMERIC_CHARSET = "0123456789ABCDEFGHIJKLMNOPQRSTUVW
int QrCode::getFormatBits(Ecc ecl) {
switch (ecl) {
case Ecc::LOW : return 1;
case Ecc::MEDIUM : return 0;
case Ecc::QUARTILE: return 3;
case Ecc::HIGH : return 2;
case LOW : return 1;
case MEDIUM : return 0;
case QUARTILE: return 3;
case HIGH : return 2;
default: throw std::logic_error("Unreachable");
}
}
@ -251,7 +249,8 @@ QrCode QrCode::encodeText(const char *text, Ecc ecl) {
QrCode QrCode::encodeBinary(const vector<uint8_t> &data, Ecc ecl) {
vector<QrSegment> segs{QrSegment::makeBytes(data)};
vector<QrSegment> segs;
segs.push_back(QrSegment::makeBytes(data));
return encodeSegments(segs, ecl);
}
@ -282,17 +281,18 @@ QrCode QrCode::encodeSegments(const vector<QrSegment> &segs, Ecc ecl,
assert(dataUsedBits != -1);
// Increase the error correction level while the data still fits in the current version number
for (Ecc newEcl : {Ecc::MEDIUM, Ecc::QUARTILE, Ecc::HIGH}) { // From low to high
if (boostEcl && dataUsedBits <= getNumDataCodewords(version, newEcl) * 8)
ecl = newEcl;
Ecc ecls[3] = {MEDIUM, QUARTILE, HIGH};
for (uint8_t i = 0; i < 3; ++i) { // From low to high
if (boostEcl && dataUsedBits <= getNumDataCodewords(version, ecls[i]) * 8)
ecl = ecls[i];
}
// Concatenate all segments to create the data bit string
BitBuffer bb;
for (const QrSegment &seg : segs) {
bb.appendBits(static_cast<uint32_t>(seg.getMode().getModeBits()), 4);
bb.appendBits(static_cast<uint32_t>(seg.getNumChars()), seg.getMode().numCharCountBits(version));
bb.insert(bb.end(), seg.getData().begin(), seg.getData().end());
for (vector<QrSegment>::size_type i = 0; i < segs.size(); ++i) {
bb.appendBits(static_cast<uint32_t>(segs[i].getMode().getModeBits()), 4);
bb.appendBits(static_cast<uint32_t>(segs[i].getNumChars()), segs[i].getMode().numCharCountBits(version));
bb.insert(bb.end(), segs[i].getData().begin(), segs[i].getData().end());
}
assert(bb.size() == static_cast<unsigned int>(dataUsedBits));
@ -355,7 +355,9 @@ QrCode::QrCode(int ver, Ecc ecl, const vector<uint8_t> &dataCodewords, int msk)
drawFormatBits(msk); // Overwrite old format bits
isFunction.clear();
isFunction.shrink_to_fit();
//isFunction.shrink_to_fit();
//vector<int>(isFunction).swap(isFunction);
}
@ -510,13 +512,13 @@ vector<uint8_t> QrCode::addEccAndInterleave(const vector<uint8_t> &data) const {
vector<vector<uint8_t> > blocks;
const vector<uint8_t> rsDiv = reedSolomonComputeDivisor(blockEccLen);
for (int i = 0, k = 0; i < numBlocks; i++) {
vector<uint8_t> dat(data.cbegin() + k, data.cbegin() + (k + shortBlockLen - blockEccLen + (i < numShortBlocks ? 0 : 1)));
vector<uint8_t> dat(data.begin() + k, data.begin() + (k + shortBlockLen - blockEccLen + (i < numShortBlocks ? 0 : 1)));
k += static_cast<int>(dat.size());
const vector<uint8_t> ecc = reedSolomonComputeRemainder(dat, rsDiv);
if (i < numShortBlocks)
dat.push_back(0);
dat.insert(dat.end(), ecc.cbegin(), ecc.cend());
blocks.push_back(std::move(dat));
dat.insert(dat.end(), ecc.begin(), ecc.end());
blocks.push_back(dat);
}
// Interleave (not concatenate) the bytes from every block into a single sequence
@ -591,7 +593,7 @@ long QrCode::getPenaltyScore() const {
for (int y = 0; y < size; y++) {
bool runColor = false;
int runX = 0;
std::array<int,7> runHistory = {};
int runHistory[7] = {};
for (int x = 0; x < size; x++) {
if (module(x, y) == runColor) {
runX++;
@ -613,7 +615,7 @@ long QrCode::getPenaltyScore() const {
for (int x = 0; x < size; x++) {
bool runColor = false;
int runY = 0;
std::array<int,7> runHistory = {};
int runHistory[7] = {};
for (int y = 0; y < size; y++) {
if (module(x, y) == runColor) {
runY++;
@ -645,9 +647,9 @@ long QrCode::getPenaltyScore() const {
// Balance of dark and light modules
int dark = 0;
for (const vector<bool> &row : modules) {
for (bool color : row) {
if (color)
for (std::vector<std::vector<bool> >::const_iterator row = modules.begin(); row != modules.end(); ++row) {
for (std::vector<bool>::const_iterator color = row->begin(); color != row->end(); ++color) {
if (*color)
dark++;
}
}
@ -726,8 +728,8 @@ 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> result(divisor.size());
for (uint8_t b : data) { // Polynomial division
uint8_t factor = b ^ result.at(0);
for (vector<uint8_t>::size_type n = 0; n < data.size(); ++n) { // Polynomial division
uint8_t factor = data[n] ^ result.at(0);
result.erase(result.begin());
result.push_back(0);
for (size_t i = 0; i < result.size(); i++)
@ -749,16 +751,16 @@ uint8_t QrCode::reedSolomonMultiply(uint8_t x, uint8_t y) {
}
int QrCode::finderPenaltyCountPatterns(const std::array<int,7> &runHistory) const {
int n = runHistory.at(1);
int QrCode::finderPenaltyCountPatterns(const int runHistory[7]) const {
int n = runHistory[1];
assert(n <= size * 3);
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)
+ (core && runHistory.at(6) >= n * 4 && runHistory.at(0) >= n ? 1 : 0);
bool core = n > 0 && runHistory[2] == n && runHistory[3] == n * 3 && runHistory[4] == n && runHistory[5] == n;
return (core && runHistory[0] >= n * 4 && runHistory[6] >= n ? 1 : 0)
+ (core && runHistory[6] >= n * 4 && runHistory[0] >= n ? 1 : 0);
}
int QrCode::finderPenaltyTerminateAndCount(bool currentRunColor, int currentRunLength, std::array<int,7> &runHistory) const {
int QrCode::finderPenaltyTerminateAndCount(bool currentRunColor, int currentRunLength, int runHistory[7]) const {
if (currentRunColor) { // Terminate dark run
finderPenaltyAddHistory(currentRunLength, runHistory);
currentRunLength = 0;
@ -769,11 +771,11 @@ int QrCode::finderPenaltyTerminateAndCount(bool currentRunColor, int currentRunL
}
void QrCode::finderPenaltyAddHistory(int currentRunLength, std::array<int,7> &runHistory) const {
if (runHistory.at(0) == 0)
void QrCode::finderPenaltyAddHistory(int currentRunLength, int runHistory[7]) const {
if (runHistory[0] == 0)
currentRunLength += size; // Add light border to initial run
std::copy_backward(runHistory.cbegin(), runHistory.cend() - 1, runHistory.end());
runHistory.at(0) = currentRunLength;
std::copy_backward(runHistory, runHistory + 6, runHistory + 7);
runHistory[0] = currentRunLength;
}
@ -820,11 +822,13 @@ BitBuffer::BitBuffer()
: std::vector<bool>() {}
void BitBuffer::appendBits(std::uint32_t val, int len) {
void BitBuffer::appendBits(uint32_t val, int len) {
if (len < 0 || len > 31 || val >> len != 0)
throw std::domain_error("Value out of range");
for (int i = len - 1; i >= 0; i--) // Append bit by bit
this->push_back(((val >> i) & 1) != 0);
}
}

@ -24,14 +24,16 @@
#pragma once
#include <array>
#include <cstdint>
#include <stdexcept>
#include <string>
#include <vector>
typedef char int8_t;
typedef unsigned char uint8_t;
typedef unsigned int size_t;
typedef unsigned int uint32_t;
namespace qrcodegen {
/*
* A segment of character/binary/control data in a QR Code symbol.
* Instances of this class are immutable.
@ -43,14 +45,14 @@ namespace qrcodegen {
* Even in the most favorable conditions, a QR Code can only hold 7089 characters of data.
* Any segment longer than this is meaningless for the purpose of generating QR Codes.
*/
class QrSegment final {
class QrSegment {
/*---- Public helper enumeration ----*/
/*
* Describes how a segment's data bits are interpreted. Immutable.
*/
public: class Mode final {
public: class Mode {
/*-- Constants --*/
@ -99,7 +101,7 @@ class QrSegment final {
* byte mode. All input byte vectors are acceptable. Any text string
* can be converted to UTF-8 bytes and encoded as a byte mode segment.
*/
public: static QrSegment makeBytes(const std::vector<std::uint8_t> &data);
public: static QrSegment makeBytes(const std::vector<uint8_t> &data);
/*
@ -178,7 +180,7 @@ class QrSegment final {
* The character count (numCh) must agree with the mode and the bit buffer length,
* but the constraint isn't checked. The given bit buffer is moved and stored.
*/
public: QrSegment(const Mode &md, int numCh, std::vector<bool> &&dt);
public: QrSegment(const Mode &md, int numCh, std::vector<bool> &dt);
/*---- Methods ----*/
@ -233,14 +235,14 @@ class QrSegment final {
* supply the appropriate version number, and call the QrCode() constructor.
* (Note that all ways require supplying the desired error correction level.)
*/
class QrCode final {
class QrCode {
/*---- Public helper enumeration ----*/
/*
* The error correction level in a QR Code symbol.
*/
public: enum class Ecc {
public: enum Ecc {
LOW = 0 , // The QR Code can tolerate about 7% erroneous codewords
MEDIUM , // The QR Code can tolerate about 15% erroneous codewords
QUARTILE, // The QR Code can tolerate about 25% erroneous codewords
@ -271,7 +273,7 @@ class QrCode final {
* bytes allowed is 2953. The smallest possible QR Code version is automatically chosen for the output.
* The ECC level of the result may be higher than the ecl argument if it can be done without increasing the version.
*/
public: static QrCode encodeBinary(const std::vector<std::uint8_t> &data, Ecc ecl);
public: static QrCode encodeBinary(const std::vector<uint8_t> &data, Ecc ecl);
/*---- Static factory functions (mid level) ----*/
@ -331,7 +333,7 @@ class QrCode final {
* This is a low-level API that most users should not use directly.
* A mid-level API is the encodeSegments() function.
*/
public: QrCode(int ver, Ecc ecl, const std::vector<std::uint8_t> &dataCodewords, int msk);
public: QrCode(int ver, Ecc ecl, const std::vector<uint8_t> &dataCodewords, int msk);
@ -409,12 +411,12 @@ class QrCode final {
// Returns a new byte string representing the given data with the appropriate error correction
// codewords appended to it, based on this object's version and error correction level.
private: std::vector<std::uint8_t> addEccAndInterleave(const std::vector<std::uint8_t> &data) const;
private: std::vector<uint8_t> addEccAndInterleave(const std::vector<uint8_t> &data) const;
// Draws the given sequence of 8-bit codewords (data and error correction) onto the entire
// data area of this QR Code. Function modules need to be marked off before this is called.
private: void drawCodewords(const std::vector<std::uint8_t> &data);
private: void drawCodewords(const std::vector<uint8_t> &data);
// XORs the codeword modules in this QR Code with the given mask pattern.
@ -453,29 +455,29 @@ class QrCode final {
// Returns a Reed-Solomon ECC generator polynomial for the given degree. This could be
// implemented as a lookup table over all possible parameter values, instead of as an algorithm.
private: static std::vector<std::uint8_t> reedSolomonComputeDivisor(int degree);
private: static std::vector<uint8_t> reedSolomonComputeDivisor(int degree);
// Returns the Reed-Solomon error correction codeword for the given data and divisor polynomials.
private: static std::vector<std::uint8_t> reedSolomonComputeRemainder(const std::vector<std::uint8_t> &data, const std::vector<std::uint8_t> &divisor);
private: static std::vector<uint8_t> reedSolomonComputeRemainder(const std::vector<uint8_t> &data, const std::vector<uint8_t> &divisor);
// Returns the product of the two given field elements modulo GF(2^8/0x11D).
// All inputs are valid. This could be implemented as a 256*256 lookup table.
private: static std::uint8_t reedSolomonMultiply(std::uint8_t x, std::uint8_t y);
private: static uint8_t reedSolomonMultiply(uint8_t x, uint8_t y);
// Can only be called immediately after a light run is added, and
// returns either 0, 1, or 2. A helper function for getPenaltyScore().
private: int finderPenaltyCountPatterns(const std::array<int,7> &runHistory) const;
private: int finderPenaltyCountPatterns(const int runHistory[7]) const;
// Must be called at the end of a line (row or column) of modules. A helper function for getPenaltyScore().
private: int finderPenaltyTerminateAndCount(bool currentRunColor, int currentRunLength, std::array<int,7> &runHistory) const;
private: int finderPenaltyTerminateAndCount(bool currentRunColor, int currentRunLength, int runHistory[7]) const;
// Pushes the given value to the front and drops the last value. A helper function for getPenaltyScore().
private: void finderPenaltyAddHistory(int currentRunLength, std::array<int,7> &runHistory) const;
private: void finderPenaltyAddHistory(int currentRunLength, int runHistory[7]) const;
// Returns true iff the i'th bit of x is set to 1.
@ -485,10 +487,10 @@ class QrCode final {
/*---- Constants and tables ----*/
// The minimum version number supported in the QR Code Model 2 standard.
public: static constexpr int MIN_VERSION = 1;
public: static const int MIN_VERSION = 1;
// The maximum version number supported in the QR Code Model 2 standard.
public: static constexpr int MAX_VERSION = 40;
public: static const int MAX_VERSION = 40;
// For use in getPenaltyScore(), when evaluating which mask is best.
@ -498,8 +500,8 @@ class QrCode final {
private: static const int PENALTY_N4;
private: static const std::int8_t ECC_CODEWORDS_PER_BLOCK[4][41];
private: static const std::int8_t NUM_ERROR_CORRECTION_BLOCKS[4][41];
private: static const int8_t ECC_CODEWORDS_PER_BLOCK[4][41];
private: static const int8_t NUM_ERROR_CORRECTION_BLOCKS[4][41];
};
@ -529,7 +531,7 @@ class data_too_long : public std::length_error {
/*
* An appendable sequence of bits (0s and 1s). Mainly used by QrSegment.
*/
class BitBuffer final : public std::vector<bool> {
class BitBuffer : public std::vector<bool> {
/*---- Constructor ----*/
@ -542,7 +544,7 @@ class BitBuffer final : public std::vector<bool> {
// Appends the given number of low-order bits of the given value
// to this buffer. Requires 0 <= len <= 31 and val < 2^len.
public: void appendBits(std::uint32_t val, int len);
public: void appendBits(uint32_t val, int len);
};

Loading…
Cancel
Save