论坛首页 移动开发技术论坛

解决MiroEmulator中加载图片的Bug

浏览 3914 次
精华帖 (0) :: 良好帖 (0) :: 新手帖 (0) :: 隐藏帖 (0)
作者 正文
   发表时间:2007-09-08  
解决MiroEmulator中加载图片的Bug

作者:pandonix

日期:200798

版权声明:可以任意转载,转载时请务必以超链接形式标明文章原始出处和作者信息及本声明

原文地址:http://pandonix.iteye.com

前段时间一直在研究MiroEmulator(以下简称ME),这一个纯Java实现的J2me模拟器,支持AppletSwt以及Swing多个版本的模拟器。关于ME的介绍,请参考CleverPigMiroEmulator使用入门中文版:

http://www2.matrix.org.cn/resource/MicroEmulator_reference/MicroEmulator_applet_CN.html

ME下载地址:

http://www.microemu.org/

目前的最新版本为2.0.1

总的说来,ME已经实现了J2me大部分的类库,包括诸如NokiaUI等扩展包都已经实现。但是,遗憾的是,我在使用其运行第一个游戏就出现了问题,汗一个-_-

出现问题的大致情况为,启动游戏后,某张PNG图片没有加载成功,在屏幕中没有显示出来。

重新编译ME的源码,并启动游戏以后,发现抛出了如下的异常信息:

java.util.zip.ZipException: unknown compression method    at java.util.zip.InflaterInputStream.read(Unknown Source)    at java.io.BufferedInputStream.fill(Unknown Source)    at java.io.BufferedInputStream.read(Unknown Source)    at sun.awt.image.PNGImageDecoder.produceImage(Unknown Source)    at sun.awt.image.InputStreamImageSource.doFetch(Unknown Source)    at sun.awt.image.ImageFetcher.fetchloop(Unknown Source)

    at sun.awt.image.ImageFetcher.run(Unknown Source)

 

单从异常信息来看,MS是从Jar包中解压缩图片时出现问题。继续查找,发现出现问题的代码位于org.mircoemu.device.j2se.J2SEDeviceDisplay类中的private Image getImage(Inpustream is)函数之中。

       本人一向较懒,遇到郁闷的问题,总喜欢google&baidu来发泄-_- 一番“众里寻它”之后,在MEsf项目中,发现有人已经提出相同的问题,甚至有细心的用户,已经指出,只要PNG图片大小超过8K就会出现该问题。这也解释了,为何游戏启动时,其他图片加载正常的原因。正当欣喜遇到同道中人之时,却发现开发者并没有解决该问题,而且该问题已经作为bug提交到ME项目的bug列表中,到目前为止,尚未解决。

       给项目开发者barto写了封陈恳的求助信,可惜直到现在还没有回复(不用抱怨了,能开源就已经很不错了,呵呵)。这次,只能靠自己了-_-

       再次启动Eclipse,喝了N杯劣质咖啡之后,终于有了眉目:getImage(Inputstream is)是在getImage(String str)中被调用的,在此,PNG图片被读入,并初始化为Inputstream。调试之中发现,出问题的PNG图片,被初始化为Inputstream之后,大小保持正常,但是,getImage(Inputstream is)中,将Inputstream转化为byte数组之后,发现该图片对应的数组大小发生了变化,小于原来的大小。然而,对于那些可正常显示的PNG图片而言,这两处的打印出来的大小是一样大的。所以,可以肯定,是getImage(Inputstream is)中的转换部分代码出了问题。思考之后,决定采用ByteArrayOutputStream来转换byte数组。

修改后代码如下:

java 代码
  1.     private Image getImage(InputStream is)   
  2.             throws IOException   
  3.     {   
  4.         //这段读取时,出问题鸟   
  5. //      final int EXTEND = 1024;   
  6. //      byte[] imageBytes = new byte[1024];   
  7. //      int num;   
  8. //      int start = 0;   
  9. //      while ((num = is.read(imageBytes, start, imageBytes.length - start)) == EXTEND) {   
  10. //          byte[] newImageBytes = new byte[imageBytes.length + EXTEND];   
  11. //          System.arraycopy(imageBytes, 0, newImageBytes, 0, imageBytes.length);   
  12. //          imageBytes = newImageBytes;   
  13. //          start += EXTEND;   
  14. //      }   
  15. //         
  16. //      if (num != 0) {   
  17. //          byte[] newImageBytes = new byte[imageBytes.length - EXTEND + num];   
  18. //          System.arraycopy(imageBytes, 0, newImageBytes, 0, imageBytes.length - EXTEND + num);   
  19. //          imageBytes = newImageBytes;   
  20. //      }   
  21.         byte[] imageBytes = new byte[512];   
  22.         ByteArrayOutputStream bout = new ByteArrayOutputStream();   
  23.         int size = 0;   
  24.         while ((size = is.read(imageBytes)) > 0) {   
  25.             bout.write(imageBytes, 0, size);   
  26.         }   
  27.         imageBytes = bout.toByteArray();   
  28.         java.awt.Image image = Toolkit.getDefaultToolkit().createImage(imageBytes);   
  29.         ImageFilter filter;   
  30.         if (isColor()) {   
  31.             filter = new RGBImageFilter();   
  32.         } else {   
  33.             if (numColors() == 2) {   
  34.                 filter = new BWImageFilter();   
  35.             } else {   
  36.                 filter = new GrayImageFilter();   
  37.             }   
  38.         }   
  39.         FilteredImageSource imageSource = new FilteredImageSource(image.getSource(), filter);   
  40.         java.awt.Image resultImage = Toolkit.getDefaultToolkit().createImage(imageSource);   
  41.         // TODO not elegant solution, maybe use ImageObserver in image.getWitdth(..) instead   
  42.         MediaTracker mediaTracker = new MediaTracker(new java.awt.Canvas());   
  43.         mediaTracker.addImage(resultImage, 0);   
  44.         try {   
  45.             mediaTracker.waitForID(0);   
  46.         } catch (InterruptedException ex) {   
  47.             Logger.error(ex);   
  48.         }   
  49.         if (mediaTracker.isErrorID(0)) {   
  50.             throw new IOException();   
  51.         }   
  52.         return new J2SEImmutableImage(resultImage);   
  53.     }  

  

修改完成之后,再次运行原游戏,OK,原来不能加载的图片正常显示了。

题外话:

虽然ME已经开发的比较健全了,但是仍然不排除还存在着各种bug。在此之前,国内的gustzhang撰写的一系列文章,在ME0.9.1版本的基础上,对其作了大量的修改,有兴趣的朋友,也可以到他blog上看看:http://blog.sina.com.cn/u/1244846070ME项目源码采用maven管理,官方推荐使用maven将源码转化为eclipse工程,但是,我是真的受不了apache网站的速度,最终选择手动创建Eclipse工程。
   发表时间:2007-09-16  
楼主写的不错 
0 请登录后投票
论坛首页 移动开发技术版

跳转论坛:
Global site tag (gtag.js) - Google Analytics