#include "stdio.h"
#include "stdlib.h"
#include "malloc.h"
#include "math.h"
#define Width 256
#define Height 256
#define N 8
#define Pi 3.1415926
main()
{
FILE *FileOpen(char *filename,char *opt),*imagein,*imageout;//File为结构体,imagein和imageout是指向FILE类型结构体的指针变量(文件型指针变量),可以通过使指针指向某一个文件的结构体变量,从而通过该结构体变量中的文件信息能够访问该文件
unsigned char *image,*image1,head[1078];
int block(int img_height,int img_width,int size,unsigned char *imgin,unsigned char *imgout);
int main1();//DCT变换
int main2();//标量量化
int main3();//反量化
int main4();//反DCT变换
int main5();//反分块
int main6();//信噪比计算
image=malloc(Width*Height*sizeof(unsigned char));//用unsigned char类型是因为图像灰度值是从0到255的整数
image1=malloc(Width*Height*sizeof(unsigned char));
imagein=fopen("Lenna.bmp","rb+");//以rb+(为读/写打开一个二进制文件)方式打开名为“Lenna.bmp”的文件,用指针imagein指向该文件
imageout=fopen("Lena.bmp","wb+");//以wb+方式打开名为“Lenna.bmp”的文件,并用指针imageout指向该文件
fread(head,1078*sizeof(unsigned char),1,imagein);//从imagein所指定的文件中读取长度为1078*sizeof的1个数据项,存到head所指向的内存区
fwrite(head,1078*sizeof(unsigned char),1,imageout);//把head所指向的1*sizeof个字节输出到imageout所指向的文件中
fread(image,Width*Height*sizeof(unsigned char),1,imagein);
block(Height,Width,N,image,image1);
fwrite(image1,Width*Height*sizeof(unsigned char),1,imageout);
free(image);//释放image所指的内存区
free(image1);
fclose(imagein);//以防误用。使文件指针变量不指向该文件,不能再通过该指针对原来与其相联系的文件进行读写操作
fclose(imageout);
main1();
main2();
main3();
main4();
main5();
main6();
}
FILE *FileOpen(char *filename,char *opt)
{
FILE *fp;
fp=fopen(filename,opt);
if(fp==NULL)
{
printf("\n Can't open the file %s !\n",filename);
exit(-1);
}
return(fp);
}
int block(int img_height,int img_width,int size,unsigned char *imgin,unsigned char *imgout)//分块函数
{
int p=0;
int r,c,i,j;
for(r=0;r<img_height/size;r++)//r为所有的块的行的变化范围为0到height/size-1
{
for(c=0;c<img_width/size;c++)//c为所有的块的列的变化范围为0到width/size-1
{
for(j=0;j<size;j++)//j为每个块内行的变化范围为0到size-1
{
for(i=0;i<size;i++)//i为每个块内列的变化范围为0到size-1
{
imgout[p++]=imgin[r*size*img_width+c*size+j*img_width+i];
//c*size*imag_width为找到第r行的块
//r*size 为找到第c列的块
//j*img_width 为找到第r行第c列的块内的第j行
//i 为找到第r行第c列的块内的第j行的第i列
//依次把一维数组imgin中的按块扫描结果赋给一维数组imgout
}
}
}
}
return 0;
}
int main1()//DCT变换
{
FILE *FileOpen(char *filename,char *opt),*imagein,*imageout;
unsigned char *image,head[1078];
double *image1;
int i,j;
double *DCT(int size,unsigned char *imgin,double *imgout);
image=malloc(Width*Height*sizeof(unsigned char));
image1=malloc(Width*Height*sizeof(double));
imagein=fopen("Lena.bmp","rb+");
imageout=fopen("Lena.dat","wb+");
fread(head,1078*sizeof(unsigned char),1,imagein);
fread(image,Width*Height*sizeof(unsigned char),1,imagein);
DCT(N,image,image1);
printf("DCT变换后的前64个值为:\n");
for(i=0;i<8;i++)
{
for(j=0;j<8;j++)
{
printf("%-10.6f ",image1[i*N+j]);//输出DCT变换后的前64个值,每8个一行输出
}
printf("\n");
}
fwrite(image1,Width*Height*sizeof(double),1,imageout);
free(image);
free(image1);
fclose(imagein);
fclose(imageout);
return 0;
}
double *DCT(int size,unsigned char *imgin,double *imgout)//DCT变换函数
{
int i,j,u,v,k;
int p=0;
double C[8],D[8];
for(p=0;p<Width*Height;p++)
imgout[p]=0;
p=0;
for(k=0;k<((Width*Height)/(size*size));k++)//k=0,1,...,256*256/64表示的是所有的8*8的块数的块标(因为每个8*8块内含有64个数),即代表第0个8*8块,第1个8*8块...
{
for(u=0;u<size;u++)
{
for(v=0;v<size;v++)
{
if(u==0) C[u]=sqrt(2)/2;
else C[u]=1;
if(v==0) D[v]=sqrt(2)/2;
else D[v]=1;
for(i=0;i<size;i++)
{
for(j=0;j<size;j++)
{
imgout[p]+=(2.0/size)*C[u]*D[v]*imgin[k*size*size+i*size+j]*cos((2*j+1)*v*Pi/2/size)*cos((2*i+1)*u*Pi/2/size);
}
}//由k来控制块的变换,u,v来控制每个块内64个数据的行列变化。i,j来控制求和计算。
p++;//p表示的是输出图像序列的标号。每64个数求和计算(由i和j的循环来控制)得到一个p,对于每个块(k表示第k块),一个v对应一个p,共8个v,一个u对应8个v,每个块共8个u,所以每个块共8*8个p,即64个数
}
}
}
return imgout;
}
int main2()//标量量化
{
FILE *FileOpen(char *filename,char *opt),*imagein,*imageout;//结构体FILE定义文件指针imagein和imageout
double *image;
double *image1;
int i,j;
int SQ(int size,double *imgin,double *imgout);//定义SQ函数
image=malloc(Width*Height*sizeof(double));//分配Wideth*Height*sizeof个字节的存储区给image
image1=malloc(Width*Height*sizeof(double));
imagein=fopen("Lena.dat","rb+");//以“rb+”方式打开“Lena.dat”文件,imagein指向该文件
imageout=fopen("Lena1.dat","wb+");
fread(image,Width*Height*sizeof(double),1,imagein);//从imagein中读入长度为Width*Height*sizeof个字节的1个数据项到image中(读入数据)
SQ(N,image,image1);//调用SQ函数
printf("标量量化后的前64个值为:\n");
for(i=0;i<8;i++)
{
for(j=0;j<8;j++)
{
printf("%-10.6f ",image1[i*N+j]);//每行输出8个换行
}
printf("\n");
}
fwrite(image1,Width*Height*sizeof(double),1,imageout);//从image1中读出长度为Width*Height*sizeof个字节的1个数据项
free(image);
free(image1);
fclose(imagein);
fclose(imageout);
return 0;
}
int SQ(int size,double *imgin,double *imgout)//矢量量化函数
{int i,j,k;
int p=0;
double c[64]={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};//取自JPEG量化表
for(k=0;k<Width*Height;k+=size*size)//k表示第k*64个数
{
for(i=0;i<size;i++)
{for(j=0;j<size;j++)
{
if(imgin[k+i*size+j]>0||imgin[k+i*size+j]==0)//该if语句目的是使得出的浮点型DCT系数四舍五入取整
imgout[p]=(int)((imgin[k+i*size+j]/c[i*size+j])+0.5);
else
imgout[p]=(int)((imgin[k+i*size+j]/c[i*size+j])-0.5);
p++;
}
}
}
return 0;
}
int main3()//反量化
{
FILE *FileOpen(char *filename,char *opt),*imagein,*imageout;//结构体FILE定义文件指针imagein和imageout
double *image;
double *image1;
int i,j;
int ISQ(int size,double *imgin,double *imgout);//定义ISQ函数
image=malloc(Width*Height*sizeof(double));//分配Wideth*Height*sizeof个字节的存储区给image
image1=malloc(Width*Height*sizeof(double));
imagein=fopen("Lena1.dat","rb+");//以“rb+”方式打开“Lena1.dat”文件,imagein指向该文件
imageout=fopen("Lena2.dat","wb+");
fread(image,Width*Height*sizeof(double),1,imagein);//从imagein中读入长度为Width*Height*sizeof个字节的1个数据项到image中(读入数据)
ISQ(N,image,image1);//调用ISQ函数
printf("反量化后的前64个值为:\n");
for(i=0;i<8;i++)
{
for(j=0;j<8;j++)
{
printf("%-10.6f ",image1[i*N+j]);//每行输出8个换行
}
printf("\n");
}
fwrite(image1,Width*Height*sizeof(double),1,imageout);//从image1中读出长度为Width*Height*sizeof个字节的1个数据项
free(image);
free(image1);
fclose(imagein);
fclose(imageout);
return 0;
}
int ISQ(int size,double *imgin,double *imgout)//反量化函数
{int i,j,k;
int p=0;
double c[64]={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};//取自JPEG量化表
for(k=0;k<Width*Height;k+=size*size)//k表示第k*64个数
{
for(i=0;i<size;i++)
{for(j=0;j<size;j++)
{
imgout[p]=(imgin[k+i*size+j]*c[i*size+j]);
p++;
}
}
}
return 0;
}
int main4()//反DCT变