读取并显示一幅位图的方法

来源:互联网 发布:橘子郡美妆淘宝店扒皮 编辑:程序博客网 时间:2024/05/12 22:29

读取并显示一幅位图的方法:
1、读取文件头,文件头格式如下:
typedef struct tagBITMAPFILEHEADER {
  WORD bfType;//位图标识,必须示‘BM’
  DWORD bfSize;//标识位图文件的大小,单位是字节
  WORD bfReserved1;//未使用
  WORD bfReserved2;//未使用
  DWORD bfOffBits;//从头文件到位图数据的偏移量,主要是指头文件和调色板的长度,如果是256色的位图,则这个值为1078,文件头14+位图头40+调色板256×4
} BITMAPFILEHEADER;
这是MFC中定义的位图头文件。
2、读入位图头和位图数据
位图头的格式如下:
typedef struct tagBITMAPINFOHEADER {
  DWORD biSize;//标识该结构的大小,应该是40;
  LONG biWidth;//位图的宽度
  LONG biHeight;//位图的高
  WORD biPlanes;//必须为1
  WORD biBitCount;//标识位图的颜色数目,标识2的biBitCount次方色的位图,256色位图这里为8
  DWORD biCompression;//是否压缩;
  DWORD biSizeImage;//位图的大小,一遍是宽×高,宽必须是4的整数倍。如果是RGB位图,这里为0;
  LONG biXPelsPerMeter;//目标设备的水平分辨率
  LONG biYPelsPerMeter;//目标设备的垂直分辨率
  DWORD biClrUsed;//实际使用到的颜色数,为0表示都使用;
  DWORD biClrImportant;//重要的颜色数,为0标识都重要;
} BITMAPINFOHEADER;
位图头之后的就是调色板,结构如下:
typedef struct tagRGBQUAD {
  BYTE rgbBlue;
  BYTE rgbGreen;
  BYTE rgbRed;
  BYTE rgbReserved;
} RGBQUAD;  
调色板之后的就是位图数据了。 
3、显示位图文件:
(1)创建调色板指针,对new一个调色板的对象,如下:
 CPalette× pPalette = new CPalette;
(2)创建逻辑调色板:
 PLOGPALETTE lpLogPalette = (PLOGPALETTE)new char[PaletteSize] ;
(3)填充逻辑调色板:
 lpLogPalette->palVersion = PALVERSION; //版本
 lpLogPalette->palNumEntries = (WORD)ColorNum; //颜色数
 LPBITMAPINFO pPaletteEntry = (LPBITMAPINFO)hBitmap;   //hBitmap是指向位图头的指针;
 for(int i = 0;i<ColorNum;i++)
 {
  lpLogPalette->palPalEntry[i].peRed = pPaletteEntry->bmiColors[i].rgbRed;
  lpLogPalette->palPalEntry[i].peGreen = pPaletteEntry->bmiColors[i].rgbGreen;
  lpLogPalette->palPalEntry[i].peBlue = pPaletteEntry->bmiColors[i].rgbBlue;
  lpLogPalette->palPalEntry[i].peFlags = 0;
 }
(4)创建调色板:
 pCPalette->CreatePalette(lpLogPalette);
(5)选择当前创建的调色板:
 CPalette* pOldPalette = pDC->SelectPalette(pCPalette,TRUE);
(6)使用SetDIBitsToDevice函数将位图显示出来;

源代码如下:
1、创建一个单文档工程:CMyPaintBitmap
2、在头文件中加入如下定义:
 typedef char* HDIB;//此定义在类外
 HDIB hDIB;
 BITMAPFILEHEADER BitMapHeader;
 BITMAPINFOHEADER bitMapInfoHeader;
3、添加打开菜单的命令响应函数,函数代码如下:
void CCMyPaintBitmapView::OnFileOpen()
{
 // TODO: 在此添加命令处理程序代码
 CCMyPaintBitmapDoc* pDoc = GetDocument();
 CFileDialog file(true);
 if(IDOK != file.DoModal())
 {
  return;
 }
 CString m_strFilePath = file.GetPathName();
 
 CStdioFile DibFile;
 HDIB& hDIB = pDoc->hDIB;
 if(hDIB != NULL)
 {
  delete []hDIB;
  hDIB = NULL;
 }
 ULONGLONG nFileSize;
 ULONGLONG BitMapSize;
 BITMAPFILEHEADER& BitMapHeader = pDoc->BitMapHeader;
 if(DibFile.Open(m_strFilePath,CStdioFile::modeRead))
 {
  //读文件头
  DibFile.Read(&BitMapHeader,sizeof(BITMAPFILEHEADER));
  if(BitMapHeader.bfType != 19778)
  {
   return;
  }
  nFileSize = DibFile.GetLength();
  BitMapSize = nFileSize - sizeof(BITMAPFILEHEADER);
  hDIB = new char[BitMapSize];
  //读位图文件
  DibFile.Read(hDIB,BitMapSize);
 }

 BITMAPINFOHEADER& BitMapInfoHeader = pDoc->bitMapInfoHeader;
 //获得位图头文件
 memcpy(&BitMapInfoHeader,hDIB,sizeof(BITMAPINFOHEADER));

 //ULONGLONG biWidth = pDoc->GetMapWidth();
 使窗口无效
 Invalidate(true);
}
4、为CCMyPaintBitmapDoc类增加无暇成员函数
 ULONGLONG GetMapWidth(void)
 {
  ULONGLONG width = bitMapInfoHeader.biWidth;
  return ((width + 2)/4) * 4;
 }

5、在OnDraw函数中增加如下代码:
void CCMyPaintBitmapView::OnDraw(CDC* pDC)
{
 CCMyPaintBitmapDoc* pDoc = GetDocument();
 ASSERT_VALID(pDoc);
 if (!pDoc)
  return;

 // TODO: 在此处为本机数据添加绘制代码
 HDIB& hDIB = pDoc->hDIB;
 if(hDIB != NULL)
 {
  CPalette* pOldPalette;
  CPalette* pPalette = new CPalette;
  unsigned int PaletteSize = sizeof(LOGPALETTE) + 256 * sizeof(PALETTEENTRY);
  PLOGPALETTE lpLogPalette = (PLOGPALETTE)new char[PaletteSize];
  lpLogPalette->palVersion = 0x300;
  lpLogPalette->palNumEntries = 256;
  HDIB lpPalette = hDIB + 40;
  PALETTEENTRY* pPaletteEntry = (PALETTEENTRY*)lpPalette;
  for(int i = 0;i<256;i++)
  {
   lpLogPalette->palPalEntry[i].peBlue = pPaletteEntry->peBlue;
   lpLogPalette->palPalEntry[i].peGreen = pPaletteEntry->peGreen;
   lpLogPalette->palPalEntry[i].peRed = pPaletteEntry->peRed;
   lpLogPalette->palPalEntry[i].peFlags = 0;
   pPaletteEntry++;
  }  
  pPalette->CreatePalette(lpLogPalette);
  pOldPalette = pDC->SelectPalette(pPalette,true);
  ::SetDIBitsToDevice(pDC->m_hDC,0,0,pDoc->GetMapWidth(),pDoc->bitMapInfoHeader.biHeight,0,0,0,pDoc->bitMapInfoHeader.biHeight,LPVOID(hDIB + 1064),(BITMAPINFO*)hDIB,DIB_RGB_COLORS);
  pDC->SelectPalette(pOldPalette,true);
  delete pPalette;
 }
}
6、在CCMyPaintBitmapDoc的构造函数中增加如下语句:
 hDIB = NULL
编译运行,点击打开按钮,选择256色位图文件,即可显示到界面上


原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 绑定qq账号消息不见了怎么办 现在的注册微信怎么办 爱奇艺手机号码被别人绑定了怎么办 手机号码换了支付宝账号怎么办 qq换手机号了怎么办呢 公司被注销了公众号怎么办 qq号被限制查找怎么办 qq号别人查找不到怎么办 qq邮箱已被注册怎么办 微信付款没网络怎么办 天猫买的假货店铺关门了怎么办 鞋小了半码怎么办 迅雷会员种子不能加速怎么办 迅雷会员为什么不能加速怎么办 持有st创智股票怎么办 租的房子床坏了怎么办 宜家定时器不响怎么办 新插座插不进去怎么办 本溪人社app打不开怎么办 南宁电车超过上牌时间怎么办 苹果6s降频怎么办 0首付手机还不起怎么办 乐才app登录不上怎么办 买了笔记本网要怎么办? 电脑连接不上网络怎么办 电脑上没网络了怎么办 手机返回键不好使怎么办 笔记本无线网连接受限怎么办 魅族打电话图标没有了怎么办 京东价格保护后发票怎么办 淘宝未满十八岁怎么办 SVN提交时代码冲突怎么办 京东自营没货了怎么办 京东下了单 没货怎么办 万达广场购物卡怎么办 京东白条没额度怎么办 京东退款还收到货怎么办 退货不想要货了怎么办 安装微擎创建数据库失败怎么办 tp文件损坏或丢失怎么办 手机QQ启动有问题应该怎么办