45fan.com - 路饭网

搜索: 您的位置主页 > 网络频道 > 阅读资讯:PngEncoder类的详细分析

PngEncoder类的详细分析

2016-09-08 19:43:20 来源:www.45fan.com 【

PngEncoder类的详细分析

/*******************************************************

功能:可以把image对象转换成png byte[]但是image必须是黑白图片,而且宽度必须是8的整数被

png图像采用了简单结构无压缩存储,采用索引图像,图像只有黑白俩色,背景白,前景黑

转换后的png把原图的背景变换成白,其他颜色都变换成黑

png中只使用了一个IDAT图像信息块,所以图像大小不能超过56635byte 大概总面积不能超过720*720

时间:2006-08-10

********************************************************/

import java.io.*;

import java.util.*;

import javax.microedition.rms.*;

import javax.microedition.lcdui.*;

class PngEncoder {

private int backColor;//要转换的图片的背景颜色

int[] crc_table = new int[256];//crc校验数组

public PngEncoder(int bc) {

backColor=bc;

make_crc_table();//成生校验数组

}

public PngEncoder() {

backColor=0xFFFFFFFF;//默认图像背景为白

make_crc_table();//成生校验数组

}

//设置背景颜色

public void setBackColor(int bc){

backColor=bc;

}

//资源释放

public void Free(){

crc_table=null;

}

//成生校验数组

private void make_crc_table() {

int c;

for (int n = 0; n <= 255; n++) {

c = n;

for (int k = 0; k <= 7; k++) {

if ( (c & 1) == 1) {

c = 0xEDB88320 ^ ((c >> 1)&0x7FFFFFFF);

}

else {

c = (c >> 1)&0x7FFFFFFF;

}

}

crc_table[n] = c;

}

}

//获得一个byte b的crc校验码,c是上一次的crc校验码,第一次时带入0xFFFFFFFF

public int getByteCRC(int c, byte b) {

return crc_table[ (c ^ b) & 0x000000FF] ^ ((c >> 8)&0x00FFFFFF);

}

//把image转换成png byte[]

public byte[] ImageToPng(Image img){

if(img==null) return null;

byte[] LZ77=null,png=null;

byte bb=0;

int ii=0,crc=0,i=0,j=0,crc2=1,len=0,k=0,ip=0,rawIndex=0;

long s1=0, s2=0;

int wid=0,hei=0;

byte cd=1,ct=3,cc=2;//color depth, color type, color count

wid=img.getWidth(); hei=img.getHeight();//图片的宽度和高度

if ((wid % 8)!=0){wid=(wid / 8 + 1)*8;}//宽度必须是8的整数被

len=(1+(wid*cd) / 8)*hei;//图像数据长度,每行前加0所以每行上多出一个字节,cd是一个像素用几个bit表示的意思

if(len>0xFFFF) return null;//图太大,无法构造,必须使用多重IDAT图像信息块才可以实现,目前没有实现

//对于现在的应用足够了。

LZ77=new byte[len+11];//这里临时存放图像信息,11是辅助位的长度,3个标示,4个长度,4个alter校验位

png =new byte[len+86];//这里存放最终的png格式图片 86是除图像信息以外的所有位的长度,固定为86个

int raw[] = new int[wid*hei];//image的RGB信息,数租中的一个值对应实际图像的一个像素,用0xAARRGGBB的形式存储

img.getRGB(raw, 0, wid, 0, 0, wid, hei);

//PNG文件的标识------------------------------------------

png[ip]=(byte)0x89; ip++;

png[ip]=(byte)0x50; ip++;

png[ip]=(byte)0x4E; ip++;

png[ip]=(byte)0x47; ip++;

png[ip]=(byte)0x0D; ip++;

png[ip]=(byte)0x0A; ip++;

png[ip]=(byte)0x1A; ip++;

png[ip]=(byte)0x0A; ip++;

//------------------------------------------------------

//开始写IHDR头部信息快-------------------------------------

//长度

bb=0; png[ip]=bb; ip++;

bb=0; png[ip]=bb; ip++;

bb=0; png[ip]=bb; ip++;

bb=13; png[ip]=bb; ip++;

//标识

crc=0xFFFFFFFF;

bb=0x49; png[ip]=bb; ip++; crc=getByteCRC(crc,bb);

bb=0x48; png[ip]=bb; ip++; crc=getByteCRC(crc,bb);

bb=0x44; png[ip]=bb; ip++; crc=getByteCRC(crc,bb);

bb=0x52; png[ip]=bb; ip++; crc=getByteCRC(crc,bb);

//宽度

ii=wid;

bb=(byte)((ii >> 24) & 0x000000FF); png[ip]=bb; ip++; crc=getByteCRC(crc,bb);

bb=(byte)((ii >> 16) & 0x000000FF); png[ip]=bb; ip++; crc=getByteCRC(crc,bb);

bb=(byte)((ii >> 8) & 0x000000FF); png[ip]=bb; ip++; crc=getByteCRC(crc,bb);

bb=(byte)((ii >> 0) & 0x000000FF); png[ip]=bb; ip++; crc=getByteCRC(crc,bb);

//高度

ii=hei;

bb=(byte)((ii >> 24) & 0x000000FF); png[ip]=bb; ip++; crc=getByteCRC(crc,bb);

bb=(byte)((ii >> 16) & 0x000000FF); png[ip]=bb; ip++; crc=getByteCRC(crc,bb);

bb=(byte)((ii >> 8) & 0x000000FF); png[ip]=bb; ip++; crc=getByteCRC(crc,bb);

bb=(byte)((ii >> 0) & 0x000000FF); png[ip]=bb; ip++; crc=getByteCRC(crc,bb);

//颜色深度

bb=cd; png[ip]=bb; ip++; crc=getByteCRC(crc,bb);

//颜色类型

bb=ct; png[ip]=bb; ip++; crc=getByteCRC(crc,bb);

bb=0; png[ip]=bb; ip++; crc=getByteCRC(crc,bb);

bb=0; png[ip]=bb; ip++; crc=getByteCRC(crc,bb);

bb=0; png[ip]=bb; ip++; crc=getByteCRC(crc,bb);

//CRC

ii=crc ^ 0xFFFFFFFF;

bb=(byte)((ii >> 24) & 0x000000FF); png[ip]=bb; ip++;

bb=(byte)((ii >> 16) & 0x000000FF); png[ip]=bb; ip++;

bb=(byte)((ii >> 8) & 0x000000FF); png[ip]=bb; ip++;

bb=(byte)((ii >> 0) & 0x000000FF); png[ip]=bb; ip++;

//------------------------------------------------------

//PLTE调色板信息-----------------------------------------

//长度

ii=cc*3;

bb=(byte)((ii >> 24) & 0x000000FF); png[ip]=bb; ip++;

bb=(byte)((ii >> 16) & 0x000000FF); png[ip]=bb; ip++;

bb=(byte)((ii >> 8) & 0x000000FF); png[ip]=bb; ip++;

bb=(byte)((ii >> 0) & 0x000000FF); png[ip]=bb; ip++;

//标识

crc=0xFFFFFFFF;

bb=(byte)(0x50); png[ip]=bb; ip++; crc=getByteCRC(crc,bb);

bb=(byte)(0x4C); png[ip]=bb; ip++; crc=getByteCRC(crc,bb);

bb=(byte)(0x54); png[ip]=bb; ip++; crc=getByteCRC(crc,bb);

bb=(byte)(0x45); png[ip]=bb; ip++; crc=getByteCRC(crc,bb);

//颜色0黑

bb=(byte)(0x00); png[ip]=bb; ip++; crc=getByteCRC(crc,bb);//R

bb=(byte)(0x00); png[ip]=bb; ip++; crc=getByteCRC(crc,bb);//G

bb=(byte)(0x00); png[ip]=bb; ip++; crc=getByteCRC(crc,bb);//B

//颜色1白

bb=(byte)(0xFF); png[ip]=bb; ip++; crc=getByteCRC(crc,bb);//R

bb=(byte)(0xFF); png[ip]=bb; ip++; crc=getByteCRC(crc,bb);//G

bb=(byte)(0xFF); png[ip]=bb; ip++; crc=getByteCRC(crc,bb);//B

//CRC

ii=crc ^ 0xFFFFFFFF;

bb=(byte)((ii >> 24) & 0x000000FF); png[ip]=bb; ip++;

bb=(byte)((ii >> 16) & 0x000000FF); png[ip]=bb; ip++;

bb=(byte)((ii >> 8) & 0x000000FF); png[ip]=bb; ip++;

bb=(byte)((ii >> 0) & 0x000000FF); png[ip]=bb; ip++;

//IDAT图像信息-------------------------------------------------

//长度

ii=len+11;

bb=(byte)((ii >> 24) & 0x000000FF); png[ip]=bb; ip++; crc=getByteCRC(crc,bb);

bb=(byte)((ii >> 16) & 0x000000FF); png[ip]=bb; ip++; crc=getByteCRC(crc,bb);

bb=(byte)((ii >> 8) & 0x000000FF); png[ip]=bb; ip++; crc=getByteCRC(crc,bb);

bb=(byte)((ii >> 0) & 0x000000FF); png[ip]=bb; ip++; crc=getByteCRC(crc,bb);

//标识

crc=0xFFFFFFFF;

bb=(byte)(0x49); png[ip]=bb; ip++; crc=getByteCRC(crc,bb);

bb=(byte)(0x44); png[ip]=bb; ip++; crc=getByteCRC(crc,bb);

bb=(byte)(0x41); png[ip]=bb; ip++; crc=getByteCRC(crc,bb);

bb=(byte)(0x54); png[ip]=bb; ip++; crc=getByteCRC(crc,bb);

//无压缩数据

LZ77[0]=(byte)(0x78); LZ77[1]=(byte)(0xDA); LZ77[2]=(byte)(0x01); //LZ77标识

LZ77[3]=(byte)(len & 0x000000FF); LZ77[4]=(byte)((len >> 8) & 0x000000FF);//无压缩数据长度1*8==8 低字节在前

LZ77[5]=(byte)(LZ77[3] ^ 0xFF); LZ77[6]=(byte)(LZ77[4] ^ 0xFF);//无压缩数据长度补码

//图像信息

j=7;

for(i=1; i<=hei; i++)

{

LZ77[j]=(byte)(0x00); j++;

for(k=1; k<=wid / 8; k++)

{

bb=0;

for(int m=0; m<=7;m++){

if(raw[rawIndex+m]==backColor)//白

bb=(byte)(bb|((0x80>>m)&0x000000FF));

}

rawIndex+=8;

LZ77[j]=(byte)(bb); j++;

}

}

crc2=1;//LZ77的Adler32校验位 只校验图像信息部分,其他的不包括到校验位中

s1 = crc2 & 0x0000FFFF;

s2 = (crc2 >> 16) & 0x0000FFFF;

if (len > 0)

{

k = len;

j=7;

while (k > 0){

s1+=(LZ77[j]&0x000000FF); s2+=s1; j++; k--;

}

s1 = s1 % 65521; s2 = s2 % 65521;

}

crc2 = (int)((s2 << 16)&0xFFFF0000) | (int)(s1&0x0000FFFF);

//校验位保存

ii=crc2;

bb=(byte)((ii >> 24) & 0x000000FF); LZ77[len+7]=bb;

bb=(byte)((ii >> 16) & 0x000000FF); LZ77[len+8]=bb;

bb=(byte)((ii >> 8) & 0x000000FF); LZ77[len+9]=bb;

bb=(byte)((ii >> 0) & 0x000000FF); LZ77[len+10]=bb;

//CRC IDAT的校验位

for(i=0; i<=len+10; i++)

{

bb=LZ77[i];

png[ip]=bb; ip++;

crc=getByteCRC(crc,bb);

}

ii=crc ^ 0xFFFFFFFF;

bb=(byte)((ii >> 24) & 0x000000FF); png[ip]=bb; ip++;

bb=(byte)((ii >> 16) & 0x000000FF); png[ip]=bb; ip++;

bb=(byte)((ii >> 8) & 0x000000FF); png[ip]=bb; ip++;

bb=(byte)((ii >> 0) & 0x000000FF); png[ip]=bb; ip++;

//--------------------------------------------------------

//结束数据块-----------------------------------------------

bb=(byte)(0x00); png[ip]=bb; ip++;

bb=(byte)(0x00); png[ip]=bb; ip++;

bb=(byte)(0x00); png[ip]=bb; ip++;

bb=(byte)(0x00); png[ip]=bb; ip++;

bb=(byte)(0x49); png[ip]=bb; ip++;

bb=(byte)(0x45); png[ip]=bb; ip++;

bb=(byte)(0x4E); png[ip]=bb; ip++;

bb=(byte)(0x44); png[ip]=bb; ip++;

bb=(byte)(0xAE); png[ip]=bb; ip++;

bb=(byte)(0x42); png[ip]=bb; ip++;

bb=(byte)(0x60); png[ip]=bb; ip++;

bb=(byte)(0x82); png[ip]=bb; ip++;

//--------------------------------------------------------

LZ77=null;

raw=null;

//System.out.println(png.length);

return png;

}

}

 

本文地址:http://www.45fan.com/a/question/73710.html
Tags: 一个 功能 PngEncoder
编辑:路饭网
关于我们 | 联系我们 | 友情链接 | 网站地图 | Sitemap | App | 返回顶部