bmp 的文件格式头

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

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


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

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

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

对于已知 RGB 位图数据,绘制代码可以如下编写(BitBlt不支持缩放,StretchBlt 缩放位图,TransparentBlt 缩放并支持透明):

HDC hCompatibleDC = CreateCompatibleDC(hDc);
HBITMAP hCompatibleBitmap = CreateCompatibleBitmap(hDc, bitmapinfoheader.biWidth,
bitmapinfoheader.biHeight);
HBITMAP hOldBitmap = (HBITMAP)SelectObject(hCompatibleDC, hCompatibleBitmap);
SetDIBits(hDc, hCompatibleBitmap, 0, bitmapinfoheader.biHeight,
buffer, (BITMAPINFO*)&bitmapinfoheader, DIB_RGB_COLORS);
BitBlt(hDc, nStartX, nStartY, bitmapinfoheader.biWidth, bitmapinfoheader.biHeight,
hCompatibleDC, 0, 0, SRCCOPY);
SelectObject(hCompatibleDC, hOldBitmap);
DeleteObject(hCompatibleDC);
DeleteObject(hCompatibleDC);
// 这么干也行
StretchDIBits(hDc, nStartX, nStartY, bitmapinfoheader.biWidth,bitmapinfoheader.biHeight, 0, 0,
bitmapinfoheader.biWidth,bitmapinfoheader.biHeight, buffer, (BITMAPINFO*)&bitmapinfoheader,
DIB_RGB_COLORS, SRCCOPY);

具体实例代码:

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);
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值