bmp 的文件格式头

来源:互联网 发布:美国私立高中 知乎 编辑:程序博客网 时间:2024/04/29 03:31

本图片转载自相关开发文档

文件格式头是干什么的?如果把后缀名比作一本书的“标题”“封面”,那么文件格式头实际上就是一个文件信息,好比文章中的“导论”“前言”。在操作系统中,虽然我们有注册表中的后缀名这种机制去分别不同的文件,但是单靠后缀名是不够的,因为后缀名在某些时候会被不经意的修改。比如,恶意软件、病毒等,这就好比“挂羊头,卖狗肉”地给了你一本《九阴真经》,实际上却是个漫画书一样。因此,给不同格式的文件创建相应的文件头,就可以保证在后缀名被修改的情况下,依然能被识别。在浏览视频图片这些非线性数据结构时,我们要用创建相应的文件信息头去描述这个文件“是什么”“有什么作用”等信息,这样就可以保证,当我们的软件打开这些文件的时候,就能选择正确的方法。因为,即便是相同的图片,也有不同的格式和编解码算法,因此“前言”虽短,却很重要。他告知软件采取什么样的方式打开识别这个文件,他宣布了文件是以什么样的方式组织、编码,今天我想说的就是BMP文件头,如果我们用一些开源的编解码库获取了描述颜色的原始数据,如何人工给他创建文件头?


1.你必须查阅相关资料,获取某种格式的文件头描述。在音视频中,“文件头描述+后缀名”这2个关联的机制,被称之为“描述容器的组成结构”。

2.你应该根据需要,从原始数据中获取文件头需要的信息,比如,文件大小?设备无关性?是否压缩?编码方式?组成结构?

3.先将文件头数据一一填充,以二进制的方式写入,即使用 fwrite,绝非 fprintf。再按照组成顺序,写入原始数据。比如,bmp 位图中,文件开始部分是 height - 1 高度的一行数据,最后面才是 0 高度的数据,如果你的循环是从 height - 1 向 0 这个方向进行并写入数据的,那么你得到的图片双击打开后就是正着的,否则会上下颠倒。


具体实例代码:

void SaveFrame(AVFrame *pFrame, int width, int height, int iFrame){  FILE *pFile;  char szFilename[32];  int  y;    // Open file, 就是编写封面、书名  sprintf(szFilename, "frame%d.bmp", iFrame);  pFile=fopen(szFilename, "wb");  if(pFile==NULL)    return;    // Write header:  // SweetLover added it on Nov the 7th, 2013  // The original data format is ppm file format  // 就是写“前言”  BITMAPFILEHEADER bfh;  bfh.bfType = 0x4D42;  bfh.bfSize = width * height * 3 + 54;  bfh.bfReserved1 = 0;  bfh.bfReserved2 = 0;  bfh.bfOffBits = 0x36;  BITMAPINFOHEADER bih;  bih.biSize = 0x28;  bih.biWidth = width;  bih.biHeight = height;  bih.biPlanes = 1;  bih.biBitCount = 24;  bih.biCompression = 0;  bih.biSizeImage = width * height * 3;  bih.biXPelsPerMeter = 0;  bih.biYPelsPerMeter = 0;  bih.biClrUsed = 0;  bih.biClrImportant = 0;  fwrite(&bfh, 1, sizeof(bfh), pFile);  fwrite(&bih, 1, sizeof(bih), pFile);  // Write pixel data:  // SweetLover corrected it on Nov the 7th, 2013  // It's different from ppm file, the height in bmp file is from high to low  // 将一个个点按照从上到下的顺序画进去,所以 height 从大到 0  for(y=height-1; y>=0; y--)    fwrite(pFrame->data[0]+y*pFrame->linesize[0], 1, width*3, pFile);  // Close file  // 封底  fclose(pFile);}