Windows下BMP文件的读取及显示

转自:http://blog.csdn.net/EmilMatthew/article/details/591814

WindowsBMP文件的读取及显示

EmilMatthew(EmilMatthew@126.com)

摘要

       实现了Windows,8位及24BMP文件的读取及显示.

 

关键词: bmp文件,文件格式

 

                          Parse and show bmp file on windows platform

                             EmilMatthew(EmilMatthew@126.com)

Abstract:

       Parse and show out 8 bits and 24 bits bmp file under windows platform.

 

Key Words: bmp File, File structure

      

1前言:

       BMP文件的读取及显示是一个难度不大而又相当重要的工作。[1],[2]BMP文件格式已都有详细介绍,本文主要致力于非压缩BMP读取及显示的实践工作,实现了8位及24BMP文件的读取,并列出解析过程中所遇到的难点。

      

2bmp文件格式简介: (详见[1],[2])

2.1 8位的bmp文件主要有以下三部分依次组成:

头部信息.

调色板信息.(b ,g ,r, reversed 的顺序存放各调色板的颜色信息,256)

主数据区(存放各个像素对应的调色板的序号)

 

2.2 24位的bmp文件主要有以下两部分依次组成.

头部信息.

主数据区(b ,g ,r 的顺序存放各像素的信息)

 

2.3相关的结构体:

2.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; 

      

2.3.2调色板数据结构体: (8位中使用)

       typedef struct

       {

              BYTE b;

              BYTE g;

              BYTE r;

              BYTE reserved;

       }paletteRGB;

 

2.3.3 主数据区BGR颜色结构: (24位中使用)

typedef struct

       {

              BYTE b;

              BYTE g;

              BYTE r;

       }structRGB;

      

3解析工作:

3.1SetPixel函数

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

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

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

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

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

     

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

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

我的解决方案如下:

 

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

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

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

                 externWidth=4-externWidth%4;

           else

                 externWidth=0;

 

3.3 BMP数据矩阵的存放方式:

       应注意,在BMP文件中,数据矩阵的存放方式都是按照(对应于原图)行按从下到上,列按从左到右的顺序进行存放。

 

4核心代码:

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

//头部解析

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)

                     externWidth=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+((unsigned long)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);

                                          break;

              }

       }

 

//显示程序段:

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]);

                     }

}

 

5实验结论:

       本文对Windows下非压缩8位及24位位图的解析进行了有益的总结并加以实践,有较强的针对性.可以对需要参考的人士起到一定的帮助作用。

 

参考文献

[1]http://www.vckbase.com/document/viewdoc/?id=674

 

[2]http://topic.csdn.net/t/20030819/09/2162276.html

                                                                                                                                    

[3]浦滨,C游戏编程,北京希望电子出版社,2002.

 

[4]朱学芳、智文广,计算机图像处理导论,科学技术文献出版社,2002.

 

完成日:06/02/04

 

附录:

1本文最佳浏览定位:

http://www.emilmatthew.zk.cn/EmilPapers/06_08BMParse/index.htm

 

2测试程序下载:

http://emilmatthew.51.net/EmilPapers/06_08BMParse/code1.rar

 

3DOC文档下载:

http://emilmatthew.51.net/EmilPapers/06_08BMParse/doc.rar

若直接点击无法下载(或浏览),请将下载(或浏览)的超链接粘接至浏览器地( 推荐MYIEGREENBORWSER)址栏后按回车.若不出意外,此时应能下载.


原文地址:https://www.cnblogs.com/walccott/p/4957056.html