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

如果你的意图是做一个显示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

}
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
好的,以下是一个简单BMP 文件读取并输出信息的程序示例: ```c #include <stdio.h> #include <stdint.h> // 定义 BMP 文件头结构体 #pragma pack(push, 1) typedef struct { uint16_t type; // 文件类型,必须为 BM uint32_t size; // 文件大小,单位为字节 uint16_t reserved1; // 保留字段1 uint16_t reserved2; // 保留字段2 uint32_t offset; // 数据偏移量,即 BMP 数据起始位置相对于文件头的偏移量 uint32_t dib_size; // DIB 数据结构大小,Windows BMP 文件中此值为 40 int32_t width; // 图像宽度,单位为像素 int32_t height; // 图像高度,单位为像素 uint16_t planes; // 位面数,必须为 1 uint16_t bpp; // 每个像素的位数,即色深 uint32_t compression; // 压缩方式,0 表示不压缩 uint32_t image_size; // 图像数据大小,单位为字节,如果不压缩则为 0 int32_t x_ppm; // 水平分辨率,单位为像素每米 int32_t y_ppm; // 垂直分辨率,单位为像素每米 uint32_t colors; // 调色板颜色数,如果为 0 表示使用默认值 uint32_t important; // 重要颜色数,如果为 0 表示所有颜色都重要 } bmp_file_header_t; #pragma pack(pop) int main() { FILE *file; bmp_file_header_t header; // 打开 BMP 文件 if ((file = fopen("test.bmp", "rb")) == NULL) { printf("Failed to open the file.\n"); return 1; } // 读取 BMP 文件头 if (fread(&header, sizeof(bmp_file_header_t), 1, file) != 1) { printf("Failed to read the file header.\n"); fclose(file); return 1; } // 输出 BMP 文件信息 printf("BMP type: %c%c\n", (char)(header.type & 0xFF), (char)(header.type >> 8)); printf("File size: %d bytes\n", header.size); printf("Data offset: %d bytes\n", header.offset); printf("Width: %d pixels\n", header.width); printf("Height: %d pixels\n", header.height); printf("Bit per pixel: %d\n", header.bpp); // 关闭 BMP 文件 fclose(file); return 0; } ``` 这个程序可以读取 BMP 文件头,并输出文件的类型、大小、数据偏移量、图像宽度和高度、像素位数等信息。注意,这个程序只能读取 Windows BMP 文件的头部信息,如果要读取完整的 BMP 文件,还需要根据文件头中的信息读取图像数据区。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值