kims52 发表于 2022-3-22 00:28

关于二维码打印调用类分析

由于直接调用官方的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]
查看完整版本: 关于二维码打印调用类分析