VC生成二维码(qrcode)编码源码

发布时间:2018年2月25日 作者:未知 查看次数:1080



试了,可用。注:需要MFC,先建MFC工程,建立头文件qrcode.h复制qrcode.h的内容,建立代码文件qrcode.cpp复制qrcode.cpp的内容,显示时包含头qrcode.h。




自:http://blog.csdn.net/zuhuisu/article/details/8916407?locationNum=4&fps=1



二维码流行起来了,到处可见,好像报纸广告上面没个二维码就不上档次是的,所以好奇,略研究了一下,搜出了不少都是ZXING的C#版,或是java, 还有JS的,但暂没收到 VC MFC方面的,所以做个体力劳动,将java版的批量转换了一下, 望网友指正, 同时在我的资源下载中我提供一个DLL用于其它非MFC开发程序用:


二维码的关键点:


      数据表示:     全是数字的,0-9的数


                              数字与大字字母混合的


                             全是汉字或日文字的


                             以上三种都不是的,直接以8BIT字符来存数据


 


    容错等级:


                   H      是高           撕掉30%都无所谓,照读得出来 ,所以现在好多二维码中间搞了logo,很牛的样子


                   M       20%


                   Q    15%


                    L      5%


   版本:     1-40,    基本上1-10就够用了,本文暂实现1-10,要扩展只要增加定义就行


源码一个qrcode.h,一个qrcode.cpp, 


用法:


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);

 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

#define ErrorCorrectLevel_M  0

#define ErrorCorrectLevel_Q  3

#define ErrorCorrectLevel_H  2

 


//qrcode.cpp


#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)

#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))


int RS_BLOCK_TABLE[40][6]  = {


  // L =1

  // M =0

  // Q =3

  // H =2


  // 1

  {1, 26, 19,0,0,0},

  {1, 26, 16,0,0,0},

  {1, 26, 13,0,0,0},

  {1, 26, 9,0,0,0},

  

  // 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}


 };


 


 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[10][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} }

    };



 


CQrcodeBitBuffer::CQrcodeBitBuffer()

{

 inclements = 32;

 buffer = (BYTE*)malloc(inclements);

 memset(buffer, 0, inclements);

 buffer_len = inclements;

 length = 0;

}


CQrcodeBitBuffer::~CQrcodeBitBuffer()

{

 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[i] == 0) break;

  p.Add(pp[i]);

 }

}

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) ) {

   return MODE_NUMBER;

  }

  return MODE_ALPHA_NUM;

 } else if (isHanZi(s) ) {

  return MODE_HANZI;

 } else {

  return MODE_8BIT_BYTE;

 }

}


BOOL CQrcodeUtil::isNumber(CString s)

{

 for (int i = 0; i < s.GetLength(); i++) {

  char c = s.GetAt(i);

  if (!('0' <= c && c <= '9') ) {

   return FALSE;

  }

 }

 return TRUE;

}


BOOL CQrcodeUtil::isAlphaNum(CString s)

{

 CString othersAlpha = " $%*+-./:";

 for (int i = 0; i < s.GetLength(); i++) {

  char 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[i]) << 8) | (0xff & s[i + 1]);


  if (!(0x8140 <= c && c <= 0x9FFC) && !(0xE040 <= c && c <= 0xEBBF) ) {

   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[i];

}


CQrcodePolynomial::~CQrcodePolynomial()

{


}


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[i] = get(i);

 }

 

 // 

 for ( i = 0; i < e.getLength(); i++) {

  tnums[i] ^= 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[i] = 1 << i;

 }

 for ( i = 8; i < 256; i++) EXP_TABLE[i] =  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]] = i;

}


CQrcodeMath::~CQrcodeMath()

{


}


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[i] == 0) break;

   a.Add(p[i]);

  }

 }

}



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()

{


}


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[i], 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[i]) * 45 + getCode(data[i + 1]), 11);

  i += 2;

 }

 

 if (i < len) {

  buffer.put(getCode(data[i]), 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[i]) << 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_H;

}


CQrcode::~CQrcode()

{

 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()

{

 for(int i=0;i<qrDataList.GetSize();i++){

  delete qrDataList.GetAt(i);

 }

 qrDataList.RemoveAll();

}


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);

}


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[i];

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

  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);

    }

   }

  }

  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 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();


 for (int typeNumber = 1; typeNumber <= 10; typeNumber++) {

        if (length <= CQrcodeUtil::getMaxLength(typeNumber, mode, errorCorrectLevel) ) {

            qr->setTypeNumber(typeNumber);

            break;

        }

  if (typeNumber==10) AfxMessageBox("数据太大了");

 }


    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();

}




版权所有!www.sieye.cn
E.Mail:sieye@sohu.com QQ:66697110