【图像处理】DCT图像压缩算法(C++与Matlab)

 

以下是原创的C++代码,可在VC6.0及以上版本测试,相关头文件若缺失请在百度或谷歌下载。

#include <stdio.h>  
#include "BmpRot.h"  
#include "stdlib.h"  
#include "math.h"  
#include <iostream> 
#include <cmath>  
 //#include "stdafx.h" 
#define pi 3.14159//圆周率宏定义  
#define LENGTH_NAME_BMP 30//bmp图片文件名的最大长度  
#define num 8
float s[8][8];
float t[8][8];
int n=1,u,v,cv,cu;
using namespace std;  

//变量定义  
BITMAPFILEHEADER strHead;  
RGBQUAD strPla[256];//256色调色板  
BITMAPINFOHEADER strInfo;  
 
//显示位图文件头信息  
void showBmpHead(BITMAPFILEHEADER pBmpHead){  
    cout<<"位图文件头:"<<endl;  
    cout<<"文件大小:"<<pBmpHead.bfSize<<endl;  
    cout<<"保留字_1:"<<pBmpHead.bfReserved1<<endl;  
    cout<<"保留字_2:"<<pBmpHead.bfReserved2<<endl;  
    cout<<"实际位图数据的偏移字节数:"<<pBmpHead.bfOffBits<<endl<<endl;  
}  
  
void showBmpInforHead(tagBITMAPINFOHEADER pBmpInforHead){  
    cout<<"位图信息头:"<<endl;  
    cout<<"结构体的长度:"<<pBmpInforHead.biSize<<endl;  
    cout<<"位图宽:"<<pBmpInforHead.biWidth<<endl;  
    cout<<"位图高:"<<pBmpInforHead.biHeight<<endl;  
    cout<<"biPlanes平面数:"<<pBmpInforHead.biPlanes<<endl;  
    cout<<"biBitCount采用颜色位数:"<<pBmpInforHead.biBitCount<<endl;  
    cout<<"压缩方式:"<<pBmpInforHead.biCompression<<endl;  
    cout<<"biSizeImage实际位图数据占用的字节数:"<<pBmpInforHead.biSizeImage<<endl;  
    cout<<"X方向分辨率:"<<pBmpInforHead.biXPelsPerMeter<<endl;  
    cout<<"Y方向分辨率:"<<pBmpInforHead.biYPelsPerMeter<<endl;  
    cout<<"使用的颜色数:"<<pBmpInforHead.biClrUsed<<endl;  
    cout<<"重要颜色数:"<<pBmpInforHead.biClrImportant<<endl;  
}  


void dct(float data[num][num],float output[num][num])
{
	double cu,cv;
	short u=0;
	short v=0;
	short i=0;
	short j=0;
	for(u = 0;u < num;u++)
	{
		for(v = 0;v < num;v++)
		{
			if(u==0)
				cu = sqrt(1.0/2.0);
			else
				cu = 1;
			if(v==0)
				cv = sqrt(1.0/2.0);
			else
				cv = 1;
			double tmp=0.0;
			for(i = 0;i < num;i++)
			{
				for(j = 0;j < num;j++)
				{
					tmp+= (data[i][j])
						* cos( (2*i+1) * u * pi / (2.0*num) )
						* cos( (2*j+1) * v * pi / (2.0*num) );

				}
			}
			output[u][v]= ( cu * cv /4.0) * tmp;
			if(output[u][v]<10 && output[u][v]>-10 )
			{output[u][v]=0;}
		}

	}
          
}


void idct(float input[num][num],float output[num][num])
{
	short i,j,u,v;
	double cu,cv;
	for(i = 0;i < num;i++)
	{
		for(j = 0;j < num;j++)
		{
			double tmp=0.0;
			for(u = 0;u < num;u++)
			{
				for(v = 0;v < num;v++)
				{
					if(u==0)
						cu = sqrt(1.0/2.0);
					else
						cu = 1;
					if(v==0)
						cv = sqrt(1.0/2.0);
					else
						cv = 1;
					tmp+= (cu*cv/4.0)  * (input[u][v])
						* cos( (2*i+1) * u * pi / (2.0*num))
						* cos( (2*j+1) * v * pi / (2.0*num));
				}
			}
			output[i][j]=tmp;
		}
	}
}


int main(){  
    char strFile[LENGTH_NAME_BMP];//bmp文件名  
    IMAGEDATA *imagedata = NULL;//动态分配存储原图片的像素信息的二维数组  
    IMAGEDATA *imagedataRot = NULL;//动态分配存储旋转后的图片的像素信息的二维数组  
	IMAGEDATA *imagedataRot1 = NULL;
	IMAGEDATA *imagedataRot2 = NULL;
    int width,height,temp;//图片的宽度和高度
   
	cout<<"请输入所要读取的文件名:"<<endl;   
	cin>>strFile;  
    FILE *fpi,*fpw;  
    fpi=fopen(strFile,"rb");  
    if(fpi != NULL){  
        //先读取文件类型  
        WORD bfType;  
        fread(&bfType,1,sizeof(WORD),fpi);  
        if(0x4d42!=bfType)  
        {  
            cout<<"the file is not a bmp file!"<<endl;  
            return NULL;  
        }  
        //读取bmp文件的文件头和信息头  
        fread(&strHead,1,sizeof(tagBITMAPFILEHEADER),fpi);  
        //showBmpHead(strHead);//显示文件头  
        fread(&strInfo,1,sizeof(tagBITMAPINFOHEADER),fpi);  
        //showBmpInforHead(strInfo);//显示文件信息头  
  
        //读取调色板  
        for(unsigned int nCounti=0;nCounti<strInfo.biClrUsed;nCounti++)  
        {  
            fread((char *)&(strPla[nCounti].rgbBlue),1,sizeof(BYTE),fpi);  
            fread((char *)&(strPla[nCounti].rgbGreen),1,sizeof(BYTE),fpi);  
            fread((char *)&(strPla[nCounti].rgbRed),1,sizeof(BYTE),fpi);  
            fread((char *)&(strPla[nCounti].rgbReserved),1,sizeof(BYTE),fpi);  
        }  
  
        width = strInfo.biWidth;  
        height = strInfo.biHeight;  
        //图像每一行的字节数必须是4的整数倍  
        width = (width * sizeof(IMAGEDATA) + 3) / 4 * 4;  
        //imagedata = (IMAGEDATA*)malloc(width * height * sizeof(IMAGEDATA));  
        imagedata = (IMAGEDATA*)malloc(width * height);  
        imagedataRot = (IMAGEDATA*)malloc( width  * height * sizeof(IMAGEDATA));  
		imagedataRot1 =  (IMAGEDATA*)malloc(width * height); 
		imagedataRot2 =  (IMAGEDATA*)malloc(width * height); 
        //初始化原始图片的像素数组  
        for(int i = 0;i < height;++i)  
        {  
            for(int j = 0;j < width;++j)  
            {  
                (*(imagedata + i * width + j)).blue = 0;  
                //(*(imagedata + i * width + j)).green = 0;  
                //(*(imagedata + i *  width + j)).red = 0;  
            }  
        }  
        //初始化旋转后图片的像素数组  
        for( i = 0;i <  height;++i)  
        {  
            for(int j = 0;j <  width;++j)  
            {  
                (*(imagedataRot + i *  width + j)).blue = 0;  
                //(*(imagedataRot + i *  width + j)).green = 0;  
                //(*(imagedataRot + i *  width + j)).red = 0;  
            }  
        }  
		
        //fseek(fpi,54,SEEK_SET);  
        //读出图片的像素数据  
        fread(imagedata,sizeof(struct tagIMAGEDATA) * width,height,fpi);  
        fclose(fpi);  
    }  
    else  
    {  
        cout<<"file open error!"<<endl;  
        return NULL;  
    }  
  
    int i,j,x,y;
float a[8][8]={0.0};
	for(int m = 0;m < 64;m++)
	{	
		for(int n = 0;n < 64;n++)
		{	
			for(i = 0;i < 8;i++)
			{	for(j = 0;j < 8;j++)
				{
                   a[i][j]=(float)(*(imagedata + (m*8+i) *  width + (n*8+j))).blue;   
				}
			}
	dct(a,s);
	for(x = 0;x < 8;x++)
			{
				for(y = 0;y < 8;y++)
				{
					if( x+y >=4 )
						s[x][y]=0;
				}
			}
	idct(s,t);
      for(i = 0;i < 8;i++)
			{
				for(j = 0;j < 8;j++)
				{
					(*(imagedataRot + (m*8+i )*  width + n*8+j)).blue=(unsigned char)t[i][j]; 
				}
			}
		}
    }
    //保存bmp图片  
    if((fpw=fopen("b.bmp","wb"))==NULL)  
    {  
        cout<<"create the bmp file error!"<<endl;  
        return NULL;  
    }  
    WORD bfType_w=0x4d42;  
    fwrite(&bfType_w,1,sizeof(WORD),fpw);  
    //fpw +=2;  
    fwrite(&strHead,1,sizeof(tagBITMAPFILEHEADER),fpw);  
    strInfo.biWidth = width;  
    strInfo.biHeight =  height;  
    fwrite(&strInfo,1,sizeof(tagBITMAPINFOHEADER),fpw);  
    for(unsigned int nCounti=0;nCounti<strInfo.biClrUsed;nCounti++)  
    {  
        fwrite(&strPla[nCounti].rgbBlue,1,sizeof(BYTE),fpw);  
        fwrite(&strPla[nCounti].rgbGreen,1,sizeof(BYTE),fpw);  
        fwrite(&strPla[nCounti].rgbRed,1,sizeof(BYTE),fpw);  
        fwrite(&strPla[nCounti].rgbReserved,1,sizeof(BYTE),fpw);  
    }  
    //保存像素数据  
    for(i =0;i <  height;++i)  
    {  
        for(int j = 0;j <  width;++j)  
        {  
            fwrite( &((*(imagedataRot + i *width + j)).blue),1,sizeof(BYTE),fpw);  
            //fwrite( &((*(imagedataRot + i *  width + j)).green),1,sizeof(BYTE),fpw);  
            //fwrite( &((*(imagedataRot + i * width + j)).red),1,sizeof(BYTE),fpw);  
        }  
    }  
    fclose(fpw);     
   
    //释放内存  
    delete[] imagedata;  
    delete[] imagedataRot;  

}   

Matlab版本会在后面更新,敬请期待!Matlab效果如下:

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值