您的位置:首页 > 其它

VC实现二维码(qrcode)编码源码

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

}

int CQrcodeMath::gexp(int n)

{

while (n < 0) {

n += 255;

}

while (n >= 256) {

n -= 255;

}

return EXP_TABLE
;

}

CQrcodeRSBlock::CQrcodeRSBlock(int totalCount, int dataCount)

{

this->totalCount = totalCount;

this->dataCount = dataCount;

}

CQrcodeRSBlock::~CQrcodeRSBlock()

{

}

void CQrcodeRSBlock::getRsBlockTable(int typeNumber, int errorCorrectLevel, CUIntArray &a)

{

int *p = NULL;

switch(errorCorrectLevel) {

case ErrorCorrectLevel_L :

p = RS_BLOCK_TABLE[(typeNumber - 1) * 4 + 0];

break;

case ErrorCorrectLevel_M :

p = RS_BLOCK_TABLE[(typeNumber - 1) * 4 + 1];

break;

case ErrorCorrectLevel_Q :

p = RS_BLOCK_TABLE[(typeNumber - 1) * 4 + 2];

break;

case ErrorCorrectLevel_H :

p = RS_BLOCK_TABLE[(typeNumber - 1) * 4 + 3];

default :

break;

}

if (p!=NULL){

for (int i=0;i<6;i++){

if (p[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();

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: