关于二维码打印调用类分析
由于直接调用官方的qrencode库生成二维码,比较麻烦,自写了个二维码调用类,希望大家多多指导/*
微信及一般手机扫描器的支持纠错模式 L和M 高纠错率的汉字的不支持建议使用 L或M模式
字母或数字可以支持高纠错
二维码版本分1-40 基本上1-20够用,本程序支持1-20
M纠错情况下410汉字 666字节 970字母 1600数字
L纠错情况下528汉字 858字节 1249字母 2061数字
版本1是由21X21个方块组成每个版本增加4个方块 版本40由177X177个方块组成
版本1最多可存储25个字符或41个数字版本40可以存储4296个字符或7089个数字
三个位置探测图形是7*7方块 黑框宽度1 内白框宽度1 内部黑矩形3*3
版本信息只有版本7以上才存在
版本2以上需要矫正图形
格式信息,记录使用的掩码和纠错等级
二维码最外边要留一圈空白区,主要是为了便于识别而存在
数据模式(要写到格式信息中)
ECI 0111 特殊字符集要使用对应的特殊的扫描器
数字编码(Numeric) 0001 0-9
字母数字 0010 0-9 大写A-Z(没有小写) 9个其他字符($ % * + - . / : 空格)
8-bit Byte 0100
Kanji 1000 日文编码
Structured Append 0011 混合编码
FUNC1 0101 (First position) 主要给一些特殊的工业或行业使用 如GS1条形码
1001 (Second position)
Terminator(消息结束) 0000
1101 中文 但大多使用日文方式表述中文
Kanji mode这是日文编码,也是双字节编码。同样,也可以用于中文编码。
日文和汉字的编码会减去一个值。如:在0X8140 to 0X9FFC中的字符会减去8140,在0XE040到0XEBBF中的字符要减去0XC140,
然后把结果前两个16进制位拿出来乘以0XC0,然后再加上后两个16进制位,最后转成13bit的编码。
汉字部分的双字节部分GB18030-2000(二维码值只支持双字节汉字 不支持4字节的)
第一字节 0xB0-0xF7 第二字节0xA1-0xFE
0x81-0xA0 0x40-0xFE
0xAA-0xFE 0x40-0xA0
各种版本对应数据位数
数字编码 字母和数字 字节 Kanji
V1-9 10 9 8 8
V10-26 12 11 16 10
V27-40 14 13 16 12
版本10对应的容纳数据个数
纠错级别 数字 字母数字 字节日文汉字
L 652 395 271 167
M 513 311 213 131
Q 364 221 151 93
H 288 174 119 74
用法:
a)直接画在dc上
CQrcode *qrcode = CQrcode::getMinimumQRCode("http://www.csdn.net", ErrorCorrectLevel_H);
qrcode->Draw(pDC, 4, 4);
b)保存为bmp图像:
CQrcode *qrcode = CQrcode::getMinimumQRCode("http://www.csdn.net", ErrorCorrectLevel_H);
qrcode->SaveToBmp("c:\\csdn.bmp", 4, 4);
*/
https://static.52pojie.cn/static/image/hrline/1.gif
//qrcode.h:
//二维码产生头文件
class CQrcodeBitBuffer
{
public:
void put(BOOL bit);
void put(int num, int length);
BOOL get(int index);
CString toString();
int getLengthInBits();
BYTE* getBuffer();
CQrcodeBitBuffer();
virtual ~CQrcodeBitBuffer();
private:
BYTE *buffer;
int buffer_len;
int length;
int inclements;
};
//多项式
class CQrcodePolynomial
{
public:
CQrcodePolynomial mod(CQrcodePolynomial &e);
CQrcodePolynomial multiply(CQrcodePolynomial &e);
CString toLogString();
CString toString();
int getLength();
int get(int idx);
//
CQrcodePolynomial(CUIntArray& nums, int shift);
CQrcodePolynomial(const CQrcodePolynomial &p);
CQrcodePolynomial& operator=(const CQrcodePolynomial &p);
virtual ~CQrcodePolynomial();
CUIntArray m_nums;
};
class CQrcodeUtil
{
public:
static int unsignedRightShift(int v, int n);
static int getBCHTypeNumber(int data);
static int getBCHTypeInfo(int data);
static int getBCHDigit(int data);
static BOOL isHanZi(CString s);
static BOOL isAlphaNum(CString s);
static BOOL isNumber(CString s);
static int getMode(CString s);
static BOOL getMask(int maskPattern, int i, int j);
static CQrcodePolynomial getErrorCorrectPolynomial(int errorCorrectLength);
static void getPatternPosition(int typeNumber, CUIntArray &p);
static int getMaxLength(int typeNumber, int mode, int errorCorrectLevel);
CQrcodeUtil();
virtual ~CQrcodeUtil();
};
class CQrcodeMath
{
public:
int gexp(int n);
int glog(int n);
static CQrcodeMath * getInstance();
CQrcodeMath();
virtual ~CQrcodeMath();
private:
CUIntArray EXP_TABLE;
CUIntArray LOG_TABLE;
};
class CQrcodeData: public CObject
{
public:
int getLengthInBits(int type);
virtual void write(CQrcodeBitBuffer &buffer);
virtual int getLength();
int getMode();
CQrcodeData(int mode, CString data);
virtual ~CQrcodeData();
CString data;
private:
int mode;
};
class CQrcodeNumber : public CQrcodeData
{
public:
virtual void write(CQrcodeBitBuffer &buffer);
int parseInt(CString s);
CQrcodeNumber(CString data);
virtual ~CQrcodeNumber();
};
class CQrcodeAlphaNum : public CQrcodeData
{
public:
int getCode(char c);
virtual void write(CQrcodeBitBuffer &buffer);
CQrcodeAlphaNum(CString data);
virtual ~CQrcodeAlphaNum();
};
class CQrcodeHanzi : public CQrcodeData
{
public:
virtual void write(CQrcodeBitBuffer &buffer);
virtual int getLength();
CQrcodeHanzi(CString data);
virtual ~CQrcodeHanzi();
};
class CQrcode8BitByte : public CQrcodeData
{
public:
virtual void write(CQrcodeBitBuffer &buffer);
CQrcode8BitByte(CString data);
virtual ~CQrcode8BitByte();
};
class CQrcode2DIntArray
{
public:
CUIntArray * GetIntArray(int r);
int GetAt(int r,int c);
void SetAt(int r,int c,int v);
CQrcode2DIntArray();
virtual ~CQrcode2DIntArray();
private:
CObArray a;
};
class CQrcodeRSBlock: public CObject
{
public:
CQrcodeRSBlock(int totalCount, int dataCount);
virtual ~CQrcodeRSBlock();
int getDataCount();
int getTotalCount();
static void getRsBlockTable(int typeNumber, int errorCorrectLevel, CUIntArray &a);
static void getRSBlocks(int typeNumber, int errorCorrectLevel, CObArray &RBSlocks);
private:
int totalCount;
int dataCount;
};
class CQrcode
{
public:
void SaveToBmp(CString filename, int cellSize, int margin);
void Draw(CDC *pdc,int cellSize, int margin);
static CQrcode* getMinimumQRCode(CString data, int errorCorrectLevel,int *errcode);//添加错误代码 liu
void mapData(BYTE* bytes,int bytes_size, int maskPattern);
static BYTE* createData(int typeNumber, int errorCorrectLevel, CObArray &dataArray, int* bytesSize);
static BYTE* createBytes(CQrcodeBitBuffer &buffer, CObArray &rsBlocks, int* bytesSize);
void setupTypeNumber(BOOL test);
void setupTypeInfo(BOOL test, int maskPattern);
void setupTimingPattern();
void setupPositionAdjustPattern();
void setupPositionProbePattern(int row, int col);
static int getLostPoint(CQrcode *qrcode);
int getBestMaskPattern();
void make();
void make(BOOL test, int maskPattern);
int getModuleCount();
BOOL isDark(int row, int col);
CQrcodeData * getData(int index);
int getDataCount();
void clearData();
void addData(CString data, int mode);
void addData(CString data);
void setErrorCorrectLevel(int errorCorrectLevel);
void setTypeNumber(int typeNumber);
CQrcode();
virtual ~CQrcode();
private:
BYTE *modules;
int moduleCount;
int typeNumber;
int errorCorrectLevel;
CObArray qrDataList;
};
//纠错码
#define ErrorCorrectLevel_L1 //7%的字码可修正
#define ErrorCorrectLevel_M0 //15%
#define ErrorCorrectLevel_Q3 //25%
#define ErrorCorrectLevel_H2 //30%
https://static.52pojie.cn/static/image/hrline/3.gif
cpp源文件
#include "StdAfx.h"
#include "qrcode.h"
#define MODE_NUMBER(1<<0)
#define MODE_ALPHA_NUM (1<<1)
#define MODE_8BIT_BYTE (1<<2)
#define MODE_HANZI (1<<3)//13也可以
#define PATTERN000 0
#define PATTERN001 1
#define PATTERN010 2
#define PATTERN011 3
#define PATTERN100 4
#define PATTERN101 5
#define PATTERN110 6
#define PATTERN111 7
#define PAD0 0xEC //补齐码
#define PAD1 0x11 //补齐码
#define G15 ((1<<10)|(1<<8)|(1<<5)|(1<<4)|(1<<2)|(1<<1)|(1<<0))
#define G18 ((1<<12)|(1<<11)|(1<<10)|(1<<9)|(1<<8)|(1<<5)|(1<<2)|(1<<0))
#define G15_MASK ((1<<14)|(1<<12)|(1<<10)|(1<<4)|(1<<1))
//20个版本 纠错码特性表
int RS_BLOCK_TABLE= {
// L =1
// M =0
// Q =3
// H =2
// 1
{1, 26, 19,0,0,0},//L
{1, 26, 16,0,0,0},//M
{1, 26, 13,0,0,0},//Q
{1, 26, 9,0,0,0}, //H
// 2
{1, 44, 34,0,0,0},
{1, 44, 28,0,0,0},
{1, 44, 22,0,0,0},
{1, 44, 16,0,0,0},
// 3
{1, 70, 55,0,0,0},
{1, 70, 44,0,0,0},
{2, 35, 17,0,0,0},
{2, 35, 13,0,0,0},
// 4
{1, 100, 80,0,0,0},
{2, 50, 32,0,0,0},
{2, 50, 24,0,0,0},
{4, 25, 9,0,0,0},
// 5
{1, 134, 108,0,0,0},
{2, 67, 43,0,0,0},
{2, 33, 15, 2, 34, 16},
{2, 33, 11, 2, 34, 12},
// 6
{2, 86, 68,0,0,0},
{4, 43, 27,0,0,0},
{4, 43, 19,0,0,0},
{4, 43, 15,0,0,0},
// 7
{2, 98, 78,0,0,0},
{4, 49, 31,0,0,0},
{2, 32, 14, 4, 33, 15},
{4, 39, 13, 1, 40, 14},
// 8
{2, 121, 97,0,0,0},
{2, 60, 38, 2, 61, 39},
{4, 40, 18, 2, 41, 19},
{4, 40, 14, 2, 41, 15},
// 9
{2, 146, 116,0,0,0},
{3, 58, 36, 2, 59, 37},
{4, 36, 16, 4, 37, 17},
{4, 36, 12, 4, 37, 13},
// 10
{2, 86, 68, 2, 87, 69},
{4, 69, 43, 1, 70, 44},
{6, 43, 19, 2, 44, 20},
{6, 43, 15, 2, 44, 16},
//------------------------
//11
{4, 101, 81, 0, 0, 0},
{1, 80, 50, 4, 81, 51},
{4, 50, 22, 4, 51, 23},
{3, 36, 12, 8, 37, 13},
//12
{2, 116, 92, 2, 117, 93},//L
{6, 58, 36, 2, 59, 37},//M
{4, 46, 20, 6, 47, 21},//Q
{7, 42, 14, 4, 43, 15},//H
//13
{4, 133, 107, 0, 0, 0},
{8, 59, 37, 1, 60, 38},
{8, 44, 20, 4, 45, 21},
{12, 33, 11, 4, 34, 12},
//14
{3, 145, 115, 1, 146, 116},
{4, 64, 40, 5, 65, 41},
{11, 36, 16, 5, 37, 17},
{11, 36, 12, 5, 37, 13},
//15
{5, 109, 87, 1, 110, 88},
{5, 65, 41, 5, 66, 42},
{5, 54, 24, 7, 55, 25},
{11, 36, 12, 7, 37, 13},
//16
{5, 122, 98, 1, 123, 99},
{7, 73, 45, 3, 74, 46},
{15, 43, 19, 2, 44, 20},
{3, 45, 15, 13, 46, 16},
//17
{1, 135, 107, 5, 136, 108},
{10, 74, 46, 1, 75, 47},
{1, 50, 22, 15, 51, 23},
{2, 42, 14, 17, 43, 15},
//18
{5, 150, 120, 1, 151, 121},
{9, 69, 43, 4, 70, 44},
{17, 50, 22, 1, 51, 23},
{2, 42, 14, 19, 43, 15},
//19
{3, 141, 113, 4, 142, 114},
{3, 70, 44, 11, 71, 45},
{17, 47, 21, 4, 48, 22},
{9, 39, 13, 16, 40, 14},
//20
{3, 135, 107, 5, 136, 108},
{3, 67, 41, 13, 68, 42},
{15, 54, 24, 5, 55, 25},
{15, 43, 15, 10, 44, 16}
};
int PATTERN_POSITION_TABLE ={
{0,0,0,0,0,0,0},
{6, 18,0,0,0,0,0},
{6, 22,0,0,0,0,0},
{6, 26,0,0,0,0,0},
{6, 30,0,0,0,0,0},
{6, 34,0,0,0,0,0},
{6, 22, 38,0,0,0,0},
{6, 24, 42,0,0,0,0},
{6, 26, 46,0,0,0,0},
{6, 28, 50,0,0,0,0},
{6, 30, 54,0,0,0,0},
{6, 32, 58,0,0,0,0},
{6, 34, 62,0,0,0,0},
{6, 26, 46, 66,0,0,0},
{6, 26, 48, 70,0,0,0},
{6, 26, 50, 74,0,0,0},
{6, 30, 54, 78,0,0,0},
{6, 30, 56, 82,0,0,0},
{6, 30, 58, 86,0,0,0},
{6, 34, 62, 90,0,0,0},
{6, 28, 50, 72, 94,0,0},
{6, 26, 50, 74, 98,0,0},
{6, 30, 54, 78, 102,0,0},
{6, 28, 54, 80, 106,0,0},
{6, 32, 58, 84, 110,0,0},
{6, 30, 58, 86, 114,0,0},
{6, 34, 62, 90, 118,0,0},
{6, 26, 50, 74, 98, 122,0},
{6, 30, 54, 78, 102, 126,0},
{6, 26, 52, 78, 104, 130,0},
{6, 30, 56, 82, 108, 134,0},
{6, 34, 60, 86, 112, 138,0},
{6, 30, 58, 86, 114, 142,0},
{6, 34, 62, 90, 118, 146,0},
{6, 30, 54, 78, 102, 126, 150},
{6, 24, 50, 76, 102, 128, 154},
{6, 28, 54, 80, 106, 132, 158},
{6, 32, 58, 84, 110, 136, 162},
{6, 26, 54, 82, 110, 138, 166},
{6, 30, 58, 86, 114, 142, 170}
};
//获取各种编码版本对应的各种模式编码的数据容量表
//[版本] [模式] [纠错级别]
int MAX_LENGTH = {
//L N A 8BHan M Q H
{ {41,25,17,10},{34,20,14,8}, {27,16,11,7},{17,10,7, 4} },
{ {77,47,32,20},{63,38,26,16},{48,29,20,12}, {34,20,14,8} },
{ {127, 77,53,32},{101, 61,42,26},{77,47,32,20}, {58,35,24,15} },
{ {187, 114, 78,48},{149, 90,62,38},{111, 67,46,28}, {82,50,34,21} },
{ {255, 154, 106, 65},{202, 122, 84,52},{144, 87,60,37}, {106, 64,44,27} },
{ {322, 195, 134, 82},{255, 154, 106, 65},{178, 108, 74,45}, {139, 84,58,36} },
{ {370, 224, 154, 95},{293, 178, 122, 75},{207, 125, 86,53}, {154, 93,64,39} },
{ {461, 279, 192, 118}, {365, 221, 152, 93},{259, 157, 108, 66}, {202, 122, 84,52} },
{ {552, 335, 230, 141}, {432, 262, 180, 111}, {312, 189, 130, 80}, {235, 143, 98,60} },
{ {652, 395, 271, 167}, {513, 311, 213, 131}, {364, 221, 151, 93}, {288, 174, 119, 74} },//10
{ {772, 468, 321, 198}, {604, 366, 251, 155}, {427, 259, 177, 109}, {331, 200, 137, 85} },
{ {883, 535, 367, 226}, {691, 419, 287, 177}, {489, 296, 203, 125}, {374, 227, 155, 96} },
{ {1022, 619, 425, 262}, {796, 483, 331, 204}, {580, 352, 241, 149}, {427, 259, 177, 109} },
{ {1101, 667, 458, 282}, {871, 528, 362, 223}, {621, 376, 258, 159}, {468, 283, 194, 120} },
{ {1250, 758, 520, 320}, {991, 600, 412, 254}, {703, 426, 292, 180}, {530, 321, 220, 136} },//15
{ {1408, 854, 586, 361}, {1082, 656, 450, 277}, {775, 470, 322, 198}, {602, 365, 250, 154} },
{ {1548, 938, 644, 397}, {1212, 734, 504, 310}, {876, 531, 364, 224}, {674, 408, 280, 173} },
{ {1725, 1046, 718, 442}, {1346, 816, 560, 345}, {948, 574, 394, 243}, {746, 452, 310, 191} },//18
{ {1903, 1153, 792, 488}, {1500, 909, 624, 384}, {1063, 644, 442, 272}, {813, 493, 338, 208} },
{ {2061, 1249, 858, 528}, {1600,970, 666, 410}, {1159, 702, 482, 297}, {919, 557, 382, 235} }
};
//---------------------
CQrcodeBitBuffer::CQrcodeBitBuffer()
{
inclements = 32;
buffer = (BYTE*)malloc(inclements);
memset(buffer, 0, inclements);
buffer_len = inclements;
length = 0;
}
CQrcodeBitBuffer::~CQrcodeBitBuffer()
{
// TRACE1("buffer_len=%d\r\n",buffer_len);
free(buffer);
}
BYTE* CQrcodeBitBuffer::getBuffer()
{
return buffer;
}
int CQrcodeBitBuffer::getLengthInBits()
{
return length;
}
CString CQrcodeBitBuffer::toString()
{
CString s;
for (int i = 0; i < getLengthInBits(); i++) {
s += get(i) ? "1" : "0";
}
return s;
}
BOOL CQrcodeBitBuffer::get(int index)
{
int n = CQrcodeUtil::unsignedRightShift(buffer, 7 - index % 8);
return (n&1) == 1;
}
void CQrcodeBitBuffer::put(int num, int length)
{
int t;
for (int i = 0; i < length; i++) {
t = CQrcodeUtil::unsignedRightShift(num, length-i-1);
put((t & 1) == 1);
}
}
void CQrcodeBitBuffer::put(BOOL bit)
{
if (length == buffer_len * 8) {
BYTE* newBuffer = (BYTE*)malloc(buffer_len + inclements);
memset(newBuffer, 0, buffer_len + inclements);
memcpy(newBuffer, buffer, buffer_len);
free(buffer);
buffer = newBuffer;
buffer_len += inclements;
}
if (bit) {
buffer |= CQrcodeUtil::unsignedRightShift(0x80, length % 8);
}
length++;
}
//---------------------------------------
CQrcodeUtil::CQrcodeUtil()
{
}
CQrcodeUtil::~CQrcodeUtil()
{
}
void CQrcodeUtil::getPatternPosition(int typeNumber, CUIntArray &p)
{
int *pp = PATTERN_POSITION_TABLE;
for(int i=0;i<7;i++)
{
if (pp == 0) break;
p.Add(pp);
}
}
//typeNumer 编码版本(1-40) mode 模式 errorCorrectLevel纠错级别 (0-3)
int CQrcodeUtil::getMaxLength(int typeNumber, int mode, int errorCorrectLevel)
{
int t = typeNumber - 1;
int e = 0;
int m = 0;
switch(errorCorrectLevel) {
case ErrorCorrectLevel_L : e = 0; break;
case ErrorCorrectLevel_M : e = 1; break;
case ErrorCorrectLevel_Q : e = 2; break;
case ErrorCorrectLevel_H : e = 3; break;
default :
return 0;
}
switch(mode) {
case MODE_NUMBER : m = 0; break;
case MODE_ALPHA_NUM : m = 1; break;
case MODE_8BIT_BYTE : m = 2; break;
case MODE_HANZI : m = 3; break;
default :
return 0;
}
return MAX_LENGTH;
}
CQrcodePolynomial CQrcodeUtil::getErrorCorrectPolynomial(int errorCorrectLength)
{
CUIntArray tnums;
tnums.Add(1);
CQrcodePolynomial a(tnums,0);
CQrcodeMath *qrmath = CQrcodeMath::getInstance();
for (int i = 0; i < errorCorrectLength; i++) {
tnums.RemoveAll();
tnums.Add(1);
tnums.Add(qrmath->gexp(i));
CQrcodePolynomial b(tnums,0);
a = a.multiply(b);
}
return a;
}
BOOL CQrcodeUtil::getMask(int maskPattern, int i, int j)
{
switch (maskPattern) {
case PATTERN000 : return (i + j) % 2 == 0;
case PATTERN001 : return i % 2 == 0;
case PATTERN010 : return j % 3 == 0;
case PATTERN011 : return (i + j) % 3 == 0;
case PATTERN100 : return (i / 2 + j / 3) % 2 == 0;
case PATTERN101 : return (i * j) % 2 + (i * j) % 3 == 0;
case PATTERN110 : return ( (i * j) % 2 + (i * j) % 3) % 2 == 0;
case PATTERN111 : return ( (i * j) % 3 + (i + j) % 2) % 2 == 0;
default :
return FALSE;
}
return FALSE;
}
int CQrcodeUtil::getMode(CString s)
{
if (isAlphaNum(s) ) {
if (isNumber(s) ) {
// TRACE("数字模式\r\n");
return MODE_NUMBER;
}
//TRACE("数字字母混合\r\n");
return MODE_ALPHA_NUM;
} else if (isHanZi(s) ) {
// TRACE("汉字模式\r\n");
return MODE_HANZI;
} else {
// TRACE("字节模式\r\n");
return MODE_8BIT_BYTE;
}
}
BOOL CQrcodeUtil::isNumber(CString s)
{
char c;
int i=0;
for ( i = 0; i < s.GetLength(); i++) {
c = s.GetAt(i);
if (!('0' <= c && c <= '9') ) {
return FALSE;
}
}
return TRUE;
}
BOOL CQrcodeUtil::isAlphaNum(CString s)
{
CString othersAlpha = " $%*+-./:";
char c;
for (int i = 0; i < s.GetLength(); i++) {
c = s.GetAt(i);
if (!('0' <= c && c <= '9') && !('A' <= c && c <= 'Z') && othersAlpha.Find(c) == -1) return FALSE;
}
return TRUE;
}
BOOL CQrcodeUtil::isHanZi(CString s)
{
//byte[] data = s.getBytes(QRUtil.getJISEncoding() );
int i = 0;
int dLen = s.GetLength();
while (i + 1 < dLen)
{
int c = ( (0xff & s) << 8) | (0xff & s);
if (!(0x8140 <= c && c <= 0x9FFC) && !(0xE040 <= c && c <= 0xEBBF) )return FALSE;
// if (!(0x8140 <= c && c <= 0xFEFE))return FALSE;
i += 2;
}
if (i < dLen) {
return FALSE;
}
return TRUE;
}
int CQrcodeUtil::getBCHDigit(int data)
{
int digit = 0;
while (data != 0) {
digit++;
data = unsignedRightShift(data, 1);//data >>>= 1;
}
return digit;
}
int CQrcodeUtil::getBCHTypeInfo(int data)
{
int d = data << 10;
while (getBCHDigit(d) - getBCHDigit(G15) >= 0) {
d ^= (G15 << (getBCHDigit(d) - getBCHDigit(G15) ) );
}
return ( (data << 10) | d) ^ G15_MASK;
}
int CQrcodeUtil::getBCHTypeNumber(int data)
{
int d = data << 12;
while (getBCHDigit(d) - getBCHDigit(G18) >= 0) {
d ^= (G18 << (getBCHDigit(d) - getBCHDigit(G18) ) );
}
return (data << 12) | d;
}
//
//无符号右移运算符>>> 针对8byte应该没问题
int CQrcodeUtil::unsignedRightShift(int v, int n)
{
int t = v >> n;
return t & 0x7FFFFFF;
}
//-----------------------------------------
CQrcodePolynomial::CQrcodePolynomial(const CQrcodePolynomial &p)
{
if(this == &p)return;
m_nums.RemoveAll();
for(int i=0;i<p.m_nums.GetSize();i++) m_nums.Add(p.m_nums.GetAt(i));
}
CQrcodePolynomial& CQrcodePolynomial::operator=(const CQrcodePolynomial &p)
{
if(this == &p)return *this;
m_nums.RemoveAll();
for(int i=0;i<p.m_nums.GetSize();i++) m_nums.Add(p.m_nums.GetAt(i));
return *this;
}
//
CQrcodePolynomial::CQrcodePolynomial(CUIntArray& nums, int shift)
{
int length = nums.GetSize();
int offset = 0;
while (offset < length && nums == 0) {
offset++;
}
int i;
//this.num = new int;
m_nums.RemoveAll();
for ( i=0;i<length - offset + shift;i++) m_nums.Add(0);
//System.arraycopy(num, offset, this.num, 0, num.length - offset);
for ( i=offset;i<length;i++) m_nums = nums;
}
CQrcodePolynomial::~CQrcodePolynomial()
{
m_nums.RemoveAll(); //liu add
}
int CQrcodePolynomial::get(int idx)
{
return m_nums;
}
int CQrcodePolynomial::getLength()
{
return m_nums.GetSize();
}
CString CQrcodePolynomial::toString()
{
CString s,t;
for (int i = 0; i < getLength(); i++) {
if (i > 0) {
s += ",";
}
t.Format("%d", get(i) );
s += t;
}
return s;
}
CString CQrcodePolynomial::toLogString()
{
CString s,t;
CQrcodeMath *qrmath = CQrcodeMath::getInstance();
for (int i = 0; i < getLength(); i++) {
if (i > 0) {
s += ",";
}
t.Format("%d", qrmath->glog(get(i)) ); //QRMath.glog(get(i) )
s += t;
}
return s;
}
CQrcodePolynomial CQrcodePolynomial::multiply(CQrcodePolynomial &e)
{
CUIntArray tnums;
int i;
for( i=0;i<getLength() + e.getLength() - 1;i++)
{
tnums.Add(0);
}
CQrcodeMath *qrmath = CQrcodeMath::getInstance();
for ( i = 0; i < getLength(); i++) {
for (int j = 0; j < e.getLength(); j++) {
tnums ^= qrmath->gexp(qrmath->glog(get(i) ) + qrmath->glog(e.get(j) ) );
}
}
return CQrcodePolynomial(tnums,0);
}
CQrcodePolynomial CQrcodePolynomial::mod(CQrcodePolynomial &e)
{
if (getLength() - e.getLength() < 0) {
return (*this);
}
CQrcodeMath *qrmath = CQrcodeMath::getInstance();
//
int ratio = qrmath->glog(get(0));
ratio -= qrmath->glog(e.get(0));
//
//int[] num = new int;
CUIntArray tnums;
int i;
for(i=0;i<getLength();i++) tnums.Add(0);
for ( i = 0; i < getLength(); i++) {
tnums = get(i);
}
//
for ( i = 0; i < e.getLength(); i++) {
tnums ^= qrmath->gexp(qrmath->glog(e.get(i)) + ratio);
}
//
CQrcodePolynomial pt(tnums,0);
return pt.mod(e);
}
//-----------------------------------------------------
CQrcodeMath *pQrmath = NULL;
CQrcodeMath::CQrcodeMath()
{
int i;
for ( i = 0; i < 256; i++) EXP_TABLE.Add(0);
for ( i = 0; i < 8; i++) {
EXP_TABLE = 1 << i;
}
for ( i = 8; i < 256; i++) EXP_TABLE =EXP_TABLE^ EXP_TABLE^ EXP_TABLE^ EXP_TABLE;
for ( i = 0; i < 256; i++)LOG_TABLE.Add(0);
for ( i = 0; i < 255; i++)LOG_TABLE] = i;
}
CQrcodeMath::~CQrcodeMath()
{
if(pQrmath!=NULL) delete pQrmath;//liu add
}
CQrcodeMath * CQrcodeMath::getInstance()
{
if (pQrmath!=NULL){
return pQrmath;
}
pQrmath = new CQrcodeMath();
return pQrmath;
}
int CQrcodeMath::glog(int n)
{
if (n < 1) {
return 0;
}
return LOG_TABLE;
}
int CQrcodeMath::gexp(int n)
{
while (n < 0) {
n += 255;
}
while (n >= 256) {
n -= 255;
}
return EXP_TABLE;
}
//---------------------------------------------------
CQrcodeRSBlock::CQrcodeRSBlock(int totalCount, int dataCount)
{
this->totalCount = totalCount;
this->dataCount= dataCount;
}
CQrcodeRSBlock::~CQrcodeRSBlock()
{
}
void CQrcodeRSBlock::getRsBlockTable(int typeNumber, int errorCorrectLevel, CUIntArray &a)
{
int *p = NULL;
switch(errorCorrectLevel) {
case ErrorCorrectLevel_L :
p = RS_BLOCK_TABLE[(typeNumber - 1) * 4 + 0];
break;
case ErrorCorrectLevel_M :
p =RS_BLOCK_TABLE[(typeNumber - 1) * 4 + 1];
break;
case ErrorCorrectLevel_Q :
p =RS_BLOCK_TABLE[(typeNumber - 1) * 4 + 2];
break;
case ErrorCorrectLevel_H :
p = RS_BLOCK_TABLE[(typeNumber - 1) * 4 + 3];
default :
break;
}
if (p!=NULL){
for (int i=0;i<6;i++){
if (p == 0) break;
a.Add(p);
}
}
}
void CQrcodeRSBlock::getRSBlocks(int typeNumber, int errorCorrectLevel, CObArray &RBSlocks)
{
CUIntArray rsBlock;
getRsBlockTable(typeNumber, errorCorrectLevel, rsBlock);
int length = rsBlock.GetSize() / 3;
//
for (int i = 0; i < length; i++) {
int count = rsBlock;
int totalCount = rsBlock;
int dataCount= rsBlock;
for (int j = 0; j < count; j++) {
RBSlocks.Add(new CQrcodeRSBlock(totalCount, dataCount) );
}
}
}
int CQrcodeRSBlock::getDataCount() {
return dataCount;
}
int CQrcodeRSBlock::getTotalCount() {
return totalCount;
}
//----------------------------------------------
CQrcode2DIntArray::CQrcode2DIntArray()
{
}
CQrcode2DIntArray::~CQrcode2DIntArray()
{
//liu add
//TRACE1("~CQrcode2DIntArray size=%d\r\n",a.GetSize());
/* 基本型数据不需要释放
if(a.GetSize()>0)
{
int i;
for(i=0;i<a.GetSize();i++)
delete a.GetAt(i);
a.RemoveAll();
}
*/
}
void CQrcode2DIntArray::SetAt(int r, int c, int v)
{
for(int i=a.GetSize()-1;i<r;i++) a.Add(new CUIntArray());
CUIntArray *p = (CUIntArray*) a.GetAt(r);
for(int j=p->GetSize()-1;j<c;j++) p->Add(0);
p->SetAt(c, v);
}
int CQrcode2DIntArray::GetAt(int r, int c)
{
CUIntArray *p = (CUIntArray*) a.GetAt(r);
return p->GetAt(c);
}
CUIntArray * CQrcode2DIntArray::GetIntArray(int r)
{
return (CUIntArray*) a.GetAt(r);
}
//------------------------------------------------
CQrcode8BitByte::CQrcode8BitByte(CString data) : CQrcodeData(MODE_8BIT_BYTE, data)
{
}
CQrcode8BitByte::~CQrcode8BitByte()
{
}
void CQrcode8BitByte::write(CQrcodeBitBuffer &buffer)
{
for (int i = 0; i < data.GetLength(); i++) {
buffer.put(data, 8);
}
}
CQrcodeAlphaNum::CQrcodeAlphaNum(CString data) : CQrcodeData(MODE_ALPHA_NUM, data)
{
}
CQrcodeAlphaNum::~CQrcodeAlphaNum()
{
}
void CQrcodeAlphaNum::write(CQrcodeBitBuffer &buffer)
{
int i = 0;
int len = data.GetLength();
while (i + 1 < len) {
buffer.put(getCode(data) * 45 + getCode(data), 11);
i += 2;
}
if (i < len) {
buffer.put(getCode(data), 6);
}
}
int CQrcodeAlphaNum::getCode(char c)
{
if ('0' <= c && c <= '9') {
return c - '0';
} else if ('A' <= c && c <= 'Z') {
return c - 'A' + 10;
} else {
switch (c) {
case ' ' : return 36;
case '$' : return 37;
case '%' : return 38;
case '*' : return 39;
case '+' : return 40;
case '-' : return 41;
case '.' : return 42;
case '/' : return 43;
case ':' : return 44;
default :
return 36;
}
}
}
//---------------------------------------
CQrcodeData::CQrcodeData(int mode, CString data)
{
this->mode = mode;
this->data = data;
}
CQrcodeData::~CQrcodeData()
{
}
int CQrcodeData::getMode()
{
return mode;
}
int CQrcodeData::getLength()
{
return data.GetLength();
}
void CQrcodeData::write(CQrcodeBitBuffer &buffer)
{
}
int CQrcodeData::getLengthInBits(int type)
{
if (1 <= type && type < 10) {
// 1 - 9
switch(mode) {
case MODE_NUMBER : return 10;
case MODE_ALPHA_NUM: return 9;
case MODE_8BIT_BYTE : return 8;
case MODE_HANZI : return 8;
default :
return 8;
}
} else if (type < 27) {
// 10 - 26
switch(mode) {
case MODE_NUMBER : return 12;
case MODE_ALPHA_NUM: return 11;
case MODE_8BIT_BYTE : return 16;
case MODE_HANZI : return 10;
default :
return 10;
}
} else if (type < 41) {
// 27 - 40
switch(mode) {
case MODE_NUMBER : return 14;
case MODE_ALPHA_NUM : return 13;
case MODE_8BIT_BYTE : return 16;
case MODE_HANZI : return 12;
default :
return 12;
}
} else {
return 8;
}
}
//----------------------------------------------
CQrcodeHanzi::CQrcodeHanzi(CString data) : CQrcodeData(MODE_HANZI, data)
{
}
CQrcodeHanzi::~CQrcodeHanzi()
{
}
int CQrcodeHanzi::getLength()
{
return data.GetLength()/2;
}
void CQrcodeHanzi::write(CQrcodeBitBuffer &buffer)
{
int dlen = data.GetLength();
int i = 0;
while (i + 1 < dlen) {
int c = ( (0xff & data) << 8) | (0xff & data);
if (0x8140 <= c && c <= 0x9FFC) {
c -= 0x8140;
} else if (0xE040 <= c && c <= 0xEBBF) {
c -= 0xC140;
} else {
i += 2;
continue;
}
c = ( CQrcodeUtil::unsignedRightShift(c, 8) & 0xff) * 0xC0 + (c & 0xff);
buffer.put(c, 13);
i += 2;
}
if (i < dlen) {
}
}
//---------------------------------------
CQrcodeNumber::CQrcodeNumber(CString data) : CQrcodeData(MODE_NUMBER, data)
{
}
CQrcodeNumber::~CQrcodeNumber()
{
}
int CQrcodeNumber::parseInt(CString s)
{
int num = 0;
for (int i = 0; i < s.GetLength(); i++) {
num = num * 10 + (s.GetAt(i) - '0');
}
//CString ss;ss.Format("%d",num);AfxMessageBox(ss);
return num;
}
void CQrcodeNumber::write(CQrcodeBitBuffer &buffer)
{
int i = 0;
int dataLen = data.GetLength();
int num;
while (i + 2 < dataLen) {
num = parseInt(data.Mid(i, 3));//数字类型的数据,每三位数 变成一个10位的二进制,如果256变成 0010000000
buffer.put(num, 10);
i += 3;
}
if (i < dataLen ) {
if (dataLen - i == 1) {
num = parseInt(data.Mid(i, 1));
buffer.put(num, 4);
} else if (dataLen - i == 2) {
num = parseInt(data.Mid(i, 2));
buffer.put(num, 7);
}
}
}
//---------------------------------------------
CQrcode::CQrcode()
{
modules = NULL;
typeNumber = 1;
errorCorrectLevel = ErrorCorrectLevel_L;
}
CQrcode::~CQrcode()
{
// TRACE("析构CQrcode\r\n");
clearData();
}
void CQrcode::setTypeNumber(int typeNumber)
{
this->typeNumber = typeNumber;
}
void CQrcode::setErrorCorrectLevel(int errorCorrectLevel)
{
this->errorCorrectLevel = errorCorrectLevel;
}
void CQrcode::addData(CString data)
{
addData(data, CQrcodeUtil::getMode(data) );
}
void CQrcode::addData(CString data, int mode)
{
switch(mode) {
case MODE_NUMBER :
qrDataList.Add(new CQrcodeNumber(data) );
break;
case MODE_ALPHA_NUM :
qrDataList.Add(new CQrcodeAlphaNum(data) );
break;
case MODE_8BIT_BYTE :
qrDataList.Add(new CQrcode8BitByte(data) );
break;
case MODE_HANZI :
qrDataList.Add(new CQrcodeHanzi(data) );
break;
default :
;
}
}
void CQrcode::clearData()
{
int iNum=qrDataList.GetSize();
for(int i=0;i<iNum;i++){
delete qrDataList.GetAt(i);
}
qrDataList.RemoveAll();
if(modules!=NULL)//liu add
free(modules);
}
int CQrcode::getDataCount()
{
return qrDataList.GetSize();
}
CQrcodeData * CQrcode::getData(int index)
{
return (CQrcodeData*) qrDataList.GetAt(index);
}
BOOL CQrcode::isDark(int row, int col)
{
if (modules != 0 ) {
return (modules == 1) ? TRUE : FALSE; //1==true 2==false
} else {
return FALSE;
}
return TRUE;
}
int CQrcode::getModuleCount()
{
return moduleCount;
}
void CQrcode::make(BOOL test, int maskPattern)
{
//二维码方框像数大小
moduleCount = typeNumber * 4 + 17;
//modules = new Boolean;
modules = (BYTE*)malloc(moduleCount*moduleCount);
memset(modules, 0, moduleCount*moduleCount);
//
setupPositionProbePattern(0, 0);
setupPositionProbePattern(moduleCount - 7, 0);
setupPositionProbePattern(0, moduleCount - 7);
setupPositionAdjustPattern();
setupTimingPattern();
setupTypeInfo(test, maskPattern);
if (typeNumber >= 7) {
setupTypeNumber(test);
}
//QRData[] dataArray = (QRData[])qrDataList.toArray(new QRData);
//byte[] data = createData(typeNumber, errorCorrectLevel, dataArray);
//mapData(data, maskPattern);
int bytes_len = 0;
BYTE* bytes = createData(typeNumber, errorCorrectLevel, qrDataList, &bytes_len);
mapData(bytes, bytes_len, maskPattern);
//bytes怎么没有释放?liu
if(bytes!=NULL) //added by liu
free(bytes);
}
void CQrcode::make()
{
make(FALSE, getBestMaskPattern() );
}
int CQrcode::getBestMaskPattern()
{
int minLostPoint = 0;
int pattern = 0;
for (int i = 0; i < 8; i++) {
make(true, i);
int lostPoint = getLostPoint(this);
if (i == 0 || minLostPoint >lostPoint) {
minLostPoint = lostPoint;
pattern = i;
}
}
return pattern;
}
int CQrcode::getLostPoint(CQrcode *qrcode)
{
int moduleCount = qrcode->getModuleCount();
int lostPoint = 0;
int row;
// LEVEL1
for ( row = 0; row < moduleCount; row++) {
for (int col = 0; col < moduleCount; col++) {
int sameCount = 0;
BOOL dark = qrcode->isDark(row, col);
for (int r = -1; r <= 1; r++) {
if (row + r < 0 || moduleCount <= row + r) {
continue;
}
for (int c = -1; c <= 1; c++) {
if (col + c < 0 || moduleCount <= col + c) {
continue;
}
if (r == 0 && c == 0) {
continue;
}
if (dark == qrcode->isDark(row + r, col + c) ) {
sameCount++;
}
}
}
if (sameCount > 5) {
lostPoint += (3 + sameCount - 5);
}
}
}
// LEVEL2
for ( row = 0; row < moduleCount - 1; row++) {
for (int col = 0; col < moduleCount - 1; col++) {
int count = 0;
if (qrcode->isDark(row, col ) ) count++;
if (qrcode->isDark(row + 1, col ) ) count++;
if (qrcode->isDark(row, col + 1) ) count++;
if (qrcode->isDark(row + 1, col + 1) ) count++;
if (count == 0 || count == 4) {
lostPoint += 3;
}
}
}
// LEVEL3
for ( row = 0; row < moduleCount; row++) {
for (int col = 0; col < moduleCount - 6; col++) {
if (qrcode->isDark(row, col)
&& !qrcode->isDark(row, col + 1)
&&qrcode->isDark(row, col + 2)
&&qrcode->isDark(row, col + 3)
&&qrcode->isDark(row, col + 4)
&& !qrcode->isDark(row, col + 5)
&&qrcode->isDark(row, col + 6) ) {
lostPoint += 40;
}
}
}
int col;
for ( col = 0; col < moduleCount; col++) {
for (int row = 0; row < moduleCount - 6; row++) {
if (qrcode->isDark(row, col)
&& !qrcode->isDark(row + 1, col)
&&qrcode->isDark(row + 2, col)
&&qrcode->isDark(row + 3, col)
&&qrcode->isDark(row + 4, col)
&& !qrcode->isDark(row + 5, col)
&&qrcode->isDark(row + 6, col) ) {
lostPoint += 40;
}
}
}
// LEVEL4
int darkCount = 0;
for ( col = 0; col < moduleCount; col++) {
for (int row = 0; row < moduleCount; row++) {
if (qrcode->isDark(row, col) ) {
darkCount++;
}
}
}
int ratio = abs(100 * darkCount / moduleCount / moduleCount - 50) / 5;
lostPoint += ratio * 10;
return lostPoint;
}
void CQrcode::setupPositionProbePattern(int row, int col)
{
for (int r = -1; r <= 7; r++) {
for (int c = -1; c <= 7; c++) {
if (row + r <= -1 || moduleCount <= row + r
|| col + c <= -1 || moduleCount <= col + c) {
continue;
}
if ( (0 <= r && r <= 6 && (c == 0 || c == 6) )
|| (0 <= c && c <= 6 && (r == 0 || r == 6) )
|| (2 <= r && r <= 4 && 2 <= c && c <= 4) ) {
//modules = new Boolean(true);
modules[(row + r) * moduleCount + (col + c)] = 1; //01
} else {
//modules = new Boolean(false);
modules[(row + r) * moduleCount + (col + c)] = 2; //10
}
}
}
}
void CQrcode::setupPositionAdjustPattern()
{
CUIntArray pos;
// int[] pos = QRUtil.getPatternPosition(typeNumber);
CQrcodeUtil::getPatternPosition(typeNumber, pos);
int row,col;
int pos_length = pos.GetSize();
for (int i = 0; i < pos_length; i++)
{
for (int j = 0; j < pos_length; j++)
{
row = pos;
col = pos;
//if (modules != null) {
if (modules != 0) {
continue;
}
for (int r = -2; r <= 2; r++) {
for (int c = -2; c <= 2; c++) {
if (r == -2 || r == 2 || c == -2 || c == 2 || (r == 0 && c == 0) ) {
//modules = new Boolean(true);
modules[(row+r)*moduleCount + col + c] = 1;//01
} else {
//modules = new Boolean(false);
modules[(row+r)*moduleCount + col + c] = 2;//10
}
}
}
}
}
}
void CQrcode::setupTimingPattern()
{
for (int r = 8; r < moduleCount - 8; r++) {
//if (modules != null) {
if (modules != 0) {
continue;
}
//modules = new Boolean(r % 2 == 0);
modules = (r % 2) == 0 ? 1 : 2;
}
for (int c = 8; c < moduleCount - 8; c++) {
if (modules != 0) {
continue;
}
//modules = new Boolean(c % 2 == 0);
modules = (c % 2) == 0 ? 1 : 2;
}
}
void CQrcode::setupTypeInfo(BOOL test, int maskPattern)
{
int data = (errorCorrectLevel << 3) | maskPattern;
int bits = CQrcodeUtil::getBCHTypeInfo(data);
BOOL mod = FALSE;
int i;
// 縦方向
for ( i = 0; i < 15; i++) {
//Boolean mod = new Boolean(!test && ( (bits >> i) & 1) == 1);
mod = FALSE;if (!test && ( (bits >> i) & 1) == 1) mod = TRUE;
if (i < 6) {
//modules = mod;
modules = mod ? 1:2;
} else if (i < 8) {
//modules = mod;
modules[(i+1)*moduleCount + 8] = mod ? 1:2;
} else {
//modules = mod;
modules[(moduleCount - 15 + i)*moduleCount + 8] = mod ? 1:2;
}
}
// 横方向
for ( i = 0; i < 15; i++) {
//Boolean mod = new Boolean(!test && ( (bits >> i) & 1) == 1);
mod = FALSE;if (!test && ( (bits >> i) & 1) == 1) mod = TRUE;
if (i < 8) {
//modules = mod;
modules = mod ? 1:2;
} else if (i < 9) {
//modules = mod;
modules = mod ? 1:2;
} else {
//modules = mod;
modules = mod ? 1:2;
}
}
// 固定
//modules = new Boolean(!test);
modules[(moduleCount - 8)*moduleCount + 8] = !test ? 1:2;
}
void CQrcode::setupTypeNumber(BOOL test)
{
int bits = CQrcodeUtil::getBCHTypeNumber(typeNumber);
BOOL mod = FALSE;
int i;
for ( i = 0; i < 18; i++) {
//Boolean mod = new Boolean(!test && ( (bits >> i) & 1) == 1);
mod = FALSE;if (!test && ( (bits >> i) & 1) == 1) mod = TRUE;
//modules = mod;
modules[(i/3)*moduleCount + i % 3 + moduleCount - 8 - 3] = mod ? 1:2;
}
for ( i = 0; i < 18; i++) {
//Boolean mod = new Boolean(!test && ( (bits >> i) & 1) == 1);
mod = FALSE;if (!test && ( (bits >> i) & 1) == 1) mod = TRUE;
//modules = mod;
modules[(i % 3 + moduleCount - 8 - 3)*moduleCount + (i / 3)] = mod ? 1:2;
}
}
BYTE* CQrcode::createData(int typeNumber, int errorCorrectLevel, CObArray &dataArray, int* bytesSize)
{
//RSBlock[] rsBlocks = RSBlock.getRSBlocks(typeNumber, errorCorrectLevel);
CObArray rsBlocks;
CQrcodeRSBlock::getRSBlocks(typeNumber, errorCorrectLevel, rsBlocks);
int i;
CQrcodeBitBuffer buffer;
CQrcodeData *pqrdata = NULL;
for ( i = 0; i < dataArray.GetSize(); i++) {
pqrdata = (CQrcodeData *)dataArray.GetAt(i);
buffer.put(pqrdata->getMode(), 4);
buffer.put(pqrdata->getLength(), pqrdata->getLengthInBits(typeNumber) );
pqrdata->write(buffer);
}
// 最大データ数を計算
int totalDataCount = 0;
CQrcodeRSBlock *pblock = NULL;
for ( i = 0; i < rsBlocks.GetSize(); i++) {
pblock = (CQrcodeRSBlock *)rsBlocks.GetAt(i);
totalDataCount += pblock->getDataCount();
}
if (buffer.getLengthInBits() > totalDataCount * 8) {
/*throw new IllegalArgumentException("code length overflow. ("
+ buffer.getLengthInBits()
+ ">"
+totalDataCount * 8
+ ")");
*/
return NULL;
}
// 終端コード
if (buffer.getLengthInBits() + 4 <= totalDataCount * 8) {
buffer.put(0, 4);
}
// padding
while (buffer.getLengthInBits() % 8 != 0) {
buffer.put(FALSE);
}
// padding
while (TRUE) {
if (buffer.getLengthInBits() >= totalDataCount * 8) {
break;
}
buffer.put(PAD0, 8);
if (buffer.getLengthInBits() >= totalDataCount * 8) {
break;
}
buffer.put(PAD1, 8);
}
return createBytes(buffer, rsBlocks, bytesSize);
}
BYTE* CQrcode::createBytes(CQrcodeBitBuffer &buffer, CObArray &rsBlocks, int* bytesSize)
{
int offset = 0;
int i,r;
int maxDcCount = 0;
int maxEcCount = 0;
int dcCount;
int ecCount;
CUIntArray *pint = NULL;
CQrcode2DIntArray dcdata;
CQrcode2DIntArray ecdata;
int rsBlocks_length = rsBlocks.GetSize();
CQrcodeRSBlock *pblock = NULL;
for ( r = 0; r < rsBlocks_length; r++) {
pblock = (CQrcodeRSBlock *)rsBlocks.GetAt(r);
dcCount = pblock->getDataCount();
ecCount = pblock->getTotalCount() - dcCount;
maxDcCount = maxDcCount > dcCount ? maxDcCount:dcCount;
maxEcCount = maxEcCount > ecCount ? maxEcCount:ecCount;
for (i = 0; i < dcCount; i++) {
dcdata.SetAt(r,i, 0xff & buffer.getBuffer());
}
offset += dcCount;
CQrcodePolynomial rsPoly = CQrcodeUtil::getErrorCorrectPolynomial(ecCount);
pint = dcdata.GetIntArray(r);
CQrcodePolynomial rawPoly((*pint), rsPoly.getLength() - 1);
CQrcodePolynomial modPoly = rawPoly.mod(rsPoly);
//
for ( i = 0; i < (rsPoly.getLength() - 1); i++) {
int modIndex = i + modPoly.getLength() - (rsPoly.getLength() - 1);
ecdata.SetAt(r,i, (modIndex >= 0)? modPoly.get(modIndex) : 0);
}
}
int totalCodeCount = 0;
for ( i = 0; i < rsBlocks_length; i++) {
pblock = (CQrcodeRSBlock *)rsBlocks.GetAt(i);
totalCodeCount += pblock->getTotalCount();
}
BYTE* data = (BYTE*)malloc(totalCodeCount);
//TRACE1("datalen=%d\r\n",totalCodeCount);
memset(data, 0 , totalCodeCount);
(*bytesSize) = totalCodeCount;
int index = 0;
for ( i = 0; i < maxDcCount; i++) {
for ( r = 0; r < rsBlocks_length; r++) {
pint = dcdata.GetIntArray(r);
if (i < pint->GetSize()) {
data = (BYTE)dcdata.GetAt(r,i);
}
}
}
for ( i = 0; i < maxEcCount; i++) {
for ( r = 0; r < rsBlocks_length; r++) {
pint = ecdata.GetIntArray(r);
if (i < pint->GetSize()) {
data = (BYTE)ecdata.GetAt(r,i);
}
}
}
//删除rsBlocksliu add
for(i=0;i<rsBlocks.GetSize();i++)
{
delete rsBlocks.GetAt(i);
}
///////////////////////
return data;
}
void CQrcode::mapData(BYTE* bytes, int bytes_size, int maskPattern)
{
int inc = -1;
int row = moduleCount - 1;
int bitIndex = 7;
int byteIndex = 0;
for (int col = moduleCount - 1; col > 0; col -= 2) {
if (col == 6) col--;
while (true) {
for (int c = 0; c < 2; c++) {
if (modules == 0) {
BOOL dark = FALSE;
if (byteIndex < bytes_size) {
dark = ( ( (bytes >> bitIndex) & 1) == 1);
}
BOOL mask = CQrcodeUtil::getMask(maskPattern, row, col - c);
if (mask) {
dark = !dark;
}
modules = dark ? 1:2;
bitIndex--;
if (bitIndex == -1) {
byteIndex++;
bitIndex = 7;
}
}
}
row += inc;
if (row < 0 || moduleCount <= row) {
row -= inc;
inc = -inc;
break;
}
}
}
}
CQrcode* CQrcode::getMinimumQRCode(CString data, int errorCorrectLevel,int *errorcode)
{
if (errorcode==NULL) return NULL;
if(errorCorrectLevel<0 || errorCorrectLevel>3) {//标准检查
*errorcode=1;
return NULL;
}
if(data.GetLength()==0) //没有数据
{
*errorcode=2;
return NULL;
}
*errorcode=0;
int mode = CQrcodeUtil::getMode(data);
CQrcode *qr = new CQrcode();
qr->setErrorCorrectLevel(errorCorrectLevel);
qr->addData(data, mode);
CQrcodeData *pdata = (CQrcodeData *)qr->getData(0);
int length = pdata->getLength();//占用字节长度
TRACE1("长度%d\r\n",length);
inttypeNumber;
bool bFind=false;
for ( typeNumber = 1; typeNumber <= 20; typeNumber++) {
if (length <= CQrcodeUtil::getMaxLength(typeNumber, mode, errorCorrectLevel) ) {
qr->setTypeNumber(typeNumber);
bFind=true;
break;
}
}
TRACE1("V=%d\r\n",typeNumber);
if(!bFind)
*errorcode=3;//超出长度
else
qr->make();
return qr;
}
void CQrcode::Draw(CDC *pdc, int cellSize, int margin)
{
int imageSize = getModuleCount() * cellSize + margin * 2;
int row,col;
for (int y = 0; y < imageSize; y++) {
for (int x = 0; x < imageSize; x++) {
if (margin <= x && x < imageSize - margin
&& margin <= y && y < imageSize - margin) {
col = (x - margin) / cellSize;
row = (y - margin) / cellSize;
if (isDark(row, col) ) {
pdc->SetPixel(x, y, RGB(0,0,0));
} else {
pdc->SetPixel(x, y, RGB(255,255,255));
}
} else {
pdc->SetPixel(x, y, RGB(255,255,255));
}
}
}
}
typedef struct _T_PIXEL
{
BYTE b; //代表blue
BYTE g; //代表green
BYTE r; //代表red
}T_PIXEL;
void CQrcode::SaveToBmp(CString filename, int cellSize, int margin)
{
BITMAPFILEHEADER BMPHeader; //BMP文件头
BITMAPINFO BMPInfo; //BMP信息块
BITMAPINFOHEADER BMPInfoHeader; //BMP信息头(即包含在BMP信息块的 信息头)
//RGBQUAD BMPRgbQuad; //BMP色彩表(即包含在BMP信息块的色彩表)
CFile BMPFile;
if (!BMPFile.Open(filename,CFile::modeCreate|CFile::modeWrite)) //创建BMP文件
{
AfxMessageBox("无法创建文件"+filename);
return;
}
//SetBMPFileHeader
int imageSize = getModuleCount() * cellSize + margin * 2;
BMPHeader.bfType=0x4D42;
BMPHeader.bfSize=3*imageSize*imageSize+0x36; //指示 整个BMP文件字节数,其中0x36是文件头本身的长度
BMPHeader.bfReserved1=0x0;
BMPHeader.bfReserved2=0x0;
BMPHeader.bfOffBits=0x36; //x36是文件头本身的长度
//以上共占据14个字节
BMPInfoHeader.biSize=sizeof(BITMAPINFOHEADER); //指示 文件信息头大小
BMPInfoHeader.biWidth=imageSize; //图片宽度
BMPInfoHeader.biHeight=imageSize; //图片高度
BMPInfoHeader.biPlanes=1;
BMPInfoHeader.biBitCount=24; //图片位数,位24位图
//以上共占据14+16个字节
BMPInfoHeader.biCompression=0; //表示没有压缩
BMPInfoHeader.biSizeImage=0x30; //因为没有压缩,所以可以设置为0
BMPInfoHeader.biXPelsPerMeter=0x0;
BMPInfoHeader.biYPelsPerMeter=0x0;
BMPInfoHeader.biClrUsed=0; //表明使用所有索引色
BMPInfoHeader.biClrImportant=0; //说明对图象显示有重要影响的颜色索引的数目,0表示都重要。
//以上共占据14+16+24个字节
BMPInfo.bmiHeader=BMPInfoHeader;
BMPFile.Write(&(BMPHeader),sizeof(BMPHeader));
BMPFile.Write(&BMPInfoHeader,sizeof(BMPInfo)-sizeof(RGBQUAD));
//
T_PIXEL p;
int row,col;
for (int y = imageSize; y >= 0 ; y--) {
for (int x = 0; x < imageSize; x++) {
if (margin <= x && x < imageSize - margin && margin <= y && y < imageSize - margin) {
col = (x - margin) / cellSize;
row = (y - margin) / cellSize;
if (isDark(row, col) ) {
p.b = 0; p.g = 0; p.r = 0;
} else {
p.b = 255; p.g = 255; p.r = 255;
}
} else {
p.b = 255; p.g = 255; p.r = 255;
}
BMPFile.Write(&p, sizeof(T_PIXEL));
}
}
//
BMPFile.Flush();
BMPFile.Close();
}
页:
[1]