原理就不说了 我相信代码可以说明一切。另外如果像素不够,可以读颜色表。。。代码自己去搜索,
#include "stdio.h"
#include "Windows.h"
#include "math.h"
#define PI 3.1415926
//几个全局变量,存放读入图像的位图数据、宽、高、颜色表及每像素所占位数(比特)
//此处定义全局变量主要为了后面的图像数据访问及图像存储作准备
unsigned char *pBmpBufIn=NULL;//读入图像数据的指针
unsigned char *pBmpBufOut=NULL;//输出图像数据的指针
int bmpWidthIn;//输入图像的宽
int bmpHeightIn;//输入图像的高
int bmpWidthOut;
int bmpHeightOut;
RGBQUAD *pColorTable;//颜色表指针
int biBitCountIn;//输入图像类型
int biBitCountOut;//输出图像类型
struct ComplexNumber
{
float imag;// imaginary虚部
float real;//实部
};
ComplexNumber *m_pFFTBuf;
/***********************************************************************
* 函数名称:
* readBmp()
*
*函数参数:
* char *bmpName -文件名字及路径
*
*返回值:
* 0为失败,1为成功
*
*说明:给定一个图像文件名及其路径,读图像的位图数据、宽、高、颜色表及每像素
* 位数等数据进内存,存放在相应的全局变量中
***********************************************************************/
bool readBmp(char *bmpName)
{
//二进制读方式打开指定的图像文件
FILE *fp=fopen(bmpName,"rb");
if(fp==0) return 0;
//跳过位图文件头结构BITMAPFILEHEADER
fseek(fp, sizeof(BITMAPFILEHEADER),0);
//定义位图信息头结构变量,读取位图信息头进内存,存放在变量head中
BITMAPINFOHEADER head;
fread(&head, sizeof(BITMAPINFOHEADER), 1,fp);
//获取图像宽、高、每像素所占位数等信息
bmpWidthIn = head.biWidth;
bmpHeightIn = head.biHeight;
biBitCountIn = head.biBitCount;
//定义变量,计算图像每行像素所占的字节数(必须是4的倍数)
int lineByte=(bmpWidthIn * biBitCountIn/8+3)/4*4;
//灰度图像有颜色表,且颜色表表项为256
if(biBitCountIn==8){
//申请颜色表所需要的空间,读颜色表进内存
pColorTable=new RGBQUAD[256];
fread(pColorTable,sizeof(RGBQUAD),256,fp);
}
//申请位图数据所需要的空间,读位图数据进内存
if(pBmpBufIn==NULL)
pBmpBufIn=new unsigned char[lineByte * bmpHeightIn];
fread(pBmpBufIn,1,lineByte * bmpHeightIn,fp);
//关闭文件
fclose(fp);
return 1;
}
/***********************************************************************
* 函数名称:
* saveBmp()
*
*函数参数:
* char *bmpName -文件名字及路径
* unsigned char *imgBuf -待存盘的位图数据
* int width -像素为单位待存盘位图的宽
* int height -像素为单位待存盘位图高
* int biBitCount -每像素所占位数
* RGBQUAD *pColorTable -颜色表指针
*返回值:
* 0为失败,1为成功
*
*说明:给定一个图像位图数据、宽、高、颜色表指针及每像素所占的位数等信息,
* 将其写到指定文件中
***********************************************************************/
bool saveBmp(char *bmpName, unsigned char *imgBuf, int width, int height,
int biBitCount, RGBQUAD *pColorTable)
{
//如果位图数据指针为0,则没有数据传入,函数返回
if(!imgBuf)
return 0;
//颜色表大小,以字节为单位,灰度图像颜色表为1024字节,彩色图像颜色表大小为0
int colorTablesize=0;
if(biBitCount==8)
colorTablesize=1024;
//待存储图像数据每行字节数为4的倍数
int lineByte=(width * biBitCount/8+3)/4*4;
//以二进制写的方式打开文件
FILE *fp=fopen(bmpName,"wb");
if(fp==0) return 0;
//申请位图文件头结构变量,填写文件头信息
BITMAPFILEHEADER fileHead;
fileHead.bfType = 0x4D42;//bmp类型
//bfSize是图像文件4个组成部分之和
fileHead.bfSize= sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER)
+ colorTablesize + lineByte*height;
fileHead.bfReserved1 = 0;
fileHead.bfReserved2 = 0;
//bfOffBits是图像文件前三个部分所需空间之和
fileHead.bfOffBits=54+colorTablesize;
//写文件头进文件
fwrite(&fileHead, sizeof(BITMAPFILEHEADER),1, fp);
//申请位图信息头结构变量,填写信息头信息
BITMAPINFOHEADER head;
head.biBitCount=biBitCount;
head.biClrImportant=0;
head.biClrUsed=0;
head.biCompression=0;
head.biHeight=height;
head.biPlanes=1;
head.biSize=40;
head.biSizeImage=lineByte*height;
head.biWidth=width;
head.biXPelsPerMeter=0;
head.biYPelsPerMeter=0;
//写位图信息头进内存
fwrite(&head, sizeof(BITMAPINFOHEADER),1, fp);
//如果灰度图像,有颜色表,写入文件
if(biBitCount==8)
fwrite(pColorTable, sizeof(RGBQUAD),256, fp);
//写位图数据进文件
fwrite(imgBuf, height*lineByte, 1, fp);
//关闭文件
fclose(fp);
return 1;
}
void FFT1D(ComplexNumber *arrayBuf, int n)
{
//循环变量
int i, k, r;
//申请临时复数缓冲区buf1,长度为n
ComplexNumber *buf1=new ComplexNumber[n];
//将arrayBuf拷贝进buf1
memcpy(buf1,arrayBuf,sizeof(ComplexNumber)*n);
//申请临时复数缓冲区buf2,长度为n
ComplexNumber *buf2=new ComplexNumber[n];
//将arrayBuf数组元素基2抽取并重新排列
//若0、1、2、3、4、5、6、7八点序列对调后变作0、4、2、6、1、5、3、7
int t1,t2;
for(r=1;pow(double(2),r)<n;r++){
t1=pow(double(2),r);
t2=pow(double(2),r-1);
for(k=0;k<t1;k++){
for(i=0;i<n/t1;i++){
buf2[k*n/t1+i].real=buf1[k/2*n/t2+i*2+k%2].real;
buf2[k*n/t1+i].imag=buf1[k/2*n/t2+i*2+k%2].imag;
}
}
memcpy(buf1,buf2,sizeof(ComplexNumber)*n);
}
//采用蝶型算法进行快速傅立叶变换
//buf1是第r级的输入,buf2存放第r级的输出
float c,s;
for(r=1;pow(double(2),r)<=n;r++){
t1=pow(double(2),r);
for(k=0;k<n/t1;k++){
for(i=t1/2;i<t1;i++){
//加权因子
c=cos(-2*PI*(i-t1/2)/t1);
s=sin(-2*PI*(i-t1/2)/t1);
buf1[k*t1+i].real= buf2[k*t1+i].real*c - buf2[k*t1+i].imag*s;
buf1[k*t1+i].imag=buf2[k*t1+i].imag*c+buf2[k*t1+i].real*s;
}
}
for(k=0; k<n/t1; k++){
for(i=0;i<t1/2;i++){
buf2[k*t1+i].real= buf1[k*t1+i].real+buf1[k*t1+i+t1/2].real;
buf2[k*t1+i].imag= buf1[k*t1+i].imag+buf1[k*t1+i+t1/2].imag;
}
for(i=t1/2;i<t1;i++){
buf2[k*t1+i].real= buf1[k*t1+i-t1/2].real-buf1[k*t1+i].real;
buf2[k*t1+i].imag= buf1[k*t1+i-t1/2].imag-buf1[k*t1+i].imag;
}
}
//第r级的输出存入buf1,作为下一级的输入数据
memcpy(buf1,buf2,sizeof(ComplexNumber)*n);
}
//傅立叶变换的结果存入arrayBuf
memcpy(arrayBuf,buf2,sizeof(ComplexNumber)*n);
//释放缓冲区
delete[]buf2;
delete[]buf1;
}
void ImgFFT2D(unsigned char* imgBuf, int width, int height,
unsigned char *imgBufOut)
{
//循环变量
int i, j, u, v;
//图像数据变成复数类型存入m_pFFTBuf
for(i=0;i<width*height;i++){
m_pFFTBuf[i].real=imgBuf[i];
m_pFFTBuf[i].imag=0;
}
//申请ComplexNumber结构体数组,长度为height
ComplexNumber *array=new ComplexNumber[height];
//先纵向一维快速傅立叶变换
for(u=0;u<width;u++){
for(v=0;v<height;v++){
array[v].real=m_pFFTBuf[v*width+u].real;
array[v].imag=m_pFFTBuf[v*width+u].imag;
}
FFT1D(array, height);
for(v=0;v<height;v++){
m_pFFTBuf[v*width+u].real=array[v].real;
m_pFFTBuf[v*width+u].imag=array[v].imag;
}
}
delete []array;
//再横向一维快速傅立叶变换
for(v=0;v<height;v++){
FFT1D(m_pFFTBuf+v*width, width);
}
//将频谱图以图像形式存入imgBufOut
float t;
int i0,j0;
for(i=0;i<height;i++){
//i0 = i;
//j0 = j;
for(j=0;j<width;j++){
if(i<height/2)
i0=i+height/2;
else
i0=i-height/2;
if(j<width/2)
j0=j+width/2;
else
j0=j-width/2;
t=sqrt(m_pFFTBuf[i0*width+j0].real*m_pFFTBuf[i0*width+j0].real
+m_pFFTBuf[i0*width+j0].imag*m_pFFTBuf[i0*width+j0].imag);
t=t/500;
if(t>255)
imgBufOut[i*width+j]=255;
else
imgBufOut[i*width+j]=t;
}
}
}
void Fourier()
{
char readPath[100];
strcpy(readPath,"lena.bmp");
readBmp(readPath);
bmpWidthOut=bmpWidthIn;
bmpHeightOut=bmpHeightIn;
biBitCountOut=biBitCountIn;
pBmpBufOut=new unsigned char[bmpHeightOut*bmpWidthOut];
memset(pBmpBufOut,0,bmpHeightOut*bmpWidthOut);
m_pFFTBuf=new ComplexNumber[bmpHeightOut*bmpWidthOut];
memset(m_pFFTBuf,0,sizeof(ComplexNumber)*bmpWidthOut*bmpHeightOut);
ImgFFT2D(pBmpBufIn,bmpWidthOut,bmpHeightOut,pBmpBufOut);
}
void main()
{
Fourier();
//将图像数据存盘
char writePath[]="22.BMP";
saveBmp(writePath, pBmpBufOut, bmpWidthOut, bmpHeightOut, biBitCountOut, pColorTable);
//清除缓冲区,pBmpBuf和pColorTable是全局变量,在文件读入时申请的空间
delete []pBmpBufIn;
delete []pBmpBufOut;
delete []pColorTable;
}