【问题标题】:Bitmap too large - Out of Memory?位图太大 - 内存不足?
【发布时间】:2012-07-27 05:29:11
【问题描述】:

我正在尝试在我的设备上为某个人的一些动作设置动画。我创建了一个精灵表,最终为 1.23Mb。图像尺寸为 5000 x 1500 像素。工作表有 8 行,每行都是它自己的操作。 (走,鞠躬,跳……)。最长的动作是 32 张图像。所以图像基本上是 32 列,8 行。所以,现在我加载它:

只要我这样做:

private Bitmap bmp;
bmp = BitmapFactory.decodeResource(getResources(), R.drawable.myImage);

我收到一个错误:

线程 [ main](挂起(OutOfMemoryError 异常))
BitmapFactory.decodeResource(Resources, int, BitmapFactory$Options) 行:385 BitmapFactory.decodeResource(Resources, int) 行:404
GameView.(Context) 行:25 FightActivity.onCreate(Bundle) 行:13 FightActivity(Activity).performCreate(Bundle) 行:4465
Instrumentation.callActivityOnCreate(Activity, Bundle) 行:1049
ActivityThread.performLaunchActivity(ActivityThread$ActivityClientRecord, 意图)行:1920
ActivityThread.handleLaunchActivity(ActivityThread$ActivityClientRecord, Intent) 行:1981 ActivityThread.access$600(ActivityThread, ActivityThread$ActivityClientRecord, Intent) 行:123
ActivityThread$H.handleMessage(Message) 行:1147
ActivityThread$H(Handler).dispatchMessage(Message) 行:99 Looper.loop() 行:137 ActivityThread.main(String[]) 行:4424
Method.invokeNative(Object, Object[], Class, Class[], Class, int, boolean) 行:不可用 [本机方法] Method.invoke(Object, 对象...) 行:511 ZygoteInit$MethodAndArgsCaller.run() 行:784
ZygoteInit.main(String[]) 行:551 NativeStart.main(String[]) 行:不可用[本机方法]

我是否受限于某个文件大小?看起来很奇怪?如果是这样,我唯一的选择是将精灵分割成单独的“动作”图像,而不是在一个大精灵表中的每行一系列动作图像?

希望有人可以帮助新手。

【问题讨论】:

  • 澄清 - 您是否要制作 32*5k x 8*1.5k = 19.2 亿像素的图像?导致 32 位进程崩溃没有问题。
  • 不,抱歉。该图像大小为 5,000 x 1,500 像素,文件大小为 1.23 MB。该图像包含 8 行“帧”,即每行 32 帧。因此,它包含 32x8 的图像,然后我将其显示。因此,它包含 256 个小图像。
  • 文件大小不是问题,你的分辨率是
  • 我第一次创建图像时,它只有 5 行 32 张图像,文件大小为 0.8 Meg。它工作得很好。然后我在文件中添加了 3 行图像。相同的分辨率.. 但现在,更大。而现在它失败了。所以,因为我已经到了 1500 到 5000(当它只有 5 行时可能是 3000 到 1500),这就是问题所在?这是个问题。 :(
  • 想法:1) 检查格式 - 你需要 32 位还是 8 位。2) 使图像更小[将其拆分或缩小]。 3) 为什么不是两个分辨率的幂?

标签: java android


【解决方案1】:

为角色中的每个动画制作一个单独的 spritesheet,保存对常见动画的引用,并根据需要加载。这足够灵活,您的动画不会滞后,除非您需要从内存中加载位图更改,例如当您从运行更改为空闲或其他时,(尽管这两个足够常见,您可以将它们保存在很长一段时间的记忆)。

增加 VM 堆大小只是部分解决方案,如果您持有如此大的位图,许多设备将无法获得所需的堆大小。就像他们上面所说的,磁盘上的图像文件大小仅对于在 Google Play 上部署应用程序很重要(用户将下载更少),但在 ram 上,图像是完全原始的,这意味着每个像素都很重要(例如:一个完全红色的 128x128 位图需要与完全彩色的空间相同,具有完全相同的颜色深度)。

我为您提出了一个解决方案,它使用这个很棒的软件(我与它没有任何关系,除了我自己使用它,它很棒)可以立即创建您的 spritesheets 并以各种格式导出坐标供您使用。 TexturePacker.

【讨论】:

    【解决方案2】:

    根据图像的复杂性,另一个答案可能是使用矢量图形。有许多库具有不同级别的文档和许可要求。

    示例; http://www.andengine.org/

    https://play.google.com/store/apps/details?id=org.anddev.farmtower.eco(本游戏使用的AndEngine)

    【讨论】:

      【解决方案3】:

      一个简单的计算就能得到答案。假设每像素 32 位,则有 ((5000x1500) 像素) * (每像素 32 位) / (每字节 8 位) / (1024 * 每 Mb 1024 位) = 28MB。

      我在 Google 上进行了搜索,发现不同版本的 Android 和不同手机的默认堆大小从 16MB 到 32MB 不等。我想我认为 24​​MB 是最常见的。因此,您很可能只是因为图像内存不足。查看这篇文章以了解您的堆大小:https://stackoverflow.com/a/9428660/1448071

      编辑:似乎没有增加 Android 虚拟机堆大小的好方法。有一个带有 setMinimumHeapSize 函数的 VMRuntime.getRuntime() 函数,这里描述了 Android: how to increase heap size at runtime?。但它似乎正在被弃用。我建议你拆分你的精灵。

      【讨论】:

      • 等一下 - 文件大小是 1.23 兆字节...不是 28 兆字节。这是一个小文件。
      • 您的文件是 bmp 文件还是 png/jpeg/gif/tiff?如果是后者,你的图片会被大大压缩,但是当你作为位图加载时会被解压到全尺寸。
      • 这是一种 BMP 文件格式。所以,您认为可能在内存中,Android 正在“解压缩”您上面提到的文件,并且它使用 28MB 的内存来存储图像,在磁盘上是 1.23Mb?
      • 是的。快速浏览一下 Wikipedia 并学到了一些新东西 :) “索引彩色图像可以使用 4 位或 8 位 RLE 或 Huffman 1D 算法进行压缩。OS/2 BITMAPCOREHEADER2 24bpp 图像可以使用 24 位 RLE 算法进行压缩。 "所以很可能你的 BMP 被压缩了。
      • 哦,混蛋。所以,我唯一的选择是将这些行分成单独的图像,比如胶片。我希望有一个精灵表。我从来没有做过精灵动画(或者Java,或者Android开发,就此而言),所以我不确定这样做的标准是什么。维护一个文件会更容易和更易于维护。妈的……
      【解决方案4】:

      您需要增加 VM 堆大小。我很想为你获取链接,但我想这是我能做的最好的 atm -Increase heap size in Java

      【讨论】:

        猜你喜欢
        • 2011-09-01
        • 2016-08-23
        • 2023-03-15
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-10-04
        • 2013-05-08
        • 1970-01-01
        相关资源
        最近更新 更多