24位色BMP文件的简单分析及示例程序

来源:互联网 发布:淘宝频繁退货会怎样 编辑:程序博客网 时间:2024/06/06 02:01
如果你的意图是做一个显示BMP文件的程序,那么请参阅BMP文件详细格式分析,如果你仅仅是想知道怎么从一个未压缩的24位色BMP文件中把数据点阵信息读出,用来做其它的用途(当然也包括显示图像),那么这篇文章会对你有帮助。

虽然有很复杂的定义,但是我们平时使用的BMP文件都多是8位色或24位色的,而这两种格式中,以24位色最为普遍。可以通过查看文件偏移量地址001C,得到图形的色数。

查看地址0000起的两个字节,如果ACSII码显示为“BM”,可判断这是一个BMP文件。确切的说这是一个Windows下的BMP文件。

查看地址000A起的一个双字(DWord),可以得到文件信息头和图像信息头的总长度,这很重要,通过读取它,可以用于文件指针的Seek,找到数据区的起点。

至于图像文件的宽和高,可以通过0012和0016起的两个双字来获得。

紧跟在文件信息头和数据信息头之后的就是数据区,24位色BMP图没有调色板。

数据区里的数据是线性的,行主序,依次是 点一的B值,点一的G值,点一的R值,点二的B值,点二的G值,点二的R值,等等,需要注意的是,Windows中普遍采用了行倒向扫描的约定,即,BMP文件中原点在左下角,向上,向右,增加。这一点,需要在将数据区数据向结构体数组读取的时候,做一个小技巧,如果不做倒向的取值,你将会显示出一个颠倒的图像。(当然,这是指用Windows GDI画图,如果你使用OpenGL,你将会得到一个正向的图)

还有一点也需要注意:Windows要求每一行的数据的长度必须是4Bytes的整数倍,如果不是,要以值为0的字节补充,如果读取的时候不处理,会得到一个倾斜的图像。举例:一张479*360的24位色BMP图片,宽度是479个像素,每一行的数据长度是479*3(个字节用于RGB三色) =1437,不是4的倍数,所以,在这行数据的后面,要补上3个字节,值为0,凑成1440,达到4的倍数,然后,才是下一行的数据。在做程序的时候,需要把这些冗余点的值舍去。

看到这里就可以了,我有一个新的代码实现,比下面的要好,强烈推荐你使用

void CTextureyView::OnFileOpen()

{

CFileDialog dlg(true);

       if(IDOK==dlg.DoModal())

       {

        FileName=dlg.GetFileName();

           Invalidate(true);

       }//IDOK  

}

void CTextureyView::OnDraw(CDC* pDC)
{
CTextureyDoc* pDoc = GetDocument();
ASSERT_VALID(pDoc);
if (FileName!="")
{

      typedef struct
{
    BYTE b;
    BYTE g;
    BYTE r;
}structRGB;


DWORD fw,fh;//图像的宽和高
DWORD hl;//文件头和信息头的总长

CFile* pFile;
try
{
    pFile=new CFile(FileName,CFile::modeRead);

    pFile->Seek(10,CFile::begin);
    pFile->Read(&hl,4);
    pFile->Seek(0x12,CFile::begin);
       pFile->Read(&fw,4);
    pFile->Seek(0x16,CFile::begin);
       pFile->Read(&fh,4);

    int att;//用于处理行扫描时的4补位

    if((fw*3)%4!=0)
     att=4-(fw*3)%4;
    else
     att=0;
  

          
       structRGB** srgb=new structRGB*[fh];
       for(int s=0;s<fh;s++)
        srgb[s]=new structRGB[fw];
     
  
             BYTE* pBuffer= new BYTE[3*fw*fh];

             pFile->Seek(hl,CFile::begin);


             pFile->Read(pBuffer,3*fw*fh);

          for(int i=0;i<fh;i++)
       {
          for(int j=0;j<fw;j++)
       {
         srgb[fh-1-i][j].b=pBuffer[i*(fw*3+att)+j*3];
      srgb[fh-1-i][j].g=pBuffer[i*(fw*3+att)+j*3+1];
      srgb[fh-1-i][j].r=pBuffer[i*(fw*3+att)+j*3+2];
       }

    }

      for(int n=0;n<fh;n++)
    for(int m=0;m<fw;m++)
    {
     pDC->SetPixel(m,n,RGB(srgb[n][m].r,srgb[n][m].g,srgb[n][m].b));
    }



}

catch(CFileException* pe)
{
      pe->ReportError();
      if(pFile)
      {
       delete pFile;
      }
}
      pFile->Close();


}//if FileName!=NULL

}
原创粉丝点击