![]() |
|
|
深入理解png终极篇 在midp1.0上实现完美翻转 在midp1.0上实现翻转图片是一个老生长谈的话题了一直以来都没有完美的解决方案 以前的解决方法一直是* setClip and drawImage 方式模拟绘制像素来实现速度极慢 改进的方法又会有白底 总之约等于鸡肋 使一些动作游戏很难做到1.0上 现在我来实现在midp1.0上的完美翻转 怎么实现呢 大家都知道png的IDAT数据段存储了重要的像素信息如果能修改IDAT数据段实现翻转就易如反掌 IDAT数据段的数据是使用lz77压缩算法压缩过的如果在手机端解压在修改数据则会耗费很长的时间 2秒左右了其实lz77压缩算法还提供了一种无压缩的压缩方式如果我们可以创建无压缩的IDAT数据那 在手机端翻转图片就很快了但现在几乎没有软件能生成这样的png 于是我做了一个 png2png来解决这个 问题 http://www.j2medev.com/bbs/dispbbs.asp?boardID=17&ID=20692&page=1 如png2png.jar放于c:/png2png.jar 需要压缩 c:/test.png 输出文件为c:/test.png 压缩率为 不压缩 则运行命令为 java -jar c:/png2png.jar c:/test.png c:/test.png 0 这样输出的c:/test.png 就是不压缩IDAT的png了 虽然比压缩的png大很多但打包到jar里就和普通的png差不多大了甚至还小一些 在j2me端我用200行代码实现了水平垂直的4方向翻转 其中有一个public static Image createImage(String file, int flip);方法实现了翻转 其中flip 0 代表Sprite.TRANS_NONE, //0无翻转 这样做了一些简单修改使我的动画引擎完美呈现于midp1.0上 这实际上是一种以空间换时间的方法 此文献给广大被midp1.0折磨的人 public static byte[] getBytes(String file) throws IOException { public static Image createImage(String file, int flip) { off += 8; while (chunklen != 0) { chunklen = readInt(data, off); off += 4; chunktype = readInt(data, off); off += 4; if (chunktype == 1229472850) { _IHDR = off - 8; System.out.println("_IHDR = " + _IHDR); } else if (chunktype == 1347179589) { _PLTE = off - 8; System.out.println("_PLTE = " + _PLTE); } else if (chunktype == 1951551059) { _tRNS = off - 8; ; System.out.println("_tRNS = " + _tRNS); } else if (chunktype == 1229209940) { _IDAT = off - 8; System.out.println("_IDAT = " + _IDAT); } off += (chunklen + 4); i++; } width = readInt(data, _IHDR + 8); height = readInt(data, _IHDR + 12); System.out.println(width + " = " + height); Pixels = new byte[width * height]; for (int j = 0; j < height; j++) { System.arraycopy(data, _IDAT + 8 + 7 + 1 + (width + 1) * j, Pixels, width * j, width); } for (int m = 0; m < height; m++) { for (int n = 0; n < width; n++) { if (flip == 1) { data[_IDAT + 8 + 7 + 1 + m * (width + 1) + n] = Pixels[m * width + (width - 1 - n)]; } else if (flip == 2) { data[_IDAT + 8 + 7 + 1 + m * (width + 1) + n] = Pixels[(height - 1 - m) * width + n]; } else if (flip == 3) { data[_IDAT + 8 + 7 + 1 + m * (width + 1) + n] = Pixels[(height - 1 - m) * width + (width - 1 - n)]; } } } int adler = (int) adler32(1l, data, _IDAT + 8 + 7, (width + 1) * height); writeInt(data, _IDAT + 8 + 7 + (width + 1) * height, adler); writeCRC(data, _IDAT); Pixels = null; System.gc(); Image img = Image.createImage(data, 0, data.length); data = null; System.gc(); return img; } catch (Exception ex) { ex.printStackTrace(); } return null; } public static void writeInt(byte[] dst, int pos, int val) { public static int readInt(byte[] dst, int pos) { //读一个int public static void writeCRC(byte[] data, int chunkpos) { public static int[] crc_table; //CRC 表 mkc = 0xedb88320 ^ (mkc >>> 1); } else { mkc = mkc >>> 1; } } crc_table[mkn] = mkc; } } for (n = off; n < len + off; n++) { c = crc_table[(c ^ buf[n]) & 0xff] ^ (c >>> 8); } return c; } public static long adler32(long adler, byte[] buf, int index, int len) { long s1 = adler & 0xffff; while (len > 0) { s1 += buf[index++] & 0xff; s2 += s1; s1 += buf[index++] & 0xff; s2 += s1; s1 += buf[index++] & 0xff; s2 += s1; s1 += buf[index++] & 0xff; s2 += s1; s1 += buf[index++] & 0xff; s2 += s1; s1 += buf[index++] & 0xff; s2 += s1; s1 += buf[index++] & 0xff; s2 += s1; s1 += buf[index++] & 0xff; s2 += s1; s1 += buf[index++] & 0xff; s2 += s1; s1 += buf[index++] & 0xff; s2 += s1; s1 += buf[index++] & 0xff; s2 += s1; s1 += buf[index++] & 0xff; s2 += s1; s1 += buf[index++] & 0xff; s2 += s1; k -= 16; } if (k != 0) { do { s1 += buf[index++] & 0xff; s2 += s1; } while (--k != 0); } s1 %= BASE; s2 %= BASE; } return (s2 << 16) | s1; }
|