BREW中将PNG转换成BMP的方法(解码转换)

PNG转BMP方法
本文介绍了一种将PNG格式图像转换为BMP格式的方法。该方法通过对PNG图像数据进行解码,包括解开GZIP压缩、解析PNG文件头、读取颜色调色板等步骤,并最终构造出BMP图像的IDIB结构。

上回我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的像素,它是一个很方便的途径).部分代码如下:

None.gif boolean PngDecoder_ToBMP(PngDecoder  *  pMe, byte   *  pPngRaw,IDIB  *  pDIB)
ExpandedBlockStart.gifContractedBlock.gif
dot.gif {
InBlock.gif    
byte * block;
InBlock.gif    
byte * data;
InBlock.gif    
int i,j,index;
InBlock.gif    uint32 len;
InBlock.gif    Head head;    
InBlock.gif
InBlock.gif
InBlock.gif    
if(pPngRaw[0]!=0x89 || pPngRaw[1]!=0x50 || pPngRaw[2]!=0x4E || pPngRaw[3]!=0x47 || pPngRaw[4]!=0x0D || pPngRaw[5]!=0x0A)
InBlock.gif        
return FALSE;
InBlock.gif
InBlock.gif    
//缺省认为都是 0x08(8bits color depth) 0x03(调色板)
InBlock.gif
    IDIB_FlushPalette(pDIB);
InBlock.gif    pDIB
->pPaletteMap=NULL;
InBlock.gif    pDIB
->nDepth=8;
InBlock.gif    pDIB
->nColorScheme=0;
InBlock.gif    pDIB
->nPitch=pDIB->cx;
InBlock.gif    pDIB
->ncTransparent=IBITMAP_RGBToNative(pMe->pScreen,MAKE_RGB(255,255,255));
InBlock.gif    
InBlock.gif    
//调色板
InBlock.gif
    index=33;
InBlock.gif    readHead(pPngRaw
+index,&head);
InBlock.gif    
if(STRCMP(head.type,"PLTE")==0)
ExpandedSubBlockStart.gifContractedSubBlock.gif    
dot.gif{
InBlock.gif        len
=head.len;
InBlock.gif        index
+=8;        
InBlock.gif        pDIB
->pRGB=(uint32*)MALLOC(sizeof(uint32)*(len/3));
InBlock.gif        MEMSET(pDIB
->pRGB,0,(len/3)*sizeof(uint32));
InBlock.gif        
for(j=0,i=index;i<index+len;j++,i+=3)
ExpandedSubBlockStart.gifContractedSubBlock.gif        
dot.gif{
InBlock.gif            
//低位
InBlock.gif
            pDIB->pRGB[j]=((uint32)pPngRaw[i]<<16)+((uint32)pPngRaw[i+1]<<8)+(uint32)pPngRaw[i+2];
InBlock.gif            
ExpandedSubBlockEnd.gif        }

InBlock.gif        pDIB
->cntRGB=j;
InBlock.gif        index
+=len+4;
ExpandedSubBlockEnd.gif    }

InBlock.gif    
InBlock.gif    
//读透明色
InBlock.gif
    readHead(pPngRaw+index,&head);
InBlock.gif    
if(STRCMP(head.type,"tRNS")==0)
ExpandedSubBlockStart.gifContractedSubBlock.gif    
dot.gif{
InBlock.gif        len
=head.len;
InBlock.gif        index
+=8;
InBlock.gif        j
=(int)pPngRaw[index];
InBlock.gif        pDIB
->ncTransparent=IBITMAP_RGBToNative(pMe->pScreen,(RGBVAL)pDIB->pRGB[j]);
InBlock.gif        index
+=len+4;        
ExpandedSubBlockEnd.gif    }

InBlock.gif
InBlock.gif    
//Step 2: 读数据放入block里
InBlock.gif    
//数据长
InBlock.gif
    readHead(pPngRaw+index,&head);
InBlock.gif    
if(STRCMP(head.type,"IDAT")==0)
ExpandedSubBlockStart.gifContractedSubBlock.gif    
dot.gif{
InBlock.gif        len
=head.len;  
InBlock.gif        block
=(byte*)MALLOC(len);
InBlock.gif        
InBlock.gif        index
+=10//IDAT块前面两个字节是标志:0x78 0x5E
InBlock.gif
        
InBlock.gif        MEMSET(block,
0,len);
InBlock.gif        MEMCPY(block,
&pPngRaw[index],len);
InBlock.gif        
InBlock.gif        
//Step 3:解压缩
InBlock.gif
        
InBlock.gif        data 
= GZIP_Inflate(pMe->gzip,block,pDIB->cx*pDIB->cy+pDIB->cy);
InBlock.gif        len
=pMe->gzip->uncompressed_index;
InBlock.gif
InBlock.gif        pDIB
->pBmp=(byte*)MALLOC(pDIB->cx*pDIB->cy);
InBlock.gif        
for(i=0;i<pDIB->cy;i++)
InBlock.gif            
for(j=0;j<pDIB->cx;j++)
ExpandedSubBlockStart.gifContractedSubBlock.gif            
dot.gif{
InBlock.gif                pDIB
->pBmp[i*pDIB->cx+j]=data[i*(pDIB->cx+1)+j+1];
ExpandedSubBlockEnd.gif            }

InBlock.gif        
InBlock.gif
InBlock.gif        FREEIF(block);
InBlock.gif        block
=NULL;
InBlock.gif        FREEIF(data);    
InBlock.gif        data
=NULL;
ExpandedSubBlockEnd.gif    }

InBlock.gif    
InBlock.gif    
return TRUE;
ExpandedBlockEnd.gif}

pPngRaw是加载的PNG图像数据,可以来自于文件或网络,转换的结果放到pDIB里.

 

转载于:https://www.cnblogs.com/sharetop/archive/2006/05/09/394718.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值