吾爱破解 - 52pojie.cn

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

查看: 1236|回复: 0
收起左侧

[学习记录] 关于二维码打印调用类分析

[复制链接]
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);
*/



//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_L  1 //7%的字码可修正   
#define ErrorCorrectLevel_M  0 //15%
#define ErrorCorrectLevel_Q  3 //25%
#define ErrorCorrectLevel_H  2 //30%



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[80][6]  = {

  // 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[40][7] ={
  {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[20][4][4] = {
      //L N   A    8B  Han           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[index / 8], 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[length / 8] |= CQrcodeUtil::unsignedRightShift(0x80, length % 8);
}

length++;
}


//---------------------------------------

CQrcodeUtil::CQrcodeUtil()
{

}

CQrcodeUtil::~CQrcodeUtil()
{

}


void CQrcodeUtil::getPatternPosition(int typeNumber, CUIntArray &p)
{
int *pp = PATTERN_POSITION_TABLE[typeNumber - 1];
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[t][e][m];
}

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[i + 1]);
     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[offset] == 0) {
  offset++;
}

int i;
//this.num = new int[length - offset + shift];
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[i-offset] = nums;
}

CQrcodePolynomial::~CQrcodePolynomial()
{
   m_nums.RemoveAll(); //liu add
}

int CQrcodePolynomial::get(int idx)
{
return m_nums[idx];
}

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[i + j] ^= 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[getLength()];
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[i - 4]^ EXP_TABLE[i - 5]^ EXP_TABLE[i - 6]^ EXP_TABLE[i - 8];
for ( i = 0; i < 256; i++)  LOG_TABLE.Add(0);
for ( i = 0; i < 255; i++)  LOG_TABLE[EXP_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[n];
}

int CQrcodeMath::gexp(int n)
{
while (n < 0) {
  n += 255;
}

while (n >= 256) {
  n -= 255;
}

return EXP_TABLE[n];
}


//---------------------------------------------------

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[i * 3 + 0];
  int totalCount = rsBlock[i * 3 + 1];
  int dataCount  = rsBlock[i * 3 + 2];

  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[i + 1]), 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[i + 1]);

    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[row*moduleCount + col] != 0 ) {
  return (modules[row*moduleCount + col] == 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[moduleCount][moduleCount];
  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[qrDataList.size()]);
  //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[row + r][col + c] = new Boolean(true);
    modules[(row + r) * moduleCount + (col + c)] = 1; //01
   } else {
    //modules[row + r][col + c] = 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[j];
  
   //if (modules[row][col] != null) {
   if (modules[row*moduleCount+col] != 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[row + r][col + c] = new Boolean(true);
      modules[(row+r)*moduleCount + col + c] = 1;//01
     } else {
      //modules[row + r][col + c] = new Boolean(false);
      modules[(row+r)*moduleCount + col + c] = 2;//10
     }
    }
   }

  }
}
}

void CQrcode::setupTimingPattern()
{
for (int r = 8; r < moduleCount - 8; r++) {
  //if (modules[r][6] != null) {
  if (modules[r*moduleCount + 6] != 0) {
   continue;
  }
  //modules[r][6] = new Boolean(r % 2 == 0);
  modules[r*moduleCount + 6] = (r % 2) == 0 ? 1 : 2;
}
for (int c = 8; c < moduleCount - 8; c++) {
  if (modules[6*moduleCount+ c] != 0) {
   continue;
  }
  //modules[6][c] = new Boolean(c % 2 == 0);
  modules[6*moduleCount+ c] = (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[8] = mod;
    modules[i*moduleCount + 8] = mod ? 1:2;
   } else if (i < 8) {
    //modules[i + 1][8] = mod;
    modules[(i+1)*moduleCount + 8] = mod ? 1:2;
   } else {
    //modules[moduleCount - 15 + i][8] = 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[8][moduleCount - i - 1] = mod;
    modules[8*moduleCount + moduleCount - i - 1] = mod ? 1:2;
   } else if (i < 9) {
    //modules[8][15 - i - 1 + 1] = mod;
    modules[8*moduleCount + 15 - i - 1 + 1] = mod ? 1:2;
   } else {
    //modules[8][15 - i - 1] = mod;
    modules[8*moduleCount + 15 - i - 1] = mod ? 1:2;
   }
  }

  // 固定
  //modules[moduleCount - 8][8] = 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[i / 3][i % 3 + moduleCount - 8 - 3] = 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[i % 3 + moduleCount - 8 - 3][i / 3] = 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()[i + offset]);
   }
   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[index++] = (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[index++] = (BYTE)ecdata.GetAt(r,i);
    }
   }
  }
  //删除rsBlocks  liu 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[row*moduleCount + col - c] == 0) {
     
      BOOL dark = FALSE;

      if (byteIndex < bytes_size) {
       dark = ( ( (bytes[byteIndex] >> bitIndex) & 1) == 1);
      }

      BOOL mask = CQrcodeUtil::getMask(maskPattern, row, col - c);

      if (mask) {
       dark = !dark;
      }
     
      modules[row*moduleCount + col - c] = 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);
    int  typeNumber;
        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();
}

发帖前要善用论坛搜索功能,那里可能会有你要找的答案或者已经有人发布过相同内容了,请勿重复发帖。

您需要登录后才可以回帖 登录 | 注册[Register]

本版积分规则

返回列表

RSS订阅|小黑屋|处罚记录|联系我们|吾爱破解 - LCG - LSG ( 京ICP备16042023号 | 京公网安备 11010502030087号 )

GMT+8, 2024-11-25 15:33

Powered by Discuz!

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表