Image对象转成PNG格式字节 。没有做LZ77压。
共三个文件。
pngtools.java image转png格式工具类
bytestools.java byte操作类
crcutil crc校验类
转载请注明出处,可自由使用,无使用限,但商用请通知我。
pngtools.java


/** *//**
* @功能:image 生成 png 字节
* @作者: imuse
* @MAIL: postzhu@hotmail.com
* @blog: http://blog.youkuaiyun.com/imuse
* @注 可自由使用,无使用限制。如商用请通知我
*/

import javax.microedition.lcdui.Image;



public class PngTools ...{
public static final int BIT4 = 4;
public static final int BIT8 = 8;

/** *//** PNG tag. */

private static final byte PNG[] = ...{-119, 80, 78, 71, 13, 10, 26, 10};

/** *//** IHDR tag. */

private static final byte IHDR[] = ...{73, 72, 68, 82};

/** *//** PLTE tag. */

private static final byte PLTE[] = ...{0x50,0x4C,0x54,0x45};

/** *//** IDAT tag. */

private static final byte IDAT[] = ...{73, 68, 65, 84};

/** *//** LZ77 tag. */

private static final byte LZ77[] = ...{0x78, (byte)0xDA, 0x01};

/** *//** IEND tag. */

private static final byte IEND[] = ...{(byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x49, (byte) 0x45, (byte) 0x4E, (byte) 0x44, (byte) 0xAE, (byte) 0x42, (byte) 0x60, (byte) 0x82};

/** *//**
* @功能 Image转成PNG字节
* @参数 Image srcImage 原图<br>int bit色深<br>
* @返回值 转换后的图片
* */


public static byte[] imageToPng(Image srcImg, int bit)...{
int srcW = srcImg.getWidth();
int srcH = srcImg.getHeight();
int[] srcRGB = new int[srcW];
int[] nColorArr = new int[0];
//取出图片中所用到的所有颜色

for (int i = 0; i < srcH; i++) ...{
//取一行颜色
srcImg.getRGB(srcRGB, 0, srcW, 0, i, srcW, 1);
//取一行颜色中的不同值
int[] temp = GetColorArr(srcRGB);
//将本行与上一次的结果连接
int[] count = new int[nColorArr.length+temp.length];
System.arraycopy(nColorArr, 0, count, 0, nColorArr.length);
System.arraycopy(temp, 0, count, nColorArr.length, temp.length);
//取连接后的结果再次取不同颜色
nColorArr = GetColorArr(count);
}

//如果没找到颜色则返回空

if(nColorArr.length==0)...{
return null;
}
int nPosCRC = 0;
byte[] bRet;
//固定头
bRet = BytesTools.appendBytes(null, PNG);
//固定头长度
bRet = BytesTools.appendBytes(bRet, BytesTools.intToBytes(13));
nPosCRC = bRet.length;
//IHDR
bRet = BytesTools.appendBytes(bRet, IHDR);
//宽
bRet = BytesTools.appendBytes(bRet, BytesTools.intToBytes(srcW));
//高
bRet = BytesTools.appendBytes(bRet, BytesTools.intToBytes(srcH));
//色深
bRet = BytesTools.appendBytes(bRet, (byte)bit);
//颜色类型
bRet = BytesTools.appendBytes(bRet, 0x03);
//规定此处总为0
bRet = BytesTools.appendBytes(bRet, 0x00);
//同上
bRet = BytesTools.appendBytes(bRet, 0x00);
//非隔行扫描
bRet = BytesTools.appendBytes(bRet, 0x00);
//头信息CRC
int nCRC = CRCUtil.checksum(bRet, nPosCRC, bRet.length-nPosCRC);
bRet = BytesTools.appendBytes(bRet, BytesTools.intToBytes(nCRC));
//颜色总数
int nColorLen = nColorArr.length;
bRet = BytesTools.appendBytes(bRet, BytesTools.intToBytes(nColorLen*3));
nPosCRC = bRet.length;
//PLTE
bRet = BytesTools.appendBytes(bRet, PLTE);

for (int i = 0; i < nColorLen; i++) ...{
bRet = BytesTools.appendBytes(bRet, intToRGBBytes(nColorArr[i]));
}
//CRC PLTE
nCRC = CRCUtil.checksum(bRet, nPosCRC, bRet.length-nPosCRC);
bRet = BytesTools.appendBytes(bRet, BytesTools.intToBytes(nCRC));
//IDTA长度
int nIdtaLen = 0;

if(bit==BIT4)...{
nIdtaLen = (srcW/2+1)*srcH;

}else if(bit==BIT8)...{
nIdtaLen = (srcW+1)*srcH;
}
int nLen = 4+LZ77.length+4+nIdtaLen;
bRet = BytesTools.appendBytes(bRet, BytesTools.intToBytes(nLen));
nPosCRC = bRet.length;
//IDAT
bRet = BytesTools.appendBytes(bRet, IDAT);
//无压缩的LZ77压缩块
bRet = BytesTools.appendBytes(bRet, LZ77);
//长度
bRet = BytesTools.appendBytes(bRet, getIDATLen(nIdtaLen));
//数据区域
int nAl = bRet.length;

if(bit==BIT4)...{
bRet = BytesTools.appendBytes(bRet, getPngBytes(srcImg, nColorArr));

}else if(bit==BIT8)...{
bRet = BytesTools.appendBytes(bRet, getPngBytes8(srcImg, nColorArr));
}
//Adler32
bRet = BytesTools.appendBytes(bRet, Adler(bRet, nAl, bRet.length-nAl));
//CRC
nCRC = CRCUtil.checksum(bRet, nPosCRC, bRet.length-nPosCRC);
bRet = BytesTools.appendBytes(bRet, BytesTools.intToBytes(nCRC));
//IEND
bRet = BytesTools.appendBytes(bRet, IEND);
return bRet;
}
//Adler校验

private static byte[] Adler(byte[] bData, int nStart, int nLen)...{
int adler1=1;
int adler2=0;
nLen += nStart;
for(int i=nStart;i<nLen;i++)

...{
adler1=adler1+((int)bData[i]&0xff);
adler2=adler1+adler2;
adler1%=65521;
adler2%=65521;
}
int nRet = (adler2<<16) | adler1 ;
return BytesTools.intToBytes(nRet);
}
//8位色深IDAT数据

private static byte[] getPngBytes8(Image srcImg, int[] nColorArr)...{
int srcW = srcImg.getWidth();
int srcH = srcImg.getHeight();
int[] srcRGB = new int[srcW];
byte[] bRet = new byte[(srcW+1)*srcH];
int nPos = 0;

for (int i = 0; i < srcH; i++) ...{
srcImg.getRGB(srcRGB, 0, srcW, 0, i, srcW, 1);
nPos = i;
bRet[i*srcW+nPos] = 0;

for (int j = 0; j < srcW; j++) ...{
bRet[i*srcW+nPos+j+1] = (byte)(getColorIndex(srcRGB[j], nColorArr)&0xFF);
}
}
return bRet;
}
//4位色深IDAT数据

private static byte[] getPngBytes(Image srcImg, int[] nColorArr)...{
int srcW = srcImg.getWidth();
int srcH = srcImg.getHeight();
int[] srcRGB = new int[srcW];
byte[] bRet = new byte[(srcW/2+1)*srcH];
int nPos = 0;

for (int i = 0; i < srcH; i++) ...{
srcImg.getRGB(srcRGB, 0, srcW, 0, i, srcW, 1);
nPos = i;
bRet[i*srcW/2+nPos] = 0;
int nIndex = 0;

for (int j = 0; j < srcW; j++) ...{

if(j%2==1 && j!=0)...{
nIndex = nIndex | (getColorIndex(srcRGB[j], nColorArr)&0xFF);
bRet[i*srcW/2+j/2+1+nPos] = (byte)nIndex;

}else...{
nIndex = (getColorIndex(srcRGB[j], nColorArr)&0xFF)<<4;
}
}
}
return bRet;
}
//取颜色索引

private static int getColorIndex(int nColor, int[] nColorArr)...{
int nLen = nColorArr.length;
int nIndex = -1;

for (int i = 0; i < nLen; i++) ...{

if(nColor==nColorArr[i])...{
nIndex = i;
break;
}
}
return nIndex;
}
//将一个int color转红绿蓝byte数组

private static byte[] intToRGBBytes(int nColor)...{
byte[] bColor = new byte[3];
//红
bColor[0] = (byte)(nColor>>16&0xFF);
//绿
bColor[1] = (byte)(nColor>>8&0xFF);
//蓝
bColor[2] = (byte)(nColor&0xFF);
return bColor;
}
//IDAT数据的长度,格式为:前两字节为IDAT长度,低字节在前,后两字节为前两字节的^值.

private static byte[] getIDATLen(int nLen)...{
byte[] bRet = new byte[4];
bRet[0] = (byte)(nLen & 0xFF);
bRet[1] = (byte)(nLen >> 8 & 0xFF);
bRet[2] = (byte)(bRet[0] ^ 0xFF);
bRet[3] = (byte)(bRet[1] ^ 0xFF);
return bRet;
}

//从一个int数据中取出不同的int值

private static int[] GetColorArr(int[] nArr)...{
int nLen = nArr.length;
int nRet[] = new int[0];

for (int i = 0; i < nLen; i++) ...{
int nrLen = nRet.length;
boolean is = true;

for (int j = 0; j < nrLen; j++) ...{

if(nArr[i]==nRet[j])...{
is = false;
break;
}
}

if(is)...{
int[] temp = new int[nrLen+1];
System.arraycopy(nRet, 0, temp, 0, nrLen);
temp[nrLen] = nArr[i];
nRet = temp;
}
}
return nRet;
}
}

bytestools.java


/** *//**
* @功能:字节工具类
* @作者: imuse
* @MAIL: postzhu@hotmail.com
* @blog: http://blog.youkuaiyun.com/imuse
* @注 可自由使用,无使用限制。如商用请通知我
*/

public class BytesTools ...{




/** *//**
* @功能: 将一个int值转为byte数组
* @参数: int nNum 要转的int值
* @返回值: byte[] bytesRet 转后的byte数组
*/

public static byte[] intToBytes(int nNum) ...{
byte[] bytesRet = new byte[4];
bytesRet[0] = (byte) ((nNum >> 24) & 0xFF);
bytesRet[1] = (byte) ((nNum >> 16) & 0xFF);
bytesRet[2] = (byte) ((nNum >> 8) & 0xFF);
bytesRet[3] = (byte) (nNum & 0xFF);
return bytesRet;
}


/** *//**
* @功能: 将一个长度为4 byte数组转为int
* @参数: byte[] bNum要转的字节数组
* @返回值: int retInt 转后的int值
*/

public static int bytesToInt(byte[] bNum) ...{
return bytesToInt(bNum, 0);
}

/** *//**
* @功能: 将一个长度为4 byte数组转为int
* @参数: byte[] bNum要转的字节数组<br>int nStartPos起始位置
* @返回值: int retInt 转后的int值
*/

public static int bytesToInt(byte[] bNum, int nStartPos) ...{
int retInt = 0;
retInt = ((bNum[nStartPos++] & 0xFF) << 24);
retInt += (bNum[nStartPos++] & 0xFF) << 16;
retInt += (bNum[nStartPos++] & 0xFF) << 8;
retInt += bNum[nStartPos] & 0xFF;
return retInt;
}


/** *//**
* @功能: 将一个INT的转为byte数组后追加到指定数组后
* @参数: byte[] bDes追加目标<br>int bSrc要追加的int
* @返回值: byte[] 追加后的字节数组
*/

public static byte[] appendBytes(byte[] bDes, int bSrc) ...{

return appendBytes(bDes, new byte[]...{(byte)bSrc});
}

/** *//**
* @功能: 将一个byte 数组追加到指定数组后
* @参数: byte[] bDes追加目标<br>byte[] bSrc要追加的字节数组
* @返回值: byte[] 追加后的字节数组
*/

public static byte[] appendBytes(byte[] bDes, byte[] bSrc) ...{
byte[] ret = null;

if (bDes == null) ...{
ret = bSrc;
}

if (bSrc == null) ...{
ret = bDes;
}

if (bDes != null && bSrc != null) ...{
ret = new byte[bDes.length + bSrc.length];
System.arraycopy(bDes, 0, ret, 0, bDes.length);
System.arraycopy(bSrc, 0, ret, bDes.length, bSrc.length);
}
return ret;
}


/** *//**
* @功能: 截取指定byte 数组中的字节数组
* @参数: byte[] bSrc原字节数组<br>int nStartPos原字节数组起始位置<br>int nLen截取长度
* @返回值: byte[] 截取后的字节数组
*/

public static byte[] subBytes(byte[] bSrc, int nStartPos, int nLen) ...{
byte[] ret = null;

if (bSrc != null) ...{
ret = new byte[nLen];

if((nStartPos+nLen)<=bSrc.length)...{
System.arraycopy(bSrc, nStartPos, ret, 0, nLen);
}
}
return ret;
}

/** *//**
* @功能: 查找子字节数组在父字节数组中的位置
* @参数: byte[] bSrc父字节数组<br>byte[] bSub子字节数组
* @返回值: int 在父字节数组中的位置,如未找到则返回-1
*/

public static int findSubBytesPos(byte[] bSrc, byte[] bSub)...{
int ret = -1;
int nSubLen = bSub.length;
int nLen = bSrc.length-nSubLen;
boolean b=true;

for(int i=0; i<=nLen; i++)...{
b = true;

for (int j = 0; j < nSubLen; j++) ...{

if(bSrc[i+j]!=bSub[j])...{
b = false;
break;
}
}

if(b)...{
ret = i;
break;
}
}
return ret;
}
}

crcutil.java


/** *//**
* @功能:CRC校验
* @作者: imuse
* @MAIL: postzhu@hotmail.com
* @blog: http://blog.youkuaiyun.com/imuse
* @注 可自由使用,无使用限制。如商用请通知我
*/

public class CRCUtil ...{
private static int[] crc_table;

private static void make_crc_table() ...{
int c;
int n, k;
crc_table = new int[256];

for (n = 0; n < 256; n++) ...{
c = n;

for (k = 0; k < 8; k++) ...{
if ((c & 1) == 1)
c = 0xedb88320 ^ (c >>> 1);
else
c = c >>> 1;
}
crc_table[n] = c;
}
}

private static int update_crc(byte[] buf, int nStart, int nLen) ...{
int c = 0xffffffff;
int n;

if (crc_table == null) ...{
make_crc_table();
}

for (n = nStart; n < nLen + nStart; n++) ...{
c = crc_table[(c ^ buf[n]) & 0xff] ^ (c >>> 8);
}
return c;
}

/** *//**
* @功能: 生成CRC校验码
* @参数: byte[] buf数据区域<br>int nStart起始位置<br>int nLen计算长度<br>
* @返回值: int CRC校验码
* */

public static int checksum(byte[] buf, int nStart, int nLen) ...{
return update_crc(buf, nStart, nLen) ^ 0xffffffff;
}
}