上一篇介绍过了位图的基本概念,相信大家对bmp格式的图片存储结构已经了解了,下面就以一个win32控制台程序来实现真彩图(也就是24位位图)转为为256级灰度图,这在图像处理上非常重要。
为什么用控制台程序而不是MFC等窗口程序呢,是因为这程序更能说明算法实现的过程,而不拘泥于MFC的框架下。
程序如下:(注释很好,不用过多解释)
#include <stdio.h>
#include <windows.h>
#define WIDTHBYTES(i) ( ( (i+31)/32 )*4) //使每一行的宽度是4个字节的倍数
#define IMAGETYPE 0x4d42 //表示字符BM
int main(int argc,char* argv)
{
BITMAPFILEHEADER bmpfileheader; //文件头
BITMAPINFOHEADER bmpinfoheader; //信息头
unsigned char *matrix; //像素矩阵,用unsigned char是因为它的范围刚好为0—255
FILE *finput; //读取操作流
FILE *foutput; //出操作流
DWORD imageSize = 0; //图像像素数据部分大小
//打开文件
finput=fopen("picture.bmp","r+b");
if (finput == NULL)
{
printf("Open failed\n");
return EXIT_FAILURE;
}
else
{
printf("Open Successsfully\n");
}
fread(&bmpfileheader,sizeof(BITMAPFILEHEADER),1,finput);//读取文件头
fread(&bmpinfoheader,sizeof(BITMAPINFOHEADER),1,finput);//读取信息头
//判断是否为24位真彩图
if ( bmpfileheader.bfType!=IMAGETYPE || bmpinfoheader.biBitCount != 24)
{
printf("The error picture!");
return EXIT_FAILURE;
}
//计算位图像素部分的大小,也可以是bmpinfoheader.biSizeImage 但它有时候是0,不可靠。
imageSize = WIDTHBYTES(bmpinfoheader.biWidth*bmpinfoheader.biBitCount) * bmpinfoheader.biHeight;
matrix = new unsigned char[imageSize];
memset(matrix,0,imageSize);
//读取象素矩阵
fread(matrix,1,imageSize,finput);
fclose(finput);
//每个像素点转化为灰度值,用的公式是:Gray = R*0.299 + G*0.587 + B*0.114
for(unsigned long k=0;k<imageSize;k=k+3)
{
*(matrix+k)=*(matrix+k+1)=*(matrix+k+2)=(*(matrix+k)*0.299+*(matrix+k+1)*0.587+*(matrix+k+2)*0.114);
}
//创建新的灰度图
foutput=fopen("test.bmp","w+b");
fwrite(&bmpfileheader,sizeof(BITMAPFILEHEADER),1,foutput);
fwrite(&bmpinfoheader,sizeof(BITMAPINFOHEADER),1,foutput);
fwrite(matrix,1,imageSize,foutput);
fclose(foutput);
delete []matrix;
printf("转化成功\n");
return EXIT_SUCCESS;
}
实现结果:把一张bmp格式的真彩图放在工程目录下,运行程序生成一个灰度图。