使用二维数组读取bmp文件

kangue 2007-05-30 05:28:51
1.定义一个二维数组如下:
BYTE aArray[PICHeigh][PICWidth];
其中PICHeigh和PICWidth是固定的,如果图像的大小和PICHeigh、PICWidth不符合的话,要进行图像的缩放,二维数组大小保持固定。

2.使用通用对话框打开bmp文件,如下,Bmp文件是256级的灰度图:
CFileDialog FileDlg(TRUE, "", NULL, OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT | OFN_ALLOWMULTISELECT, "BMP(*.bmp)|*.bmp|所有文件(*.*)|*.*||",AfxGetMainWnd());

问题1:怎样把bmp图像的内容读到aArray二维数组中?
问题2:把二维数组的内容回放到一CDC* pDC中,怎样速度最快?


问题1要有源代码,我写的一直有错,调不通了,有好代码再加分

...全文
1192 8 打赏 收藏 转发到动态 举报
写回复
用AI写文章
8 条回复
切换为时间正序
请发表友善的回复…
发表回复
kangue 2007-05-31
  • 打赏
  • 举报
回复
谢谢jixingzhong(瞌睡虫·星辰)和believefym(feng) ,现在我没有用GDI+

我做的代码如下:
CFile file;
BITMAPFILEHEADER bf;
BITMAPINFOHEADER bi;

if(file.Open(filename,CFile::modeRead|CFile::shareDenyNone,NULL)==0)
{
AfxMessageBox("无法打开文件",MB_OK,0);
return;
}
file.Read(&bf,sizeof(bf));//读文件信息头
if(bf.bfType!=0x4d42 )
{
AfxMessageBox("非BMP文件!",MB_OK,0);
return;
}
file.Read(&bi,sizeof(bi));//读图象信息头
int numQuad=0;
if(bi.biBitCount<24)//判断图像的颜色位数
{
numQuad=1<<bi.biBitCount;//调色板数
}
//读信息头和调色板数据
BITMAPINFO* pbi=(BITMAPINFO*)HeapAlloc(GetProcessHeap(),0,sizeof
(BITMAPINFOHEADER)+numQuad*sizeof(RGBQUAD));
memcpy(pbi,&bi,sizeof(bi));
RGBQUAD* quad=(RGBQUAD*)((BYTE*)pbi+sizeof(BITMAPINFOHEADER));
if(numQuad!=0)
{
file.Read(quad,sizeof(RGBQUAD)*numQuad);
}
//读图像数据
bi.biSizeImage=bf.bfSize-bf.bfOffBits;
BYTE* lpBuf=(BYTE*)(HeapAlloc(GetProcessHeap(),0,bi.biSizeImage));
file.Read(lpBuf,bi.biSizeImage);
//放入数据矩阵

int i,j,k;

for(i=bi.biHeight-1;i>=0;i--)
{
k=0;
for(j=0;j<bi.biWidth;j=j++)
{
k++;
tempArray[i][k]=lpBuf[j*2+i*2*bi.biWidth];
}
}
ppWnd=GetDlgItem(IDC_STATIC_diff);
ppDC=ppWnd->GetDC();

//把二维数组显示出来 第一种方法
for(i=0;i<bi.biHeight;i++)
{
for(j=0;j<bi.biWidth;j++)
{
ppDC->SetPixelV(j,i,RGB(tempArray[i][j],tempArray[i][j],tempArray[i][j]));
}
}

file.Close();

现在图像读出来后再显示失真了,就像被放大了一样,估计是语句 tempArray[i][k]=lpBuf[j*2+i*2*bi.biWidth];
的问题,但是这个lpBuf转到二位矩阵要怎么转呢?
对于256色灰度图,一个像素应该是一个字节才对,可是如果写成
tempArray[i][k]=lpBuf[j+i*bi.biWidth];失真的就更厉害了
通过断点看见参数:bi.biBitCount = 32; (bi).biSize = 40; (bi).biPlanes = 1; (bi).biWidth = 352; (bi).biHeight = 288,
这里bi.biBitCount怎么是32呢?保存的是32位图么?这里不同的位数和lpBuf中的像素对应位置是什么关系?

脑子转不过来了,想不明白,谁明白的指点一下
yuyunliuhen 2007-05-30
  • 打赏
  • 举报
回复
mark
believefym 2007-05-30
  • 打赏
  • 举报
回复
一个像素用4个字节表示,存放ARGB信息,所以用一个二维的byte数组貌似不太合适,用二维的int,或者三维的byte数组
1,用GDI+,BitmapData类,scan0函数,msdn查一下
//Bitmap panoBmp
Rect rect1(0,0,panoWidth,panoHeight);
BitmapData* panBmpData=new BitmapData;
panoBmp->LockBits(&rect1,ImageLockModeWrite,PixelFormat32bppRGB,panBmpData);
int* panP=(int*)panBmpData->Scan0;

循环存放到int的二维数组中,关系如下
array[i][j] = panP[panoWidth*i+j];

2,第二个问题问得有点奇怪,如果是想把位图输出
CPaintDC dc(this);
Graphics g(dc.m_hDC);
g.DrawImage(panoBmp,0,0,panoWidth,panoHeight);


以上代码是基于GDI+的,其中的注意事项、初始化等可google一下
jixingzhong 2007-05-30
  • 打赏
  • 举报
回复
推荐去 VC 的图形版块搜索一下相关帖子吧
jixingzhong 2007-05-30
  • 打赏
  • 举报
回复
另外参看:http://www.moon-soft.com/program/bbs/readelite9961.htm
星羽 2007-05-30
  • 打赏
  • 举报
回复
看看bmp的格式自己写咯

http://blog.csdn.net/kesalin/archive/2006/09/12/1213163.aspx
jixingzhong 2007-05-30
  • 打赏
  • 举报
回复
这个可以不:

bmp文件格式简介:
  1、8位的bmp文件主要有以下三部分依次组成:
  头部信息.
  调色板信息.(按b ,g ,r, reversed 的顺序存放各调色板的颜色信息,共256个)
  主数据区(存放各个像素对应的调色板的序号)

  2、24位的bmp文件主要有以下两部分依次组成.
  头部信息.
  主数据区(按b ,g ,r 的顺序存放各像素的信息)

  3、相关的结构体:
  3.1头部信息结构体:
  a)位图文件头
typedef struct tagBITMAPFILEHEADER { // bmfh
 WORD bfType;
 DWORD bfSize;
 WORD bfReserved1;
 WORD bfReserved2;
 DWORD bfOffBits;
} BITMAPFILEHEADER;

  其中的bfType值应该是“BM”(0x4d42),标志该文件是位图文件。bfSize的值是位图文件的大小

  b)位图信息头
typedef struct tagBITMAPINFOHEADER{ // bmih
 DWORD biSize;
 LONG biWidth; //以像素为单位的图像宽度
 LONG biHeight;// 以像素为单位的图像长度
 WORD biPlanes;
 WORD biBitCount;// 每个像素的位数
 DWORD biCompression;
 DWORD biSizeImage;
 LONG biXPelsPerMeter;
 LONG biYPelsPerMeter;
 DWORD biClrUsed;
 DWORD biClrImportant;
} BITMAPINFOHEADER;

  3.2、调色板数据结构体: (8位中使用)
typedef struct
{
 BYTE b;
 BYTE g;
 BYTE r;
 BYTE reserved;
}paletteRGB;

  3.3、主数据区BGR颜色结构: (24位中使用)
typedef struct
{
 BYTE b;
 BYTE g;
 BYTE r;
}structRGB;

  解析工作:

  1、SetPixel函数

  在windows vc编译环境下,使用sdk编程方式,画像素点的函数为:

COLORREF SetPixel( int x, int y, COLORREF crColor );

  其中,COLORREF类型的颜色值是这样定义的:

crColor=b<<16+g<<8+r;

  或等价于 crColor=b*65536+g*256+r;

  2、Windows环境下扫描行的字节数:

  Windows规定一个扫描行所占的字节数必须是4的倍数(即以long为单位),不足的以0填充.这一点相当重要,忽视这点将导致错误发生.

  我的解决方案如下:

externWidth=(mBMFileInfo.bmWidth*mBMFileInfo.bmBitCount)/8;

//计算每行实际的字节宽度

if(externWidth%4!=0)//计算应补足的字节数.
 externWidth=4-externWidth%4;
else
 externWidth=0;

  核心代码:

  这里只列出核以的代码段,详细代码请参阅源码:

//头部解析

void BMParse::showHeadInfo()
{
 assertF(mInputFile!=NULL,"in showHeadInfo,mInputFile is null\n");
 fread(&mBMFileStr,sizeof(BMPFileStr),1,mInputFile);
 fread(&mBMFileInfo,sizeof(BMPFileInfo),1,mInputFile);

 //adjusting

 mWinBMPFileStr.bfType=mBMFileStr.bfType;
 mWinBMPFileStr.bfSize=mBMFileStr.bfSize1+mBMFileStr.bfSize2*65536;
 mWinBMPFileStr.reserved1=mBMFileStr.reserved1;
 mWinBMPFileStr.reserved2=mBMFileStr.reserved2;
 mWinBMPFileStr.bfOffset=mBMFileStr.bfOffset1+mBMFileStr.bfOffset2*65536;
 return;
}

//颜色区(8位的带调色板)解析:

void BMParse::parseBMPMatrix()
{
 if(mWinBMPFileStr.bfType!=19778)
 {
  cout<<"This is not a bmp file"<<endl;
  return;
 }

 if(mBMFileInfo.bmCompression!=0)
 {
  cout<<"File is compressed"<<endl;
  return;
  }

 int i,j;
 structRGB tmpRGB;
 BYTE tmpData;
 int externWidth;
 bmpMatrix=(unsigned long**)malloc(sizeof(unsigned long*)*mBMFileInfo.bmHeight);
 for(i=0;i<mBMFileInfo.bmHeight;i++)
  bmpMatrix[i]=(unsigned long*)malloc(sizeof(unsigned long)*mBMFileInfo.bmWidth);

  //bmp file structure in windows,keep %4==0 in row byte num.

  externWidth=(mBMFileInfo.bmWidth*mBMFileInfo.bmBitCount)/8;
  if(externWidth%4!=0)
   xternWidth=4-externWidth%4;
  else
   externWidth=0;
   switch(mBMFileInfo.bmBitCount)
   {
    case 8: paletteArr=(paletteRGB*)malloc(sizeof(paletteRGB)*256);
    for(i=0;i<256;i++)
    {
      fread(&paletteArr[i],sizeof(paletteRGB),1,mInputFile);
      fseek(mInputFile,1078, SEEK_SET);

      for(j=mBMFileInfo.bmHeight-1;j>=0;j--)
      {
       for(i=0;i<mBMFileInfo.bmWidth;i++)
       {
        fread(&tmpData,sizeof(BYTE),1,mInputFile);
        bmpMatrix[j][i]=((unsigned long)paletteArr[tmpData].b)*65536+((unsignedlong)paletteArr[tmpData].g)*256+(unsigned long)paletteArr[tmpData].r;
       }
       /*补齐位调整*/
       for(i=0;i<externWidth;i++)
       fread(&tmpData,sizeof(BYTE),1,mInputFile);

      }
      break;
     case 16:
      printf("not finished\n");
      break;
     case 24:
      for(j=mBMFileInfo.bmHeight-1;j>=0;j--)
      {
       for(i=0;i<mBMFileInfo.bmWidth;i++)
       {
        fread(&tmpRGB,sizeof(structRGB),1,mInputFile);
        bmpMatrix[j][i]=((unsigned long)tmpRGB.b)*65536+((unsigned long)tmpRGB.g)*256+(unsigned long)tmpRGB.r;
       }
       /*补齐位调整*/
       for(i=0;i<externWidth;i++)
        fread(&tmpData,sizeof(BYTE),1,mInputFile);
      }
      break;
     default: printf("bmBitCount:%d not finished\n",mBMFileInfo.bmBitCount);
     reak;
    }
   }

  //显示程序段:
  void BMParse::showBMP(HDC inHdc)
  {
   int i,j;
   for(j=0;j<mBMFileInfo.bmHeight;j++)
   for(i=0;i<mBMFileInfo.bmWidth;i++)
   {
    SetPixel(inHdc,i,j,bmpMatrix[j][i]);
   }
  }
kangue 2007-05-30
  • 打赏
  • 举报
回复
补充:使用vc6

64,646

社区成员

发帖
与我相关
我的任务
社区描述
C++ 语言相关问题讨论,技术干货分享,前沿动态等
c++ 技术论坛(原bbs)
社区管理员
  • C++ 语言社区
  • encoderlee
  • paschen
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
  1. 请不要发布与C++技术无关的贴子
  2. 请不要发布与技术无关的招聘、广告的帖子
  3. 请尽可能的描述清楚你的问题,如果涉及到代码请尽可能的格式化一下

试试用AI创作助手写篇文章吧