zoukankan      html  css  js  c++  java
  • 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)址栏后按回车.若不出意外,此时应能下载.


  • 相关阅读:
    c# gdi设置画刷透明
    char,varchar,nvarchar,text区别与联系
    banner无缝轮播【小封装】
    div中的内容垂直居中的五种方法
    jQuery hover() 方法
    年过三十,我为什么要学习ios 与安卓App 移动端技术
    CentOS 中用 Split 命令分割文件的方法
    centos E440 安装无线网卡
    CentOS7修改默认运行级别
    iwconfig: command not found 解决方案
  • 原文地址:https://www.cnblogs.com/walccott/p/4957056.html
Copyright © 2011-2022 走看看