J2ME对PNG格式的支持很诡异--不校检CRC?

来源:互联网 发布:淘宝精装修 编辑:程序博客网 时间:2024/06/05 18:05

先看下面一张图片先

.

这是一张用PhotoShop生成的png图片.下面是它的原始数据.

上图选择的地方,就是主要要改的调色板数据块(PLTE chunk),关于PNG的规格在http://dev.gameres.com/Program/Visual/Other/PNGFormat.htm这里有说明,中文的.

大家发现这张图片仅用了两种颜色,红和白.所以在PLTE(50 4C 54 45)后看到FF FF FF FF 00 00三个字节为一种颜色.这里就是白和红.最后的四位(EB 5A E7 93)就是CRC码.如果将FF 00 00 改成00 FF 00.即把红色改成绿色.用ACDSee发现打不开图片.提示"原始数据格式无法识别"因为这里还需要重新生成CRC.

最下面是生成CRC码的算法,验证了很多次,应该没错的.虽然对CRC具体原理还不够理解.一开始我以为只需传FF FF FF 00 FF 00这六个字节就可以.在这里失败了很多次.才反复验证了我的CRC算法.后来在网友写的图片淡入处理的程序中,才发现原来是还要包含前面8的八个字节.于是满怀欣喜的把这14个字节传进去,生成出1C 62 F5 FE.改到图片里面,用ACDSee打开可依旧提示"原始数据格式无法识别".我就纳闷了.为什么网友写的程序可以正常显示图片呢?难道J2ME没有校检CRC码.于是我索性把程序中更新CRC的代码给注释掉.发现程序真的正常运行.很大打击因为花了很多时间在检查自己的代码上面.

如上图. 虽然觉得很奇怪不过,想想也对.J2ME的程序本来就资源紧张.对于仅用来显示的图片不校检CRC可以省下一些时间.所以J2ME不校检CRC的做法是可以理解的.但我更奇怪的是很多程序里面都有更新CRC码.甚至都生成错.比如上图的程序.

startPos就是数据块数据的开始位置.-8就包含了长度和数据块类型码.这样生成的CRC码是错的.所以ACDSee提示错误.难道还有很多人不知道J2ME不校检CRC.可惜没有J2ME的源码可以看

后来我在http://www.w3.org/TR/PNG/#5Chunk-layout才发现正确的CRC是用数据块类型码+数据块数据来生成的.

 

终于成功,改成绿色相应的CRC码是C6 E6 2E 0C

  1. //生成CRC码
  2.     public int creatCRC(byte[] data ,int start, int length){
  3.         long crc=0xFFFFFFFFL;
  4.         for(int i=start;i<length;i++){
  5.             crc=(crcTable[(int)((crc^data[i] )& 0xFF)]^(crc>>8));
  6.         }
  7.         return (int)(crc^0xFFFFFFFF);
  8.     }
  9.     
  10.     
  11.     static long poly=0xEDB88320L;
  12.     //  建立CRC校验查找表
  13.     long crcTable[];
  14.     public void createTable(){
  15.         crcTable=new long[256];
  16.         long crc;
  17.         for(int i=0;i<256;i++){
  18.             crc=(long)i;
  19.             for(int j=0;j<8;j++){
  20.                 if((crc0x1)==1)
  21.                     crc=poly^(crc>>1);
  22.                 else
  23.                 crc>>=1;
  24.             }
  25.             crcTable[i]=crc;
  26.         }
  27.     }