上回我SHARE了一个将PNG转成BMP的方法,通过直接向Buffer里Draw一个PNG来实现的,今天我想共享给大家的是用自己解码来实现PNG转成BMP的方法,这个方法更正统,不过实现也相对比较麻烦一点.
PNG 的格式除了几个头以外,关键是它的数据用GZip做了压缩,所以,要实现PNG的解码,需要先了解的背景知识只有两个:1.PNG/BMP的编码格式, 2.GZIP的编码格式.这两种文档的编码格式,可以Google一下,会有很多相关资料,我就不再罗嗦了.把自己的实现说一下吧.
1.解开GZIP的方法,我用拿来主义,将网上流传的一个KJava的代码翻译了一下,改写成C代码就OK了.源文件可以点击这里.
在翻译的过程中,注意一下java与c的语法,大体上就可以了,并没有太大难度,好象就是将byte的数组换成byte的指针,记得malloc就一定要free.
2.解析PNG也不复杂,大家可以参考这个文档(中 文的,也说的比较清楚).从头里可以得到一些信息(我因为实用的原因,只处理特定的格式,8bit索引).然后,拿到数据,解压缩得以像素值,就可以构造 出一个IDIB结构.我们知道IDIB是BREW中唯一能直接操作像素点的接口(如果想手工操作BMP的像素,它是一个很方便的途径).部分代码如下:
boolean PngDecoder_ToBMP(PngDecoder
*
pMe,
byte
*
pPngRaw,IDIB
*
pDIB)
{
byte * block;
byte * data;
int i,j,index;
uint32 len;
Head head;
if(pPngRaw[0]!=0x89 || pPngRaw[1]!=0x50 || pPngRaw[2]!=0x4E || pPngRaw[3]!=0x47 || pPngRaw[4]!=0x0D || pPngRaw[5]!=0x0A)
return FALSE;
//缺省认为都是 0x08(8bits color depth) 0x03(调色板)
IDIB_FlushPalette(pDIB);
{
byte * block;
byte * data;
int i,j,index;
uint32 len;
Head head;
if(pPngRaw[0]!=0x89 || pPngRaw[1]!=0x50 || pPngRaw[2]!=0x4E || pPngRaw[3]!=0x47 || pPngRaw[4]!=0x0D || pPngRaw[5]!=0x0A)
return FALSE;
//缺省认为都是 0x08(8bits color depth) 0x03(调色板)
IDIB_FlushPalette(pDIB);