简单JPEG类模拟

#include <iostream>
#include <fstream>
#include <string>
#include <algorithm>
//BMP数据加解压
using namespace std;
#define USE_ACCURATE_ROUNDING

#define RIGHT_SHIFT(x, shft)  ((x) >> (shft))

#ifdef USE_ACCURATE_ROUNDING
#define ONE ((int) 1)
#define DESCALE(x, n)  RIGHT_SHIFT((x) + (ONE << ((n) - 1)), n)
#else
#define DESCALE(x, n)  RIGHT_SHIFT(x, n)
#endif
#define CONST_BITS  13
#define PASS1_BITS  2

#define FIX_0_298631336  ((int)  2446) /* FIX(0.298631336) */
#define FIX_0_390180644  ((int)  3196) /* FIX(0.390180644) */
#define FIX_0_541196100  ((int)  4433) /* FIX(0.541196100) */
#define FIX_0_765366865  ((int)  6270) /* FIX(0.765366865) */
#define FIX_0_899976223  ((int)  7373) /* FIX(0.899976223) */
#define FIX_1_175875602  ((int)  9633) /* FIX(1.175875602) */
#define FIX_1_501321110  ((int) 12299) /* FIX(1.501321110) */
#define FIX_1_847759065  ((int) 15137) /* FIX(1.847759065) */
#define FIX_1_961570560  ((int) 16069) /* FIX(1.961570560) */
#define FIX_2_053119869  ((int) 16819) /* FIX(2.053119869) */
#define FIX_2_562915447  ((int) 20995) /* FIX(2.562915447) */
#define FIX_3_072711026  ((int) 25172) /* FIX(3.072711026) */

#define W1 2841     /* 2048*sqrt(2)*cos(1*pi/16) */
#define W2 2676     /* 2048*sqrt(2)*cos(2*pi/16) */
#define W3 2408     /* 2048*sqrt(2)*cos(3*pi/16) */
#define W5 1609     /* 2048*sqrt(2)*cos(5*pi/16) */
#define W6 1108     /* 2048*sqrt(2)*cos(6*pi/16) */
#define W7 565       /* 2048*sqrt(2)*cos(7*pi/16) */

/* private data */
static int iclip[1024]; 

/* clipping table */
static int *iclp;

/* two dimensional inverse discrete cosine transform */
// fidct_init() MUST BE CALLED BEOFRE THE FIRST CALL TO THIS FUNCTION!
typedef unsigned char BYTE;
struct JPEGSENDDATA
{
	//huffman编码后的y,u,v各表的数据长度
	int yHufLen, uHufLen, vHufLen;
	//原BMP图的高row,宽col,像素BYTE数
	int row, col, pixel;
   //huffman编码后的数据,格式为 huffman后的y,u,v表 
	//后再分别接y,u,v表的huffman树
	BYTE *m_data;
	//m_data数据的总长度
	int dataLen;
	//huffman解压后y,u,v的长度,作为解 Z编码 输入的数据
	int yZcodeLen, uZcodeLen, vZcodeLen;
	//离散余弦变换后的y,u,v各表的第一个数据的大小,用于DPM编码
	int  m_yTableFirstByte,m_uTableFirstByte,m_vTableFirstByte;
	int crc32;
	//int hufftreeCrc32_y;
	//int hufftreeCrc32_u;
	//int hufftreeCrc32_v;
};

struct HUFFTREE
{
	int weight;
	short lchild, rchild, parent;
	bool in_tree;
	//lchild->weight < rchild->weight
};

class JPEG
{//模拟JPEG加解压BMP数据
public:
	//TO JPEG
	//data : 输入的BMP内存中的图像部分的数据
	//row BMP图片高,col BMP图片宽,pixel像素BYTE数
	//注:不释放data的数据,调用者外面自己释放data
	JPEG(BYTE *data, int row, int col, int pixel);
	//TO BMP
	//注:内部不释放data的数据,调用者外面自己释放data
	JPEG(JPEGSENDDATA *data);
	~JPEG();
	void PrintY();
	void PrintU();
	void PrintV();
	void PrintData();
	//返回解缩后的BMP内容BYTE的数据
	BYTE * ReturnData();
	//返回压缩后的JPEG头格式的数据
	JPEGSENDDATA *ReturnSendData();

private:
		//临时调试
	inline void DispatchDCT();
	inline void DispatchTDCT();
	//BMP->JPEG
	inline bool DispatchDCT2();
	//JPEG->BMP
	inline bool DispatchTDCT2();
	//反离散余弦变换
	inline void fidct_init();
	inline void fidct(int * block);
	inline void TDCT(int *lpBuf);
	//离散余弦变换
	inline void fdct(int *block);
	inline void fast_fdct(int *block);
	inline void DCT(int *lpBuf);
	//量化
	inline void Quantize();
	//反量化
	inline void TQuantize();
	//RGB->YUV
	inline bool RGBDataToYuv();
	//YUV->RGB
	inline bool YuvDataToRGB();
	//Z编码
	inline bool Zcode(int *&lpBuf, const int &bufSize, int &zcodeLen);
	//解Z编码
	inline bool TZcode(int *&lpBuf, const int &bufSize, int &zcodeLen);
	//HUFFMAN压缩
	inline bool HuffmanCompress();
	//解HUFFMAN压缩
	inline bool HuffmanDesCompress();
	//临时调试
	inline void NotHaveHuffman();
	inline void InitJpegData();
	inline void AjustGB();
private:
	BYTE *m_data;
	int     *m_y, *m_u, *m_v;
	int  m_yTableFirstByte,m_uTableFirstByte,m_vTableFirstByte;
	int  m_pixel, m_col, m_row;
	int m_ySize, m_uSize, m_vSize;
	int m_yZcodeLen, m_uZcodeLen, m_vZcodeLen;
	JPEGSENDDATA *m_send_data;
};

class HUFFMAN
{//采用数组树结构
	typedef int    HUFFDATATYPE_EN;
	typedef unsigned char HUFFDATATYPE_DES;
	typedef unsigned char BYTE;
public:
	HUFFMAN(HUFFDATATYPE_EN *arry, int size);
	HUFFMAN(HUFFDATATYPE_DES *arry, int size, HUFFDATATYPE_DES *hufftr, int hufLen);
		//HUFFMAN压缩
	bool HuffCode(BYTE *&ret, int &ret_pos);
		//解HUFFMAN压缩
	bool HuffDesCode(HUFFDATATYPE_EN *&ret);
		//返回HUFFMAN树
	bool ReturnHuffTree(HUFFTREE * &hufftr);
	//计算和显示HUFFMAN树,用于验证
	void CounTreeCrc(int &ret);
	void PrintSendTree();
	~HUFFMAN();

private:
	//获取最小点对
	inline void MakeMinPair(const short &end);
	//建树
	inline bool MakeHuffTree();
private:
	//数组树的结构
	HUFFTREE m_freq[512];
    HUFFDATATYPE_EN *m_arry;
	HUFFDATATYPE_DES *m_outarry;
	int m_arryLen, m_AfterhufLen;
	short m_min_a, m_min_b;
	//std::string m_str[256];
	short m_root;
	int m_freqCodeLen[256];
	bool *m_freqCode[256];
};


 

#include "JPEG.h"
#include "crc32.h"
#include <assert.h>
std::ofstream fwhrsenderr("C:\\WhrSendErr.TXT");
std::ofstream fwhrrecverr("C:\\WhrRecvErr.TXT");
std::ofstream ftreeSend("C:\\sendTree.TXT");
//A Mod B=A-(A div B) * B
#define MOD(x, n) (x - ((x >> n) << n))

JPEG::JPEG(BYTE *data, int row, int col, int pixel)
{
	assert(data != NULL && row > 0 && col > 0 && pixel > 0);
	m_pixel = pixel, m_row = row, m_col = col;
	m_data = data;
	m_send_data = NULL;
}

JPEG::JPEG(JPEGSENDDATA *data)
{
	assert(data != NULL);
	m_pixel = data->pixel, m_row = data->row, m_col = data->col;
	m_send_data = data;
	m_yTableFirstByte = data->m_yTableFirstByte;
	m_uTableFirstByte = data->m_uTableFirstByte;
	m_vTableFirstByte = data->m_vTableFirstByte;
	m_data = NULL;
	m_y = m_u = m_v = NULL;
	m_ySize = m_uSize = m_vSize = 0;
	m_yZcodeLen = m_uZcodeLen = m_vZcodeLen = 0;
}

JPEG::~JPEG()
{
	if (m_y != NULL) delete [] m_y;
	if (m_u != NULL) delete [] m_u;
	if (m_v != NULL) delete [] m_v;
}

bool JPEG::RGBDataToYuv()
{
	//示例:
	//RGB数据1....1 2....2 (1行8个1和8个2,共8行)
	//                    ...............
	//                    ...............
	//                    1....1 2....2 
	//分割后为1...........................1 2..................2(连续64个1和连续64个2)
	//yr 8 * 8
	int yc = m_col  + MOD(m_col, 3);
	int yr = m_row + MOD(m_row, 3);
	m_ySize = yc * yr;

	//r, c扩展
	int row = (m_row + MOD(m_row, 4));
	int col   = (m_col + MOD(m_col, 4)); 
	//u, v 16 * 16
	int uc = col >> 1;
	int ur = row >> 1;
	m_uSize = m_ySize;//uc * ur;

	int vc = uc = yc, vr = ur = yr;
	m_vSize = m_uSize;

	//m_y = new BYTE[m_ySize];
	//m_u = new BYTE[m_uSize];
	//m_v = new BYTE[m_vSize];
	m_y = new int[m_ySize];
	m_u = new int[m_uSize];
	m_v = new int[m_vSize];
	assert(m_y != NULL || m_u != NULL || m_v != NULL);
	//memset(m_y, 0,  m_ySize);
	//memset(m_u, 0, m_uSize);
	//memset(m_v, 0, m_vSize );
	memset(m_y, 0,  m_ySize<<2);
	memset(m_u, 0, m_uSize<<2);
	memset(m_v, 0, m_vSize<<2);

	//y方向级数增加y % 8 == 0递增
	int yBlock = yc << 3;
	int yBase = 0;
	int uBase = 0;
	int uBlock = yBlock >> 1;
	int pos = 0;
	for (int i = 0; i < m_row; ++i)
	{
		yBase = (i >> 3) * yBlock;
		uBase = (i >> 4) * uBlock;

		int yTiBase = MOD((i << 3), 6);
		int uTiBase = MOD(((i >> 1) << 3), 6);
		for (int j = 0; j < m_col; ++j, pos++)
		{
			//(j / 8) * 64
			//int R = (int)m_data[pos++];
			//int G = (int)m_data[pos++];
			//int B = (int)m_data[pos];
			int B = (int)m_data[pos++];
			int G = (int)m_data[pos++];
			int R = (int)m_data[pos++];
			//int y = ((66*R+129*G+25*B+128)>>8)+16;
/*
			if (y < 0) y = 0;
			else if (y > 255) y = 255;*/
			int t = yBase + ((j >> 3)<<6) + MOD(j, 3) + yTiBase;
			m_y[t] = ((66*R+129*G+25*B+128)>>8)+16;///*(BYTE)*/y;
			//if (MOD(i, 1) == 0 && MOD(j, 1) == 0)
			//{
				//(j / 16)*64
				//int t = uBase + ((j >> 4)<<6) + MOD((j >> 1), 3) + uTiBase;
				//int u = ((-38*R-74*G+112*B+128)>>8)+128;
/*
				if (u < 0) u = 0;
				else if (u > 255) u = 255;*/

				//int v = ((112*R-94*G-18*B+128)>>8)+128;
/*
				if (v < 0) v = 0;
				else if (v > 255) v = 255;*/

				m_u[t] = ((-38*R-74*G+112*B+128)>>8)+128;///*(BYTE)*/u;
				m_v[t] = ((112*R-94*G-18*B+128)>>8)+128;///*(BYTE)*/v;
			//}
		}
	}
	return true;
}

bool JPEG::YuvDataToRGB()
{
	//yr 8 * 8
	int yc = m_col  + MOD(m_col, 3);
	int yr = m_row + MOD(m_row, 3);

	//r, c扩展
	int row = (m_row +  MOD(m_row, 4));
	int col   = (m_col + MOD(m_col, 4)); 
	//u, v 16 * 16
	int uc = col >> 1;
	int ur = row >> 1;

	int vc = uc = yc, vr = ur = yr;

	int size = m_row * m_col * m_pixel;
	if (m_data != NULL) delete [] m_data;
	m_data = NULL;
	m_data = new BYTE[size];
	assert(m_data != NULL);
	memset(m_data, 0, size);

	//y方向级数增加y % 8 == 0递增
	int pos = 0;
	int yBlock = yc << 3;
	int yBase = 0;
	int uBase = 0;
	int uBlock = yBlock >> 1;
	int R = 0,G = 0,B = 0, Y = 0, U = 0, V = 0;
	for (int i = 0; i < m_row; ++i)
	{
		//
		yBase = (i >> 3) * yBlock;
		uBase = (i >> 4) * uBlock;

		int yTiBase = MOD((i << 3), 6);
		int uTiBase = MOD(((i >> 1) << 3), 6);
		for (int j = 0; j < m_col; ++j, pos++)
		{
			//(j / 8) * 64
			int t = yBase + ((j >> 3)<<6) + MOD(j, 3) + yTiBase;
			Y = (int)(m_y[t] - 16);
			//if (MOD(i, 1) == 0 && MOD(j, 1) == 0)
			//{
				//(j / 16)*64
				//int t = uBase + ((j >> 4)<<6) + MOD((j >> 1), 3) + uTiBase;
				U = (int)(m_u[t] - 128);
				V = (int)(m_v[t]  - 128);
			//}
			Y *= 298;
			//m_data[pos++] = (BYTE)((Y+409*V+128)>>8);//R
			//m_data[pos++] = (BYTE)((Y-100*U-208*V+128)>>8);//G
			//m_data[pos]     = (BYTE)((Y+516*U+128)>>8);//B
			R  = ((Y+409*V+128)>>8);
			G = ((Y-100*U-208*V+128)>>8);
			B = ((Y+516*U+128)>>8);

			if (R < 0) R = 0;
			else if (R > 255) R = 255;
			if (G < 0) G = 0;
			else if (G > 255) G = 255;
			if (B < 0) B = 0;
			else if (B > 255) B = 255;

			m_data[pos++]     = (BYTE)B;//B
			m_data[pos++]     = (BYTE)G;//G
			m_data[pos++]     =(BYTE)R; //R
		}
	}
	return true;
}

void JPEG::PrintY()
{
	//yr 8 * 8
	int yc = m_col  + m_col % 8;
	int yr = m_row + m_row % 8;

	cout << "Y is :\n";
	for (int i = 0; i < yr * yc; ++i)
	{
		if (i % 64 == 0) cout << endl;
		cout << int(m_y[i]) << "\t";
	}
	cout << endl;
}

void JPEG::PrintU()
{
	//r, c扩展
	int row = (m_row + m_row % 16);
	int col   = (m_col + m_col % 16); 
	//u, v 16 * 16
	int uc = col >> 1;
	int ur = row >> 1;

	int vc = uc, vr = ur;
	cout << "U is :\n";
	for (int i = 0; i < ur * uc; ++i)
	{
		if (i % 64 == 0) cout << endl;
		cout << int(m_u[i]) << "\t";
	}
	cout << endl;
}

void JPEG::PrintV()
{
	//r, c扩展
	int row = (m_row + m_row % 16);
	int col   = (m_col + m_col % 16); 
	//u, v 16 * 16
	int uc = col >> 1;
	int ur = row >> 1;
	cout << "U is :\n";
	for (int i = 0; i < ur * uc; ++i)
	{
		if (i % 64 == 0) cout << endl;
		cout << int(m_v[i]) << "\t";
	}
	cout << endl;
}

void JPEG::PrintData()
{
	cout << "Data is :\n";
	for (int i = 0; i < m_row; ++i)
	{
		cout << endl;
		for (int j = 0; j < m_col * m_pixel; ++j)
		{
			cout << int(m_data[i * m_col * m_pixel + j]) << "\t";
		}
	}
	cout << "\n";
}

void JPEG::DCT(int *lpBuf)
{//8 * 8离散余弦变换
	int tp0, tp1, tp2, tp3, tp4, tp5, tp6, tp7;
	int tp10, tp11, tp12, tp13;
	int z1, z2, z3, z4, z5, z6;

	//对行运算
	int *dataptr = lpBuf;
	for (int i = 0; i < 8; ++i)
	{
		tp0  = dataptr[0] + dataptr[7];
		tp7  = dataptr[0] - dataptr[7];
		tp1  = dataptr[1] + dataptr[6];
		tp6  = dataptr[1] - dataptr[6];
		tp2  = dataptr[2] + dataptr[5];
		tp5  = dataptr[2] - dataptr[5];
		tp3  = dataptr[3] + dataptr[4];
		tp4  = dataptr[3] - dataptr[4];
		tp10 = tp0 + tp3;
		tp11 = tp1 + tp2;
		tp12 = tp1 - tp2;
		tp13 = tp0 - tp3;

		dataptr[0] = tp10 + tp11;
		dataptr[4] = (dataptr[0] >> 1) - tp11;
		//dataptr[4] = (dataptr[0] / 2) - tp11;
		/*  3 / 8 = 1 / 4 + 1 / 8  */
		dataptr[6] =  tp12 - (tp13 >> 2) - (tp13 >> 3);   
		//dataptr[6] =  tp12 - tp13 * 3 / 8;   
		dataptr[2] =  (dataptr[6] >> 2) + (dataptr[6] >> 3) + tp13; 
		//dataptr[2] =  dataptr[6] * 3 / 8 + tp13; 

		z2 = tp6 + (tp5 >> 2) + (tp5 >> 3);
		z1 = tp5 - (z2 >> 1) - (z2 >> 3);
		//z2 = tp6 + (tp5 * 3 / 8);
		//z1 = tp5 - (z2 * 5 / 8);
		z3 = tp4 + z1;
		z4 = tp4 - z1;
		z5 = z2 - tp7;
		z6 = z2 + tp7;

		dataptr[7] = z3 - (z6 >> 3);
		//dataptr[7] = z3 - (z6  / 8);
		dataptr[5] = z4 + z5 - (z5 >> 3);/* 7/8 = 1 - 1/8 */
		//dataptr[5] = z4 + z5 * 7 / 8;
		dataptr[3] = (dataptr[5] >> 1) - z5;
		//dataptr[3] = (dataptr[5] / 2) - z5;
		//dataptr[1] = (z3 >> 3) - z6;
		dataptr[1] = z6;

		//dataptr指向下一行
		dataptr += 8;
	}


	//对列运算
	dataptr = lpBuf;
	for (int i = 0; i < 8; ++i)
	{
		tp0  = dataptr[0] + dataptr[56];
		tp7  = dataptr[0] - dataptr[56];
		tp1  = dataptr[8] + dataptr[48];
		tp6  = dataptr[8] - dataptr[48];
		tp2  = dataptr[16] + dataptr[40];
		tp5  = dataptr[16] - dataptr[40];
		tp3  = dataptr[24] + dataptr[32];
		tp4  = dataptr[24] - dataptr[32];
		tp10 = tp0 + tp3;
		tp11 = tp1 + tp2;
		tp12 = tp1 - tp2;
		tp13 = tp0 - tp3;

		dataptr[0] = tp10 + tp11;
		dataptr[32] = (dataptr[0] >> 1) - tp11;
		//dataptr[32] = (dataptr[0] / 2) - tp11;
		/*  3 / 8 = 1 / 4 + 1 / 8  */
		dataptr[48] =  tp12 - (tp13 >> 2) - (tp13 >> 3);   
		//dataptr[48] =  tp12 - (tp13 * 3 / 8);  
		dataptr[16] =  (dataptr[48] >> 2) + (dataptr[48] >> 3) + tp13;
		//dataptr[16] =  (dataptr[48] * 3 / 8) + tp13; 

		z2 = tp6 + (tp5 >> 2) + (tp5 >> 3);
		z1 = tp5 - (z2 >> 1) - (z2 >> 3);
		//z2 = tp6 + (tp5 * 3 / 8);
		//z1 = tp5 - (z2 * 5 / 8);
		z3 = tp4 + z1;
		z4 = tp4 - z1;
		z5 = z2 - tp7;
		z6 = z2 + tp7;

		dataptr[56] = z3 - (z6 >> 3);
		//dataptr[56] = z3 - (z6 / 8);
		dataptr[40] = z4 + z5 - (z5 >> 3);/* 7/8 = 1 - 1/8 */
		//dataptr[40] = z4 + z5 * 7 / 8;/* 7/8 = 1 - 1/8 */
		dataptr[24] = (dataptr[40] >> 1) - z5;
		//dataptr[24] = (dataptr[40] / 2) - z5;
		//dataptr[8] = (z3 >> 3) - z6;
		dataptr[8] = z6;

		//dataptr指向下一行
		dataptr++;
	}
}

void JPEG::TDCT(int *lpBuf)
{//8 * 8离散反余弦变换
	int t0, t1, t2, t3, t4, t5, t6, t7;
	int t10, t11, t12, t13;
	int z1, z2, z3, z4, z5;

	//列变换 30次加减法,20次移位 
	int * dataptr = lpBuf;
	for (int i = 0; i < 8; ++i)
	{
		t10 = (dataptr[0] >> 1) + dataptr[32];
		t11 = dataptr[0] - t10;
		t13 = dataptr[16] - (dataptr[48] >> 2) - (dataptr[48] >> 3);
		t12 = dataptr[48] + (t13 >> 2) + (t13 >> 3);
		t1  = ((t11 + t12) >> 1);
		t2  = t11 - t1;
		t0  = ((t10 + t13) >> 1);
		t3  = t10 - t0;
		z3  = dataptr[56] + (dataptr[8] >> 3);
		z5  = (dataptr[40] >> 1) - dataptr[24];
		z4  = dataptr[40] + z5 - (z5 >> 3);
		z2  = ((z5 + dataptr[8]) >> 1);
		t7  = dataptr[8] - z2;
		t4  = ((z3 + z4) >> 1);
		z1  = z3 - t4;
		t5  = z1 + (z2 >> 1) + (z2 >> 3);
		t6  = z2 - (t5 >> 2) - (t5 >> 3);
		dataptr[0] = ((t0 + t7) >> 1);
		dataptr[56]= t0 - dataptr[0];
		dataptr[8] = ((t1 + t6) >> 1);
		dataptr[48]= t1 - dataptr[8];
		dataptr[16]= ((t2 + t5) >> 1);
		dataptr[40]= t2 - dataptr[16];
		dataptr[24]= ((t3 + t4) >> 1);
		dataptr[32]= t3 - dataptr[24];

		dataptr++;
	}

	//行变换
	dataptr = lpBuf;
	for (int i = 0; i < 8; ++i)
	{
		t10 = (dataptr[0] >> 1) + dataptr[4];
		t11 = dataptr[0] - t10;
		t13 = dataptr[2] - (dataptr[6] >> 2) - (dataptr[6] >> 3);
		t12 = dataptr[6] + (t13 >> 2) + (t13 >> 3);
		t1  = ((t11 + t12) >> 1);
		t2  = t11 - t1;
		t0  = ((t10 + t13) >> 1);
		t3  = t10 - t0;
		z3  = dataptr[7] + (dataptr[1] >> 3);
		z5  = (dataptr[5] >> 1) - dataptr[3];
		z4  = dataptr[5] + z5 - (z5 >> 3);
		z2  = ((z5 + dataptr[1]) >> 1);
		t7  = dataptr[1] - z2;
		t4  = ((z3 + z4) >> 1);
		z1  = z3 - t4;
		t5  = z1 + (z2 >> 1) + (z2 >> 3);
		t6  = z2 - (t5 >> 2) - (t5 >> 3);
		dataptr[0] = ((t0 + t7) >> 1);
		dataptr[7]= t0 - dataptr[0];
		dataptr[1] = ((t1 + t6) >> 1);
		dataptr[6]= t1 - dataptr[1];
		dataptr[2]= ((t2 + t5) >> 1);
		dataptr[5]= t2 - dataptr[2];
		dataptr[3]= ((t3 + t4) >> 1);
		dataptr[4]= t3 - dataptr[3];

		dataptr += 8;
	}
}

void JPEG::DispatchDCT()
{
	JPEG::RGBDataToYuv();
	int i = 0;
	for (; i < m_uSize; i += 64)
	{
		DCT(m_y + i);
		DCT(m_u + i);
		DCT(m_v + i);
	}
	for (;i < m_ySize; i+=64)
		DCT(m_y + i);

		JPEG::Quantize();

	JPEG::Zcode(m_y, m_ySize, m_yZcodeLen);
	JPEG::Zcode(m_u, m_uSize, m_uZcodeLen);
	JPEG::Zcode(m_v, m_vSize, m_vZcodeLen);
	JPEG::HuffmanCompress();
}

void JPEG::DispatchTDCT()
{
	JPEG::HuffmanDesCompress();
	JPEG::TZcode(m_y, m_ySize, m_yZcodeLen);
	JPEG::TZcode(m_u, m_uSize, m_uZcodeLen);
	JPEG::TZcode(m_v, m_vSize, m_vZcodeLen);

	JPEG::TQuantize();
	int i = 0;
	fidct_init();
	for (; i < m_uSize; i += 64)
	{
		TDCT(m_y + i);
		TDCT(m_u + i);
		TDCT(m_v + i);
	}
	for (;i < m_ySize; i+=64)
		TDCT(m_y + i);
	JPEG::YuvDataToRGB();
}

bool JPEG::DispatchDCT2()
{
	JPEG::RGBDataToYuv();

	//取消与外面数据关联
	m_data = NULL;

	int i = 0;
	for (; i < m_uSize; i += 64)
	{
		
		fdct(m_y + i);
		fdct(m_u + i);
		fdct(m_v + i);
		//JPEG::fast_fdct(m_y + i);
		//JPEG::fast_fdct(m_u + i);
		//JPEG::fast_fdct(m_v + i);
	}
	for (;i < m_ySize; i+=64)
		fdct(m_y + i);
		//JPEG::fast_fdct(m_y + i);

	//{
	//	std::ofstream couty("C:\\outyz.txt");
	//	for (int j = 0; j < m_ySize; ++j)
	//		couty << m_y[j] << " ";
	//	std::ofstream coutu("C:\\outuz.txt");
	//	for (int j = 0; j < m_uSize; ++j)
	//		coutu << m_u[j] << " ";
	//	std::ofstream coutv("C:\\outvz.txt");
	//	for (int j = 0; j < m_vSize; ++j)
	//		coutv << m_v[j] << " ";
	//}

	JPEG::Quantize();

	//{
	//		std::ofstream couty("C:\\see_who_in_Zcode.txt");
	//		   couty << "Y IN";
	//}

	//CRC32 cr32;

	if (!JPEG::Zcode(m_y, m_ySize, m_yZcodeLen))/* goto _ERR;*/
	{
		/*std::ofstream couty("C:\\see_who_in_Zcode.txt");
		couty << "u IN";*/
		fwhrsenderr << "Zcode in YYYY\t";
		 goto _ERR;
	}
	if (!JPEG::Zcode(m_u, m_uSize, m_uZcodeLen))// goto _ERR;
	{
		//std::ofstream couty("C:\\see_who_in_Zcode.txt");
		//couty << "v IN";
		fwhrsenderr << "Zcode in UUUU\t";
		goto _ERR;
	}
	if (!JPEG::Zcode(m_v, m_vSize, m_vZcodeLen)) //goto _ERR;
	{
		fwhrsenderr << "Zcode in VVVV\t";
		goto _ERR;
	}
	//{
	//	std::ofstream couty("C:\\outy.txt");
	//	for (int j = 0; j < m_yZcodeLen; ++j)
	//		couty << m_y[j] << " ";
	//	std::ofstream coutu("C:\\outu.txt");
	//	for (int j = 0; j < m_uZcodeLen; ++j)
	//		coutu << m_u[j] << " ";
	//	std::ofstream coutv("C:\\outv.txt");
	//	for (int j = 0; j < m_vZcodeLen; ++j)
	//		coutv << m_v[j] << " ";
	//}
	
	//{
	//	m_yZcodeLen = m_ySize;
	//	m_uZcodeLen = m_uSize;
	//	m_vZcodeLen = m_vSize;

	//	JPEG::NotHaveHuffman();	
	//}

	if (!JPEG::HuffmanCompress())/* goto _ERR;*/
	{
		fwhrsenderr << "HuffmanCompress\t";
		goto _ERR;
	}
	//
	//m_send_data->crc32 = cr32.GetCRC32(m_send_data->m_data, m_send_data->dataLen);
	int crc32 = 0;
	for (int i = 0; i < m_send_data->dataLen; ++i)
	{
		crc32 += m_send_data->m_data[i];
		if (crc32 > 23456 || crc32 < -23456) crc32 = crc32 % 23456; 
	}
	m_send_data->crc32 = crc32;
/*
	std::ofstream ct("C:\\out_t.txt");
	for (int j = 0; j < 64 * 5; ++j)
		ct << m_y[j] << "\t";*/
	//std::ofstream ct("C:\\out_t.txt");
	//for (int k = 0; k < m_yZcodeLen; ++k)
	//	if (m_y[k] >= 128 || m_y[k] < -128)
	//		/*MessageBoxA(NULL, "catch", "catch", MB_OK);*/
	//		ct << "catch" << "\t";
	//for (int k = 0; k < m_uZcodeLen; ++k)
	//	if (m_u[k] >= 128 || m_u[k] < -128)
	//	   //MessageBoxA(NULL, "catch", "catch", MB_OK);
	//	   	ct << "catch" << "\t";
	////	ct << m_u[k];
	//for (int k = 0; k < m_vZcodeLen; ++k)
	//	if (m_v[k] >= 128 || m_v[k] < -128)
	//		//MessageBoxA(NULL, "catch", "catch", MB_OK);
	//			ct << "catch" << "\t";
	//	ct << m_v[k];
	return true;
_ERR:
	if (m_y != NULL) delete [] m_y;
	m_y = NULL;
	if (m_u != NULL) delete [] m_u;
	m_u = NULL;
	if (m_v != NULL) delete [] m_v;
	m_v = NULL;
	return false;
}

bool JPEG::DispatchTDCT2()
{

	//std::ofstream ct("C:\\out2_t.txt");
	//for (int j = 0; j < 64 * 5; ++j)
	//	ct << m_y[j] << "\t";
	//CRC32 cr32;
	//int crc32 = cr32.GetCRC32(m_send_data->m_data, m_send_data->dataLen);
	int crc32 = 0;
	int huflen = sizeof(HUFFTREE)*512*3;
	if ((m_send_data->uHufLen+m_send_data->yHufLen+m_send_data->vHufLen+huflen) != m_send_data->dataLen)
	{
		fwhrrecverr << "datalen err\n";
		return false;
	}
	for (int i = 0; i < m_send_data->dataLen; ++i)
	{
		crc32 += m_send_data->m_data[i];
		if (crc32 > 23456 || crc32 < -23456) crc32 = crc32 % 23456; 
	}

	if (crc32 != m_send_data->crc32)
	{
		fwhrrecverr << "\ncrc32 err\n";
		return false;
	}
//return false;
	 //JPEG::InitJpegData();
	if (!JPEG::HuffmanDesCompress()) //goto _ERR;
	{
		fwhrrecverr << "HuffmanDesCompress\t";
		goto _ERR;
	}
	//{
	//	std::ofstream cty("C:\\out2y_t.txt");
	//	for (int j = 0; j < m_yZcodeLen; ++j)
	//		cty << m_y[j] << " ";
	//	std::ofstream ctu("C:\\out2u_t.txt");
	//	for (int j = 0; j < m_uZcodeLen; ++j)
	//		ctu << m_u[j] << " ";
	//	std::ofstream ctv("C:\\out2v_t.txt");
	//	for (int j = 0; j < m_vZcodeLen; ++j)
	//		ctv << m_v[j]  << " ";
	//}
	//{
	//	std::ofstream couty("C:\\see_who_in_Zcode.txt");
	//	couty << "Y IN";
	//}
	if (!JPEG::TZcode(m_y, m_ySize, m_yZcodeLen))// goto _ERR;
	{
		fwhrrecverr << "Tzcode YYY\t";
		goto _ERR;
	}
	//{
	//	std::ofstream couty("C:\\see_who_in_Zcode.txt");
	//	couty << "u IN";
	//}
	if (!JPEG::TZcode(m_u, m_uSize, m_uZcodeLen)) //goto _ERR;
	{
		fwhrrecverr << "Tzcode UUU\t";
		goto _ERR;
	}
	//{
	//	std::ofstream couty("C:\\see_who_in_Zcode.txt");
	//	couty << "v IN";
	//}
	if (!JPEG::TZcode(m_v, m_vSize, m_vZcodeLen)) //goto _ERR;
	{
		fwhrrecverr << "Tzcode VVV\t";
		goto _ERR;
	}

	JPEG::TQuantize();
	//{
	//	std::ofstream cty("C:\\out2yz_t.txt");
	//	for (int j = 0; j < m_ySize; ++j)
	//		cty << m_y[j] << " ";
	//	std::ofstream ctu("C:\\out2uz_t.txt");
	//	for (int j = 0; j < m_uSize; ++j)
	//		ctu << m_u[j] << " ";
	//	std::ofstream ctv("C:\\out2vz_t.txt");
	//	for (int j = 0; j < m_vSize; ++j)
	//		ctv << m_v[j]  << " ";
	//}
	int i = 0;
	fidct_init();
	for (; i < m_uSize; i += 64)
	{
		fidct(m_y + i);
		fidct(m_u + i);
		fidct(m_v + i);
		//ctv << i << "\t";
	}
	for (;i < m_ySize; i+=64)
		fidct(m_y + i);
	JPEG::YuvDataToRGB();
	//JPEG::AjustGB();
	return true;
_ERR:
	if (m_y != NULL) delete [] m_y;
	m_y = NULL;
	if (m_u != NULL) delete [] m_u;
	m_u = NULL;
	if (m_v != NULL) delete [] m_v;
	m_v = NULL;
	return false;
}

void JPEG::fidct(int * block)
{ 
	static int *blk;
	static long i;
	static long X0, X1, X2, X3, X4, X5, X6, X7, X8;
	for (i = 0; i < 8; i++)  
		/* idct rows */
	{ 
		blk = block + (i << 3); 
		if (!((X1 = blk[4] << 11) | (X2 = blk[6]) | (X3 = blk[2]) | (X4 = blk[1]) |    (X5 = blk[7]) | (X6 = blk[5]) | (X7 = blk[3])))  
		{  
			blk[0] = blk[1] = blk[2] = blk[3] = blk[4] = blk[5] = blk[6] = blk[7] = blk[0] << 3;
			continue; 
		}
		X0 = (blk[0] << 11) + 128; 
		/* for proper rounding in the fourth stage  */
		/* first stage  */  
		X8 = W7 * (X4 + X5);
		X4 = X8 + (W1 - W7) * X4; 
		X5 = X8 - (W1 + W7) * X5; 
		X8 = W3 * (X6 + X7); 
		X6 = X8 - (W3 - W5) * X6;
		X7 = X8 - (W3 + W5) * X7;
		/* second stage  */ 
		X8 = X0 + X1; 
		X0 -= X1; 
		X1 = W6 * (X3 + X2);
		X2 = X1 - (W2 + W6) * X2;
		X3 = X1 + (W2 - W6) * X3; 
		X1 = X4 + X6; 
		X4 -= X6; 
		X6 = X5 + X7; 
		X5 -= X7;

		/* third stage  */

		X7 = X8 + X3; 
		X8 -= X3; 
		X3 = X0 + X2;
		X0 -= X2; 
		X2 = (181 * (X4 + X5) + 128) >> 8;
		X4 = (181 * (X4 - X5) + 128) >> 8;

		/* fourth stage  */

		blk[0] = (int) ((X7 + X1) >> 8);
		blk[1] = (int) ((X3 + X2) >> 8);
		blk[2] = (int) ((X0 + X4) >> 8); 
		blk[3] = (int) ((X8 + X6) >> 8); 
		blk[4] = (int) ((X8 - X6) >> 8); 
		blk[5] = (int) ((X0 - X4) >> 8);
		blk[6] = (int) ((X3 - X2) >> 8); 
		blk[7] = (int) ((X7 - X1) >> 8);

	}      
	/* end for ( i = 0; i < 8; ++i ) IDCT-rows */

	for (i = 0; i < 8; i++) 
		/* idct columns */
	{
		blk = block + i; 
		/* shortcut  */ 
		if (!   ((X1 = (blk[32] << 8)) | (X2 = blk[48]) | (X3 = blk[16]) | (X4 = blk[8])    | (X5 = blk[56]) | (X6 = blk[40]) | (X7 = blk[24])))   
		{  
			blk[0] = blk[8] = blk[16] = blk[24] = blk[32] =    blk[40] = blk[48] = blk[56] = iclp[(blk[0] + 32) >> 6]; 
			continue;  
		}
		X0 = (blk[0] << 8) + 8192;

		/* first stage  */ 
		X8 = W7 * (X4 + X5) + 4;
		X4 = (X8 + (W1 - W7) * X4) >> 3;
		X5 = (X8 - (W1 + W7) * X5) >> 3;  
		X8 = W3 * (X6 + X7) + 4;
		X6 = (X8 - (W3 - W5) * X6) >> 3;
		X7 = (X8 - (W3 + W5) * X7) >> 3;

		/* second stage  */

		X8 = X0 + X1;
		X0 -= X1;
		X1 = W6 * (X3 + X2) + 4;
		X2 = (X1 - (W2 + W6) * X2) >> 3;
		X3 = (X1 + (W2 - W6) * X3) >> 3; 
		X1 = X4 + X6;
		X4 -= X6;
		X6 = X5 + X7; 
		X5 -= X7;

		/* third stage  */ 

		X7 = X8 + X3;
		X8 -= X3;
		X3 = X0 + X2;
		X0 -= X2; 
		X2 = (181 * (X4 + X5) + 128) >> 8;
		X4 = (181 * (X4 - X5) + 128) >> 8;

		/* fourth stage  */ 

		blk[0] = iclp[(X7 + X1) >> 14];
		blk[8] = iclp[(X3 + X2) >> 14]; 
		blk[16] = iclp[(X0 + X4) >> 14];
		blk[24] = iclp[(X8 + X6) >> 14]; 
		blk[32] = iclp[(X8 - X6) >> 14];
		blk[40] = iclp[(X0 - X4) >> 14]; 
		blk[48] = iclp[(X3 - X2) >> 14]; 
		blk[56] = iclp[(X7 - X1) >> 14];
	}
}

void JPEG::fidct_init()
{ 
	int i;
	iclp = iclip + 512;
	for (i = -512; i < 512; i++) 
		iclp[i] = (i < -256) ? -256 : ((i > 255) ? 255 : i);
}

void JPEG::fdct(int *block)
{
 int tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7;
 int tmp10, tmp11, tmp12, tmp13;
 int z1, z2, z3, z4, z5;
 int *blkptr;
 int *dataptr;
 int data[64];
 int i;

 /* Pass 1: process rows. */
 /* Note results are scaled up by sqrt(8) compared to a true DCT; */
 /* furthermore, we scale the results by 2**PASS1_BITS. */

 dataptr = data;
 blkptr = block;
 for (i = 0; i < 8; i++) {
  tmp0 = (int)(blkptr[0] + blkptr[7]);
  tmp7 = (int)(blkptr[0] - blkptr[7]);
  tmp1 = (int)(blkptr[1] + blkptr[6]);
  tmp6 = (int)(blkptr[1] - blkptr[6]);
  tmp2 = (int)(blkptr[2] + blkptr[5]);
  tmp5 = (int)(blkptr[2] - blkptr[5]);
  tmp3 = (int)(blkptr[3] + blkptr[4]);
  tmp4 = (int)(blkptr[3] - blkptr[4]);

  tmp10 = tmp0 + tmp3;
  tmp13 = tmp0 - tmp3;
  tmp11 = tmp1 + tmp2;
  tmp12 = tmp1 - tmp2;

  dataptr[0] = (tmp10 + tmp11) << PASS1_BITS;
  dataptr[4] = (tmp10 - tmp11) << PASS1_BITS;

  z1 = (tmp12 + tmp13) * FIX_0_541196100;
  dataptr[2] = DESCALE(z1 + tmp13 * FIX_0_765366865, CONST_BITS - PASS1_BITS);
  dataptr[6] = DESCALE(z1 + tmp12 * (-FIX_1_847759065), CONST_BITS - PASS1_BITS);

 

  z1 = tmp4 + tmp7;
  z2 = tmp5 + tmp6;
  z3 = tmp4 + tmp6;
  z4 = tmp5 + tmp7;
  z5 = (z3 + z4) * FIX_1_175875602; /* sqrt(2) * c3 */

  tmp4 *= FIX_0_298631336; /* sqrt(2) * (-c1+c3+c5-c7) */
  tmp5 *= FIX_2_053119869; /* sqrt(2) * ( c1+c3-c5+c7) */
  tmp6 *= FIX_3_072711026; /* sqrt(2) * ( c1+c3+c5-c7) */
  tmp7 *= FIX_1_501321110; /* sqrt(2) * ( c1+c3-c5-c7) */
  z1 *= -FIX_0_899976223;  /* sqrt(2) * (c7-c3) */
  z2 *= -FIX_2_562915447;  /* sqrt(2) * (-c1-c3) */
  z3 *= -FIX_1_961570560;  /* sqrt(2) * (-c3-c5) */
  z4 *= -FIX_0_390180644;  /* sqrt(2) * (c5-c3) */

  z3 += z5;
  z4 += z5;

  dataptr[7] = DESCALE(tmp4 + z1 + z3, CONST_BITS - PASS1_BITS);
  dataptr[5] = DESCALE(tmp5 + z2 + z4, CONST_BITS - PASS1_BITS);
  dataptr[3] = DESCALE(tmp6 + z2 + z3, CONST_BITS - PASS1_BITS);
  dataptr[1] = DESCALE(tmp7 + z1 + z4, CONST_BITS - PASS1_BITS);

  dataptr += 8;   /* advance pointer to next row */
  blkptr += 8;
 }

 /* Pass 2: process columns.
  * We remove the PASS1_BITS scaling, but leave the results scaled up
  * by an overall factor of 8.
  */

 dataptr = data;
 for (i = 0; i < 8; i++) {
  tmp0 = dataptr[0] + dataptr[56];
  tmp7 = dataptr[0] - dataptr[56];
  tmp1 = dataptr[8] + dataptr[48];
  tmp6 = dataptr[8] - dataptr[48];
  tmp2 = dataptr[16] + dataptr[40];
  tmp5 = dataptr[16] - dataptr[40];
  tmp3 = dataptr[24] + dataptr[32];
  tmp4 = dataptr[24] - dataptr[32];

 

  tmp10 = tmp0 + tmp3;
  tmp13 = tmp0 - tmp3;
  tmp11 = tmp1 + tmp2;
  tmp12 = tmp1 - tmp2;

  dataptr[0] = DESCALE(tmp10 + tmp11, PASS1_BITS);
  dataptr[32] = DESCALE(tmp10 - tmp11, PASS1_BITS);

  z1 = (tmp12 + tmp13) * FIX_0_541196100;
  dataptr[16] = DESCALE(z1 + tmp13 * FIX_0_765366865, CONST_BITS + PASS1_BITS);
  dataptr[48] = DESCALE(z1 + tmp12 * (-FIX_1_847759065), CONST_BITS + PASS1_BITS);

 

  z1 = tmp4 + tmp7;
  z2 = tmp5 + tmp6;
  z3 = tmp4 + tmp6;
  z4 = tmp5 + tmp7;
  z5 = (z3 + z4) * FIX_1_175875602; /* sqrt(2) * c3 */

  tmp4 *= FIX_0_298631336; /* sqrt(2) * (-c1+c3+c5-c7) */
  tmp5 *= FIX_2_053119869; /* sqrt(2) * ( c1+c3-c5+c7) */
  tmp6 *= FIX_3_072711026; /* sqrt(2) * ( c1+c3+c5-c7) */
  tmp7 *= FIX_1_501321110; /* sqrt(2) * ( c1+c3-c5-c7) */
  z1 *= -FIX_0_899976223;  /* sqrt(2) * (c7-c3) */
  z2 *= -FIX_2_562915447;  /* sqrt(2) * (-c1-c3) */
  z3 *= -FIX_1_961570560;  /* sqrt(2) * (-c3-c5) */
  z4 *= -FIX_0_390180644;  /* sqrt(2) * (c5-c3) */

  z3 += z5;
  z4 += z5;

  dataptr[56] = DESCALE(tmp4 + z1 + z3, CONST_BITS + PASS1_BITS);
  dataptr[40] = DESCALE(tmp5 + z2 + z4, CONST_BITS + PASS1_BITS);
  dataptr[24] = DESCALE(tmp6 + z2 + z3, CONST_BITS + PASS1_BITS);
  dataptr[8] = DESCALE(tmp7 + z1 + z4, CONST_BITS + PASS1_BITS);

  dataptr++;    /* advance pointer to next column */
 }
 /* descale */
 for (i = 0; i < 64; i++)
  block[i] = (int)DESCALE(data[i], 3);
}

void JPEG::Quantize()
{

	const int std_y_qt[64] = {
		16,11,10,16,24,40,51,61,
		12,12,14,19,26,58,60,55,
		14,13,26,24,40,57,69,56,
		14,17,22,29,51,87,80,62,
		18,22,37,56,68,109,103,77,
		24,35,55,64,81,104,113,92,
		49,64,78,87,103,121,120,101,
		72,92,95,98,112,100,103,99
	};

	const int std_cr_qt[64] = {
		17,18,24,47,99,99,99,99,
		18,21,26,66,99,99,99,99,
		24,26,56,99,99,99,99,99,
		47,66,99,99,99,99,99,99,
		99,99,99,99,99,99,99,99,
		99,99,99,99,99,99,99,99,
		99,99,99,99,99,99,99,99,
		99,99,99,99,99,99,99,99
	};
	int i = 0;
	int t = 0;
	m_yTableFirstByte = m_y[0];
	m_uTableFirstByte = m_u[0];
	m_vTableFirstByte = m_v[0];
	for (; i < m_uSize; ++i)
	{
		t = MOD(i, 6);
		if (t != 0) 
		{
			m_y[i] /= std_y_qt[t];
			m_u[i] /= std_cr_qt[t];
			m_v[i] /= std_cr_qt[t];
		} 
		else  
		{			
			m_y[i] -= m_yTableFirstByte;
			m_y[i] = m_y[i] >> 4;
			m_u[i] -= m_uTableFirstByte;
			m_u[i] = m_u[i] >> 4;
			m_v[i] -= m_vTableFirstByte;
			m_v[i] = m_v[i] >> 4;

		}

	}
	for (; i < m_ySize; ++i)
	{
		t = MOD(i, 6);
		if (t != 0) 
			m_y[i] /= std_y_qt[t];
		else 
		{
			m_y[i] -= m_yTableFirstByte;
			m_y[i] = m_y[i] >> 4;
		}
	}
	//std::ofstream cout("C:\\out.txt");
	//for (int j = 0; j < 64 * 5; ++j)
	//	cout << m_y[j] << "\t";
}

void JPEG::TQuantize()
{

	const int std_y_qt[64] = {
		16,11,10,16,24,40,51,61,
		12,12,14,19,26,58,60,55,
		14,13,26,24,40,57,69,56,
		14,17,22,29,51,87,80,62,
		18,22,37,56,68,109,103,77,
		24,35,55,64,81,104,113,92,
		49,64,78,87,103,121,120,101,
		72,92,95,98,112,100,103,99
	};

	const int std_cr_qt[64] = {
		17,18,24,47,99,99,99,99,
		18,21,26,66,99,99,99,99,
		24,26,56,99,99,99,99,99,
		47,66,99,99,99,99,99,99,
		99,99,99,99,99,99,99,99,
		99,99,99,99,99,99,99,99,
		99,99,99,99,99,99,99,99,
		99,99,99,99,99,99,99,99
	};
	int i = 0;
	int t = 0;
	for (; i < m_uSize; ++i)
	{
		t = MOD(i, 6);
		if (t != 0) 
		{
			m_y[i] *= std_y_qt[t];
			m_u[i] *= std_cr_qt[t];
			m_v[i] *= std_cr_qt[t];
		} 
		else
		{
			m_y[i] = m_y[i] << 4;
			m_y[i] += m_yTableFirstByte;
			m_u[i] = m_u[i] << 4;
			m_u[i] += m_uTableFirstByte;
			m_v[i] = m_v[i] << 4;
			m_v[i] += m_vTableFirstByte;
		}

	}
	for (; i < m_ySize; ++i)
	{
		t = MOD(i, 6);
		if (t != 0)  
			m_y[i] *= std_y_qt[t];
		else 
		{
			m_y[i] = m_y[i] << 4;
			m_y[i] += m_yTableFirstByte;
		} 
	}
}

//bool JPEG::Zcode(int *lpBuf, const int &bufSize, int &zcodeLen)
//{//lpBuf 取m_y, m_u, m_v; bufSize 取 m_ySize, m_uSize, m_vSize;
//	//zcodeLen 取 m_yZcodeLen, m_uZcodeLen, m_vZcodelen
//	if (lpBuf == NULL) return false;
//	if (bufSize <= 64) return true;
//	const int pos[64] = {
//		0,1,8,16,9,2,3,10,17,24,32,25,18,11,4,5,12,19,26,33,
//		40,48,41,34,27,20,13,6,7,14,21,28,35,42,49,56,57,50,43,
//		36,29,22,15,23,30,37,44,51,58,59,52,45,38,31,39,
//		46,53,60,61,54,47,55,62,63
//	};
//
//	zcodeLen = 0;
//	int temp[64*2];
//	int i = 0;
//////////////////
////	单独处理头64字节数据
//	for (int zero = 0; i < 64; ++i)
//	{
//		if (lpBuf[pos[i]] != 0) //|| zero == 15)
//		{//Z编码到行程编码
//			if (zero < 0 || zero > 63) return false;
//			temp[zcodeLen++] = zero;
//			temp[zcodeLen++] = lpBuf[pos[i]];
//			zero = 0;
//		}
//		else zero++;
//	}
//	//写入结束符
//	temp[zcodeLen++] = 0;
//	temp[zcodeLen++] = 0;
//	memcpy(lpBuf, temp, (zcodeLen*sizeof(int)));
//////////////////////
//	for (; i < bufSize; i += 64)
//	{
//		for (int j = 0, zero = 0; j < 64; ++j)
//		{
//			if (lpBuf[pos[j]+i] != 0)// || zero == 15)
//			{//Z编码到行程编码
//				if (zero < 0 || zero > 63) return false;
//				lpBuf[zcodeLen++] = zero;
//				lpBuf[zcodeLen++] = lpBuf[pos[j]+i];
//				//if (zcodeLen >= bufSize) return;
//				zero = 0;
//			}
//			else zero++;
//		}
//		//写入结束符
//		lpBuf[zcodeLen++] = 0;
//		lpBuf[zcodeLen++] = 0;
//	}
//	//zcodeLen--;
//	return true;
//}
//
//bool JPEG::TZcode(int *&lpBuf, const int &bufSize, int &zcodeLen)
//{//lpBuf 取m_y, m_u, m_v; bufSize 取 m_ySize, m_uSize, m_vSize;
// //zcodeLen 取 m_yZcodeLen, m_uZcodeLen, m_vZcodelen
//	if(lpBuf == NULL || bufSize <= 0 || zcodeLen <= 0)
//		return false;
//	const int pos[64] = {
//		0,1,8,16,9,2,3,10,17,24,32,25,18,11,4,5,12,19,26,33,
//		40,48,41,34,27,20,13,6,7,14,21,28,35,42,49,56,57,50,43,
//		36,29,22,15,23,30,37,44,51,58,59,52,45,38,31,39,
//		46,53,60,61,54,47,55,62,63
//	};
//
//	int *outBuf = new int[bufSize];
//	if (outBuf == NULL) return false;
//	memset(outBuf, 0, bufSize*sizeof(int));
//	int zcodepos = 0;
//	for (int i = 0; i < bufSize && zcodepos < zcodeLen; i += 64)
//	{
//		for (int curpos = 0; zcodepos < zcodeLen;  zcodepos += 2, ++curpos)
//		{
//			//1个64字节块结束
//			if (lpBuf[zcodepos] == 0 && lpBuf[zcodepos+1] == 0)
//			{ zcodepos += 2; break;}
//			curpos += lpBuf[zcodepos];
//			if(curpos < 0 || curpos > 63) 
//			{
//				fwhrrecverr << "curpos < 0 || curpos > 63\t";
//				delete [] outBuf;
//				outBuf = NULL;
//				return false;
//			}
//			outBuf[ i + pos[curpos] ] = lpBuf[zcodepos + 1];
//		}//for_curpos
//	}//for_i
//	delete [] lpBuf;
//	lpBuf = outBuf;
//	outBuf = NULL;
//	return true;
//}
//


bool JPEG::Zcode(int *&lpBuf, const int &bufSize, int &zcodeLen)
{//lpBuf 取m_y, m_u, m_v; bufSize 取 m_ySize, m_uSize, m_vSize;
	//zcodeLen 取 m_yZcodeLen, m_uZcodeLen, m_vZcodelen
	if (lpBuf == NULL || bufSize <= 0) return false;
	const int pos[64] = {
		0,1,8,16,9,2,3,10,17,24,32,25,18,11,4,5,12,19,26,33,
		40,48,41,34,27,20,13,6,7,14,21,28,35,42,49,56,57,50,43,
		36,29,22,15,23,30,37,44,51,58,59,52,45,38,31,39,
		46,53,60,61,54,47,55,62,63
	};
	int tpLen = bufSize * 2;
	int *outBuf = new int[tpLen];
	if (outBuf == NULL) return false;
	zcodeLen = 0;
	int temp[64*64];
	int i = 0;
	////////////////
	//	单独处理头64字节数据
	for (int zero = 0; i < 64; ++i)
	{
		if (lpBuf[pos[i]] != 0) //|| zero == 15)
		{//Z编码到行程编码
			if (zero < 0 || zero > 63) return false;
			temp[zcodeLen++] = zero;
			temp[zcodeLen++] = lpBuf[pos[i]];
			zero = 0;
		}
		else zero++;
	}
	//写入结束符
	temp[zcodeLen++] = 0;
	temp[zcodeLen++] = 0;
	if (zcodeLen+2 >= tpLen)
	{
		tpLen = zcodeLen + 4096;
		int *tpret = new int[tpLen];
		memcpy(tpret, temp, (zcodeLen*sizeof(int)));
		delete [] outBuf;
		outBuf = tpret;
		tpret = NULL;
	}
	else memcpy(outBuf, temp, (zcodeLen*sizeof(int)));
	////////////////////
	for (; i < bufSize; i += 64)
	{
		for (int j = 0, zero = 0; j < 64 && (i + j < bufSize); ++j)
		{
			if (lpBuf[pos[j]+i] != 0)// || zero == 15)
			{//Z编码到行程编码
				if (zero < 0 || zero > 63) 
				{
					delete [] outBuf;
					outBuf = NULL;
					return false;
				}
				outBuf[zcodeLen++] = zero;
				outBuf[zcodeLen++] = lpBuf[pos[j]+i];
				if (zcodeLen+2 >= tpLen)
				{
					tpLen = zcodeLen + 4096;
					int *tpret = new int[tpLen];
					memcpy(tpret, outBuf, zcodeLen * sizeof(int));
					delete [] outBuf;
					outBuf = tpret;
					tpret = NULL;
				}
				//if (zcodeLen >= bufSize) return;
				zero = 0;
			}
			else zero++;
		}
		//写入结束符
		outBuf[zcodeLen++] = 0;
		outBuf[zcodeLen++] = 0;
	}
	//zcodeLen--;
	delete [] lpBuf;
	lpBuf = outBuf;
	outBuf = NULL;
	return true;
}

bool JPEG::TZcode(int *&lpBuf, const int &bufSize, int &zcodeLen)
{//lpBuf 取m_y, m_u, m_v; bufSize 取 m_ySize, m_uSize, m_vSize;
	//zcodeLen 取 m_yZcodeLen, m_uZcodeLen, m_vZcodelen
	if(lpBuf == NULL || bufSize <= 0 || zcodeLen <= 0)
		return false;
	const int pos[64] = {
		0,1,8,16,9,2,3,10,17,24,32,25,18,11,4,5,12,19,26,33,
		40,48,41,34,27,20,13,6,7,14,21,28,35,42,49,56,57,50,43,
		36,29,22,15,23,30,37,44,51,58,59,52,45,38,31,39,
		46,53,60,61,54,47,55,62,63
	};

	int *outBuf = new int[bufSize];
	if (outBuf == NULL) return false;
	memset(outBuf, 0, bufSize*sizeof(int));
	int zcodepos = 0;
	for (int i = 0; i < bufSize && zcodepos < zcodeLen; i += 64)
	{
		for (int curpos = 0; zcodepos < zcodeLen;  zcodepos += 2, ++curpos)
		{
			//1个64字节块结束
			if (lpBuf[zcodepos] == 0 && lpBuf[zcodepos+1] == 0)
			{ zcodepos += 2; break;}
			curpos += lpBuf[zcodepos];
			if(curpos < 0 || curpos > 63) 
			{
				fwhrrecverr << "curpos < 0 || curpos > 63\t" << "pos = " << zcodeLen << "\t";
				delete [] outBuf;
				outBuf = NULL;
				return false;
			}
			outBuf[ i + pos[curpos] ] = lpBuf[zcodepos + 1];
		}//for_curpos
	}//for_i
	delete [] lpBuf;
	lpBuf = outBuf;
	outBuf = NULL;
	return true;
}


JPEGSENDDATA * JPEG::ReturnSendData()
{ 
	//JPEG::DispatchDCT();
	if (!JPEG::DispatchDCT2())
	{
		fwhrsenderr << "JPEG::DispatchDCT2()\t";
		return NULL;
	}
	return m_send_data;
}

BYTE * JPEG::ReturnData()
{
	//JPEG::DispatchTDCT();
	if (!JPEG::DispatchTDCT2()) /*return NULL;*/
	{
		fwhrrecverr << "JPEG::DispatchTDCT2()\t";
		return NULL;
	}
	return m_data;
}

bool JPEG::HuffmanCompress()
{
	int ty = m_yZcodeLen, tu = m_uZcodeLen, tv = m_vZcodeLen;
	//int crctree_y,crctree_u,crctree_v;

	BYTE *rety = NULL;BYTE *retu = NULL;BYTE *retv = NULL;
    int huflen = 0,  data_len = 0, freqstart = 0;
	HUFFTREE * treey = NULL,* treeu = NULL,* treev = NULL;
	HUFFMAN hufy(m_y, m_yZcodeLen);
	HUFFMAN hufu(m_u, m_uZcodeLen);
	HUFFMAN hufv(m_v, m_vZcodeLen);
	if (!hufy.HuffCode(rety, m_yZcodeLen)) 
	{
		fwhrsenderr << "!hufy.HuffCode(rety, m_yZcodeLen)\t";
		goto _ERR;
	}
	//hufy.CounTreeCrc(crctree_y);
	//for (int j = 0; j < 64 * 5; ++j)
	//	cout << (int)rety[j] << "\t";

	if (!hufu.HuffCode(retu, m_uZcodeLen))
	{
		fwhrsenderr << "!hufu.HuffCode(retu, m_uZcodeLen)\t";
		goto _ERR;
	}
	//hufu.CounTreeCrc(crctree_u);
	if (!hufv.HuffCode(retv, m_vZcodeLen))
	{
		fwhrsenderr << "!hufv.HuffCode(retv, m_vZcodeLen)\t";
		goto _ERR;
	}
	//if (m_data != NULL) delete [] m_data;
	//hufv.CounTreeCrc(crctree_v);
	huflen = sizeof(HUFFTREE)*512;
	data_len = m_yZcodeLen + m_uZcodeLen + m_vZcodeLen + huflen+huflen+huflen;
	m_data = new BYTE[data_len];
	if (m_data == NULL)
	{
		fwhrsenderr << "m_data == NULL\t";
		goto _ERR;
	}
	memcpy(m_data, rety, m_yZcodeLen);
	delete [] rety;
	rety = NULL;
	memcpy(m_data + m_yZcodeLen, retu, m_uZcodeLen);
	delete [] retu;
	retu = NULL;
	memcpy(m_data + m_yZcodeLen + m_uZcodeLen, retv, m_vZcodeLen);
	delete [] retv;
	retv = NULL;
	freqstart = m_yZcodeLen + m_uZcodeLen + m_vZcodeLen;
	if (!hufy.ReturnHuffTree(treey))
	{
		fwhrsenderr << "!hufy.ReturnHuffTree(treey)\t";
		goto _ERR;
	}
	memcpy(m_data + freqstart, treey, huflen);
	delete [] treey;treey=NULL;
	if (!hufu.ReturnHuffTree(treeu))
	{
		fwhrsenderr << "!hufy.ReturnHuffTree(treey)\t";
		goto _ERR;
	}
	memcpy(m_data + freqstart + huflen, treeu, huflen);
	delete [] treeu;treeu=NULL;
	if (!hufv.ReturnHuffTree(treev))
	{
		fwhrsenderr << "!hufy.ReturnHuffTree(treey)\t";
		goto _ERR;
	}
	memcpy(m_data + freqstart + huflen + huflen, treev, huflen);
	delete [] treev;treev=NULL;

	m_send_data = new JPEGSENDDATA;
	if (m_send_data == NULL)
	{
		fwhrsenderr << "m_send_data == NULL\t";
		goto _ERR;
	}
	m_send_data->col = m_col;
	m_send_data->dataLen = data_len;
	m_send_data->m_data = m_data;
	m_send_data->m_yTableFirstByte = m_yTableFirstByte;
	m_send_data->m_uTableFirstByte = m_uTableFirstByte;
	m_send_data->m_vTableFirstByte = m_vTableFirstByte;
	m_data = NULL;
	m_send_data->pixel = m_pixel;
	m_send_data->row = m_row;
	m_send_data->uHufLen = m_uZcodeLen;
	m_send_data->vHufLen = m_vZcodeLen;
	m_send_data->yHufLen = m_yZcodeLen;
	m_send_data->yZcodeLen = ty;
	m_send_data->uZcodeLen = tu;
	m_send_data->vZcodeLen = tv;

	//m_send_data->hufftreeCrc32_y = crctree_y;
	//m_send_data->hufftreeCrc32_u = crctree_u;
	//m_send_data->hufftreeCrc32_v = crctree_v;
	return true;

_ERR:
	if (rety != NULL) delete [] rety;
	rety = NULL;
	if (retu != NULL) delete [] retu;
	retu = NULL;
	if (retv != NULL) delete [] retv;
	retv = NULL;
	if (m_data != NULL) delete [] m_data;
	m_data = NULL;
	if (m_send_data != NULL) delete m_send_data;
	m_send_data = NULL;
	if (treey != NULL)delete [] treey;treey=NULL;
	if (treeu != NULL)delete [] treeu;treeu=NULL;
	if (treev != NULL)delete [] treev;treev=NULL;
	return false;
}

bool JPEG::HuffmanDesCompress()
{

	//if (m_send_data->m_data != NULL) delete [] m_send_data->m_data;
	//m_send_data->m_data = NULL;
	//if (m_send_data != NULL) delete [] m_send_data;
	//m_send_data = NULL;
	//return false;
/*
	std::ofstream cout("C:\\out2.txt");
	for (int j = 0; j < 64 * 5; ++j)
		cout << m_y[j] << "\t";*/
	if (m_send_data == NULL) 
	{
		fwhrrecverr << "m_send_data == NULL\t";
		return false;
	}
	if (m_send_data->m_data == NULL)
	{
		//delete m_send_data;
		//m_send_data = NULL;
		fwhrrecverr << "m_send_data->m_data == NULL\t";
		return false;
	}
	//yr 8 * 8
	int yc = m_col  + MOD(m_col, 3);
	int yr = m_row + MOD(m_row, 3);

	//r, c扩展
	int row = (m_row +  MOD(m_row, 4));
	int col   = (m_col + MOD(m_col, 4)); 
	//u, v 16 * 16
	int uc = col >> 1;
	int ur = row >> 1;
	uc = yc, ur = yr;
	int freqstart = m_send_data->yHufLen + m_send_data->uHufLen + m_send_data->vHufLen;
	int hufftreeLen = sizeof(HUFFTREE)<<9;

	BYTE *y = (BYTE *)m_send_data->m_data ;
	if (y == NULL || m_send_data->m_data == NULL)
	{
		//delete [] m_send_data->m_data;
		//m_send_data->m_data = NULL;
		//delete [] m_send_data;
		//m_send_data = NULL;
		fwhrrecverr << "y == NULL || m_send_data->m_data == NULL\t";
		return false;
	}
	//for (int j = 0; j < 64 * 5; ++j)
	//	/*ct << (int)y[j] << "\t";*/
	//	int kk = (int)y[j];
	HUFFMAN hufy(y, m_send_data->yZcodeLen+1, 
		(BYTE *)m_send_data->m_data+ freqstart, m_send_data->yHufLen);

	//int crctree = 0;
	//hufy.CounTreeCrc(crctree);
	//if (crctree != m_send_data->hufftreeCrc32_y)
	//{
	//	hufy.PrintSendTree();
	//}

	if (!hufy.HuffDesCode(m_y))
	{
		//delete [] m_send_data->m_data;
		//m_send_data->m_data = NULL;
		//delete [] m_send_data;
		//m_send_data = NULL;
		fwhrrecverr << "(!hufy.HuffDesCode(m_y)\t";
		return false;
	}
////////////////////////////////////////////////////////////////////////////////////////
	y = (BYTE *)m_send_data->m_data + m_send_data->yHufLen;
	if (y == NULL ||(m_send_data->m_data+ freqstart+hufftreeLen) == NULL)
	{
		//delete [] m_send_data->m_data;
		//m_send_data->m_data = NULL;
		//delete [] m_send_data;
		//m_send_data = NULL;
		fwhrrecverr << "y == NULL ||(m_send_data->m_data+ freqstart+hufftreeLen) == NULL\t";
		return false;
	}

	HUFFMAN hufu(y, m_send_data->uZcodeLen+1, 
		(BYTE *)m_send_data->m_data+ freqstart+hufftreeLen, m_send_data->uHufLen);
	
	//crctree = 0;
	//hufu.CounTreeCrc(crctree);
	//if (crctree != m_send_data->hufftreeCrc32_u)
	//{
	//	hufu.PrintSendTree();
	//}

	if (!hufu.HuffDesCode(m_u))
	{
		//delete [] m_send_data->m_data;
		//m_send_data->m_data = NULL;
		//delete [] m_send_data;
		//m_send_data = NULL;
		fwhrrecverr << "!hufu.HuffDesCode(m_u)\t";
		return false;
	}
////////////////////////////////////////////////////////////////////////////////////////
	y = (BYTE *)m_send_data->m_data + m_send_data->yHufLen + m_send_data->uHufLen;
	if (y == NULL || (m_send_data->m_data+ freqstart+hufftreeLen+hufftreeLen) == NULL)
	{
		//delete [] m_send_data->m_data;
		//m_send_data->m_data = NULL;
		//delete [] m_send_data;
		//m_send_data = NULL;
		fwhrrecverr << "y == NULL || (m_send_data->m_data+ freqstart+hufftreeLen+hufftreeLen) == NULL\t";
		return false;
	}
	HUFFMAN hufv(y, m_send_data->vZcodeLen+1, 
		(BYTE *)m_send_data->m_data+ freqstart+hufftreeLen+hufftreeLen, m_send_data->vHufLen);
	
	//crctree = 0;
	//hufv.CounTreeCrc(crctree);
	//if (crctree != m_send_data->hufftreeCrc32_v)
	//{
	//	hufv.PrintSendTree();
	//}


	if (!hufv.HuffDesCode(m_v))
	{
		//delete [] m_send_data->m_data;
		//m_send_data->m_data = NULL;
		//delete [] m_send_data;
		//m_send_data = NULL;
		fwhrrecverr << "!hufv.HuffDesCode(m_v)\t";
		return false;
	}
/////////////////////////////////////////////////////

	//{
	//	std::ofstream ct("C:\\out2y_t.txt");
	//	for (int j = 0; j < m_send_data->yZcodeLen; ++j)
	//		ct << m_y[j] << " ";
	//	std::ofstream ct("C:\\out2u_t.txt");
	//	for (int j = 0; j < m_send_data->uZcodeLen; ++j)
	//		ct << m_u[j] << " ";
	//	std::ofstream ct("C:\\out2v_t.txt");
	//	for (int j = 0; j < m_send_data->vZcodeLen; ++j)
	//		ct << m_v[j]  << " ";
	//}



	m_ySize = yc * yr;
	m_uSize = uc * ur;
	m_vSize = m_uSize;
	m_yZcodeLen = m_send_data->yZcodeLen;
	m_uZcodeLen = m_send_data->uZcodeLen;
	m_vZcodeLen = m_send_data->vZcodeLen;

	//if (m_send_data->m_data != NULL) delete [] m_send_data->m_data;
	//m_send_data->m_data = NULL;
	//if (m_send_data != NULL) delete [] m_send_data;
	//m_send_data = NULL;
	return true;
}

void JPEG::fast_fdct(int *block)
{
	const int DCTSIZE = 8;
	int tmp0, tmp1, tmp2, tmp3, tmp4,tmp5, tmp6, tmp7;
	int tmp10, tmp11, tmp12,tmp13;
	int z1, z2, z3, z4, z5, z11,z13;
	int *dataptr;
	int ctr;


	dataptr = block;
	for (ctr = DCTSIZE-1; ctr>= 0; ctr--) {
		tmp0 = dataptr[0] + dataptr[7];
		tmp7 = dataptr[0] - dataptr[7];
		tmp1 = dataptr[1] + dataptr[6];
		tmp6 = dataptr[1] - dataptr[6];
		tmp2 = dataptr[2] + dataptr[5];
		tmp5 = dataptr[2] - dataptr[5];
		tmp3 = dataptr[3] + dataptr[4];
		tmp4 = dataptr[3] - dataptr[4];



		tmp10 = tmp0 + tmp3; 
		tmp13 = tmp0 - tmp3;
		tmp11 = tmp1 + tmp2;
		tmp12 = tmp1 - tmp2;

		dataptr[0] = tmp10 + tmp11;
		dataptr[4] = tmp10 - tmp11;

		z1 = int((tmp12 + tmp13) * (0.707106781));
		dataptr[2] = tmp13 + z1; 
		dataptr[6] = tmp13 - z1;


		tmp10 = tmp4 + tmp5; 
		tmp11 = tmp5 + tmp6;
		tmp12 = tmp6 + tmp7;


		z5 = int((tmp10 - tmp12) * (0.382683433));
		z2 = int((0.541196100) * tmp10 + z5);
		z4 = int((1.306562965) * tmp12 + z5);
		z3 = int(tmp11 * (0.707106781));

		z11 = tmp7 +z3;  
		z13 = tmp7 - z3;

		dataptr[5] = z13 + z2; 
		dataptr[3] = z13 - z2;
		dataptr[1] = z11 + z4;
		dataptr[7] = z11 - z4;

		dataptr +=DCTSIZE;  
	}


	dataptr = block;
	for (ctr = DCTSIZE-1; ctr>= 0; ctr--) {
		tmp0 = dataptr[DCTSIZE*0] + dataptr[DCTSIZE*7];
		tmp7 = dataptr[DCTSIZE*0] - dataptr[DCTSIZE*7];
		tmp1 = dataptr[DCTSIZE*1] + dataptr[DCTSIZE*6];
		tmp6 = dataptr[DCTSIZE*1] - dataptr[DCTSIZE*6];
		tmp2 = dataptr[DCTSIZE*2] + dataptr[DCTSIZE*5];
		tmp5 = dataptr[DCTSIZE*2] - dataptr[DCTSIZE*5];
		tmp3 = dataptr[DCTSIZE*3] + dataptr[DCTSIZE*4];
		tmp4 = dataptr[DCTSIZE*3] - dataptr[DCTSIZE*4];



		tmp10 = tmp0 + tmp3; 
		tmp13 = tmp0 - tmp3;
		tmp11 = tmp1 + tmp2;
		tmp12 = tmp1 - tmp2;

		dataptr[DCTSIZE*0] = tmp10 + tmp11;
		dataptr[DCTSIZE*4] = tmp10 - tmp11;

		z1 = int((tmp12 + tmp13) * ( 0.707106781));
		dataptr[DCTSIZE*2] = tmp13 + z1;
		dataptr[DCTSIZE*6] = tmp13 - z1;


		tmp10 = tmp4 + tmp5; 
		tmp11 = tmp5 + tmp6;
		tmp12 = tmp6 + tmp7;


		z5 = int((tmp10 - tmp12) * ( 0.382683433));
		z2 = int(( 0.541196100) * tmp10 + z5);
		z4 = int(( 1.306562965) * tmp12 + z5);
		z3 = int(tmp11 * ( 0.707106781));

		z11 = tmp7 +z3;  
		z13 = tmp7 - z3;

		dataptr[DCTSIZE*5] = z13 + z2;
		dataptr[DCTSIZE*3] = z13 - z2;
		dataptr[DCTSIZE*1] = z11 + z4;
		dataptr[DCTSIZE*7] = z11 - z4;

		dataptr++;   
	}
}


void JPEG::NotHaveHuffman()
{
	m_send_data = new JPEGSENDDATA;
	assert(m_send_data != NULL);
	m_send_data->dataLen = m_yZcodeLen+m_uZcodeLen+m_vZcodeLen;
	m_send_data->m_data  = new BYTE[m_send_data->dataLen];
	assert(m_send_data->m_data != NULL);
	int pos = 0;
	for (int i = 0; i < m_yZcodeLen; ++i)
		m_send_data->m_data[pos++]=BYTE(m_y[i]);
	for (int i = 0; i < m_uZcodeLen; ++i)
		m_send_data->m_data[pos++]=BYTE(m_u[i]);
	for (int i = 0; i < m_vZcodeLen; ++i)
		m_send_data->m_data[pos++]=BYTE(m_v[i]);
	m_send_data->pixel = m_pixel;
	m_send_data->row = m_row;
	m_send_data->col = m_col;
	m_send_data->yZcodeLen = m_yZcodeLen;
    m_send_data->uZcodeLen = m_uZcodeLen;
    m_send_data->vZcodeLen = m_vZcodeLen;
	m_send_data->yHufLen = m_yZcodeLen;
	m_send_data->uHufLen = m_uZcodeLen;
	m_send_data->vHufLen = m_vZcodeLen;
	m_send_data->m_yTableFirstByte = m_yTableFirstByte;
	m_send_data->m_uTableFirstByte = m_uTableFirstByte;
	m_send_data->m_vTableFirstByte = m_vTableFirstByte;
}

void JPEG::InitJpegData()
{
	//m_col = m_send_data->col;
	//m_row = m_send_data->row;
	//m_pixel = m_send_data->pixel;
	m_yZcodeLen = m_send_data->yZcodeLen;
	m_uZcodeLen = m_send_data->uZcodeLen;
	m_vZcodeLen = m_send_data->vZcodeLen;

	//m_yTableFirstByte = m_send_data->m_yTableFirstByte;
	//m_uTableFirstByte = m_send_data->m_uTableFirstByte;
	//m_vTableFirstByte = m_send_data->m_vTableFirstByte;

	//yr 8 * 8
	int yc = m_col  + MOD(m_col, 3);
	int yr = m_row + MOD(m_row, 3);

	//r, c扩展
	int row = (m_row +  MOD(m_row, 4));
	int col   = (m_col + MOD(m_col, 4)); 
	//u, v 16 * 16
	int uc = col >> 1;
	int ur = row >> 1;
	uc = yc, ur = yr;
	m_ySize = yc * yr;
	m_uSize = uc * ur;
	m_vSize = m_uSize;



	m_y = new int[m_yZcodeLen];
	assert(m_y != NULL);
	m_u = new int[m_uZcodeLen];
	assert(m_u != NULL);
	m_v = new int[m_vZcodeLen];
	assert(m_v != NULL);
	int pos = 0;
	for (int i = 0; i < m_yZcodeLen; ++i)
		m_y[i] = int(char(m_send_data->m_data[pos++]));
	for (int i = 0; i < m_uZcodeLen; ++i)
		m_u[i] = int(char(m_send_data->m_data[pos++]));
	for (int i = 0; i < m_vZcodeLen; ++i)
		m_v[i] = int(char(m_send_data->m_data[pos++]));
	delete [] m_send_data->m_data;
	m_send_data->m_data = NULL;
	delete m_send_data;
	m_send_data = NULL;
}

void JPEG::AjustGB()
{
	int lb = 0, lg = 0, rb = 0, rg = 0;
	//for (int i = 4; i < m_col-4; i += 4)
	//	if (MOD(i,1) == 0)
	//	{//bgra
	//	  lb = m_data[i-4];
	//	  lg = m_data[i-3];
	//	  rb = m_data[i+4];
	//	  rg = m_data[i+5];
	//	  m_data[i+1]
	//	  m_data[i] = ((lb + rb)>>1);//b
	//	  m_data[i+1] = ((lg + rg)>>1);
	//	}

		//对列整理
	int startpos = 0, colByte = ((m_col*m_pixel)<<1);
	for (int i = 0; i < m_row; i += 2)
	  {
		for (int j = 4; j< colByte-4; j += 4)
		{
				lb = m_data[j + startpos-4];
				lg = m_data[j + startpos-3];
				rb = m_data[j + startpos+4];
				rg = m_data[j + startpos+5];
				m_data[j + startpos] = ((lb + rb)>>1);//b
				m_data[j + startpos+1] = ((lg + rg)>>1);//r
		}//for_j
		startpos += colByte;
	  }//for_i

	//行列整理
	//startpos = m_col*m_pixel, colByte = ((m_col*m_pixel)<<1);
	//int upb = 0, upg = 0, downb = 0, downg = 0, one_col_byte = startpos;
	//for (int i = 0; i < m_row-2; i += 2)
	//{
	//	for (int j = 0; j< one_col_byte;  j += 4)
	//	{
	//		upb = m_data[startpos + j - one_col_byte];
	//		downb = m_data[startpos + j + one_col_byte];
	//		upg = m_data[startpos + j + 1- one_col_byte];
	//		downg = m_data[startpos + j + 1 + one_col_byte];
	//		m_data[startpos + j] = ((upb+downb)<<1);
	//		m_data[startpos + j + 1] = ((upg+downg)<<1);
	//	}//for_j
	//	startpos += colByte;
	//}//for_i
}


/////////////////////////////////////////     class of HUFFMAN   ////////////////////////////////////////////////////////////////////

HUFFMAN::HUFFMAN(HUFFDATATYPE_EN *arry, int size)
{//arry要加压的数据,size加压数据的大小
	assert(arry != NULL && size > 0);
	m_arry = arry;
	m_arryLen = size;
	m_root = 0;
	//memset(m_freqCode, NULL, (sizeof(bool)<<8));
	const int initChild = 520;
	for (short i = 0; i < 512; ++i) 
	{
		m_freq[i].in_tree = false;
		m_freq[i].lchild = initChild;
		m_freq[i].parent = 0;
		m_freq[i].rchild = initChild;
		m_freq[i].weight = 0;
	}

	for (short i = 0; i < 256; ++i) 
	{
		m_freqCode[i] = NULL;
		m_freqCodeLen[i] = 0;
	}
}

HUFFMAN::HUFFMAN(HUFFDATATYPE_DES *arry, int size, HUFFDATATYPE_DES *hufftr, int hufLen)
{//m_arryLen = size 是解压后的文件的长度,arry是要解压的程序,hufftr是加压时的huffman树
//root是huffman树的根,hufLen数据HUFFMAN压缩后的长度
	assert(arry != NULL && size > 0 && hufftr != NULL && hufLen > 0);
	m_outarry = arry;
	m_arryLen = size;
	m_AfterhufLen = hufLen;
	for (short i = 0; i < 256; ++i)
		m_freqCode[i] = NULL;
	memcpy((BYTE*)m_freq, hufftr, (sizeof(HUFFTREE)<<9));

	for (short i = 0; i < 512; ++i)
		if (m_freq[i].parent == 0 && m_freq[i].weight > 0/* && m_freq[i].in_tree*/)
			m_root = i;
}

HUFFMAN::~HUFFMAN()
{
	for (int i = 0; i < 256; ++i)
		if (m_freqCode[i] != NULL)
		{
			delete [] m_freqCode[i];
			m_freqCode[i] = NULL;
		}
}

bool HUFFMAN::MakeHuffTree()
{
	for (int i = 0; i < m_arryLen; ++i)
		m_freq[ BYTE(m_arry[i]) ].weight++;
	short end = 256;
	for (short i = 0; i < 256; ++i, end++)
	{
		HUFFMAN::MakeMinPair(end);
		if (m_min_a == -1 || m_min_b == -1) break;
		m_freq[m_min_a].parent = m_freq[m_min_b].parent = end;
		m_freq[end].weight = m_freq[m_min_a].weight + m_freq[m_min_b].weight;
		if (m_freq[m_min_a].weight > m_freq[m_min_b].weight)
		{
			short tp_min = m_min_a;
			m_min_a = m_min_b;
			m_min_b = tp_min;
		}
		m_freq[end].lchild = m_min_a ; 
		m_freq[end].rchild =m_min_b; 
		m_freq[m_min_a].in_tree = m_freq[m_min_b].in_tree = true;
	}
	for (short i = 0; i < 256; ++i)
	{
		std::string str;
		short t = i;
		bool bIn = false;
		while (m_freq[t].parent != 0)
		{
			bIn = true;
			short tp = t;
			t = m_freq[t].parent;
			//左0 右 1
			if (m_freq[t].lchild == tp) str += '0';
			else str += '1';
		}
		//reverse(m_str[i], m_str[i] + m_str[i].size());
		if (bIn)
		{
			m_freqCodeLen[i] = (int)str.size();
			m_freqCode[i] = new bool[m_freqCodeLen[i]];
			for (int j = 0; j < m_freqCodeLen[i]; ++j)
				if (str[m_freqCodeLen[i]-1-j] == '0') m_freqCode[i][j] = false;
				else m_freqCode[i][j] = true;
		}
	}//for_i
	return true;
}

void HUFFMAN::MakeMinPair(const short &end)
{
	m_min_a = -1, m_min_b = -1;
	int wei_a = 2147483647, wei_b = 2147483647;
	for (short i = 0; i < end; ++i)
	{
		if (!m_freq[i].in_tree && m_freq[i].weight > 0)
		{//a first, b next
			if (wei_a > m_freq[i].weight)
			{
				wei_b = wei_a;
				m_min_b = m_min_a;
				wei_a = m_freq[i].weight;
				m_min_a = i;
			}
			else if (wei_b > m_freq[i].weight)
			{
					wei_b = m_freq[i].weight;
					m_min_b = i;
			}

		}//if_m_freq
	}//for_i
}
//std::ofstream cout_in_htree("C:\\in_htree.txt");
//std::ofstream cout_in_data("C:\\in_data.txt");
bool HUFFMAN::HuffCode(BYTE *&ret, int &ret_pos)
{
	if (!HUFFMAN::MakeHuffTree()) return false;
	//{
	//	
	//	for (int j = 0; j < 256; ++j)
	//	{
	//		cout_in_htree << j << "is   :" << m_str[j] << "\n";
	//  	    cout_in_data << m_arry[j] << "\t";
	//	}
	//	cout_in_htree << "\n\n\n\n\n\n\n=============================\n\n\n==========================\n\n\n\n";
	//	cout_in_data<< "\n\n\n\n\n\n\n=============================\n\n\n==========================\n\n\n\n";

	//}
	unsigned char bit1[8] = {
		0x80,
		0x40,
		0x20,
		0x10,
		0x8,
		0x4,
		0x2,
		0x1
	};//置1 
	unsigned char bit0[8] = {
		0x7F,
		0xBF,
		0xDF,
		0xEF,
		0xF7,
		0xFB,
		0xFD,
		0xFE
	};//置0 
	ret = new BYTE[m_arryLen];
	if (ret == NULL) return false;
	ret_pos = 0;
	int k = 0, strpos = 0;
	BYTE c;
	int allocSize = m_arryLen;
	for (int i = 0; i < m_arryLen; ++i)
	{
		c = BYTE(m_arry[i]);
		for (strpos = 0; strpos < m_freqCodeLen[c]; strpos++)
		{
			if (m_freqCode[c][strpos]) ret[ret_pos] |= bit1[k++];
			else ret[ret_pos] &= bit0[k++];
			
			if (k == 8)
			{
				k = 0; ret_pos++;
				if (ret_pos >= allocSize)
				{
					allocSize = ret_pos + 4096;
					BYTE *retp = new BYTE[allocSize];
					if (retp == NULL) 
					{
						delete [] ret;
						ret = NULL;
						return false;
					}
					memcpy(retp, ret, sizeof(BYTE) * ret_pos);
					delete [] ret;
					ret = retp;
					retp = NULL;
				}
			}
		}//while_k
	}//for_i
	if (k > 0) ret_pos++;
	return true;
}

//std::ofstream cout_hufftree("C:\\out_huftree.txt");
bool HUFFMAN::HuffDesCode(HUFFDATATYPE_EN *&ret)
{
	//HUFFMAN::MakeHuffTree();
	//{

	//	for (short i = 0; i < 256; ++i)
	//	{
	//		short t = i;
	//		while (m_freq[t].parent != 0)
	//		{
	//			short tp = t;
	//			t = m_freq[t].parent;
	//			//左0 右 1
	//			if (m_freq[t].lchild == tp) m_str[i] += '0';
	//			else m_str[i] += '1';
	//		}
	//		//reverse(m_str[i], m_str[i] + m_str[i].size());
	//		int len = m_str[i].size();
	//		int halt_len = len >> 1;
	//		len--;
	//		for (int j = 0; j < halt_len; ++j)
	//		{
	//			char c = m_str[i][j];
	//			m_str[i][j] = m_str[i][len-j];
	//			m_str[i][len-j] = c;
	//		}
	//	}//for_i
	//	for (int j = 0; j < 256; ++j)
	//		cout_hufftree << j << "is   :" << m_str[j] << "\n";
	//	cout_hufftree << "\n\n\n\n\n\n\n=============================\n\n\n==========================\n\n\n\n";
	//}
	unsigned char bit1[8] = {
		0x80,
		0x40,
		0x20,
		0x10,
		0x8,
		0x4,
		0x2,
		0x1
	};//置1 

	ret = new HUFFDATATYPE_EN[m_arryLen];
	if (ret == NULL) return false;
	//try
	//{
		int pos = 0, k = 0;
		for (int i = 0; i < m_arryLen; ++i)
		{
			unsigned short t = m_root;
			while (true)
			{
			//测试位是否为0,左0 右 1
			//test = /*unsigned char(*/m_outarry[pos]/*)*/ & bit1[k++];
			//if (test == 0) t = m_freq[t].lchild;
			//else t = m_freq[t].rchild;
				if ((m_outarry[pos] & bit1[k]) == bit1[k])
					t = m_freq[t].rchild;
				else t = m_freq[t].lchild;
				k++;
				if (k == 8)
				{
					k = 0;
					pos++;
					if (pos > m_AfterhufLen)
					{
						return true;
						if (ret != NULL) delete [] ret;
						ret = NULL;
						return false;
					}
				}
				if (t < 256) break;//叶子是小于256的,打在叶子上就是结果了
			}
			ret[i] = HUFFDATATYPE_EN(char(t));
		}//for_i
		return true;
	//}
	//catch (...)
	//{
	//	if (ret != NULL) delete [] ret;
	//	ret = NULL;
	//	return false;
	//}

	//std::ofstream ct("C:\\out2_t.txt");
	//for (int j = 0; j < 64 * 5; ++j)
	//	ct << ret[j] << "\t";

}

bool HUFFMAN::ReturnHuffTree(HUFFTREE * &hufftr)
{//返回huffman的树和根
	if (hufftr != NULL) delete [] hufftr;
	hufftr = new HUFFTREE[512];
	if (hufftr == NULL) return false;
	memcpy(hufftr, m_freq, sizeof(HUFFTREE) * 512);
	return true;
}

void HUFFMAN::PrintSendTree()
{
	for (int i = 0; i < 256; ++i)
	{
		ftreeSend << "i=" << i << "\tw=" << m_freq[i].weight << "\tpar="
			               << m_freq[i].weight   <<"\tlch=" << m_freq[i].lchild << "\trch=" << m_freq[i].rchild
						   << "\tin_tree=";
		if (m_freq[i].in_tree) ftreeSend << "true\n";
		else ftreeSend << "false\n";
	}
}

//void HUFFMAN::PrintSendTree()
//{
//	for (int i = 0; i < 256; ++i)
//	{
//		ftreeSend << "i=" << i << "\tw=" << m_freq[i].weight << "\tpar="
//			<< m_freq[i].weight   <<"\tlch=" << m_freq[i].lchild << "\trch=" << m_freq[i].rchild
//			<< "\tin_tree=";
//		if (m_freq[i].in_tree) ftreeSend << "true\n";
//		else ftreeSend << "false\n";
//	}
//}

void HUFFMAN::CounTreeCrc(int &ret)
{
	ret = 0;
	for (int i = 0; i < 256; ++i)
	{
		ret = m_freq[i].weight+m_freq[i].lchild+m_freq[i].rchild+m_freq[i].parent;
		if (m_freq[i].in_tree) ++ret;
		if (ret > 200000 || ret < -200000) ret %= 200000;
	}
}


 

 

使用

输入 32位BMP数据部分,使用 GetBitmapBits ;获得BMP数据部分

 struct BITMAPDATA
  {//BMP格式数据消息头
       WORD bitCount;//单位像素包含BYTE数
       DWORD bitWid, bitHei;//图片以像素为单位的宽和高
  };

 BITMAPDATA lp;
 BYTE *lpBitmapData = NULL;
//函数见下面
GetBmpBits(lp.bitCount, lp.bitWid, lp.bitHei, lpBitmapData);

JPEG jpeg(lpBitmapData, lp.bitHei, lp.bitWid, lp.bitCount);
JPEGSENDDATA *sendJpeg = jpeg.ReturnSendData();//压缩后的数据保存于sendJpeg



 

bool GetBmpBits(WORD &pixelBytes, DWORD &width, DWORD &height, BYTE *&lpMemBitmapBits)
{////获取当前屏幕为BMP数据返回
	//采样
	BITMAP	bm;
	HBITMAP hBit = GetScreenToHBitmap();

	//OpenClipboard(NULL);
	//EmptyClipboard();
	//SetClipboardData(CF_BITMAP, hBit);
	//CloseClipboard();

	GetObjectW(hBit, sizeof(bm), (LPSTR)&bm);
	//DWORD dwBitCount   = 32; //32位图
	pixelBytes = bm.bmBitsPixel / 8; 
	DWORD bmpWidth = (bm.bmWidth * bm.bmBitsPixel + bm.bmBitsPixel - 1) / bm.bmBitsPixel;
	DWORD dwBitmapSize = bmpWidth * bm.bmHeight   * pixelBytes;
	width = bm.bmWidth;
	height= bm.bmHeight;
	if (dwBitmapSize <= 0 || pixelBytes <= 0 || bmpWidth <= 0) return false; 
	lpMemBitmapBits = new BYTE[dwBitmapSize];
	if (lpMemBitmapBits == NULL) return false;

	GetBitmapBits(hBit, dwBitmapSize, lpMemBitmapBits);
	BYTE *tp = new BYTE[dwBitmapSize];
	DWORD bits = bmpWidth * pixelBytes;
	//数据倒置,BMP数据特点
	for (LONG i = 0, j = bm.bmHeight - 1; i < bm.bmHeight; ++i, --j)
	{
		memcpy((tp + i * bits), (lpMemBitmapBits + j * bits), bits);
	}

	delete [] lpMemBitmapBits;
	lpMemBitmapBits = tp;
	///////////////////////////////////////////////
	//std::ofstream file3("c:\\out1.txt");//
	//for (int i = 0; i < width * 8; ++i)
	//{
	//	file3 << int(lpMemBitmapBits[i]) << " ";
	//	if (i %width == 0) file3 << "\r\n";
	//}
	//////////////////////////////////////////////
	tp = NULL;
	DeleteObject(hBit);
	return true;
}

解压:

JPEG jpeg(recvJpeg);
//将JPEG格式的数据转换为BMP数据格式
BYTE *bitmapdata = jpeg.ReturnData();

 

 

 

简单说明

 

压缩步骤:

1 颜色转换(采样ARGB->YUV采用1:1:1比例)

2 DCT变换(快速离散余弦变换)

3 量化 (采用JPEG标准量化表)

4 Z编码

5 使用DPCM对直流系数(DC)进行编码(只是对第一个8*8子块首位作偏差)

6 AC 使用RLE编码

7 标准HUFFMAN 编码,进一步压缩

 

颜色转换

原RGB数据(注:1为 1,1,1结构, 2 为 2,2,2结构):

11111111 22222222

11111111 22222222

11111111 22222222

11111111 22222222

11111111 22222222

11111111 22222222

11111111 22222222

11111111 22222222

分割后(注:1为 1,2 为 2):

Y,U,V数组表都为:

11111111 11111111 11111111 11111111 11111111 11111111 11111111 11111111  22222222  22222222 22222222  22222222  22222222  22222222    22222222    22222222  22222222

 

参考:

http://www.ibm.com/developerworks/cn/linux/l-cn-jpeg

http://fengyezufeng.blog.163.com/blog/static/96771294200961722445725

你可能感兴趣的:(简单JPEG类模拟)