原创 在VC中显示BMP图片

2010-7-2 09:25 3595 7 7 分类: 工程师职场

显示.bmp文件:操作xxDoc.h, xxDoc.cpp, xxView.cpp即可完成


1、新建单文档文件 BmpView



2、在BmpViewDoc.h中添加


// Attributes
public:
 BITMAPINFOHEADER bi;   //信息头
 RGBQUAD* quad;         //调色板
 BYTE* lpBuf;     //图像数据
 BITMAPINFO* pbi;      
 int flag;              //标志表示是否打开了bmp文件
 int numQuad;        //调色板数目
 BYTE* lpshowbuf;    //用于显示的图像数据
 int zoomfactor;        //缩放比率



3、在BmpViewDoc.cpp的OnFileOpen() 中添加


 // TODO: Add your command handler code here
 LPCTSTR lpszFilter="BMP Files(*.bmp)|*.bmp|任何文件|*.*||";
 CFileDialog dlg1(TRUE,lpszFilter,NULL,OFN_HIDEREADONLY|OFN_OVERWRITEPROMPT,lpszFilter,NULL);
 CString filename;
 CFile file;
 BITMAPFILEHEADER bf;


 //打开文件对话框
 if(dlg1.DoModal()==IDOK)
 {
  filename=dlg1.GetPathName();
  if(file.Open(filename,CFile::modeRead|CFile::shareDenyNone,NULL)==0)
  { 
   //读取文件失败
   AfxMessageBox("无法打开文件!",MB_OK,0);
   return;
  }
  //读取文件头
  file.Read(&bf,sizeof(bf));
  //判断是否是BMP文件
  if(bf.bfType!=0x4d42)//'BM'
  {
   AfxMessageBox("非BMP文件!",MB_OK,0);
   return;
  }
  //判断文件是否损坏
  if(file.GetLength()!=bf.bfSize)
  {
   AfxMessageBox("文件已损坏,请检查!",MB_OK,0);
   return;
  }


  //读文件信息头
  file.Read(&bi,sizeof(bi));
     
  //计算调色板数目
  numQuad=0;
  if(bi.biBitCount<24)
  {
   numQuad=1<<bi.biBitCount;
  }
  
  //为图像信息pbi申请空间
  pbi=(BITMAPINFO*)HeapAlloc(GetProcessHeap(),0,sizeof(BITMAPINFOHEADER)+numQuad*sizeof(RGBQUAD));
  memcpy(pbi,&bi,sizeof(bi));
  quad=(RGBQUAD*)((BYTE*)pbi+sizeof(BITMAPINFOHEADER));
  
  //读取调色板
  if(numQuad!=0)
  {
   file.Read(quad,sizeof(RGBQUAD)*numQuad);
  }
  
  //为图像数据申请空间
  bi.biSizeImage=bf.bfSize-bf.bfOffBits;
  lpBuf=(BYTE*)HeapAlloc(GetProcessHeap(),0,bi.biSizeImage);
  //读取图像数据
  file.Read(lpBuf,bi.biSizeImage);
  
  //图像读取完毕,关闭文件,设置标志
  file.Close();
  flag=1;
  zoomfactor=1;
  lpshowbuf=NULL;
  PrepareShowdata();
  UpdateAllViews(NULL,0,NULL);
 }


 



4、在BmpViewDoc 中添加 成员函数bool CBmpViewDoc::PrepareShowdata()


 BYTE** image;
 BYTE** originimage;
 int i,j;
 int linewidth;


 if(lpshowbuf!=NULL)
  HeapFree(GetProcessHeap(),0,lpshowbuf);
 if(zoomfactor>=1)
 {//放大
  pbi->bmiHeader.biHeight=bi.biHeight*zoomfactor;
  pbi->bmiHeader.biWidth=bi.biWidth*zoomfactor;
 
  //每行四字节补齐,计算每行字节数:
  linewidth=(pbi->bmiHeader.biWidth*pbi->bmiHeader.biBitCount+31)/32*4;
  
  //计算显示图像所需内存大小
  pbi->bmiHeader.biSizeImage=linewidth*pbi->bmiHeader.biHeight;
  
  //申请内存
  lpshowbuf=(BYTE*)HeapAlloc(GetProcessHeap(),0,pbi->bmiHeader.biSizeImage);
  
  //生成对lpshowbuf的二维数组索引:
  image=new BYTE*[pbi->bmiHeader.biHeight];
  for(i=0;i<pbi->bmiHeader.biHeight;i++)
   image=lpshowbuf+i*linewidth;
  
  originimage=new BYTE*[bi.biHeight];
  for(i=0;i<bi.biHeight;i++)
   originimage=lpBuf+i*bi.biSizeImage/bi.biHeight;


  //赋值
  if(bi.biBitCount<24)
  {
   for(i=0;i<pbi->bmiHeader.biHeight;i++)
    for(j=0;j<linewidth;j++)
     image[j]=originimage[i/zoomfactor][j/zoomfactor];
  }
  else if(bi.biBitCount==24)
  {//24位真彩色
   for(i=0;i<pbi->bmiHeader.biHeight;i++)
    for(j=0;j<pbi->bmiHeader.biWidth;j++)
    {
    image[j*3]=originimage[i/zoomfactor][(j/zoomfactor)*3];
    image[j*3+1]=originimage[i/zoomfactor][(j/zoomfactor)*3+1];
    image[j*3+2]=originimage[i/zoomfactor][(j/zoomfactor)*3+2];
    }
  }
  else
  {//32位色
   for(i=0;i<pbi->bmiHeader.biHeight;i++)
    for(j=0;j<pbi->bmiHeader.biWidth;j++)
    {
    image[j*4]=originimage[i/zoomfactor][(j/zoomfactor)*4];
    image[j*4+1]=originimage[i/zoomfactor][(j/zoomfactor)*4+1];
    image[j*4+2]=originimage[i/zoomfactor][(j/zoomfactor)*4+2];
     image[j*4+3]=originimage[i/zoomfactor][(j/zoomfactor)*4+3];
    }
  }
 }
 else
 {//缩小
  pbi->bmiHeader.biHeight=bi.biHeight/(-zoomfactor);
  pbi->bmiHeader.biWidth=bi.biWidth/(-zoomfactor);
 
  //每行四字节补齐,计算每行字节数:
  linewidth=(pbi->bmiHeader.biWidth*pbi->bmiHeader.biBitCount+31)/32*4;
  
  //计算显示图像所需内存大小
  pbi->bmiHeader.biSizeImage=linewidth*pbi->bmiHeader.biHeight;
  
  //申请内存
  lpshowbuf=(BYTE*)HeapAlloc(GetProcessHeap(),0,pbi->bmiHeader.biSizeImage);
  
  //生成对lpshowbuf的二维数组索引:
  image=new BYTE*[pbi->bmiHeader.biHeight];
  for(i=0;i<pbi->bmiHeader.biHeight;i++)
   image=lpshowbuf+i*linewidth;
  
  originimage=new BYTE*[bi.biHeight];
  for(i=0;i<bi.biHeight;i++)
   originimage=lpBuf+i*bi.biSizeImage/bi.biHeight;


  //赋值
  if(bi.biBitCount<24)
  {
   for(i=0;i<pbi->bmiHeader.biHeight;i++)
    for(j=0;j<linewidth;j++)
     image[j]=originimage[i*(-zoomfactor)][j*(-zoomfactor)];
  }
  else if(bi.biBitCount==24)
  {//24位真彩色
   for(i=0;i<pbi->bmiHeader.biHeight;i++)
    for(j=0;j<pbi->bmiHeader.biWidth;j++)
    {
    image[j*3]=originimage[i*(-zoomfactor)][(j*(-zoomfactor))*3];
    image[j*3+1]=originimage[i*(-zoomfactor)][(j*(-zoomfactor))*3+1];
    image[j*3+2]=originimage[i*(-zoomfactor)][(j*(-zoomfactor))*3+2];
    }
  }
  else
  {//32位色
   for(i=0;i<pbi->bmiHeader.biHeight;i++)
    for(j=0;j<pbi->bmiHeader.biWidth;j++)
    {
    image[j*4]=originimage[i*(-zoomfactor)][(j*(-zoomfactor))*4];
    image[j*4+1]=originimage[i*(-zoomfactor)][(j*(-zoomfactor))*4+1];
    image[j*4+2]=originimage[i*(-zoomfactor)][(j*(-zoomfactor))*4+2];
    image[j*4+3]=originimage[i*(-zoomfactor)][(j*(-zoomfactor))*4+3];
    }
  }
 }


 return TRUE;



5、在BmpViewView中添加WM_PAINT消息,在消息响应函数中添加
 CPaintDC dc(this); // device context for painting
 
 // TODO: Add your message handler code here
  //得到文档指针
 CBmpViewDoc* pDoc = GetDocument();
 ASSERT_VALID(pDoc);


 //是否已打开某个BMP文件
 if(pDoc->flag==1)
 {
  //指定是显示的颜色
  SetDIBitsToDevice(dc.m_hDC,0,0,pDoc->pbi->bmiHeader.biWidth,
   pDoc->pbi->bmiHeader.biHeight,0,0,0,
   pDoc->pbi->bmiHeader.biHeight,pDoc->lpshowbuf,
   pDoc->pbi,DIB_RGB_COLORS);  
 }
 // Do not call CView::OnPaint() for painting messages
(1)程序代码


文章评论0条评论)

登录后参与讨论
我要评论
0
7
关闭 站长推荐上一条 /3 下一条