基本信息
源码名称:对图像做空间滤波
源码大小:0.33M
文件格式:.rar
开发语言:C/C++
更新时间:2015-07-02
   源码介绍

滤波之前



滤波之后




#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include "bmpstruct.h"

/***************************************************************************************/
/*************读取BMP文件的文件头,并保存于filehead指向的区域***************************/
/***************************************************************************************/
int read_bmp_filehead( char* bmpName, BITMAPFILEHEADER* filehead)
{
	FILE* fp;
	fp=fopen(bmpName, "rb");
	if (fp==NULL)
	{
		printf("Can't open %s\n",bmpName);
		return 0;
	}
	else
	{
		fread(&filehead->bfType, 2, 1, fp);//从BMP文件读取2个字节的数据
	    fread(&filehead->bfSize, 4, 1, fp);//从BMP文件读取4个字节的数据
		fread(&filehead->bfReserved1, 2, 1, fp);//从BMP文件读取2个字节的数据
		fread(&filehead->bfReserved2, 2, 1, fp);//从BMP文件读取2个字节的数据
		fread(&filehead->bfOffBits, 4, 1, fp);//从BMP文件读取4个字节的数据
	}
	fclose(fp);
	return 1;
}

/***************************************************************************************/
/**************读取BMP文件的信息头,并保存于infohead指向的区域**************************/
/***************************************************************************************/
int read_bmp_infohead( char* bmpName, BITMAPINFOHEADER* infohead)
{
	FILE* fp;
	fp=fopen(bmpName, "rb");
	if (fp==NULL)
	{
		printf("Can't open %s\n",bmpName);
		return 0;
	}
	else
		fseek(fp, 14, 0);//跳过BMP文件起始的14个字节
		fread(infohead, 40, 1, fp);//从BMP文件一次性读取40个字节的数据
	fclose(fp);
	return 1;
}

/***************************************************************************************/
/*****************读取BMP文件的颜色表,并保存在color数组*********************************/
/***************************************************************************************/
int read_bmp_colortable( char* bmpName, int bitCount, int colorused, RGBQUAD* color)
{
	int colornum;
	FILE* fp;
	fp=fopen(bmpName, "rb");
	if (fp==NULL)
	{
		printf("Can't open %s\n",bmpName);
		return 0;
	}
	if (bitCount==24)
	{
		printf("The true color BMP doesn't have color table!\n");//24位的真彩BMP没有颜色表
		return 0;
	}
	else if (colorused==0)//当BMP信息头的colorused为零时,则颜色表的颜色总数为2的bitCount次幂
	{
		colornum=(int) pow(2, bitCount);//颜色表的颜色总数
		fseek(fp, 54, 0);
		fread(color, 4*colornum, 1, fp);
	}
	else
	{
		fseek(fp, 54, 0);
		fread(color, 4*colorused, 1, fp);
	}
	
	fclose(fp);
	return 1;
}

/***************************************************************************************/
/********读取BMP文件的位图数据保存到某个二维数组,并返回二维数组的指针******************/
/***************************************************************************************/
BYTE**	read_bmpData2array(char* bmpName, int width, int height, int bitCount, int dataoffset)
{
	int totalbytes_line;
	BYTE** array_pointer;
	int i, j, k;
	
	FILE* fp;
	fp=fopen(bmpName, "rb");//用"rb"的方式打开一个文件
	if (fp==NULL)
	{
		printf("Can't open %s\n",bmpName);
		return 0;
	}
    
	totalbytes_line=(width*bitCount 31)/32*4;//经过补零之后,每一行的总字节数
	
	//给二维数组动态分配内存
	array_pointer=(BYTE**) malloc(height*sizeof(BYTE*));
	for(k=0; k<height; k  )
	{
		array_pointer[k]=malloc(totalbytes_line*sizeof(BYTE));
		if(array_pointer[k]==NULL)
		{
			printf("The malloc of array_pointer[k] fail", k);
		}  
	}  
	
	fseek(fp, dataoffset, 0);
	for (i=0; i<height; i  )
		for (j=0; j<totalbytes_line; j  )
		array_pointer[i][j]=fgetc(fp);//将位图数据按序读到二维数组

	fclose(fp);   
	return(array_pointer);
}

/***************************************************************************************/
/***********************************创建空间滤波的模板**********************************/
/*函数输入为滤波模板的高和宽
/*函数返回值为指向存储模板系数的二维数组的指针
/***************************************************************************************/
BYTE** create_template( int plate_height, int plate_width )
{
	BYTE** coefficient_array;
	int i, j;

	//给二维数组动态分配内存
	coefficient_array=(BYTE**) malloc(plate_height*sizeof(BYTE*));
	for(i=0; i<plate_height; i  )
	{
		coefficient_array[i]=malloc(plate_width*sizeof(BYTE));
		if(coefficient_array[i]==NULL)
		{
			printf("The malloc of coefficient_array[%d] failed", i);
		}  
	}  

	//给二维数组赋值,即确定模板的系数
	for(i=0; i<plate_height; i  )
		for(j=0; j<plate_width; j  )
		{
			coefficient_array[i][j]=1;//均值滤波模板的系数全为1
		}
	
	return coefficient_array;
}

/***************************************************************************************/
/*************************************对图像做对均值滤波********************************/
//函数输入array_pointer为指向存储位图数据的二维数组的指针
//coefficient_array为指向存储滤波模板系数的二维数组的指针
//img_width和img_height分别是待处理BMP图片的高和宽
//plate_width和plate_height分别是滤波模板的高和宽
/***************************************************************************************/
int average_filter(BYTE** array_pointer, BYTE** coefficient_array, DWORD img_width, DWORD img_height, int plate_width, int plate_height)
{
	DWORD i, j;
	int m, n;
	float sum_weight, sum_coefficient=0.0f;
	int distance=(plate_height-1)/2; //滤波模板中心到边界的距离,本实验中plate_width和plate_height相等,且都是奇数
	
	//求滤波模板的系数和
	for(m=0; m<plate_height; m  )
		for(n=0; n<plate_width; n  )
		{
			sum_coefficient=sum_coefficient coefficient_array[m][n];
		}

	//对像素点作均值滤波,本实验将滤波模板中心的移动范围限制在距离图像边缘distance个像素处
	for(i=distance; i<img_height-distance; i  )
		for(j=distance; j<img_width-distance; j  )
		{
			 //每次循环前,将加权和置零
			sum_weight=0.0f;
			
			 //求加权和
			for(m=0-(plate_height-1)/2; m<=(plate_height-1)/2; m  )
				for(n=0-(plate_width-1)/2; n<=(plate_width-1)/2; n  )
				{
					sum_weight=sum_weight coefficient_array[distance m][distance n]*array_pointer[i m][j n];
				}

			array_pointer[i][j]=(BYTE) (sum_weight/sum_coefficient 0.5); //求均值滤波的结果,并四舍五入
		}

	return 0;
}

/***************************************************************************************/
/**********************创建一个新的BMP文件(不含位图数据和颜色表)**********************/
/***************************************************************************************/
int create_blankBmp(char* newbmpName, BITMAPFILEHEADER* filehead, BITMAPINFOHEADER* infohead)
{
	FILE* fp;
	fp=fopen(newbmpName, "w ");//用"w "的方式新建一个文件,并打开
	if (fp==NULL)
	{
		printf("Can't open %s\n",newbmpName);
		return 0;
	}
	fwrite(&filehead->bfType, 2, 1, fp);//依次写入文件头信息
	fwrite(&filehead->bfSize, 4, 1, fp);
	fwrite(&filehead->bfReserved1, 2, 1, fp);
	fwrite(&filehead->bfReserved2, 2, 1, fp);
	fwrite(&filehead->bfOffBits, 4, 1, fp);
	fwrite(infohead, 40, 1, fp);//写入信息头信息
	
	fclose(fp);

	return 1;
}

/***************************************************************************************/
/*************************向新建BMP文件填充颜色表和位图数据*****************************/
/***************************************************************************************/
int input_color_data(char* newbmpName, BITMAPFILEHEADER* filehead, BITMAPINFOHEADER* infohead, RGBQUAD* color, BYTE** array_pointer)
{
	DWORD h, w, n;
	FILE* fp;
	fp=fopen(newbmpName, "rb ");//用"rb "的方式打开已经建立的目标BMP文件
	if (fp==NULL)
	{
		printf("Can't open %s\n",newbmpName);
		return 0;
	}

    fseek(fp, 54, 0);
		fwrite(color, 4*256, 1, fp);//先写入颜色表
	
	h=infohead->biHeight;//8位BMP图像的高
   	w=((infohead->biWidth)*8 31)/32*4;//8位BMP图像的每一行补零之后所占的总字节数
	for(n=0; n<h; n  )
   		fwrite(array_pointer[n], w, 1, fp);//写入各个像素的值
	
	fclose(fp);

	return 1;
}