* 音视频入门文章目录 *

BMP 文件格式解析

BMP 文件由文件头、位图信息头、颜色信息和图形数据四部分组成。

位图文件头(14个字节) 位图信息头(40个字节) 颜色信息 图形数据
  • 文件头与信息头一共是 54 字节
  • RGB 数据部分:

    RGB24 文件存储的顺序是 RGB, RGB, RGB ...... RGB

    BMP 文件 RGB 数据存储的顺序是 BGR, BGR, BGR ... BGR

位图文件头

位图文件头分 4 部分,共 14 字节

名称 占用空间 内容 示例数据
bfType 2字节 标识,就是“BM” BM
bfSize 4字节 整个 BMP 文件的大小 0x000C0036(786486)
bfReserved1 2字节 保留字 0
bfReserved2 2字节 保留字 0
bfOffBits 4字节 偏移数,即位图文件头+位图信息头+调色板的大小 0x36(54)

位图信息头

位图信息头共 40 字节

名称 占用空间 内容 示例数据
biSize 4字节 位图信息头的大小,为40 0x28(40)
biWidth 4字节 位图的宽度,单位是像素 0x200(512)
biHeight 4字节 位图的高度,单位是像素 0x200(512)
biPlanes 2字节 固定值1 1
biBitCount 2字节 每个像素的位数 1-黑白图,4-16色,8-256色,24-真彩色,32-带 alpha 通道 0x18(24)
biCompression 4字节 压缩方式,BI_RGB(0)为不压缩 0
biSizeImage 4字节 位图全部像素占用的字节数,BI_RGB时可设为0 0x0C
biXPelsPerMeter 4字节 水平分辨率(像素/米) 0
biYPelsPerMeter 4字节 垂直分辨率(像素/米) 0
biClrUsed 4字节 位图使用的颜色数 如果为0,则颜色数为2的biBitCount次方 0
biClrImportant 4字节 重要的颜色数,0代表所有颜色都重要 0

将 RGB24 像素点数据转成 BMP 格式图片

转换代码:

#include <stdio.h>
#include <stdlib.h> // 彩虹的七种颜色
u_int32_t rainbowColors[] = {
0XFF0000, // 红
0XFFA500, // 橙
0XFFFF00, // 黄
0X00FF00, // 绿
0X007FFF, // 青
0X0000FF, // 蓝
0X8B00FF // 紫
}; /*bmp file header*/
typedef struct {
unsigned int bfSize; /* Size of file */
unsigned short bfReserved1; /* Reserved */
unsigned short bfReserved2; /* ... */
unsigned int bfOffBits; /* Offset to bitmap data */
} BitmapFileHeader; /*bmp info header*/
typedef struct {
unsigned int biSize; /* Size of info header */
int biWidth; /* Width of image */
int biHeight; /* Height of image */
unsigned short biPlanes; /* Number of color planes */
unsigned short biBitCount; /* Number of bits per pixel */
unsigned int biCompression; /* Type of compression to use */
unsigned int biSizeImage; /* Size of image data */
int biXPelsPerMeter; /* X pixels per meter */
int biYPelsPerMeter; /* Y pixels per meter */
unsigned int biClrUsed; /* Number of colors used */
unsigned int biClrImportant; /* Number of important colors */
} BitmapInfoHeader; void writeRGBToBmp(char *filename, int width, int height) {
FILE *bitmapFile = fopen(filename, "wb");
if(!bitmapFile) {
printf("Could not write file \n");
return;
} uint16_t bfType = 0x4d42; BitmapFileHeader fileHeader;
fileHeader.bfReserved1 = 0;
fileHeader.bfReserved2 = 0;
fileHeader.bfSize = 2 + sizeof(BitmapFileHeader) + sizeof(BitmapInfoHeader) + width*height*3;
fileHeader.bfOffBits = 0x36; BitmapInfoHeader infoHeader;
infoHeader.biSize = sizeof(BitmapInfoHeader);
infoHeader.biWidth = width;
infoHeader.biHeight = height;
infoHeader.biPlanes = 1;
infoHeader.biBitCount = 24;
infoHeader.biSizeImage = 0;
infoHeader.biCompression = 0;
infoHeader.biXPelsPerMeter = 5000;
infoHeader.biYPelsPerMeter = 5000;
infoHeader.biClrUsed = 0;
infoHeader.biClrImportant = 0; fwrite(&bfType, sizeof(bfType), 1, bitmapFile);
fwrite(&fileHeader, sizeof(fileHeader), 1, bitmapFile);
fwrite(&infoHeader, sizeof(infoHeader), 1, bitmapFile); // 写入图像数据
for (int i = 0; i < width; ++i) { // 当前颜色
u_int32_t currentColor = rainbowColors[0];
if(i < 100) {
currentColor = rainbowColors[0];
} else if(i < 200) {
currentColor = rainbowColors[1];
} else if(i < 300) {
currentColor = rainbowColors[2];
} else if(i < 400) {
currentColor = rainbowColors[3];
} else if(i < 500) {
currentColor = rainbowColors[4];
} else if(i < 600) {
currentColor = rainbowColors[5];
} else if(i < 700) {
currentColor = rainbowColors[6];
}
// 当前颜色 R 分量
u_int8_t R = (currentColor & 0xFF0000) >> 16;
// 当前颜色 G 分量
u_int8_t G = (currentColor & 0x00FF00) >> 8;
// 当前颜色 B 分量
u_int8_t B = currentColor & 0x0000FF; for (int j = 0; j < height; ++j) {
// 按 BGR 顺序写入一个像素 RGB24 到文件中
fwrite(&B, 1, 1, bitmapFile);
fwrite(&G, 1, 1, bitmapFile);
fwrite(&R, 1, 1, bitmapFile);
}
} // 关闭文件
fclose(bitmapFile);
} int main() {
writeRGBToBmp("/Users/staff/Desktop/rainbow-700x700.bmp", 700, 700);
return 0;
}

检查生成的 BMP 图片

Congratulations! 图片查看软件识别出我们的 BMP 图片了,预览正常!

BUT!好像哪里不对劲?!我们的彩虹倒过来了!

彩虹的颜色,从上到下应该是:

红 -> 橙 -> 黄 -> 绿 -> 青 -> 蓝 -> 紫

这张图是:

紫 -> 蓝 -> 青 -> 绿 -> 黄 -> 橙 -> 红

处理图片倒立问题

BitmapInfoHeader 中的 biHeight 字段,

biHeight 为正,位图自底向顶扫描,

biHeight 为负,位图自顶向底扫描。

如果这个值的设置和原始位图文件扫描方式不符,则图像显示可能会颠倒。

将上面的转换代码中,BitmapInfoHeader 部分:

// infoHeader.biHeight = height;
infoHeader.biHeight = -height;

Congratulations!

成功用像素点拼出了一张 “真正” 的图片!


代码:

rgb-to-bmp

参考资料:

维基百科-BMP

位图(bmp)文件格式分析

RGB24转换成BMP图像

关于RGB32和RGB24的区别

non-dword-aligned-pixel-to-dword-aligned-bitmap

generate-bmp-file-from-array-of-rgb-values

内容有误?联系作者:


最新文章

  1. After the exam
  2. CRM 启用或禁用自定义代码执行
  3. 用Yaml文件进行元素管理【转】
  4. linux 认证方式
  5. IOS_OC_百度地图与社交分享
  6. MasterCard信用卡测试卡号-creditcard-1
  7. vector容器
  8. 运行预构建 Linux 映像的 Windows Azure 虚拟机中的交换空间 – 第 1 部分
  9. pthread_setschedprio()函数详解!!!
  10. CC ANUMLA(STL的运用)
  11. 深入浅出AQS之独占锁模式
  12. js 判断一个文本框是否获得焦点
  13. .Net Core中Dapper的使用详解
  14. [20190322]测试相同语句遇到导致cursor pin S的疑问.txt
  15. Linux LAMP架构搭建
  16. eos源码剖析之controller
  17. android开发(34) 自定义 listView的分割线( 使用xml drawable画多条线)
  18. maven package install deploy区别
  19. learning shell built-in variables (1)
  20. JS教程:window.location使用方法的区别

热门文章

  1. python中的with的用法,上下文管理器
  2. Java List 和 Array 转化
  3. osg define shape(create box)
  4. HBase里配置SNAPPY压缩以后regionserver启动不了的问题
  5. LeetCode_108. Convert Sorted Array to Binary Search Tree
  6. c#.net从ftp下载文件到本地
  7. 超详细的RNN代码实现(tensorflow)
  8. SSRS 2016 Forms Authentication
  9. 【计算机视觉】Selective Search for Object Recognition论文阅读1
  10. 高级UI-Snackbar