BMP文件格式,RGB之间格式转换 碰到坑,MARK

很多人在转储bmp文件的时候,会出现各种各样的问题,特别是抓屏的时候,经常保存下来的图片 怪怪的,偏差很大!比如下面:

有时候,明明感觉自己是对的,但往往结果很让人抓狂。

这种情况一般是对bmp文件格式理解不对,或者没有透彻导致,当然至少是显示出来,所以大部分是对的,只是某些地方出错!

网上也有很多bmp文件格式,但都说得不够透彻,导致实际总要走些弯路。

bmp是常见图片格式,使用非常广泛。近期在处理ui库的时候,了解下bmp格式,也发现其中一些坑,记录下。

bmp格式很简单,网上搜索一堆,百科上也有介绍,这里就不重复介绍,

最重要就是文件头,主要是 前54字节,可以用UE看看 bmp:

注意:

1. 红色框里的内容,是重点

2. 表示数值的,都是低在前,包括后面的像素点。例如,RGB888 实际存放顺序是 BGR888

颜色:有几种标准,RGB是常见一种,也非常好理解,所以下面重点是RGB颜色标准。

由于4色,黑白色,16色,256色,色差失真太大,除了特殊场合,现在很少用了,因此,我也不怎么去尝试。

对于256色,其实存在画板的概念,可以提升图片效果,降低存储空间,有兴趣可以去了解下

重点说下:16位色 24位色

注意区别:16色与16位色,16色就是16种颜色,非常单调;16位色,就是用16bit 来表示颜色,有65536种颜色,比较丰富。

24位色就是24bit来表示颜色,那么有256*256*256种颜色,那么颜色更丰富,满足大部分的正常使用。

既然24位色这么好,为什么还有用16位色呢?甚至更低色?主要场合不一样,位数越少,表现效果当然越差了,但存储占空间就越少,意味着处理就更快,在显示要求并不是那么高的地方,还是很有市场的,另外颜色也受到显示对象限制,有年代的人应该知道以前屏幕是单色的,因此再多的色彩最终还是 0或1;后来出现彩色屏幕,但颜色也很少,就那么几种,但比单色效果好很多了;再后来出现 真彩色,才使得我们进入888的时代,当然以后更多,颜色也更绚丽。总之,颜色取决于你的设备/处理能力/硬件成本。

前面说到的 RGB888就是 24位色=8+8+8

那么16位色又是?RGB565=5+6+5,还有RGB555=5+5+5 ,一般RGB565比较多。

“在我们的计算机中图像是以RGB888格式显示图像的,24位图每个像素保存了32bit的数据,即RGB888+Alpha,Alpha就是半透明填充字节……”  但设备当中,我们经常用RGB565,因此两者之间是要转换的,转换算法,网上很多,也很简单,这里就不重复描述。

当然实际不会这么简单,我就碰到这么一个坑,通过坑,就好好理解BMP格式。

不知道大家有没有注意到bmp格式里的 001EH 这里的含义:

  • 0 - 不压缩 (使用BI_RGB表示)
  •       1 - RLE 8-使用8位RLE压缩方式(用BI_RLE8表示)
  •       2 - RLE 4-使用4位RLE压缩方式(用BI_RLE4表示)
  •       3 - Bitfields-位域存放方式(用BI_BITFIELDS表示)   一般用于bit12以及bit32,这里是 重点!重点!重点!重点!

因为目标文件是RGB565,16bit,所以 001E这里要填 3,注意不能填0!注意不能填0 !注意不能填0!

那么填了3是否就OK了呢?不是!因为16bit,还有RGB565 以及 RGB555两种标准,你还要告诉对方用哪种格式!不然系统就傻了!

那么怎么告诉系统呢?需要在 原先54字节 后面增加一些信息,主要增加16字节内容:

内容 长度 填写(注意还是要低在前)
红色占位 4字节 RGB565 要填:0x0000F800
绿色占位 4字节 RGB565 要填:0x000007E0
蓝色占位 4字节 RGB565 要填:0x0000001F
预留 4字节 填00

注意:

由于头信息变成 70字节了,因此 偏移量/长度  地方的值也要随着改变

还有一个地方:000EH 这个地方要增加16,这里要填 0x38 !

ps:由此可见,如果是RGB555的话,这些地方也要改

可以看下实际51*51的头,用UE:

还有一个坑,就是bmp要4字节对齐,本来是很好理解的,但实际却是

“每一行都得4字节对齐,不足的用 00H 补齐”

举个例子:

如果图片是 51 * 51  格式: RGB565(一个像素点为2字节)

每行字节数=51*2=102字节,102不是4倍数,所以要补偿两个00,使之=104字节。

实际文件长度一共补偿了102字节。

下面给一个我创建bmp头函数,就可以实现自己的bmp头,由于平时就用到RGB888 跟 RGB565 两种,所以没考虑其他类型的,如果有兴趣可以完善以下代码,使之更加通用!

  1 //pTitle 固定为70字节, 创建
  2 //byBits 位数,比如16 24
  3 //nWidth 图片宽度(多少像素点)
  4 //nHeight 图片高度(多少像素点)
  5 //nFileLen 图片总像素点 = nWidth * nHeight
  6 void CreateBmpTitle(byte *pTitle,byte byBits,UINT nWidth,UINT nHeight,UINT nFileLen)
  7 {
  8     int nPos = 0;
  9     memset(pTitle,0,70);
 10
 11     //每个像素占多少字节
 12     byte bmpBytes = 2;
 13     if(byBits <= 8)
 14     {
 15         bmpBytes = 1;
 16     }
 17     else if(byBits <= 16)
 18     {
 19         bmpBytes = 2;
 20     }
 21     else if(byBits <= 24)
 22     {
 23         bmpBytes = 3;
 24     }
 25     else
 26     {
 27         bmpBytes = 4;
 28     }
 29
 30     //每一行都要凑齐4
 31     UINT nLineLen = nWidth * bmpBytes;
 32     if((nLineLen % 4) != 0)
 33     {
 34         UINT nAdd = (4 - (nLineLen % 4)) * nHeight;
 35         nFileLen += nAdd;
 36     }
 37
 38     pTitle[nPos++] = ‘B‘;
 39     pTitle[nPos++] = ‘M‘;
 40
 41     //文件长度
 42     SetUINT_L(nFileLen+70,pTitle,nPos);
 43     nPos += 8;//预留4也跳过
 44
 45     //偏移量
 46     SetUINT_L(70,pTitle,nPos);
 47     nPos += 4;
 48
 49     //windows, 56
 50     SetUINT_L(56,pTitle,nPos);
 51     nPos += 4;
 52
 53     //宽度
 54     SetUINT_L(nWidth,pTitle,nPos);
 55     nPos += 4;
 56     //高度
 57     SetUINT_L(nHeight,pTitle,nPos);
 58     nPos += 4;
 59     //平面数=1
 60     SetUSHORT_L(1,pTitle,nPos);
 61     nPos += 2;
 62
 63     //bits 数
 64     SetUSHORT_L((USHORT)byBits,pTitle,nPos);
 65     nPos += 2;
 66
 67     if(byBits == 24)
 68     {
 69         nPos += 4;
 70     }
 71     else if((byBits == 16) || (byBits == 15) || (byBits == 32))
 72     {
 73         //BI_BITFIELDS
 74         SetUINT_L(3,pTitle,nPos);
 75         nPos += 4;
 76     }
 77
 78     //内容长度,必须为4倍数
 79     SetUINT_L(nFileLen,pTitle,nPos);
 80     nPos += 4;
 81
 82     SetUINT_L(0xb12,pTitle,nPos);
 83     nPos += 4;
 84
 85     SetUINT_L(0xb12,pTitle,nPos);
 86     nPos += 4;
 87
 88     if(byBits == 16)
 89     {
 90         // 565 分别表示 RGB 所在bit位数
 91         nPos = 54;
 92
 93         SetUINT_L(0xF800,pTitle,nPos);
 94         nPos += 4;
 95
 96         SetUINT_L(0x07E0,pTitle,nPos);
 97         nPos += 4;
 98
 99         SetUINT_L(0x001F,pTitle,nPos);
100         nPos += 4;
101     }
102
103
104     ///其他都是0
105 }

原文地址:https://www.cnblogs.com/winafa/p/11652343.html

时间: 2024-10-11 10:17:28

BMP文件格式,RGB之间格式转换 碰到坑,MARK的相关文章

bmp,jpg,png,tif,wmf,emf与eps图片格式转换

wmf/emf是两种Microsoft Windows的图形文件格式.它是一个矢量图格式,但是也允许包含位图.本质上,一个WMF文件保存一系列可以用来重建图片的Windows GDI命令.在某种程度上,它类似于印刷业广泛使用的PostScript格式. 关于wmf2eps安装使用的问题可参考如下两个网页. http://www.kellogg.northwestern.edu/rc/miktex-install.htm http://www.wolf-s.homepage.t-online.de

bmp文件格式中rgb555与rgb888之间的转换,24位与16位位图的转换

今日,有同事问我,rgb555模式下的位图文件的格式问题,于是花了一下午的时间通过猜测与测试,分析出了如下bmp文件在rgb555模式下的文件存储规律: 1:bmp文件的文件信息头中的biBitCount数据应该为16 在rgb555模式下,一个像素占用2字节,rgb分别占用5位,另外有一位是填充位. 2:16位数据的组成如下 第一个字节:g5g4g3b7b6b5b4b3 第二个字节:0r7r6r5r4r3g7g6 其中第二个字节的左边第一位为填充位,我在实验中用0填充. 3:该16位bmp图像

3.13. Notepad++中Windows,Unix,Mac三种格式之间的转换

由于历史原因,导致Windows,Unix/Linux,Mac三者之间,对于文件中所用回车换行符,表示的方法,都不一样. 这就导致了很多人都会遇到回车换行符的困惑,和需要在不同格式间进行转换. 其中,关于回车换行符的详细解释,去看这里[13] 此处,介绍一下,如何通过Notepad++实现在这三者之间进行转换. 3.13.1. 查看当前文件格式(换行符用的是什么字符) 当前是Windows的平台,所以通过“显示所有字符”: 默认所查看到的是Windows的CR LF: 3.13.2. 从Wind

Notepad++中Windows,Unix,Mac三种格式之间的转换

http://www.crifan.com/files/doc/docbook/rec_soft_npp/release/htmls/npp_func_windows_unix_mac.html 由于历史原因,导致Windows,Unix/Linux,Mac三者之间,对于文件中所用回车换行符,表示的方法,都不一样. 这就导致了很多人都会遇到回车换行符的困惑,和需要在不同格式间进行转换. 其中,关于回车换行符的详细解释,去看这里[13] 此处,介绍一下,如何通过Notepad++实现在这三者之间进

office之间的格式转换解析 如何将ppt转换成word

Office文档之间可以进行相互转换吗?这个问题问出来,很多人的第一反应就是不能,Microsoft office有不少的类型文档,针对不同的领域,有各自不同的功能,正因为他们直接的"不同",所以将格式转换变得困难.也不是没有人试过,像是复制后粘贴就是一种好方法,但是说"转换"还太勉强.下面为大家介绍:office之间的格式转换解析,如何将ppt转换成word? 步骤1,首先下一个可以转换文档格式的工具,请将下载安装软件,并点击"立即运行"在安装

YUV RGB 格式转换

第一个公式是RGB转YUV(范围0-255)时用的,第二个公式是用在YUV转换RGB(范围0-255)时用的.1. Y = 0.257 * R + 0.504 * G + 0.098 * B + 16; U = -0.148 * R - 0.291 * G + 0.439 * B + 128; V = 0.439 * R - 0.368 * G - 0.071 * B + 128; 黑色:Y=16 ,U= V =128 红色:Y=82 ,U=90,V=240 绿色:Y=145,U=54,V=34

JSON的基本格式以及与JavaScript之间的转换

JSON的基本格式以及与JavaScript之间的转换 近来,发现很多人写json格式的数据时,总是没有达到JSON的规范,虽然在语言要求不严格的情况下能够通过, 但是,难免会遇到这样那样的问题,到时候再做修改,担心为时晚矣,故计划写此博文. JSON的语法规则: 1.数据需要以键值对的形式书写: e g: { "name" : "zychao" } 2.数据与数据之间需要通过逗号分隔: e g: { "name" : "zychao&

dos与unix文件格式之间的转换

1. VI编辑器中转换 在VI中使用命令 set ff?(fileformat)可以查看文件的格式,使用set ff=dos(unix)可以设置文件的格式 2.使用sed处理(来至http://www.cnblogs.com/yangyh/archive/2011/08/12/linux.html) Sed命令笔记 Tag:linux sed 正则 替换 DOS/Windows和Linux/Unix的文件换行回车格式不同,基于 DOS/Windows 的文本文件在每一行末尾有一个 CR(回车)和

【视频处理】YUV与RGB格式转换

YUV格式具有亮度信息和色彩信息分离的特点,但大多数图像处理操作都是基于RGB格式. 因此当要对图像进行后期处理显示时,需要把YUV格式转换成RGB格式. RGB与YUV的变换公式如下: YUV(256 级别) 可以从8位 RGB 直接计算: Y = 0.299 R + 0.587 G + 0.114 B U = - 0.1687 R - 0.3313 G + 0.5 B + 128 V = 0.5 R - 0.4187 G - 0.0813 B + 128 反过来,RGB 也可以直接从YUV