PngTools及CRCUtil及BytesTools是网络上找的资源。 package lab.sodino.img; import java.io.IOException; import java.io.OutputStream; import javax.microedition.io.Connector; import javax.microedition.io.file.FileConnection; import javax.microedition.lcdui.Graphics; import javax.microedition.lcdui.Image; import javax.microedition.midlet.MIDlet; import javax.microedition.midlet.MIDletStateChangeException; /** @author sodino */ public class PngSaveTest extends MIDlet { protected void destroyApp(boolean unconditional) throws MIDletStateChangeException { // TODO Auto-generated method stub } protected void pauseApp() { // TODO Auto-generated method stub } protected void startApp() throws MIDletStateChangeException { Image img = createSaveImg(); byte[] data = PngTools.imageToPng(img, 8); try { FileConnection fc = (FileConnection) Connector.open("file:///root1/test.png"); if (fc.exists() == false) { fc.create(); } OutputStream os = fc.openOutputStream(); os.write(data); os.close(); fc.close(); } catch (IOException e) { e.printStackTrace(); } } private Image createSaveImg() { int imgWH = 200; Image img = Image.createImage(imgWH, imgWH); Graphics g = img.getGraphics(); g.setColor(0xffff00); g.fillRect(0, 0, imgWH, imgWH); g.setColor(0xff); g.drawString("SodinoTest", imgWH >> 1, imgWH >> 1, Graphics.HCENTER | Graphics.TOP); return img; } } package lab.sodino.img; import javax.microedition.lcdui.Image; public class PngTools { /** * png 色深 */ 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 &nb, sp; 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; } /** * change image to support alpha * * @param img source image * @param alphaColor color data ,such as : 0x00rrggbb * @return alpha image */ final static Image createAlphaImage(Image img, int alphaColor) { int w = img.getWidth(); int h = img.getHeight(); int[] imgData = new int[w * h]; img.getRGB(imgData, 0, w * h, 0, 0, w, h); for (int i = 0; i < imgData.length; i++) { if ((imgData[i] & alphaColor) == alphaColor) { imgData[i] = imgData[i] & alphaColor; } } Image alphaImage = Image.createRGBImage(imgData, w, h, true); return alphaImage; } static public String convertToString(double number) { String strRaw; String strResult; int signBase = 1; int signIndex = 1; int baseStartBit = -1; int baseDotBit = -1; int expSymbolBit = -1; int index = 0; int i; int bitCount; // Just for test // strRaw = "+123456789.123456789E-5"; // strRaw = "-123456789.123456789E+5"; // strRaw = "123456789.123456789E5"; // strRaw = "-123456789.123456789E15"; // strRaw = "-123456789.123456789E9"; // strRaw = "+123456789.123456789E-15"; // strRaw = "+123456789.123456789E-9"; // strRaw = "123E10"; // strRaw = "123E-10"; // strRaw = "123E-2"; // strRaw = "123"; // strRaw = "123.0"; strRaw = Double.toString(number); strResult = new String(); bitCount = strRaw.length(); System.out.println("strRaw = " + strRaw); for (i = 0; i < bitCount; i++) { if (strRaw.charAt(i) == '+') { // Do nothing; } else if (strRaw.charAt(i) == '-') { if (baseStartBit == -1) { signBase = -1; } else if (expSymbolBit != -1) { signIndex = -1; } else { return null; // the format of double number is illegal. } } else if (strRaw.charAt(i) == 'E' || strRaw.charAt(i) == 'e') { if (expSymbolBit != -1) { return null; } expSymbolBit = i; } else if (strRaw.charAt(i) == '.') { if (baseStartBit == -1 || expSymbolBit != -1) { return null; // the format of double number is illegal } baseDotBit = i; } else { if (baseStartBit == -1) { baseStartBit = i; } else if (expSymbolBit != -1) { index = index * 10 + Character.digit(strRaw.charAt(i), 10); } } } if (baseStartBit == -1) { return null; } if (signBase == -1) { strResult += "-"; } if (expSymbolBit == -1) { strResult = strRaw; } else { if (signIndex == 1) { int baseDecimalBits; if (baseDotBit == -1) { baseDecimalBits = 0; } else { baseDecimalBits = expSymbolBit - baseDotBit - 1; } if (baseDecimalBits >= index) { if (baseDotBit == -1) { strResult = null; } else { strResult += strRaw.substring(baseStartBit, baseDotBit); strResult += strRaw.substring(baseDotBit + 1, baseDotBit + 1 + index); strResult += "."; strResult += strRaw.substring(baseDotBit + 1 + index, expSymbolBit); } } else { if (baseDotBit == -1) { strResult += strRaw.substring(baseStartBit, expSymbolBit); } else { strResult += strRaw.substring(baseStartBit, baseDotBit); strResult += strRaw.substring(baseDotBit + 1, expSymbolBit); } for (i = 0; i < index - baseDecimalBits; i++) { strResult += "0"; } } } else if (signIndex == -1) { int baseIntegerBits; if (baseDotBit == -1) { baseIntegerBits = expSymbolBit - baseStartBit; } else { baseIntegerBits = baseDotBit - baseStartBit; } if (baseIntegerBits > index) { if (baseDotBit == -1) { strResult += strRaw.substring(baseStartBit, expSymbolBit - index); strResult += "."; strResult += strRaw.substring(expSymbolBit - index, expSymbolBit); } else { strResult += strRaw.substring(baseStartBit, baseDotBit - index); strResult += "."; strResult += strRaw.substring(baseDotBit - index, baseDotBit); strResult += strRaw.substring(baseDotBit + 1, expSymbolBit); } } else { strResult += "0."; for (i = 0; i < index - baseIntegerBits; i++) { strResult += "0"; } if (baseDotBit == -1) { strResult += strRaw.substring(baseStartBit, expSymbolBit); } else { strResult += strRaw.substring(baseStartBit, baseDotBit); strResult += strRaw.substring(baseDotBit + 1, expSymbolBit); } } } else { strResult = null; } } System.out.println("***pngTools-convertToString(double):strResult = " + strResult); return strResult; } } package lab.sodino.img; public class CRCUtil { private static int[] crc_table; private static void make_crc_table() { int c; int n; int 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 = -306674912 ^ (c >>> 1); } else { c = c >>> 1; } } crc_table[n] = c; } } private static int update_crc(byte[] buf, int nStart, int nLen) { int c = -1; int n; if (crc_table == null) { make_crc_table(); } for (n = nStart; n < nLen + nStart; n++) { c = crc_table[(c ^ buf[n]) & 255] ^ (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) ^ -1; } } package lab.sodino.img; public class BytesTools { static int bytes2int(byte[] b) { //byte[] b=new byte[]{1,2,3,4}; int mask = 0xff; int temp = 0; int res = 0; for (int i = 0; i < 4; i++) { res <<= 8; temp = b[i] & mask; res |= temp; } return res; } static byte[] int2bytes(int num) { byte[] b = new byte[4]; int mask = 0xff; for (int i = 0; i < 4; i++) { b[i] = (byte) (num >>> (24 - i * 8)); } return b; } /** */ /** * @鍔熻兘: 灏嗕竴涓猧nt鍊艰浆涓篵yte鏁扮粍 * @?傛暟: int nNum 瑕?杞殑int鍊? * @杩斿洖鍊? byte[] bytesRet 杞?庣殑byte鏁扮粍 */ public static byte[] intToBytes(int nNum) { byte[] bytesRet = new byte[4]; bytesRet[0] = (byte) ((nNum >> 24) & 255); bytesRet[1] = (byte) ((nNum >> 16) & 255); bytesRet[2] = (byte) ((nNum >> 8) & 255); bytesRet[3] = (byte) (nNum & 255); 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++] & 255) << 24); retInt += (bNum[nStartPos++] & 255) << 16; retInt += (bNum[nStartPos++] & 255) << 8; retInt += bNum[nStartPos] & 255; return retInt; } /** * @鍔熻兘: 灏嗕竴涓狪NT鐨勮浆涓篵yte鏁扮粍?庤拷鍔犲埌鎸囧畾鏁扮粍?? * @?傛暟: byte[] bDes杩藉姞鐩爣<br>int bSrc瑕?杩藉姞鐨刬nt * @杩斿洖鍊? byte[] 杩藉姞?庣殑瀛楄妭鏁扮粍 */ public static byte[] appendBytes(byte[] bDes, int bSrc) { return appendBytes(bDes, new byte[]{(byte) bSrc}); } /** */ /** * @鍔熻兘: 灏嗕竴涓猙yte 鏁扮粍杩藉姞鍒版寚瀹氭暟缁勫?? * @?傛暟: 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; } /** */ /** * @鍔熻兘: 鎴?栨寚瀹歜yte 鏁扮粍涓殑瀛楄妭鏁扮粍 * @?傛暟: 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; } }