16位位图格式及对16位位图的一点个人总结

原文地址::http://hi.baidu.com/rmgsxpxtzebcdpd/item/2fa5bf4e7f576c0be9350470


http://hi.baidu.com/wentao/blog/item/f8404a90a266098ba977a4c9.html

       16位位图表示位图最多有2^16种颜色。每个色素用16位(2个字节)表示。这种格式叫作高彩色,或叫增强型16位色,或64K色。

       当biCompression成员的值是BI_RGB时,它没有调色板。16位中,最低的5位表示蓝色分量,中间的5位表示绿色分量,高的5位表示红色分量,一共占用了15位,最高的一位保留,设为0。这种格式也被称作555 16位位图。

        如果biCompression成员的值是BI_BITFIELDS,那么情况就复杂了,首先是原来调色板的位置被三个DWORD变量占据,称为红、绿、蓝掩码。分别用于描述红、绿、蓝分量在16位中所占的位置。在Windows 95(或98)中,系统可接受两种格式的位域:555和565,在555格式下,红、绿、蓝的掩码分别是:0x7C00、0x03E0、0x001F,而在565格式下,它们则分别为:0xF800、0x07E0、0x001F。你在读取一个像素之后,可以分别用掩码“与”上像素值,从而提取出想要的颜色分量(当然还要再经过适当的左右移操作)。在NT系统中,则没有格式限制,只不过要求掩码之间不能有重叠。(注:这种格式的图像使用起来是比较麻烦的,不过因为它的显示效果接近于真彩,而图像数据又比真彩图像小的多,所以,它更多的被用于游戏软件)。

      RGB555是另一种16位的RGB格式,RGB分量都用5位表示(剩下的1位不用)。使用一个字读出一个像素后,这个字的各个位意义如下:
     高字节             低字节
X R R R R G G       G G G B B B B B       (X表示不用,可以忽略)
可以组合使用屏蔽字和移位操作来得到RGB各分量的值:

#define RGB555_MASK_RED     0x7C00
#define RGB555_MASK_GREEN   0x03E0
#define RGB555_MASK_BLUE   0x001F
R = (wPixel & RGB555_MASK_RED) >> 10;   // 取值范围0-31
G = (wPixel & RGB555_MASK_GREEN) >> 5;   // 取值范围0-31
B =   wPixel & RGB555_MASK_BLUE;         // 取值范围0-31



//========================================================

一点个人认识的总结::


1.常见的16位BMP有两种格式-----XRGB555++++RGB565,这两种BMP对应的biCompression位数据为BI_RGB+BI_BITFIELDS,这两种BMP在XP下RGB565可能不可以查看,
可以查看但有可能显示的位数为32位,但其实还是16位的BMP,可以通过看BMP文件的大小来决定其是多少位存储一个像素点数据的。由于XRGB555在XP下可以查看到,
所以在XP上很多场合下见到的BMP都是XRGB555的BMP文件。


2.photoshop可以把24位PNG/BMP转存为XRGB555+RGB565这两种格式的BMP,其中XRGB555可以在XP查看,但RGB565在XP下不可以查看,
必须借助特别的工具,比如XINVIEW.EXE这样的工具。但借助于其它工具转出来的RGB565BMP在XP下是可见的,比如Picture2Hex.exe。


3.XRGB555跟RGB565这两种格式的BMP最主要的区别是,XRGB555不带调色板(14+40个字节后就是像素点数据了),其存储的数据就是BMP点的像素数据值,也就是XRGB55的数据,
(高位第15位不起作用)
但注意在文件里面存储的数据一般是低位在前,高位在后,所以实际的数据要对应把后一个的高字节放到前一个字节的前面,
这样才是真正的点像素数据;而RGB565有调色板(其实也不是什么调色板,而只是RGB三色的掩码),BMP文件里面实际存储的数据也是跟掩码进行了运算后才存储的。


具体的运算规则如下:
我们假设在位图数据区有一个像素的数据在文件中表示为02 F1。这个数据实际上应为F102,(注意高低字节调整)


r= (F102 AND F800) >> 8 = F0h = 240
g= (F102 AND 07E0)>> 3 = 20h = 32 
b= (F102 AND 001F) << 3 = 10h =16


所以实际的RGB值应该是RGB(240,32,16)----那如果是XRGB555该存储的数值是多少呢?分别取其高5位组成一个15位的数据,再在其最高位补一个0/1,组成16位,
这样就是XRGB555的BMP文件该存储的值,但在文件里面记得低位在前,高位在后。




而对于RGB565是带RGBA这4色的掩码的,当然有的只有RGB这三基色的掩码,而不带ALPHA通道的掩码,每一个掩码为4个字节表示的值。所以RGB565通常比XRGB555多12/16个字节,
其中多16个字节是因为还带了ALPHA的掩码,但BMP通常ALPHA没实际用途,所以其值一般的00 00 00 00,也就是4个字节的00值。


这个规则也可以通过查看BMP文件的大小来总结:


    1》XRGB555 BMP大小为(800*480大小的BMP为例)----800*480*2+40+14=768054个字节
    2》RGB565 BMP大小为(800*480大小的BMP为例)----800*480*2+40+14+12/16=768066/768072个字节,后面的12/16就是3色/4色的掩码字节个数了。




4.注意BMP图像数据在BMP文件里面存储的方式,BMP文件中第1个像素点数据,其实是BMP最后一行的第一个点的数据,
BMP文件中最后1个像素点数据,其实是BMP第一行的最后一个点的数据。也就是存储路线图是从最后一行存储起,一行行存储,最后是第一行存储。




5.常见的几种16为BMP的掩码如下


16位色的BIT MASK主要有以下几种。


    // XRRRRRGG.GGGBBBBB 0x7C00 0x03E0 0x1F
    // RRRRRXGG.GGGBBBBB 0xF800 0x03E0 0x1F
    // RRRRRGGG.GGXBBBBB 0xF800 0x07C0 0x1F
    // RRRRRGGG.GGGBBBBB 0xF800 0x07E0 0x1F




6.注意BMP文件中最开头的14+40图片头提供的信息----有没调色板看情况,在PC上的BMP调色板通常为颜色索引值,在嵌入式系统上通常为RGBA的掩码




    1》文件头14个字节


 typedef struct tagBITMAPFILEHEADER 

UINT16 bfType;    
DWORD bfSize; 
UINT16 bfReserved1; 
UINT16 bfReserved2; 
DWORD bfOffBits;


} BITMAPFILEHEADER;


    2》位图信息头40个字节


ypedef struct tagBITMAPINFOHEADER
{
DWORD biSize; 
LONG biWidth; 
LONG biHeight; 
WORD biPlanes; 
WORD biBitCount; 
DWORD biCompression; 
DWORD biSizeImage; 
LONG biXPelsPerMeter; 
LONG biYPelsPerMeter; 
DWORD biClrUsed; 
DWORD biClrImportant;
} BITMAPINFOHEADER;


7.参考文章----(转)BMP文件格式详解(BMP file format)[图文解说]----http://blog.csdn.net/xqhrs232/article/details/8018358


我们讲的主要是PC机上的位图文件的构成,对于嵌入式平台,可能在调色板数据段与PC机的不同。如在嵌入式平台上常见的16位r5g6b5位图实际上采用的掩模的方式而不是索引的方式来表示图像。此时,在调色板数据段共有四个部分,每个部分为四个字节,实际表示的是彩色版规范。即:
第一个部分是红色分量的掩模
第二个部分是绿色分量的掩模
第三个部分是蓝色分量的掩模
第四个部分是Alpha分量的掩模(缺省为0)
典型的调色板规范在文件中的顺序为为:
00F8 0000 E007 0000 1F00 0000 0000 0000
其中
    00F8 0000为FB00h=1111100000000000(二进制),是蓝红分量的掩码。 
  E007 0000为 07E0h=0000011111100000(二进制),是绿色分量的掩码。 
  1F00 0000为001Fh=0000000000011111(二进制),是蓝色分量的掩码。 
    0000 0000设置为0。
将掩码跟像素值进行“与”运算再进行移位操作就可以得到各色分量值。看看掩码,就可以明白事实上在每个像素值的两个字节16位中,按从高到低取5、6、5位分别就是r、g、b分量值。取出分量值后把r、g、b值分别乘以8、4、8就可以补齐每个分量为一个字节,再把这三个字节按BGR组合,放入存储器,就可以转换为24位标准BMP格式了。
这样我们假设在位图数据区有一个像素的数据在文件中表示为02 F1。这个数据实际上应为F102:
r = (F102 AND F800) >> 8 = F0h = 240
g= (F102 AND 07E0)>> 3 = 20h = 32 
  b=(F102 AND 001F) << 3 = 10h =16




8.可以通过推算某一个点的RGB565/XRGB555表示,来真正理解这两种格式在BMP文件里面的存储形式


   1》查看图中某个像素点的RGB三色的颜色分量,比如PHOTOSHOP工具/WINDOWS下画图工具----定位到某点
   2》通过UltraEdit32工具查看BMP文件的HEX数值,找到对应位置存储的颜色值。




   现在拿个例子来演示推算过程,


   BMP文件的最后一个存储的数据其实是BMP图片第一行最后一个点的数据,所以可以把个点的数据从图片中查看到/在BMP文件中找到




    A。同一张图片在XRGB555 BMP文件中用UltraEdit32查看到的最后一个颜色值为----B2 5E----高低字节反一下其实是5EB2
    B。同一张图片在RGB565 BMP文件中用UltraEdit32查看到的最后一个颜色值为----93 C5----高低字节反一下其实是C593
    C。同一张图片在XRGB555 BMP图像文件中用画图工具查看到的RGB值为(第一行的最后一个像素),坐标值为(799,0)----RGB(189,173,148)---RGB(0xBD,0xAD,0X94)
    D。同一张图片在RGB565 BMP图像文件中用画图工具查看到的RGB值为(第一行的最后一个像素),坐标值为(799,0)----RGB(198,181,156)---RGB(0xC6,0xB5,0X9C)


1》先推算XRGB555格式的:
    XRGB555没有掩码----5EB2展成16位就是----0101,1110,1011,0010h


      1>最高位无效
      2>R值读取为----1011,1h=0xb8=184
      3>G值读取为----1010,1h=0xa8=168
      4>b值读取为----1001,0h=0x90=144




   组成RGB也就是RGB(184,168,144)跟通过画图工具查看到的对应位置的数据RGB(189,173,148)已经非常接近了。




   


1-A》画图工具看到的XRGB565图RGB(189,173,148)---RGB(0xBD,0xAD,0X94)推为XRGB565格式




     1>0xBD----高5位就是1011,1h
     2>0xAD----高5位就是1010,1h
     3>0x94----高5位就是1001,0h


重新组成16位就是0|1011,1h|1010,1h|1001,0h-------最前面的0是那个X位,不计算在内的位,重新读这个16位数就是5EB2跟通过UltraEdit32看到的最一个值是对应的!!!








2》再推算RGB565格式的:------记得去看他们的RGBA四色的掩码值


    RGB565的掩码值为R:0xF800;  G:0x07E0;   B:0x001F




    1>R值计算为----(0xc593 AND 0xf800)>>8=0xc0=192
    2>G值计算为----(0xc593 AND 0x07e0)>>3=0xb0=176
    3>b值计算为----(0xc593 AND 0x001f)<<3=0x98=152
    


   组成RGB也就是RGB(192,176,152)跟通过画图工具查看到的对应位置的数据RGB(198,181,156)已经非常接近了。










2-A》画图工具看到的RGB565图RGB(198,181,156)---RGB(0xC6,0xB5,0X9C)推为RGB565格式




     1>0xC6----高5位就是1100,0h
     2>0xB5----高6位就是1011,01h
     3>0x9C----高5位就是1001,1h




重新组成16位就是1100,0h|1011,01h|1001,1h-------也就是C5B3跟C593也很接近。












3》RGB565跟XRGB555的转换看看




     1>0xC0----高5位就是1100,0h
     2>0xB0----高5位就是1011,0h
     3>0x98----高5位就是1001,1h




重新组成16位就是0|1100,0h|1011,0h|1001,1h-------也就是62D3跟5EB2对不上。差别很大,这个该怎么理解?!














  • 3
    点赞
  • 30
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值