c 实现的jpeg 8×8 离散余弦DCT 正向,逆向转换

理论公式:

4b68b40ec7c64f64968d6a804ad05221.jpeg

验证数据

58a3261a8ccb4475a36b1d29b5da252c.jpeg

1.正向,数据源为YCbCr  8×8  数据


#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <sys/mman.h>
#include <string.h>
#include <unistd.h>
#include <linux/fb.h>
#include <stdlib.h>

#include <math.h>
#define PI 3.141593



int main()
{
	double o[8][8]={};
	char i[64] = {-76,-73,-67,-62,-58,-67,-64,-55,
		-65,-69,-73,-38,-19,-43,-59,-56,
		-66,-69,-60,-15,16,-24,-62,-55,
		-65,-70,-57,-6,26,-22,-58,-59,
		-61,-67,-60,-24,-2,-40,-60,-58,
		-49,-63,-68,-58,-51,-60,-70,-53,
		-43,-57,-64,-69,-73,-67,-63,-45,
		-41,-49,-59,-60,-63,-52,-50,-34
	};
	
	char (*p)[8]=(char (*)[8])i;
	
	double s;
	double au;
	double av;
	
	for(int u=0;u<8;u++){
		for(int v=0;v<8;v++){
	        for(int y=0;y<8;y++){
	           	for(int x=0;x<8;x++){
			       s=s+(1.0/4)*p[y][x]*cos((2*y+1)*u*PI/16)*cos((2*x+1)*v*PI/16);
				}
			}
	
	       if(u==0){
		       au=1.0/sqrt(2);
		   }else{
		       au=1.0;
	       }
	       if(v==0){
		       av=1.0/sqrt(2);
	       }else{
		       av=1.0;
	       }
	       
			s=s*au*av;         //-30.1856
			int s1=round(s*100);  //-3019
		    s=s1/100.0;        //-30.19
	        o[u][v]=s;
            s=0;
		}
	}
	
	for(int a=0;a<8;a++){
		for(int b=0;b<8;b++){
			printf("%0.2f,  ",o[a][b]);
		}
		puts("");
	}
}

此源数据和输出数据是Matlab 软件生成的,经验证,本程序生成的数据完全正确。

特别注意,使用math.h头,编译器必须加上参数  -lm 否则报错。

2.逆向转换

#include <sys/stat.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <sys/mman.h>
#include <string.h>
#include <unistd.h>
#include <linux/fb.h>
#include <stdlib.h>
#include <stdio.h>
#include <math.h>
#define PI 3.141593

int main(void){
	double i[64]={-415.38, -30.19, -61.20, 27.24, 56.12, -20.10, -2.39, 0.46,
		           4.47,  -21.86, -60.76, 10.25 ,13.15, -7.09,  -8.54 , 4.88,
		          -46.83,  7.37, 77.13,  -24.56,  -28.91, 9.93, 5.42, -5.65,
		          -48.53,  12.07, 34.10, -14.76, -10.24, 6.30,  1.83, 1.95,
		          12.12 ,  -6.55, -13.20, -3.95, -1.87,  1.75,  -2.79,3.14,
		           -7.73, 2.91, 2.38,  -5.94,  -2.38,  0.94,  4.30,  1.85,
		           -1.03,  0.18,  0.42,  -2.42,  -0.88, -3.02, 4.12,  -0.66,
		           -0.17,  0.14, -1.07, -4.19,  -1.17,   -0.10  ,0.50,  1.68
                 };
	
	char o[8][8]={};
	
	double (*p)[8]=(double (*)[8])i;
	
	double s;
	double au;
	double av;
	
	for(int y=0;y<8;y++){
		for(int x=0;x<8;x++){
			
			for(int u=0;u<8;u++){
				for(int v=0;v<8;v++){
					if(u==0){
						au=1.0/sqrt(2);
					}else{
						au=1.0;
					}
					if(v==0){
						av=1.0/sqrt(2);
					}else{
						av=1.0;
					}
					
					s=s+(1.0/4)*au*av*p[u][v]*cos((2*y+1)*u*PI/16)*cos((2*x+1)*v*PI/16);
				}
			}
			   
			o[y][x]=s;
			s=0;
		}
	}

	for(int a=0;a<8;a++){
		for(int b=0;b<8;b++){
			printf("%d ",o[a][b]);
		}
		puts("");
	}
	
	return 0;
}

没有加上四舍五入,数据有微小差别。

猜你喜欢

转载自blog.csdn.net/m0_59802969/article/details/134766119