BMP文件的读取
运行测试效果:
代码:
void CMyView::OnReadBmp()
{//读取BMP文件并显示
CDC *pDC = GetDC();
CFileDialog dlg(TRUE);
if(dlg.DoModal()==IDOK)
{//选择要打开的BMP图片
strFilePath=dlg.GetPathName();
}
if(strFilePath=="")
{//取消
return;
}
FILE *fp=fopen(strFilePath,"r");
BITMAPFILEHEADER fileheader;
BITMAPINFO info;
fread(&fileheader,sizeof(fileheader),1,fp);
if(fileheader.bfType!=0x4D42)
{//不是BMP位图文件
pDC->TextOut(100,200,"无位图文件 请选择位图文件");
fclose(fp);
return ;
}
UCHAR *buffer = NULL;
//读位图头部
fread(&info.bmiHeader, sizeof(BITMAPINFOHEADER), 1, fp);
//位图宽度
long width=info.bmiHeader.biWidth;
this->width = width;
//位图高度
long height=info.bmiHeader.biHeight;
this->height = height;
DWORD size;
if (info.bmiHeader.biSizeImage != 0)
{//带颜色表
size = info.bmiHeader.biSizeImage;
}
else
{//不带颜色表的
size = info.bmiHeader.biHeight*info.bmiHeader.biWidth*3;
}
buffer = new UCHAR[size];//分配缓冲区
if (buffer == NULL)
{//分配内存失败
delete[] buffer;
return;
}
//忽略头部字节
fseek(fp,fileheader.bfOffBits,0);
fread(buffer,size,1,fp);
int i,j;
#pragma region 16 color
// 16色图的解析
if(info.bmiHeader.biBitCount==4)
{
int pitch;
if(width%8==0)
pitch=width;
else
pitch=width+8-width%8;
RGBQUAD quad[16];
fseek(fp,fileheader.bfOffBits-sizeof(RGBQUAD)*16,0);
fread(quad,sizeof(RGBQUAD)*16,1,fp);
if(height>0)
{//height>0 表示图片颠倒
for(i=0; i<height; i++)
{
for(j=0; j<width; j++)
{
int index;
if(j%2==0)
index = buffer[(i*pitch+j)/2]/16;
if(j%2==1)
index = buffer[(i*pitch+j)/2]%16;
UCHAR r=quad[index].rgbRed;
UCHAR g=quad[index].rgbGreen;
UCHAR b=quad[index].rgbBlue;
pDC->SetPixel(j,height-i,RGB(r,g,b));
}
}
}
else
{//图片不颠倒
for(i=0; i<0-height; i++)
{
for(j=0; j<width; j++)
{
int index;
if(j%2==0)
index = buffer[(i*pitch+j)/2]/16;
if(j%2==1)
index = buffer[(i*pitch+j)/2]%16;
UCHAR r=quad[index].rgbRed;
UCHAR g=quad[index].rgbGreen;
UCHAR b=quad[index].rgbBlue;
pDC->SetPixel(j,i,RGB(r,g,b));
}
}
}
}
#pragma endregion 16 color
#pragma region 256 color
// 256色图的解析
if(info.bmiHeader.biBitCount==8)
{
int pitch;
if(width%4==0)
{
pitch=width;
}
else
{
pitch=width+4-width%4;
}
RGBQUAD quad[256];
fseek(fp,fileheader.bfOffBits-sizeof(RGBQUAD)*256,0);
fread(quad,sizeof(RGBQUAD)*256,1,fp);
if(height>0)
{//height>0 表示图片颠倒
for(int i=0;i<height;i++)
{
for(int j=0;j<width;j++)
{
int index=buffer[i*pitch+j];
UCHAR r=quad[index].rgbRed;
UCHAR g=quad[index].rgbGreen;
UCHAR b=quad[index].rgbBlue;
pDC->SetPixel(j,height-i,RGB(r,g,b));
}
}
}
else
{
for(int i=0;i<0-height;i++)
{
for(int j=0;j<width;j++)
{
int index=buffer[i*pitch+j];
UCHAR r=quad[index].rgbRed;
UCHAR g=quad[index].rgbGreen;
UCHAR b=quad[index].rgbBlue;
pDC->SetPixel(j,i,RGB(r,g,b));
}
}
}
}
#pragma endregion 256 color
#pragma region 24 bit
// 24位图解析
if(info.bmiHeader.biBitCount==24)
{
int pitch=width%4;
// bgr
if(height>0)
{//height>0 表示图片颠倒
for(int i=0;i<height;i++)
{
int realPitch=i*pitch;
for(int j=0;j<width;j++)
{
UCHAR b=buffer[(i*width+j)*3+realPitch];
UCHAR g=buffer[(i*width+j)*3+1+realPitch];
UCHAR r=buffer[(i*width+j)*3+2+realPitch];
pDC->SetPixel(j,height-i,RGB(r,g,b));
}
}
}
else
{
for(int i=0;i<0-height;i++)
{
int realPitch=i*pitch;
for(int j=0;j<width;j++)
{
UCHAR b=buffer[(i*width+j)*3+realPitch];
UCHAR g=buffer[(i*width+j)*3+1+realPitch];
UCHAR r=buffer[(i*width+j)*3+2+realPitch];
pDC->SetPixel(j,i,RGB(r,g,b));
}
}
}
}
#pragma endregion 24 bit
this->ReleaseDC(pDC);//释放掉绘制上下文
delete[] buffer;//释放缓冲区
fclose(fp); //关闭BMP文件
}
{//读取BMP文件并显示
CDC *pDC = GetDC();
CFileDialog dlg(TRUE);
if(dlg.DoModal()==IDOK)
{//选择要打开的BMP图片
strFilePath=dlg.GetPathName();
}
if(strFilePath=="")
{//取消
return;
}
FILE *fp=fopen(strFilePath,"r");
BITMAPFILEHEADER fileheader;
BITMAPINFO info;
fread(&fileheader,sizeof(fileheader),1,fp);
if(fileheader.bfType!=0x4D42)
{//不是BMP位图文件
pDC->TextOut(100,200,"无位图文件 请选择位图文件");
fclose(fp);
return ;
}
UCHAR *buffer = NULL;
//读位图头部
fread(&info.bmiHeader, sizeof(BITMAPINFOHEADER), 1, fp);
//位图宽度
long width=info.bmiHeader.biWidth;
this->width = width;
//位图高度
long height=info.bmiHeader.biHeight;
this->height = height;
DWORD size;
if (info.bmiHeader.biSizeImage != 0)
{//带颜色表
size = info.bmiHeader.biSizeImage;
}
else
{//不带颜色表的
size = info.bmiHeader.biHeight*info.bmiHeader.biWidth*3;
}
buffer = new UCHAR[size];//分配缓冲区
if (buffer == NULL)
{//分配内存失败
delete[] buffer;
return;
}
//忽略头部字节
fseek(fp,fileheader.bfOffBits,0);
fread(buffer,size,1,fp);
int i,j;
#pragma region 16 color
// 16色图的解析
if(info.bmiHeader.biBitCount==4)
{
int pitch;
if(width%8==0)
pitch=width;
else
pitch=width+8-width%8;
RGBQUAD quad[16];
fseek(fp,fileheader.bfOffBits-sizeof(RGBQUAD)*16,0);
fread(quad,sizeof(RGBQUAD)*16,1,fp);
if(height>0)
{//height>0 表示图片颠倒
for(i=0; i<height; i++)
{
for(j=0; j<width; j++)
{
int index;
if(j%2==0)
index = buffer[(i*pitch+j)/2]/16;
if(j%2==1)
index = buffer[(i*pitch+j)/2]%16;
UCHAR r=quad[index].rgbRed;
UCHAR g=quad[index].rgbGreen;
UCHAR b=quad[index].rgbBlue;
pDC->SetPixel(j,height-i,RGB(r,g,b));
}
}
}
else
{//图片不颠倒
for(i=0; i<0-height; i++)
{
for(j=0; j<width; j++)
{
int index;
if(j%2==0)
index = buffer[(i*pitch+j)/2]/16;
if(j%2==1)
index = buffer[(i*pitch+j)/2]%16;
UCHAR r=quad[index].rgbRed;
UCHAR g=quad[index].rgbGreen;
UCHAR b=quad[index].rgbBlue;
pDC->SetPixel(j,i,RGB(r,g,b));
}
}
}
}
#pragma endregion 16 color
#pragma region 256 color
// 256色图的解析
if(info.bmiHeader.biBitCount==8)
{
int pitch;
if(width%4==0)
{
pitch=width;
}
else
{
pitch=width+4-width%4;
}
RGBQUAD quad[256];
fseek(fp,fileheader.bfOffBits-sizeof(RGBQUAD)*256,0);
fread(quad,sizeof(RGBQUAD)*256,1,fp);
if(height>0)
{//height>0 表示图片颠倒
for(int i=0;i<height;i++)
{
for(int j=0;j<width;j++)
{
int index=buffer[i*pitch+j];
UCHAR r=quad[index].rgbRed;
UCHAR g=quad[index].rgbGreen;
UCHAR b=quad[index].rgbBlue;
pDC->SetPixel(j,height-i,RGB(r,g,b));
}
}
}
else
{
for(int i=0;i<0-height;i++)
{
for(int j=0;j<width;j++)
{
int index=buffer[i*pitch+j];
UCHAR r=quad[index].rgbRed;
UCHAR g=quad[index].rgbGreen;
UCHAR b=quad[index].rgbBlue;
pDC->SetPixel(j,i,RGB(r,g,b));
}
}
}
}
#pragma endregion 256 color
#pragma region 24 bit
// 24位图解析
if(info.bmiHeader.biBitCount==24)
{
int pitch=width%4;
// bgr
if(height>0)
{//height>0 表示图片颠倒
for(int i=0;i<height;i++)
{
int realPitch=i*pitch;
for(int j=0;j<width;j++)
{
UCHAR b=buffer[(i*width+j)*3+realPitch];
UCHAR g=buffer[(i*width+j)*3+1+realPitch];
UCHAR r=buffer[(i*width+j)*3+2+realPitch];
pDC->SetPixel(j,height-i,RGB(r,g,b));
}
}
}
else
{
for(int i=0;i<0-height;i++)
{
int realPitch=i*pitch;
for(int j=0;j<width;j++)
{
UCHAR b=buffer[(i*width+j)*3+realPitch];
UCHAR g=buffer[(i*width+j)*3+1+realPitch];
UCHAR r=buffer[(i*width+j)*3+2+realPitch];
pDC->SetPixel(j,i,RGB(r,g,b));
}
}
}
}
#pragma endregion 24 bit
this->ReleaseDC(pDC);//释放掉绘制上下文
delete[] buffer;//释放缓冲区
fclose(fp); //关闭BMP文件
}
作者:洞庭散人
出处:http://phinecos.cnblogs.com/
本博客遵从Creative Commons Attribution 3.0 License,若用于非商业目的,您可以自由转载,但请保留原作者信息和文章链接URL。
posted on 2009-05-09 15:25 Phinecos(洞庭散人) 阅读(2843) 评论(0) 编辑 收藏 举报
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· AI技术革命,工作效率10个最佳AI工具
2008-05-09 C++ Exercises(十二)
2007-05-09 C++ Exercises(四)