C++实现24位位图的灰度化
来源:互联网 发布:炫踪网络 ceo 编辑:程序博客网 时间:2024/06/05 16:00
关于BMP文件的结构,更详细的内容可以参考:bmp文件格式详解。
将24位真彩BMP图像灰度化的代码如下:
#include "stdafx.h" #include <iostream>#include <Windows.h> using namespace std; void main(){ FILE* stream=fopen("Source.bmp","rb");if(stream==NULL){cout<<"文件不存在"<<endl;return;} int sizeFileHeader=sizeof(BITMAPFILEHEADER);int sizeInfoHeader=sizeof(BITMAPINFOHEADER); BITMAPFILEHEADER* bitmapFileHeader=new BITMAPFILEHEADER[sizeFileHeader+1];BITMAPINFOHEADER* bitmapInfoHeader=new BITMAPINFOHEADER[sizeInfoHeader+1]; memset(bitmapFileHeader,0,sizeFileHeader+1);memset(bitmapInfoHeader,0,sizeInfoHeader+1);fread(bitmapFileHeader,sizeof(char),sizeFileHeader,stream);fseek(stream,sizeFileHeader,0);fread(bitmapInfoHeader,sizeof(char),sizeInfoHeader,stream);int srcImageLineByteCount=(((bitmapInfoHeader->biWidth*24)+31)/32)*4;int destImageLineByteCount=(((bitmapInfoHeader->biWidth)*8+31)/32)*4; //************位图信息头********************** BYTE** oldImageData=new BYTE*[bitmapInfoHeader->biHeight];for(int i=0;i<bitmapInfoHeader->biHeight;i++){oldImageData[i]=new BYTE[srcImageLineByteCount+1];memset(oldImageData[i],0,srcImageLineByteCount+1);} //***********位图数据***********************fseek(stream,sizeFileHeader+sizeInfoHeader,0);//读取图像数据for(i=0;i<bitmapInfoHeader->biHeight;i++){for (int j=0;j<srcImageLineByteCount;j++){fread(&oldImageData[i][j],sizeof(BYTE),1,stream); } } fclose(stream); //调色板RGBQUAD* pRgbQuards=new RGBQUAD[256];for(i=0;i<256;i++){pRgbQuards[i].rgbBlue=i;pRgbQuards[i].rgbRed=i;pRgbQuards[i].rgbGreen=i; } //修改信息头bitmapInfoHeader->biBitCount=8;bitmapInfoHeader->biSizeImage=(bitmapInfoHeader->biHeight)*destImageLineByteCount;bitmapInfoHeader->biClrUsed=256; // 调色板中使用的颜色索引数 //修改文件头bitmapFileHeader->bfOffBits=sizeof(BITMAPFILEHEADER)+sizeof(BITMAPINFOHEADER)+sizeof(RGBQUAD)*256;bitmapFileHeader->bfSize=bitmapFileHeader->bfOffBits+bitmapInfoHeader->biSizeImage; //写数据 BYTE** newImageData=new BYTE*[bitmapInfoHeader->biHeight]; for (i=0;i<bitmapInfoHeader->biHeight;i++){newImageData[i]=new BYTE[destImageLineByteCount];} for(i=0;i<bitmapInfoHeader->biHeight;i++){for(int j=0;j<destImageLineByteCount;j++){newImageData[i][j]=(int)((float)oldImageData[i][j*3]*0.114+(float)oldImageData[i][j*3+1]*0.587+(float)oldImageData[i][3*j+2]*0.299);}}//写入文件[cpp]FILE* fileWrite=fopen("Sink.bmp","ab");fwrite(bitmapFileHeader,sizeof(char),sizeof(BITMAPFILEHEADER),fileWrite);fwrite(bitmapInfoHeader,sizeof(char),sizeof(BITMAPINFOHEADER),fileWrite);fwrite(pRgbQuards,sizeof(RGBQUAD),256,fileWrite); for(i=0;i<bitmapInfoHeader->biHeight;i++){for(int j=0;j<destImageLineByteCount;j++){fwrite(&newImageData[i][j],sizeof(BYTE),1,fileWrite);} }fclose(fileWrite);cout<<"success"<<endl;return;}
程序中主要需要注意的部分:
1. 以原图640*480图像为例,在VC6.0中建立了一个Win32 Console Application的工程。
2. 修改信息头:
信息头共11个部分,这里需要修改3部分:
bitmapInfoHeader->biBitCount=8; // 将每个像素的数据位宽从24改为8
bitmapInfoHeader->biSizeImage=(bitmapInfoHeader->biHeight)*destImageLineByteCount; // 图像大小改为640*480字节
bitmapInfoHeader->biClrUsed=256; // 将调色板中使用的颜色索引数改为256
3. 修改文件头:
文件头共5个部分,灰度化修改两个部分:
bitmapFileHeader->bfOffBits=sizeof(BITMAPFILEHEADER)+sizeof(BITMAPINFOHEADER)+sizeof(RGBQUAD)*256; // 图像数据相对文件开头位置的偏移量
bitmapFileHeader->bfSize=bitmapFileHeader->bfOffBits+bitmapInfoHeader->biSizeImage; // 文件大小,字节数
4. 创建调色板:
RGBQUAD *ipRGB2 = (RGBQUAD*)malloc(256*sizeof(RGBQUAD));
for ( i = 0; i < 256; i++ )
ipRGB2[i].rgbRed = ipRGB2[i].rgbGreen = ipRGB2[i].rgbBlue = i;
5. 修改位图数据
这部分主要是由原真彩图的rgbRed、rgbGreen、rgbBlue分量值得到灰度图像的灰度值Y,可以用下面公式得到:
Y=0.299*rgbRed+0.587* rgbGreen+0.114*rgbBlue;
6. 按顺序写入BMP图像的各个部分
fwrite(bitmapFileHeader,sizeof(char),sizeof(BITMAPFILEHEADER),fileWrite);
fwrite(bitmapInfoHeader,sizeof(char),sizeof(BITMAPINFOHEADER),fileWrite);
fwrite(pRgbQuards,sizeof(RGBQUAD),256,fileWrite);
for(i=0;i<bitmapInfoHeader->biHeight;i++)
{
for(int j=0;j<destImageLineByteCount;j++)
{
fwrite(&newImageData[i][j],sizeof(BYTE),1,fileWrite);
}
}
注意:向文件中写入数据时,打开文件的函数fopen使用了参数“ab”,即必须用二进制格式写入。如果按照文本方式将数据流写入文件,数据0x0A将会被自动扩展为ox0D0A。这是因为0x0D是回车,0x0A是换行,文本方式写入时windows会自动转换,这样反而破坏了bmp文件格式。文件读取时,同样也需要用二进制格式。
另外,上面的程序没有释放在堆上分配的内存指针,需要注意。
原图是这样滴:
变成灰度图是这样滴:
效果还不错吧!
- C++实现24位位图的灰度化
- 24位真彩色位图和8位灰度位图相互转换(C语言实现)
- 24位真彩色位图转换成8位灰度图片的代码实现
- 完整24位真彩色位图灰度化源代码
- 完整24位真彩色位图灰度化源代码
- 完整24位真彩色位图灰度化源代码
- 24位位图转成8位灰度位图
- 24位位图转化为灰度图
- bmp位图文件:读取、写入、24位真彩转8位灰度、灰度图的二值化
- 24位真色位图转化为8位灰度位图
- 24位转8位位图,不是灰度,有颜色的,尽量减少失真
- 24位位图转8位灰度图
- 【数字图像】C++8位和24位BMP位图的平滑、锐化、二值化处理,以及24位真彩图的灰度化
- C++8位和24位bmp位图平滑、锐化和二值处理,24位真彩图的灰度化
- 仅对8位,24位图像进行灰度处理
- 24位真彩图转8位灰度图并分解位平面 c-c++实现
- 位图灰度化算法
- 位图灰度化算法
- 如何修改 SAP 登录界面的文字(事务码SE61)
- HDU 1080 Human Gene Functions
- Jquery中toggle的用法
- 传参出错注意数据库连接问题
- window.close and self.close do not close the window in Chrome
- C++实现24位位图的灰度化
- 『转』android 程序中判断当前是否连接网络,网络是否可用
- 利用.dSYM和.app文件准确定位Crash位置
- Android 命令行手动编译打包详解
- 如何修改 SAP 登录后的背景图片(事务码 SMW0,SM30)
- ireport+jasperreport+jfreechart完成数据分析
- Linux中ctrl+z 、ctrl+c、 ctrl+d区别
- SQL 统计语句
- 在C#的WPF程序使用XAML实现画线