c++ jpeg图片压缩 程序计算熵编码

纯手写,jpeg压缩流程上传到资源资源下载 

#define _CRT_SECURE_NO_WARNINGS
#define _USE_MATH_DEFINES
#include 
#include 
#include
#include
#include
#include

using namespace std;

int getArange(int a){//获得VLC映射
	if (a < 0) a = -1 * a;
	int b = 1;
	while (pow(2, b) < a) {
		b++;

	}
	return b;
}


//计算一个正数的二进制字符串
string toBinary(int a) {
	string str = "";
	vector seq;
	while (a != 0) {
		seq.push_back(a % 2);
		a /= 2;
	}

	for (int i = seq.size() - 1; i >= 0; i--) {
		str += seq[i] + '0';
	}
	if (str == "") str = "0";
	return str;
}

//计算一个负数的VLI码
string getVLI(int a) {
	string str = "";
	vector seq;
	a = -1 * a;
	while (a != 0) {

		int q = a % 2;
		if (q == 1) q = 0;
		else q = 1;

		seq.push_back(q);

		a /= 2;
	}

	for (int i = seq.size() - 1; i >= 0; i--) {
		str += seq[i] + '0';
	}

	return str;

}

struct code {  //熵编码的结构
	string ssss;
	string diff;
	code(string ss, string dif) {
		ssss = ss;
		diff = dif;
	}

};

struct midsyn {  //cd 的中间符号(sssrrr,ac)
	int a, b, c;
	midsyn(int a1, int a2, int a3) {
		a = a1;
		b = a2;
		c = a3;
	}
};

class code_block
{
public:
	vector vc;

	code_block() {  //默认构造方法

	}


private:

};


//定义8x8 的图像块类 
class pixel_block
{
public:
	double matrix[8][8];

	pixel_block() {  //默认构造方法

		for (int i = 0; i < 8; i++)
			for (int j = 0; j < 8; j++) {
				matrix[i][j] = 0.0;
			}
	}

	//正向离散余弦变换
	double dct(int u, int v) {
		double re_value=0;
		if (u == 0 && v == 0) {
			double result = 0;
			double cv = 1 / sqrt(2);
			for(int i=0;i<8;i++)
				for (int j = 0; j < 8; j++) {
					result += matrix[i][j];
				}
			re_value = 1.0 / 4.0 * cv * cv * result;
		}
		else {
			double result = 0;
			
			for (int i = 0; i < 8; i++)
				for (int j = 0; j < 8; j++) {
					result += matrix[i][j]*cos((2*i+1)*u*M_PI/16)* cos((2 * j + 1) * v * M_PI / 16.0);
				}
			
			re_value = 1.0 / 4.0  * result;
			
		}

		return re_value;
	}

private:

};


int main()
{
	FILE* file = fopen("d03.data", "rb");
	int h, w;
	fread(&h, sizeof(int), 1, file); // 高度
	fread(&w, sizeof(int), 1, file); // 宽度


	unsigned char* pixels = new unsigned char[h * w];
	fread(pixels, sizeof(unsigned char), h * w, file);

	fclose(file);

	int width = w / 8;//8x8 像素矩阵的一行块数
	int height = h / 8; // 8x8 像素矩阵的一列块数

	//cout << width << " " << height;
	

	//8x8像素块的划分
	vector> blocks;
	vector temp(width);
	blocks.resize(height, temp);


	for (int i = 0; i < h; i++)
	{
		for (int j = 0; j < w; j++)
		{
			double value = pixels[i*w + j];
			blocks[i / 8][j / 8].matrix[i % 8][j % 8] = value;

		}
		
	}


	//FDCT的结果矩阵
	vector> DCT;
	vector temp1(width);
	DCT.resize(height, temp1);

  //FDCT 正向离散余弦变换
	for (int i = 0; i < height; i++) {
		for (int j = 0; j < width; j++) {
			//blocks[i][j]  8x8像素
			for (int u = 0; u < 8; u++) {
				for (int v = 0; v < 8; v++) {	
					
					DCT[i][j].matrix[u][v] = blocks[i][j].dct(u, v);
					
				}
			}
			
		}
    }

	//量化
	//对经过FDCT变换后的频率系数进行量化
   //目的:降低非0系数的幅度,增加0值系数的数目

	//定义量化表
	int quantity[8][8] = { {16,11,10,16,24,40,51,61},
								 {12,12,14,19,26,58,60,55},
								 {14,13,16,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} };

	//量化操作

	for (int i = 0; i < height; i++) {
		for (int j = 0; j < width; j++) {
			//DCT[i][j]  8x8像素
			for (int u = 0; u < 8; u++) {
				for (int v = 0; v < 8; v++) {
					//cout << DCT[i][j].matrix[u][v] << " ";
					//cout << DCT[i][j].matrix[u][v] / quantity[u][v] << " ";
					DCT[i][j].matrix[u][v] = round(DCT[i][j].matrix[u][v]/quantity[u][v]);
					//if(u==0&&v==0)
					//cout << DCT[i][j].matrix[u][v]<<" "; //输出dc系数
				}
			}

		}
	}

	//熵编码
	vector> entropy;
	vector temp2(width);
	entropy.resize(height, temp2);

	/// 对 dc系数的 dpcm编码
	for (int i = 0; i < height; i++) {
		for (int j = 1; j < width; j++) {
			//DCT[i][j]  8x8像素
			DCT[i][j].matrix[0][0] = DCT[i][j].matrix[0][0] - DCT[i][j - 1].matrix[0][0];

		}
	}

	//霍夫曼映射表
	string huffman[12] = { "00","010","011","100","101","110","1110","11110","111110","1111110","11111110","111111110" };

	for (int i = 0; i < height; i++) {
		for (int j = 0; j < width; j++) {
			string sss = huffman[getArange(DCT[i][j].matrix[0][0])];
			string diff;
			//DCT[i][j]  8x8像素
			if (DCT[i][j].matrix[0][0] >= 0)
				diff = toBinary(DCT[i][j].matrix[0][0]);
			else
				diff = getVLI(DCT[i][j].matrix[0][0]);

			code c(sss, diff);
			entropy[i][j].vc.push_back(c);

			//cout << diff << endl << sss << endl;
		}
	}

	//ac系数的编码  游程长度编码
	//(RLE)

	//生成中间符号
	//亮度ac编码表
	string AcHuff[16][11] = 
	{ {"1010","00","01","100","1011","11010","1111000","11111000","1111110110","1111111110000010","1111111110000011" }
	,{"1100","11011","1111001","111110110","11111110110","1111111110000100","1111111110000101","1111111110000110","1111111110000111","1111111110001000"}
	,{"11100","11111001","1111110111","1111111110001001","1111111110001010","1111111110001011","1111111110001100","1111111110001101","1111111110001110"}
    ,{"111010","111110111","111111110101","1111111110001111","1111111110010000","1111111110010001","1111111110010010","1111111110010011","1111111110010100","1111111110010101"}
	,{"111011","1111111000","1111111110010110","1111111110010111","1111111110011000","1111111110011001","1111111110011010","1111111110011011","1111111110011100","1111111110011101"}
	,{"1111010","11111110111","1111111110011110","1111111110011111","1111111110100000","1111111110100001","1111111110100010","1111111110100011","1111111110100100","1111111110100101"}
	,{"1111011","111111110110","1111111110100110","1111111110100111","1111111110101000","1111111110101001","1111111110101010","1111111110101011","1111111110101100","1111111110101101"}
	,{"11111010","111111110111","1111111110101110","1111111110101111","11111111101100000","1111111110110001","1111111110110010","1111111110110011","1111111110110100","1111111110110101"}
	,{"111111000","111111111000000","1111111110110110","1111111110110111","1111111110111000","1111111110111001","1111111110111010","1111111110111011","1111111110111100","1111111110111101"}
	,{"111111001","1111111110111110","1111111110111111","1111111111000000","1111111111000001","1111111111000010","1111111111000011","1111111111000100","1111111111000101","1111111111000110"}
	,{"111111010","1111111111000111","1111111111001000","1111111111001001","1111111111001010","1111111111001011","1111111111001100","1111111111001101","1111111111001110","1111111111001111"}
	,{"1111111001","1111111111010000","1111111111010001","1111111111010010","1111111111010011","1111111111010100","1111111111010101","1111111111010110","1111111111010111","1111111111011000"}
	,{"1111111010","1111111111011001","1111111111011010","1111111111011011","1111111111011100","1111111111011101","1111111111011110","1111111111011111","1111111111100000","1111111111100001"}
	,{"11111111000","1111111111100010","1111111111100011","1111111111100100","1111111111100101","1111111111100110","1111111111100111","1111111111101000","1111111111101001","1111111111101010"}
    ,{"1111111111101011","1111111111101100","1111111111101101","1111111111101110","1111111111101111","1111111111110000","1111111111110001","1111111111110010","1111111111110011","1111111111110100"}
	,{"11111111001","1111111111110101","1111111111110110","1111111111110111","1111111111111000","1111111111111001","1111111111111010","1111111111111011","1111111111111100","1111111111111101","1111111111111110"}
	};

	//z字行编排
	int zseq[8][8] = { {0,1,5,6,14,15,27,28}
	,{2,4,7,13,16,26,29,42}
	,{3,8,12,17,25,30,41,43}
	,{9,11,18,24,31,40,44,53}
	,{10,19,23,32,39,45,52,54}
	,{20,22,33,38,46,51,55,60}
	,{21,34,37,47,50,56,59,61}
	,{35,36,48,49,57,58,62,63} };



	for (int i = 0; i < height; i++) {
		for (int j = 0; j < width; j++) {

			//计算出一个 [1,64] 的列表
			int zlist[64];
			for (int i = 0; i < 64; i++) zlist[i] = 0;
			//DCT[i][j]  8x8像素
			for (int u = 0; u < 8; u++) {
				for (int v = 0; v < 8; v++) {
					
					zlist[zseq[u][v]] = DCT[i][j].matrix[u][v];
					
				}
			}

			//根据zlist 计算熵编码
			int zeroNum = 0;
			vector mid;
			for (int y = 0; y < 64; y++) {
				if (zlist[y] == 0) {
					zeroNum++;
					if (zeroNum >= 16) {
						midsyn m(zeroNum-1, 0, 0);
						mid.push_back(m);
						zeroNum = 0;
					}

					if (y == 63) {
						int length = mid.size() - 1;
						while (mid[length].c == 0) {
							mid[length].a = 0;
							length--;
							if (length == -1)break;
						}
						int ggg = mid.size() ;
						//cout << length << " " << ggg-2<= 0)
					d = toBinary(mid[p].c);
				else
				    d = getVLI(mid[p].c);
				//cout << d << endl;

				code c(s, d);
				entropy[i][j].vc.push_back(c);

			}

		//	cout << endl << endl;

		}
	}

	ofstream out("entropy.txt");
	
	

	for (int i = 0; i < height; i++)
		for (int j = 0; j < width; j++)
		{
			for (int u = 0; u < entropy[i][j].vc.size(); u++) {
				cout << entropy[i][j].vc[u].ssss << " " << entropy[i][j].vc[u].diff << " ";
				out << entropy[i][j].vc[u].ssss << " " << entropy[i][j].vc[u].diff <<" ";
				
			}
		}
	out << "\n";
	cout << endl;

	out.close();

	return 0;
}

 

你可能感兴趣的:(c++)