天天看點

【圖像處理】DCT圖像壓縮算法(C++與Matlab)

【圖像處理】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;  

}   
           
【圖像處理】DCT圖像壓縮算法(C++與Matlab)

Matlab版本會在後面更新,敬請期待!Matlab效果如下:

【圖像處理】DCT圖像壓縮算法(C++與Matlab)
【圖像處理】DCT圖像壓縮算法(C++與Matlab)

繼續閱讀