【问题标题】:Issues with Image loading in J2ME applications on Motorola phones摩托罗拉手机上 J2ME 应用程序中的图像加载问题
【发布时间】:2010-09-20 21:09:54
【问题描述】:

在 J2ME 应用程序中加载图像的标准方法是使用 Image.createImage 方法,推荐的图像格式是 PNG。

现在,J2ME 规范没有对该方法的实现或图像在内存中的表示作出任何限制,因此,每个供应商都有不同的实现。

尤其是摩托罗拉有这个非常糟糕的实现,其中 PNG 在图像创建时被完全解码为 ARGB 字节数组。这意味着尺寸为 176x208 的 8K png 占用大约 170K 的峰值内存来加载,而 Image 对象本身使用的内存大约为 145K!在诺基亚、索尼爱立信等其他手机上,相同的图像只需要大约 16K 即可加载和存储在内存中。我不知道他们使用了哪些智能优化,但出于某种难以理解的原因,摩托罗拉的 JVM 没有。

这对我的 J2ME 应用程序造成了严重破坏,几乎不可能在摩托罗拉手机上运行一个像样的版本。我尝试了各种解决方法,例如使用图像的 gzip'd ARGB 字节数组并在绘制过程中对其进行放气,但这会导致绘制速度减慢 10 倍!

有人知道这个问题的解决方法吗? J2ME 的开源 PNG 图像解码器具有摩托罗拉所缺乏的智能?或者是否可以对 PNG 图像进行一些操作以减少其内存占用? (我目前使用索引模式 PNG)欢迎任何指针..

高丽

【问题讨论】:

  • 您使用的是哪款手机?我不熟悉任何实际以每像素 4 个字节存储图像的摩托罗拉手机。通常是每个像素 2 个字节。

标签: java java-me png motorola


【解决方案1】:

索尼爱立信的一件事。不要给他们太多的信任。它们在加载图像时也会占用 (image_width x image_height x bytes_per_pixel) 内存。

来自 SE J2ME 开发者文档,“所有图像都以每像素 16 位的 RGB 格式存储在手机内存中,可能具有每像素 1 位或 8 位的 Alpha 通道。 " 所以,至少 2 个字节。不同之处在于索尼爱立信手机(我不能代表诺基亚)有一个单独的内存块,用于在将图像加载到堆中之前先填充图像(您可以通过使用 Runtime.getRuntime().freeMemory 包装负载来查看这一点()...堆大小只会增加几个字节,这是新对象的大小)。

这并不是在为摩托罗拉辩护,因为我确实在从 SE 手机移植到摩托罗拉时遇到了麻烦,但这并不是因为 SE 能够找到一种以更优化的方式将图像存储在堆中的方法。摩托罗拉只是将所有内容都存储在堆中,这就是您用完更快的原因。

较小的图像是一个好主意,不仅在解码器部分,而且从堆碎片的角度来看。它将允许图像适合较小的内存块而不是大的连续块。

【讨论】:

  • 您对索尼爱立信的看法是正确的。诺基亚也是如此。
【解决方案2】:

嗯,在我看来,如果在创建图像时所有图像格式都立即解码为 ARGB 数组,那么您唯一真正能做的就是为您将用于显示的内存量创建一个上限屏幕上的东西。

您可以创建一个图像缓存,该缓存将知道每个图像为该特定设备使用了多少堆内存,加载和卸载图像是需要的。当然,这意味着依赖 Grabage Collector 可能无法让您的应用程序保持响应。

缓存管理可能需要在专用线程中进行。

如果您的应用程序屏幕足够静态而不需要太多动画,则在任何给定时间只保留一个屏幕的图像加载可能会起作用。

还请记住,MIDP 画布通常不会自行重置。如果您使用 2 次不同的 Canvas.paint() 调用在屏幕的 2 个不同区域绘制 2 个不同的图像,您应该能够在实际图像对象被垃圾收集后很长时间保持显示这两个图像不要在它们上面画任何东西。

从纯粹的商业角度来看,您需要能够告诉您的客户,某些手机的 Java 实现太差,以至于您不会支持它们。

【讨论】:

    【解决方案3】:

    【讨论】:

    • PNG 是唯一受 J2ME 规范保证支持的格式。其他任何事情都不能依赖。我听说过一个摩托罗拉支持 JPEG 而另一个相同的摩托罗拉不支持它,两者都声称是相同的固件版本。 J2ME 是一个雷区。
    • 没错,但如果有可能拥有自己的 GIF 解码器并使用它来显示 GIF 图像,它可能会成功。我会试一试。谢谢 mugafuga。
    • 好吧,原来不是解码过程,而是摩托罗拉 jvm 的“本机图像格式”导致问题 - 即,这里的本机图像格式是一个原始 ARGB 整数数组,导致一张 176x208 的图像,大小为 176*208*4=143kb。所以,不幸的是,GifDecoder 没有帮助:(
    【解决方案4】:

    摩托罗拉开发者论坛建议您将较大的图像剪切成较小的条带,然后一次性加载这些较小的条带,而不是加载整个大图像。请注意,这不会减少图像的内存占用。那仍然需要所有条带的总和(宽度*高度*每像素字节数)。但它确实减少了解码 png 图像并加载它所需的内存。所以这就是我现在正在做的事情。它帮助了一些人。但是整体内存使用仍然是个问题。

    【讨论】:

      【解决方案5】:

      更好的解决方案是将 ARGB 存储为数据(使用某种索引来压缩它),具有更改调色板等/无 PNG Header/ 的优点。而不是存储不同的PNG图像并使用createImage函数来创建图像。

      【讨论】:

        【解决方案6】:

        减少 png 图像的一种方法是通过像 png gauntlet 这样的程序运行它们 减小它的大小。

        【讨论】:

          猜你喜欢
          • 2010-09-08
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2016-04-09
          • 1970-01-01
          相关资源
          最近更新 更多