BMP文件结构分析

BMP文件结构

  文档说明:由于最近的开发需要了解BMP结构,故收集并学习了BMP结构,下面部分是从网上收集来的文档,并列出部分自己的相关代码,仅供自己和他人学习。因为这段代码现在已经不用了,所以没仔细的修改,如果有时间可能会考虑重构一下。

一.        Bitmap简介

BMP(Bitmap-File)图形文件是Windows采用的图形文件格式,在Windows环境下运行的所有图象处理软件都支持BMP图象文件格式。Windows系统内部各图像绘制操作都是以BMP为基础的。Windows 3.0以前的BMP图文件格式与显示设备有关,因此把这种BMP图象文件格式称为设备相关位图DDB(device-dependent bitmap)文件格式。Windows 3.0以后的BMP图象文件与显示设备无关,因此把这种BMP图象文件格式称为设备无关位图DIB(device-independent bitmap)格式(注:Windows 3.0以后,在系统中仍然存在DDB位图,象BitBlt()这种函数就是基于DDB位图的,只不过如果你想将图像以BMP格式保存到磁盘文件中时,微软 极力推荐你以DIB格式保存),目的是为了让Windows能够在任何类型的显示设备上显示所存储的图象。BMP位图文件默认的文件扩展名是BMP或者 bmp(有时它也会以.DIB.RLE作扩展名)。

BMP图象文件格式有如下4个特点:

(1)       与大部分的图象文件格式不同,图象的扫描线是从下到上(bottom to top)形式而不是从上到下(top to bottom)形式

(2)   BMP文件支持行程编码压缩算法(Run length Encoding),但仅限于4位和8位象素值两种模式。

(3)   BMP文件的扫描线在每行末尾进行规格化,使得BMP文件长度均能够被4整除。

二.     图象文件格式

 BMP文件由四部分组成:文件头,图象控制信息,调色板信息(或者掩码信息)和位图点阵。

      

1.       位图文件头:包含有关于文件类型、文件大小、存放位置等信息

结构如下:

typedef struct tagBITMAPFILEHEADER 
  
  
                    { 
  
  
                  WORD    bfType;                           //文件类型
  
  
                    DWORD   bfSize;                                             //文件的字节数
  
  
                    WORD    bfReserved1;                                  //保留
  
  
                    WORD    bfReserved2;                                  //保留
  
  
                    DWORD   bfOffBits; 
  
  

} BITMAPFILEHEADER, *PBITMAPFILEHEADER;

        其中:

(1)WORD  bfType  用于表示文件类型,如果它是bmp文件,那么它这个位置的值一定是”BM” 也就是0x4D42

(2)DWORD  bfSize              表示整个文件的字节数

      (3)WORD    bfReserved1      保留
  
  

(4)WORD    bfReserved2       保留

(5)DWORD   bfOffBits           表示位图的数据信息离文件头的偏移量,以字节为单位

 

2.       图象控制信息:包含位图文件的大小、压缩类型和颜色格式等信息

结构如下:

typedef struct tagBITMAPINFOHEADER

{

  DWORD  biSize; //表示本结构的大小

  LONG   biWidth; //位图的宽度

  LONG   biHeight; //位图的高度

WORD   biPlanes; //永远为1 , 附msdn解释

//Specifies the number of planes for the target device. This value must be set to 1.

  WORD   biBitCount;//位图的位数  分为1 4 8 16 24 32

  DWORD  biCompression;

  DWORD  biSizeImage; //表示位图数据区域的大小以字节为单位

  LONG   biXPelsPerMeter;

  LONG   biYPelsPerMeter;

  DWORD  biClrUsed;

  DWORD  biClrImportant;

} BITMAPINFOHEADER, *PBITMAPINFOHEADER;

     其中:

                 (1)DWORD  biSize: 说明BITMAPINFOHEADER结构所需要的字数。注:这个值并不一定是BITMAPINFOHEADER结构的 尺寸,它也可能是sizeof(BITMAPV4HEADER)的值,或是sizeof(BITMAPV5HEADER)的值。这要根据该位图文件的格式 版本来决定,不过,就现在的情况来看,绝大多数的BMP图像都是BITMAPINFOHEADER结构的。

         (2)LONG   biWidth: 说明图象的宽度,以象素为单

         (3)LONG   biHeight; 说明图象的高度,以象素为单位。注:这个值除了用于描述图像的高度之外,它还有另一个用处,就是指明该图像是倒向的位 图,还是正向的位图。如果该值是一个正数,说明图像是倒向的,如果该值是一个负数,则说明图像是正向的。大多数的BMP文件都是倒向的位图,也就是时,高度值是一个正数。(注:当高度值是一个负数时(正向图像),图像将不能被压缩(也就是说(4)biCompression成员将不能是BI_RLE8 BI_RLE4)。

         (5)WORD   biPlanes; 为目标设备说明位面数,其值将总是被设为1

         (6)WORD   biBitCount; 说明比特数/象素,其值为1481624、或32

         (7)DWORD  biCompression; 说明图象数据压缩的类型。其值可以是下述值之一:

a.      BI_RGB:没有压缩

b.      BI_RLE8:每个象素8比特的RLE压缩编码,压缩格式由2字节组成(重复象素计数和颜色索引)

c.      BI_RLE4:每个象素4比特的RLE压缩编码,压缩格式由2字节组成

d.      BI_BITFIELDS:每个象素的比特由指定的掩码决定。

(8)DWORD  biSizeImage; 说明图象的大小,以字节为单位。当用BI_RGB格式时,可设置为0

(9)LONG   biXPelsPerMeter; 说明水平分辨率,用象素/米表示

(10)LONG   biYPelsPerMeter; 说明垂直分辨率,用象素/米表示

(11)DWORD  biClrUsed; 说明位图实际使用的彩色表中的颜色索引数(设为0的话,则说明使用所有调色板项)

(12)DWORD  biClrImportant; 说明对图象显示有重要影响的颜色索引的数目,如果是0,表示都重要。

 

3.       调色板或者掩码

如果是8位位图 则存放调色板 ;16 与32位 位图则存放RGB颜色的掩码,这些掩码以DWORD大小来存放。

RGBQUAD结构描述由R、G、B相对强度组成的颜色,定义如下:

typedef struct tagRGBQUAD

 {

BYTE rgbBlue;

BYTE rgbGreen;

BYTE rgbRed;

BYTE rgbReserved;

} RGBQUAD;

其中:

    rgbBlue:   指定蓝色强度

    rgbGreen:  指定绿色强度

    rgbRed:      指定红色强度

    rgbReserved: 保留,设置为0

4.       位图点阵数据

图象的每一扫描行由表示图象象素的连续的字节组成,每一行的字节数取决于图象的颜色数目和用象素表示的图象宽度。扫描行 是由底向上存储的,这就是说,阵列中的第一个字节表示位图左下角的象素,而最后一个字节表示位图右上角的象素。(只针对与倒向DIB,如果是正向DIB 则扫描行是由顶向下存储的),倒向DIB的原点在图像的左下角,而正向DIB的原点在图像的左上角。同时,每一扫描行的字节数必需是4的整倍数,也就是 DWORD对齐的。

 

以下是对各种位图格式的简单说明,以及简单的行解码函数。对函数先大概说明一下:

每种位图格式的参数都是一致的:

Vector<Color>& row_color_vec        解码后保存的该行的各个象素值

UINT row                          需要解码的位图第row

INT32 width                        位图宽度

另外,需要说明的是,下列函数中调用的文件相关的接口和平台有关,列出函数的目的主要是说明如何4字节对齐以及相应的位图行解码。

注:GetOffBits(file_counter)     的作用是得到位图点阵数据的开始位置。

三.     1bit位图

此种位图格式最多有两种颜色,缺省情况下是黑色和白色,你也可以自己定义这两种颜色。调色板中将有两个调色板项,称为索引0和索引1。图象数据点阵中的每一位表示一个象素。如果一个位是0,显示时就使用索引0RGB值,如果位是1,则使用索引1RGB值。

BOOLEAN BmpFileDecoder::DecodeRowBy1Bit(Vector<Color>& row_color_vec,UINT row,INT32 width)

{

              UINT32 bytes_read=0;

              RGBQUAD quad[2];

              UINT32 file_counter = 0;

              GetOffBits(file_counter);

              file_counter -= (sizeof(RGBQUAD)*2);

              //read  rgb quad               

              if(!m_gw_filemanage->ReadFile(m_folder_type,m_filename,(void HUGE *)quad,file_counter,sizeof(RGBQUAD)*2,bytes_read,m_device_id))

                     return false;

 

              //read row

              GetOffBits(file_counter);

              INT rowbytes = (width+7)/8;

              rowbytes = (rowbytes+3)/4;

              rowbytes*=4;

              file_counter+=(row*rowbytes);

             

              BYTE* row_buffer = new BYTE[rowbytes];

              if(row_buffer == NULL)

              {

                     delete[] row_buffer;

                     row_buffer = 0;

                     return false;

              }

              if(!m_gw_filemanage->ReadFile(m_folder_type,m_filename,row_buffer,file_counter,rowbytes,bytes_read,m_device_id))

              {

                     return false;

              }

              //add pels

              BYTE index,b,g,r;

              for(INT m=0,n=0;n<width;m++)

              {

                     INT offset = 7;

                     do

                     {

                            index = ((row_buffer[m]>>offset)&0x01);

                            b=quad[index].rgbBlue;

                            g=quad[index].rgbGreen;

                            r=quad[index].rgbRed;

                            row_color_vec.PushBack(Color(r,g,b));

                            n++;

                            offset--;

 

                     }while((n<width) && (offset>=0));

              }

              delete[]  row_buffer;

              row_buffer = 0;

              return true;

}

四.     4bit位图

此种位图格式最多有16种颜色。每个象素用4位表示,并用这4位作为彩色表的表项来查找该象素的颜色。例如,如果位图中的第一个字节为0x1F,它表示有两个象素,第一象素的颜色就在彩色表的第2表项中查找,而第二个象素的颜色就在彩色表的第16表项中查找。此时,调色板中缺省情 况下会有16RGB项。对应于索引0到索引15

BOOLEAN BmpFileDecoder::DecodeRowBy4Bit(Vector<Color>& row_color_vec,UINT row,INT32 width)

{

              UINT32 bytes_read=0;

              RGBQUAD quad[16];

              UINT32 file_counter = 0;

              GetOffBits(file_counter);

              file_counter -= (sizeof(RGBQUAD)*16);

              //read  rgb quad               

              if(!m_gw_filemanage->ReadFile(m_folder_type,m_filename,(void HUGE *)quad,file_counter,sizeof(RGBQUAD)*16,bytes_read,m_device_id))

              {

                     return false;

              }

              //read row

              GetOffBits(file_counter);

              INT rowbytes = (width+1)/2;

              rowbytes = (rowbytes+3)/4;

              rowbytes*=4;

              file_counter+=(row*rowbytes);

             

              BYTE* row_buffer = new BYTE[rowbytes];

              if(row_buffer == NULL)

              {

                     delete[] row_buffer;

                     row_buffer = 0;

                     return false;

              }

              if(!m_gw_filemanage->ReadFile(m_folder_type,m_filename,row_buffer,file_counter,rowbytes,bytes_read,m_device_id))

              {

                     return false;

              }

              //add pels

              for(INT m=0,n=0;n<width;)

              {

                     BYTE index=((row_buffer[m]>>4)&0x0F);

                     BYTE b=quad[index].rgbBlue;

                     BYTE g=quad[index].rgbGreen;

                     BYTE r=quad[index].rgbRed;

                     row_color_vec.PushBack(Color(r,g,b));

                     n++;

                     if(n<width)

                     {

                            index=(row_buffer[m]&0x0F);

                            b=quad[index].rgbBlue;

                            g=quad[index].rgbGreen;

                            r=quad[index].rgbRed;

                            row_color_vec.PushBack(Color(r,g,b));

                            n++;

                     }

 

                     m++;

              }

              delete[]  row_buffer;

              row_buffer = 0;

              return true;

}

五.     8bit位图

此种位图格式最多有256种颜色。每个象素用8位表示,并用这8位作为彩色表的表项来查找该象素的颜色。例如,如果位图中的第一个字节为0x1F,这个象素的颜色就在彩色表的第32表项中查找。此时,缺省情况下,调色板中会有256RGB项,对应于索引0到索引255

BOOLEAN BmpFileDecoder::DecodeRowBy8Bit(Vector<Color>& row_color_vec,UINT row,INT32 width)

{

              UINT32 bytes_read=0;

              RGBQUAD quad[256];

              UINT32 file_counter = 0;

              GetOffBits(file_counter);

              file_counter -= (sizeof(RGBQUAD)*256);

             

              //read  rgb quad               

              if(!m_gw_filemanage->ReadFile(m_folder_type,m_filename,(void HUGE *)quad,file_counter,sizeof(RGBQUAD)*256,bytes_read,m_device_id))

                     return false;

      

              //read row

              GetOffBits(file_counter);

              INT rowbytes = (width+3)/4;

              rowbytes*=4;

              file_counter+=(row*rowbytes);

             

              BYTE* row_buffer = new BYTE[rowbytes];

              if(row_buffer == NULL)

              {

                     delete[] row_buffer;

                     row_buffer = 0;

                     return false;

              }

              if(!m_gw_filemanage->ReadFile(m_folder_type,m_filename,row_buffer,file_counter,rowbytes,bytes_read,m_device_id))

                     return false;

 

              //add pels

              for(INT m=0;m<width;m++)

              {

                     BYTE index=row_buffer[m];

                     BYTE b=quad[index].rgbBlue;

                     BYTE g=quad[index].rgbGreen;

                     BYTE r=quad[index].rgbRed;

                     row_color_vec.PushBack(Color(r,g,b));

              }

              delete[]  row_buffer;

              row_buffer = 0;

              return true;

}

六.     16bit位图

此种位图格式最多有216种颜色。每个色素用16位(2个字节)表示。这种格式叫作高彩色,或叫增强型16 色,或64K色。它的情况比较复杂,当biCompression成员的值是BI_RGB时,它没有调色板。16位中,最低的5位表示蓝色分量,中间的5 位表示绿色分量,高的5位表示红色分量,一共占用了15位,最高的一位保留,设为0。这种格式也被称作555 16位位图。如果biCompression成员的值是BI_BITFIELDS,那么情况就复杂了,首先是原来调色板的位置被三个DWORD变量占据, 称为红、绿、蓝掩码。分别用于描述红、绿、蓝分量在16位中所占的位置。在Windows 95(或98)中,系统可接受两种格式的位域:555565,在555格式下,红、绿、蓝的掩码分别是:0x7C000x03E00x001F,而 565格式下,它们则分别为:0xF8000x07E00x001F。你在读取一个像素之后,可以分别用掩码上像素值,从而提取出想要的颜色分量。在NT系统中,则没有格式限制,只不过要求掩码之间不能有重叠。(注:这种格式的图像使用起来是比较麻烦的,不 过因为它的显示效果接近于真彩,而图像数据又比真彩图像小的多,所以,它更多的被用于游戏软件)。

BOOLEAN BmpFileDecoder::DecodeRowBy16Bit(Vector<Color>& row_color_vec,UINT row,INT32 width)

{

              UINT32 bytes_read=0;

              INT rowbytes = (width*2+3)/4;

              rowbytes *= 4;

              //BYTE* row_buffer = new BYTE[rowbytes];

              UINT16* row_buffer = new UINT16[rowbytes/2];

              if(row_buffer == NULL)

              {

                     delete[] row_buffer;

                     row_buffer = 0;

                     return false;

              }

              UINT32 file_counter = 0;

              GetOffBits(file_counter);

              file_counter += (row*rowbytes);

 

              //read row

              if(!m_gw_filemanage->ReadFile(m_folder_type,m_filename,row_buffer,file_counter,rowbytes,bytes_read,m_device_id))

              {

                     delete[] row_buffer;

                     row_buffer = 0;

                     return false;

              }

              //add pels

              BICompressionType bicompressiontype;

              GetBICompressionType( bicompressiontype);

              if(BI_RGB == bicompressiontype)

              {

              //555 format

                     for(INT n=0;n<width;n++)

                     {

                            UINT16 rgb=row_buffer[n];

                            UINT16 tmp = 0;

                            //red

                            tmp = (rgb&0x7C00)>>7;

                            BYTE r=tmp;

                            //green

                            tmp = (rgb&0x03E0)>>2;

                            BYTE g=tmp;

                            //blue

                            tmp = ((rgb&0x001F)<<3);

                            BYTE b=tmp;

                           

                            row_color_vec.PushBack(Color(r,g,b));

                     }

              }

              else

              {

                     delete[]  row_buffer;

                     row_buffer = 0;

                     return false;

              }

              delete[]  row_buffer;

              row_buffer = 0;

              return true;

}

七.     24bit位图

此种位图格式最多有224种颜色。这种位图没有调色板(bmiColors成员尺寸为0),在位数组中,每3个字节代表一个象素,分别对应于颜色RGB

BOOLEAN BmpFileDecoder::DecodeRowBy24Bit(Vector<Color>& row_color_vec,UINT row,INT32 width)

{    

              INT rowbytes = (width*3+3)/4;

              rowbytes *= 4;

              BYTE* row_buffer = new BYTE[rowbytes];

              if(row_buffer == NULL)

              {

                     delete[] row_buffer;

                     row_buffer = 0;

                     return false;

              }

              UINT32 file_counter = 0;

              GetOffBits(file_counter);

              file_counter += (row*rowbytes);

 

              UINT32 bytes_read=0;

              //read row

              if(!m_gw_filemanage->ReadFile(m_folder_type,m_filename,row_buffer,file_counter,rowbytes,bytes_read,m_device_id))

              {

                     delete[] row_buffer;

                     row_buffer = 0;

                     return false;

              }

              //add pels

              for(INT m=0,n=0;m<width;m++,n+=3)

              {

                     BYTE b=row_buffer[n];

                     BYTE g=row_buffer[n+1];

                     BYTE r=row_buffer[n+2];

                     row_color_vec.PushBack(Color(r,g,b));

              }

              delete[]  row_buffer;

              row_buffer = 0;

              return true;

}

八.     32bit位图

此种位图格式最多有232种颜色。这种位图的结构与16位位图结构非常类似,当 biCompression成员的值是BI_RGB时,它也没有调色板,32位中有24位用于存放RGB值,顺序是:最高8位保留,红8位、绿8位、蓝8 位。这种格式也被成为888 32位图。如果 biCompression成员的值是BI_BITFIELDS时,原来调色板的位置将被三个DWORD变量占据,成为红、绿、蓝掩码,分别用于描述红、 绿、蓝分量在32位中所占的位置。在Windows 95(or 98)中,系统只接受888格式,也就是说三个掩码的值将只能是:0xFF00000xFF000xFF。而在NT系统中,你只要注意使掩码之间不产 生重叠就行。

BOOLEAN BmpFileDecoder::DecodeRowBy32Bit(Vector<Color>& row_color_vec,UINT row,INT32 width)

{

              UINT32 bytes_read=0;

              INT rowbytes = width*4;

              UINT32* row_buffer = new UINT32[width];

              if(row_buffer == NULL)

              {

                     delete[] row_buffer;

                     row_buffer = 0;

                     return false;

              }

              UINT32 file_counter = 0;

              GetOffBits(file_counter);

              file_counter += (row*rowbytes);

 

              //read row

       if(!m_gw_filemanage->ReadFile(m_folder_type,m_filename,row_buffer,file_counter,rowbytes,bytes_read,m_device_id))

              {

                     delete[] row_buffer;

                     row_buffer = 0;

                     return false;

              }

              //add pels

              BICompressionType bicompressiontype;

              GetBICompressionType( bicompressiontype);

              if(BI_RGB == bicompressiontype)

              {

                     for(INT n=0;n<width;n++)

                     {

                            UINT32 tmp=0;

                            tmp = row_buffer[n]&0x000000FF;

                            BYTE b=tmp;

                            tmp = row_buffer[n]&0x0000FF00;

                            BYTE g=tmp>>8;

                            tmp = row_buffer[n]&0x00FF0000;

                            BYTE r=tmp>>16;

                            row_color_vec.PushBack(Color(r,g,b));

                     }

              }

              else

              {

                     delete[]  row_buffer;

                     row_buffer = 0;

                     return false;

              }

              delete[]  row_buffer;

              row_buffer = 0;

              return true;

}

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
BMP格式是Windows操作系统中最常见的图像文件格式之一,它采用无压缩的位图图像存储方法,可以保存不同颜色、分辨率和位深度的图像。而RGB文件则是指将图像的颜色信息按照红、绿和蓝三种颜色通道进行分离保存的文件。 要将BMP格式转换为RGB文件,首先需要了解BMP文件结构BMP文件文件头和图像数据组成,文件头包含了文件的基本信息,而图像数据则包含了每个像素点的颜色信息。 要进行转换,可以使用编程语言或图像处理软件来实现。以编程语言为例,可以按照以下步骤进行转换: 1. 读取BMP文件文件头信息,识别出图像的宽度、高度和位深度等参数。 2. 根据位深度信息,确定每个像素点的大小。 3. 读取图像数据,按照每个像素点的大小进行解析,获取每个像素点的颜色信息。 4. 将每个像素点的颜色信息拆分为红、绿、蓝三个通道的颜色值。 5. 将红、绿、蓝三个通道的颜色值保存为RGB文件。 通过以上步骤,就能够将BMP格式的图像转换为RGB文件,其中RGB文件中的数据就是按照每个像素点的颜色信息进行分离的,可以方便地进行进一步的图像处理和分析。 需要注意的是,对于一些特殊的BMP文件,可能存在压缩或者加密的情况,这种情况下需要根据具体的情况来进行相应的处理。另外,为了保证转换的准确性和稳定性,建议使用专业的图像处理软件或者图像处理库进行转换操作。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值