二维码流行起来了,到处可见,好像报纸广告上面没个二维码就不上档次是的,所以好奇,略研究了一下,搜出了不少都是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}, {