一个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;
  }
}

 
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值