JPEG图像压缩解压算法

JPEG图像压缩解压算法


#include<iostream>
#include<string>
#include<cstdlib>
#include<cstdio>
#include<cmath>
#define MAX 100
#define N 8 	//N为每个图像分量的矩阵大小
using namespace std;

/*亮度量化值表*/
struct  BrightnessQuantizedValueTable{
	int Q[N][N];
	BrightnessQuantizedValueTable(){
		int x[N][N]={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<N;i++){
			for(int j=0;j<N;j++){
				Q[i][j] = x[i][j];
			}
		}
	}
};
BrightnessQuantizedValueTable brightnessQuantizedValueTable;//定义一个亮度量化值表

/*亮度DC差值码表*/
struct BrightnessDC_DifferenceTableList{
	string brightnessDC_DifferenceTable[12];//亮度DC差值码表  类别(数组下标)与码字映射
	BrightnessDC_DifferenceTableList(){
		brightnessDC_DifferenceTable[0]="00";
		brightnessDC_DifferenceTable[1]="010";
		brightnessDC_DifferenceTable[2]="011";
		brightnessDC_DifferenceTable[3]="100";
		brightnessDC_DifferenceTable[4]="101";
		brightnessDC_DifferenceTable[5]="110";
		brightnessDC_DifferenceTable[6]="1110";
		brightnessDC_DifferenceTable[7]="11110";
		brightnessDC_DifferenceTable[8]="111110";
		brightnessDC_DifferenceTable[9]="1111110";
		brightnessDC_DifferenceTable[10]="11111110";
		brightnessDC_DifferenceTable[11]="111111110";
	}
};
BrightnessDC_DifferenceTableList brightnessDC_DifferenceTableList;//定义一个亮度DC差值码表


/*AC系数熵编码时的中间符号*/
struct AC_EntropyCoding_MiddleSymbol{
	string R_S;
	int temp;
};
AC_EntropyCoding_MiddleSymbol ac_EntropyCoding_MiddleSymbol[N*N];//由于用函数返回结构体数组,里面的字符串会出现一些无法处理的乱码,故定义为全局变量

/*熵编码时的编码输出*/
struct EntropyCoding{
	string strTemp1;
	string strTemp;
};
EntropyCoding ac_EntropyCodingStr[N*N];//由于用函数返回结构体数组,里面的字符串会出现一些无法处理的乱码,故定义为全局变量


/* R/S与码字映射结点*/
struct StringMap{
	string key;
	string value;
};

/*亮度AC码表  R/S与码字映射表*/
/**特别注意,以下的亮度AC码表只适用于给出的测试数据,如要其它的测试数据,则必须补全亮度AC码表**/
//网上找到一个fantasy 的博客http://menmory.blog.163.com/blog/static/12690012620114535032530/ 这里面有比较详细的亮度AC码表等
struct StringMapList{
	StringMap stringMap[N*N];
	int partNum;	//该亮度AC码表中的条数

	StringMapList(){
		//部分常用亮度AC码表
		stringMap[0].key = "0/0(EOB)";
		stringMap[0].value = "1010";
		stringMap[1].key = "0/1";
		stringMap[1].value = "00";
		stringMap[2].key = "1/1";
		stringMap[2].value = "1100";
		stringMap[3].key = "1/2";
		stringMap[3].value = "11011";
		stringMap[4].key = "2/1";
		stringMap[4].value = "11100";
		stringMap[5].key = "3/2";
		stringMap[5].value = "111110111";
		stringMap[6].key = "F/0(ZRL)";
		stringMap[6].value = "11111111001";
		stringMap[7].key = "F/F";
		stringMap[7].value = "1111111111111110";
		partNum = 8;
	}
};
StringMapList stringMapList;//定义一个 部分常用亮度AC码表


/*DC差值范围表,本人通过对表找规律发现如下规律 */
int DC_Difference(int temp){
	int temp1;
	if(temp == 0){
		 temp1 = 0;
	}else{
		for(int i=1;i<=11;i++){
			if(abs(temp)<pow(2,i)){
				temp1 = i;
				break;
			}
		}
	}
	return temp1;
}


/*AC系数范围表,本人通过对表找规律发现如下规律*/
int AC_Difference(int temp){
	int temp1;
	if(temp == 0){
		 temp1 = 0;
	}else{
		for(int i=1;i<=10;i++){
			if(abs(temp)<pow(2,i)){
				temp1 = i;
				break;
			}
		}
	}
	return temp1;
}


/*将正整数十进制转换成二进制*/
string TenToTwo(int temp){
	string strTemp="";
	//旧方法
//	for(int k=abs(temp);k>0;k=k/2){
//		strTemp = strTemp + (k%2==1?'1':'0');
//	}
//	//倒置
//	int len = strTemp.length();
//	for(int k=0;k<len/2;k++){
//		char t = strTemp[k];
//		strTemp[k] = strTemp[len-1-k];
//		strTemp[len-1-k] = t;
//	}
	//新方法
	char str[N*N];
	itoa(temp,str,2);
	strTemp = str;
	return strTemp;
}


/*将正整数二进制转换成十进制*/
int TwoToTen(string strTemp){
	int temp=0;
	for(int i=0;i<strTemp.length();i++){
		temp = temp*2+strTemp[i]-'0';
	}
	return temp;
}

/*将一个负数的二进制串逐位取反*/
string ConvertToComplement(string strTemp){
	string str = "";
	for(int i=0;i<strTemp.length();i++){
		str = str + (strTemp[i]=='1'?'0':'1');
	}
	return str;
}


/*DC系数编码*/
EntropyCoding DC_EntropyCoding(int &temp,int &temp1){
	//对DC系数生成中间符号(中间符号(temp1,temp))

	//查DC差值表
	temp1 = DC_Difference(temp);

	/*测试*/
//	cout<<temp1<<endl;

	//对中间符号通过查表进行符号编码
	//对 temp1通过查亮度DC差值码表进行熵编码
	EntropyCoding dc_EntropyCodingStr;
	dc_EntropyCodingStr.strTemp1 = brightnessDC_DifferenceTableList.brightnessDC_DifferenceTable[temp1];

	//对 temp进行转换成补码
	//先将 temp转换成二进制串
	dc_EntropyCodingStr.strTemp = TenToTwo(abs(temp));
	//转换成补码
	if(temp<0){
		dc_EntropyCodingStr.strTemp = ConvertToComplement(dc_EntropyCodingStr.strTemp);
	}

	/*测试*/
//	cout<<dc_EntropyCodingStr.strTemp1<<"\t"<<dc_EntropyCodingStr.strTemp<<endl;

	return dc_EntropyCodingStr;
}


/*AC系数编码*/
bool AC_EntropyCoding(int F_[N][N],int &index){
	//对AC系数生成中间符号中/后的部分
	int SSSS[N][N];

	//查AC系数范围表,本人通过对表找规律发现如下规律
	for(int i=0;i<N;i++){
		for(int j=0;j<N;j++){
			SSSS[i][j] = AC_Difference(F_[i][j]);
		}
	}

	/*测试*/
//	for(int i=0;i<N;i++){
//		for(int j=0;j<N;j++){
//			cout<<SSSS[i][j]<<" ";
//		}
//		cout<<endl;
//	}

	//Z字形编码
	int count = 0;//计算0的个数
	int i,j,t;
	for(i=0,j=1,t=1;t<=N-2;t++){//以下语句设为一个周期,大概要执行N-2个周期(这里N=8,通过观察发现每一下一上为一周期,则有6个周期+半段)
		//向左下方向
		for(;i<N&&j>=0;i++,j--){
			if(F_[i][j]==0){
				count++;
			}else{
				char countString[N*N];
				itoa(count,countString,10);//将整数count转换为字符串并保存在countString(以10进制方式,也可指定2、8、10、16等进制实现进制转换,进制转换新玩法)
				string strTemp = "/";
				strTemp = countString + strTemp;
				//cout<<"--"<<strTemp<<"--"<<endl;
				char SSSS_String[N*N];
				itoa(SSSS[i][j],SSSS_String,10);
				strTemp = strTemp + SSSS_String;
				//cout<<"**"<<strTemp<<"**"<<endl;

				//中间符号
				ac_EntropyCoding_MiddleSymbol[index].R_S = strTemp;
				ac_EntropyCoding_MiddleSymbol[index].temp = F_[i][j];
				index++;
				count = 0;//置为0 ,计算下个不为0的数前面0的个数
			}
		}
		if(i>=N&&j<0){//当出现正中间往下时,挪回正规
			i--;
			j = j+2;
		}else if(i>=N){//当出现往下突出时,挪回正规
			i--;
			j = j+2;
		}else if(j<0){//当出现往左突出时,挪回正规
			j++;
		}

		//向右上方向
		for(;i>=0&&j<N;i--,j++){
			if(F_[i][j]==0){
				count++;
			}else{
				char countString[N*N];
				itoa(count,countString,10);
				string strTemp = "/";
				strTemp = countString + strTemp;
				//cout<<"--"<<strTemp<<"--"<<endl;
				char SSSS_String[N*N];
				itoa(SSSS[i][j],SSSS_String,10);
				strTemp = strTemp + SSSS_String;
				//cout<<"**"<<strTemp<<"**"<<endl;

				//中间符号
				ac_EntropyCoding_MiddleSymbol[index].R_S = strTemp;
				ac_EntropyCoding_MiddleSymbol[index].temp = F_[i][j];
				index++;
				count = 0;//置为0 ,计算下个不为0的数前面0的个数
			}
		}
		if(i<0&&j>=N){//当出现正中间往上时,挪回正规
			j--;
			i = i+2;
		}else if(i<0){//当出现往上突出时,挪回正规
			i++;
		}else if(j>=N){//当出现往右突出时,挪回正规
			j--;
			i = i+2;
		}
	}

	//剩下半个周期的编码
	//向左下方向
	for(;i<N&&j>=0;i++,j--){
		if(F_[i][j]==0){
			count++;
		}else{
			char countString[N*N];
			itoa(count,countString,10);
			string strTemp = "/";
			strTemp = countString + strTemp;
			//cout<<"--"<<strTemp<<"--"<<endl;
			char SSSS_String[N*N];
			itoa(SSSS[i][j],SSSS_String,10);
			strTemp = strTemp + SSSS_String;
			//cout<<"**"<<strTemp<<"**"<<endl;

			//中间符号
			ac_EntropyCoding_MiddleSymbol[index].R_S = strTemp;
			ac_EntropyCoding_MiddleSymbol[index].temp = F_[i][j];
			index++;
			count = 0;//置为0 ,计算下个不为0的数前面0的个数
		}
	}
	if(i>=N){//当出现往下突出时,挪回正规
		i--;
		j = j+2;
	}
	if(F_[i][j]==0){//最后一个点
		count++;
		ac_EntropyCoding_MiddleSymbol[index].R_S = "0/0(EOB)";
		ac_EntropyCoding_MiddleSymbol[index].temp = INT_MAX;
		index++;
	}else{
		char countString[N*N];
		itoa(count,countString,10);
		string strTemp = "/";
		strTemp = countString + strTemp;
		//cout<<"--"<<strTemp<<"--"<<endl;
		char SSSS_String[N*N];
		itoa(SSSS[i][j],SSSS_String,10);
		strTemp = strTemp + SSSS_String;
		//cout<<"**"<<strTemp<<"**"<<endl;

		//中间符号
		ac_EntropyCoding_MiddleSymbol[index].R_S = strTemp+"(EOB)";
		ac_EntropyCoding_MiddleSymbol[index].temp = F_[i][j];
		index++;
	}

	/*测试*/
//	for(int k=0;k<index;k++){
//		cout<<ac_EntropyCoding_MiddleSymbol[k].R_S<<"\t"<<ac_EntropyCoding_MiddleSymbol[k].temp<<endl;
//	}


	//对中间符号进行符号编码
	//对R/S通过查亮度AC码表进行熵编码
	for(int u=0;u<index;u++){
		for(int v=0;v<stringMapList.partNum;v++){
			if(ac_EntropyCoding_MiddleSymbol[u].R_S == stringMapList.stringMap[v].key){
				ac_EntropyCodingStr[u].strTemp1 = stringMapList.stringMap[v].value;
			}
		}
		//对 temp进行转换成补码
		//先将 temp转换成二进制串
		if(ac_EntropyCoding_MiddleSymbol[u].R_S!="0/0(EOB)"){
			ac_EntropyCodingStr[u].strTemp = TenToTwo(abs(ac_EntropyCoding_MiddleSymbol[u].temp));
			//转换成补码
			if(ac_EntropyCoding_MiddleSymbol[u].temp<0){
				ac_EntropyCodingStr[u].strTemp = ConvertToComplement(ac_EntropyCodingStr[u].strTemp);
			}

			/*测试*/
//			cout<<"**********"<<ac_EntropyCodingStr[u].strTemp<<endl;
		}else{
			ac_EntropyCodingStr[u].strTemp = ""+'\0';

			/*测试*/
//			cout<<"**********+"<<ac_EntropyCodingStr[u].strTemp<<endl;
		}
	}

	/*测试*/
//	for(int k=0;k<index;k++){
//		cout<<ac_EntropyCodingStr[k].strTemp1<<" "<<ac_EntropyCodingStr[k].strTemp<<endl;
//	}
	return true;
}

int main(){
	cout<<"压缩编码过程:"<<endl;
	/*压缩编码*/
	const double PI = acos(-1);
	double f[N][N]={139,144,149,153,155,155,155,155,
					144,151,153,156,159,156,156,156,
					150,155,160,163,158,156,156,156,
					159,161,162,160,160,159,159,159,
					159,160,161,162,162,155,155,155,
					161,161,161,161,160,157,157,157,
					162,162,161,163,162,157,157,157,
					162,162,161,161,163,158,158,158};
	//double f[N][N];
	double ff[N][N],F[N][N];
    int currentFlag=1;
	/*输入图像的一个分量样本*/
	for(int i=0;i<N;i++){
		for(int j=0;j<N;j++){
			//cin>>f[i][j];
			if(currentFlag<8){
                cout<<f[i][j]<<" ";
                currentFlag++;
			}else{
			    cout<<f[i][j]<<endl;
			currentFlag=1;
			}

		}
	}

	cout<<"源图像的一个分量样本:"<<endl;
	/*输出—源图像的一个分量样本*/
	for(int i=0;i<N;i++){
		for(int j=0;j<N;j++){
			cout<<f[i][j]<<"\t";
		}
		cout<<endl;
	}

	//图像的一个分量样本-128后
	for(int i=0;i<N;i++){
		for(int j=0;j<N;j++){
			ff[i][j] = f[i][j]-128;
		}
	}

	cout<<"源图像的一个分量样本-128后:"<<endl;
	/*输出—图像的一个分量样本-128后*/
	for(int i=0;i<N;i++){
		for(int j=0;j<N;j++){
			cout<<ff[i][j]<<"\t";
		}
		cout<<endl;
	}

	//由公式计算DCT变化后的系数矩阵
	for(int u=0;u<N;u++){
		for(int v=0;v<N;v++){
			double temp = 0.0;
			for(int i=0;i<N;i++){
				for(int j=0;j<N;j++){
					temp = temp + ff[i][j]*cos((2*i+1)*u*PI*1.0/16)*cos((2*j+1)*v*PI*1.0/16);
				}
			}
			F[u][v] = 1.0/4*(u==0?1.0/sqrt(2):1)*(v==0?1.0/sqrt(2):1)*temp;
		}
	}

	/*输出—DCT变化后的系数矩阵*/
	//DCT变化后的系数矩阵
	cout<<"DCT变化后的系数矩阵:"<<endl;
	for(int u=0;u<N;u++){
		for(int v=0;v<N;v++){
			printf("%.1f\t",F[u][v]);
			//cout<<F[u][v]<<" ";
		}
		cout<<endl;
	}

	//利用公式将DCT变化后的系数矩阵转换为规格化量化系数矩阵
	int F_[N][N];//规格化量化系数矩阵
	for(int i=0;i<N;i++){
		for(int j=0;j<N;j++){//二维数组Q 为亮度量化值表
			F_[i][j] = (int)((F[i][j]/brightnessQuantizedValueTable.Q[i][j])>0.0)?floor((F[i][j]/brightnessQuantizedValueTable.Q[i][j]) + 0.5) : ceil((F[i][j]/brightnessQuantizedValueTable.Q[i][j]) - 0.5);//进行量化,然后进行四舍五入
		}
	}

	/*输出—规格化量化系数矩阵*/
	//规格化量化系数矩阵
	cout<<"规格化量化系数:"<<endl;
	for(int u=0;u<N;u++){
		for(int v=0;v<N;v++){
			cout<<F_[u][v]<<"\t";
		}
		cout<<endl;
	}

	//对DC系数生成中间符号(temp1,temp)
	int temp = F_[0][0];
	int temp1;
	EntropyCoding dc_EntropyCodingStr = DC_EntropyCoding(temp,temp1);

	cout<<"中间符号:"<<endl;
	/*输出—DC系数中间符号*/
	cout<<temp1<<"\t"<<temp<<endl;


	int index=0; //AC系数生成中间符号的个数
	//对AC系数生成中间符号
	AC_EntropyCoding(F_,index);

	/*输出—AC系数中间符号*/
	for(int k=0;k<index;k++){
		cout<<ac_EntropyCoding_MiddleSymbol[k].R_S<<"\t";
		if(ac_EntropyCoding_MiddleSymbol[k].R_S!="0/0(EOB)"){
			cout<<ac_EntropyCoding_MiddleSymbol[k].temp;
		}
		cout<<endl;
	}

	cout<<"熵编码输出:"<<endl;
	/*输出—DC系数熵编码输出*/
	cout<<dc_EntropyCodingStr.strTemp1<<"\t"<<dc_EntropyCodingStr.strTemp<<endl;

	/*输出—AC系数熵编码输出*/
	for(int k=0;k<index;k++){
		cout<<ac_EntropyCodingStr[k].strTemp1<<"\t"<<ac_EntropyCodingStr[k].strTemp<<endl;
	}


	cout<<"----------------------------------------------------------------------"<<endl<<endl;
	cout<<"解码过程:"<<endl;
	//下面的解码过程只用到了压缩过程传输过来的熵编码和熵编码中AC系数的个数index(也可以通过一个循环来计算出这个index)

	cout<<"待解码的熵编码:"<<endl;
	/*输出—DC系数熵编码输出*/
	cout<<dc_EntropyCodingStr.strTemp1<<"\t"<<dc_EntropyCodingStr.strTemp<<endl;

	/*输出—AC系数熵编码输出*/
	for(int k=0;k<index;k++){
		cout<<ac_EntropyCodingStr[k].strTemp1<<"\t"<<ac_EntropyCodingStr[k].strTemp<<endl;
	}

	/*解码*/
	//将DC系数熵编码的编码转换为中间符号
	//对strTemp1进行反向查找亮度DC差值码表得到temp1
	int Itemp1;
	for(int i=0;i<11;i++){
		if( dc_EntropyCodingStr.strTemp1 == brightnessDC_DifferenceTableList.brightnessDC_DifferenceTable[i]){
			Itemp1 = i;
		}
	}
	//对strTemp进行反向补码得到temp,可通过查找规律发现若是负数转换为补码后首个数字必为0,正数必不为0
	int Itemp;
	if(dc_EntropyCodingStr.strTemp[0]=='0'){//为负数,先取反
		string tempStr = ConvertToComplement(dc_EntropyCodingStr.strTemp);
		//转换为10进制
		Itemp = TwoToTen(tempStr);
		//加负号
		Itemp = -Itemp;
	} else{//为正数,直接转换为10进制即可
		Itemp = TwoToTen(dc_EntropyCodingStr.strTemp);
	}

	cout<<"中间符号:"<<endl;
	/*输出—DC中间符号*/
	cout<<Itemp1<<"\t"<<Itemp<<endl;


	//将AC系数熵编码的编码转换为中间符号
	AC_EntropyCoding_MiddleSymbol Iac_EntropyCoding_MiddleSymbol[N*N];
	//遍历所有的AC系数熵编码的编码对strTemp1进行反向查找亮度AC码表得到R_S
	for(int i=0;i<index;i++){
		for(int u=0;u<stringMapList.partNum;u++){
			if(ac_EntropyCodingStr[i].strTemp1==stringMapList.stringMap[u].value){
				Iac_EntropyCoding_MiddleSymbol[i].R_S = stringMapList.stringMap[u].key;
			}
		}
		//对strTemp进行反向补码得到temp,可通过查找规律发现若是负数转换为补码后首个数字必为0,正数必不为0
		if(ac_EntropyCodingStr[i].strTemp[0]=='0'){//为负数,先取反
			string tempStr = ConvertToComplement(ac_EntropyCodingStr[i].strTemp);
			//转换为10进制
			Iac_EntropyCoding_MiddleSymbol[i].temp = TwoToTen(tempStr);
			//加负号
			Iac_EntropyCoding_MiddleSymbol[i].temp = -Iac_EntropyCoding_MiddleSymbol[i].temp;
		} else{//为正数,直接转换为10进制即可
			Iac_EntropyCoding_MiddleSymbol[i].temp = TwoToTen(ac_EntropyCodingStr[i].strTemp);
		}
	}

	/*输出—AC中间符号*/
	for(int i=0;i<index;i++){
		cout<<Iac_EntropyCoding_MiddleSymbol[i].R_S<<"\t";
		if(Iac_EntropyCoding_MiddleSymbol[i].R_S!="0/0(EOB)"){
			cout<<Iac_EntropyCoding_MiddleSymbol[i].temp;
		}
		cout<<endl;
	}

	//规格化量化系数
	int IF_[N][N];

	//初始化矩阵
	for(int u=0;u<N;u++){
		for(int v=0;v<N;v++){
			IF_[u][v]=0;
		}
	}

	//DC系数
	//还原编码
	IF_[0][0] = Itemp;
	//AC系数
	//Z字形还原编码
	int count;//计算0的个数
	int a=0,b=1; //初始位置
	for(int h=0;h<index;h++){
		//将/前的字符串转换为整数
		count = 0;
		for(int w=0;Iac_EntropyCoding_MiddleSymbol[h].R_S[w]!='/';w++){
			count = count*10 + Iac_EntropyCoding_MiddleSymbol[h].R_S[w]-'0';
		}
		/*测试*/
//		cout<<"count:"<<count<<endl;

		while(Iac_EntropyCoding_MiddleSymbol[h].R_S!="0/0(EOB)"){
			//根据查找规律发现,当行+列为奇数时向左下方向,当行+列为偶数时为右上方向
			if((a+b)%2==0){//偶数,向右上方向
				for(;count>=0&&a>=0&&b<N;a--,b++){
					if(count==0){//此时放temp
						IF_[a][b] = Iac_EntropyCoding_MiddleSymbol[h].temp;
						count--;
						break;
					}else{//此时放0
						IF_[a][b] = 0;
						count--;
					}
				}
				if(count<0){//向右上移动
					a--;
					b++;
				}
				if(a<0&&b>=N){//当出现正中间往上时,挪回正规
					b--;
					a = a+2;
				}else if(a<0){//当出现往上突出时,挪回正规
					a++;
				}else if(b>=N){//当出现往右突出时,挪回正规
					b--;
					a = a+2;
				}
				if(count<0){//跳出到第一层循环
					break;
				}
			} else{//奇数,向左下方向
				for(;count>=0&&a<N&&b>=0;a++,b--){
					if(count==0){//此时放temp
						IF_[a][b] = Iac_EntropyCoding_MiddleSymbol[h].temp;
						count--;
						break;
					}else{//此时放0
						IF_[a][b] = 0;
						count--;
					}
				}
				if(count<0){//向左下移动
					a++;
					b--;
				}
				if(a>=N&&b<0){//当出现正中间往下时,挪回正规
					a--;
					b = b+2;
				}else if(a>=N){//当出现往下突出时,挪回正规
					a--;
					b = b+2;
				}else if(b<0){//当出现往左突出时,挪回正规
					b++;
				}
				if(count<0){//跳出到第一层循环
					break;
				}
			}
		}
	}

	/*输出—规格化量化系数矩阵*/
	//规格化量化系数矩阵
	cout<<"规格化量化系数:"<<endl;
	for(int u=0;u<N;u++){
		for(int v=0;v<N;v++){
			cout<<IF_[u][v]<<"\t";
		}
		cout<<endl;
	}


	//利用公式将规格化量化系数矩阵转换为逆量化后的系数矩阵
	double IF[N][N];//逆量化后的系数矩阵
	for(int i=0;i<N;i++){
		for(int j=0;j<N;j++){//二维数组Q 为亮度量化值表
			IF[i][j] = 1.0*IF_[i][j]*brightnessQuantizedValueTable.Q[i][j];
		}
	}

	/*输出—逆量化后的系数矩阵*/
	cout<<"逆量化后的系数矩阵:"<<endl;
	for(int i=0;i<N;i++){
		for(int j=0;j<N;j++){
			cout<<IF[i][j]<<"\t";
		}
		cout<<endl;
	}

	//由公式计算IDCT变化后的系数矩阵
	double Iff[N][N];
	for(int i=0;i<N;i++){
		for(int j=0;j<N;j++){
			double sum = 0.0;
			for(int u=0;u<N;u++){
				for(int v=0;v<N;v++){
					sum = sum + (u==0?1.0/sqrt(2.0):1.0)*(v==0?1.0/sqrt(2.0):1.0)*IF[u][v]*cos((2*i+1)*u*PI*1.0/16)*cos((2*j+1)*v*PI*1.0/16);
				}
			}
			Iff[i][j] = 1.0/4*sum;
		}
	}

	/*输出—IDCT变化后的系数矩阵*/
	cout<<"IDCT变化后的系数矩阵:"<<endl;
	for(int i=0;i<N;i++){
		for(int j=0;j<N;j++){
			//cout<<Iff[i][j]<<"\t";
			printf("%.0f\t",Iff[i][j]);
		}
		cout<<endl;
	}


	cout<<"源图像的一个分量样本的重构图像:"<<endl;
	/*IDCT变化后的系数矩阵+128后变成源图像的一个分量样本的重构图像*/
	double If[N][N];
	for(int i=0;i<N;i++){
		for(int j=0;j<N;j++){
			If[i][j] = Iff[i][j]+128;
		}
	}

	/*输出—源图像的一个分量样本的重构图像*/
	for(int i=0;i<N;i++){
		for(int j=0;j<N;j++){
			//cout<<If[i][j]<<"\t";
			printf("%.0f\t",If[i][j]);
		}
		cout<<endl;
	}
	return 0;
}

 

  • 0
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值