Kanji mode这是日文编码,也是双字节编码。同样,也可以用于中文编码。
日文和汉字的编码会减去一个值。如:在0X8140 to 0X9FFC中的字符会减去8140,在0XE040到0XEBBF中的字符要减去0XC140,
然后把结果前两个16进制位拿出来乘以0XC0,然后再加上后两个16进制位,最后转成13bit的编码。
//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);
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;
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 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;
}
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;
}
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);
}
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;
}
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;
}
}
}
//---------------------------------------
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);
}
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;
}
}
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;
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
*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) {
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) {