好久没写东西咯,最近一种忙图片效果,这两天吧BMP做了,总想记录下东西下来吧,所以总结了下。本想把之前的TGA,PNG,GIF的都再一起重新总结一下,可惜时间不多,那就暂时先把BMP总结咯,位图的资料网上有很多,我只总结下自己在解码过程中遇到的几个问题。
BMP格式
BMP格式是常见的格式,早期windows3.0以前,底层图片基本上都使用BMP,所以叫DDB(device depande BMP),windows3.0以后开始脱离BMP,叫DIB(device indepande BMP).
解码过程中遇到的几个问题:
1. 信息头54个字节,在定义信息头结构体的时候要注意所在的平台,注意int是4个字节还是2个字节,往往会因为结构体自动对齐的问题使得头信息结构体算出长度为56,此时就需要将结构体声明为2字节对齐,方法是使用#pragma pack(2) ;
2. 注意在读取数据的时候,BMP的宽是使用4字节对齐,所以可能会出现“补位”的情况,这时,在计算宽的时候可以使用公式 padbytes =(长像素%4) ?(4 - (长像素%4) : 0);
3. 很多格式的图片解码出来的图片像素的起始点是在左下角,所以需要从下往上一排一排的将像素换行,即第一行和最后一行交换,以此类推。
4. 关于解码出来的是BGRA是否需要转化为RGBA,网上说是需要转化的,其实是根据具体平台参考,例如我用的linux平台就不需要再转化为RGB。
5. 现在具体说说不同位的BMP图片的解码:
u 1bit 和 4bit
之所以把它们和在一起是因为它们的解压方式十分相近,都是采用调色盘索引的方式,1bit就是只能索引0和1,即只有黑白两种颜色,4bit是可以有2^4种索引,为16色。
它们需要注意的是一个字节表示几个像素点,分别是8个和2两个,所以解码的时候一个字节要对应存几次。
u 8bit
8bit其实和前面的两种很相似咯,同样是使用调色板索引表,只是一个字节对应一个像素点,相对更简单点。其实通过文件头和8位都可以判断,其索引表都是256个字节的。
u 16bit
16位的稍微麻烦点,需要先通过文件头的压缩方式来判定,0是555格式,3是565格式,它们在转化位24bit或者32bit时使用的掩码是不同的,具体网上很多。分别是将提取出的颜色分量放在低5位,这样颜色失真一般比较严重,所以再做个均匀映射255的可以吧颜色补正。
在调试的过程中发现,原来16位BMP转24位或者32位还是很简单的,只需要稍微修改信息头的类型,文件大小,再将其存储位.bmp文件 即可。
u 24bit
24位如果绘图直接是使用RGB接很简单咯,直接解码出数据返回即可,如果是绘图图层是32位的,还需要给ALPHA位补255,buf分配空间因该是 waith * hight * 4 。
u 32bit
我本来就是使用的32位图层,所以32位解码是最简单的,去掉文件头,其余数据直接返回 OK :)
至此,BMP基本告一段落,其实还有一种情况没有考虑,就是4bit和8bit可能还带RLE压缩,虽然实际这种情况很少见,我这里暂时没有做RLE的加压工作。