【问题标题】:What is the limiting factor in loading images in Android?在 Android 中加载图像的限制因素是什么?
【发布时间】:2014-10-06 08:10:12
【问题描述】:

所以我在这里真的很困惑。与我合作的设计师希望为 Android 平板电脑提供高质量的图像(png 文件),但游戏也为功能较弱的设备提供了较小的图像。我认为堆上的内存量将是确定要使用哪组图像的指标,使用Runtime.getRuntime().maxMemory() - Runtime.getRuntime().totalMemory()。不过,情况似乎并非如此。在 BlueStacks 上,它可以很好地加载高质量的图像,它有大约 40,000,000 字节。设计师的 Galaxy Nexus 为一些较大的图像设置了黑匣子(我理解这是因为加载图像的内存不足),但他的 Galaxy Nexus 有大约 50,000,000 个可用字节,甚至比 BlueStacks 还要多。

那么限制因素是什么?还有一个相关的问题是,为什么有些手机游戏具有令人印象深刻的视觉质量,但我却无法加载一些图像?我做错了什么?

请注意,我使用的是 AndEngine,下面是我如何加载图像的示例。

BuildableBitmapTextureAtlas resetTA = new BuildableBitmapTextureAtlas(this.getTextureManager(), 310 / d, 190 / d,
            TextureOptions.BILINEAR);
    resetTR = BitmapTextureAtlasTextureRegionFactory.createTiledFromAsset(resetTA, this, "gfx/" + lowres + "reset.png", 1, 1);

    try
    {
        resetTA.build(new BlackPawnTextureAtlasBuilder<IBitmapTextureAtlasSource, BitmapTextureAtlas>(0, 0, 0));
        resetTA.load();
    }
    catch (TextureAtlasBuilderException e)
    {
        Debug.e(e);
    }

Galaxy Nexus 中未加载的图像之一是 2320x464 的 sprite sheet png 文件。

【问题讨论】:

  • 您想要的文件大约是 4MB 的堆空间,并且可能没有一个 4MB 的空间块:commonsware.com/blog/2014/06/16/art-garbage-collection.html
  • 一般来说,您应该考虑到您的内存非常有限,并以这种方式编写您的代码。许多设备根本没有内存,即使是中型 PC 也可能包含。每个应用程序都与其他应用程序和 Android 本身共享内存。我认为监控运行时内存不会给你太多帮助。加载时,您需要确保有良好的样本大小——当它只进入缩略图大小的视图时,读取 4MB 的图像是没有意义的。在此处阅读 Android 指南中的高效位图以获取真实信息 - developer.android.com/training/displaying-bitmaps/index.html
  • 过去我在 AndEngine 中遇到过不是 2^n 尺寸的大图像的问题。不确定这在以后的版本中是否仍然是一个问题,因为我几个月没有使用 AndEngine。
  • 您还应该考虑比例和投影等因素。如果只是将其投射到远处,则无需加载高质量的图像,图像质量的下降不会很明显。仅在任何给定时刻加载您需要的确切尺寸是最佳的。

标签: android andengine


【解决方案1】:

这里有两个限制因素。首先是堆内存。要为您的应用程序找到可用的堆,您可以使用 Runtime 类的方法,但这会告诉您应用程序在完全崩溃之前可以使用的最大内存。可以通过以下方式找到您的应用在 Android 中应遵守的限制:

ActivityManager am = (ActivityManager) getSystemService(ACTIVITY_SERVICE);
int memoryClass = am.getMemoryClass();
Log.d("MyTag", "Heap:  + Integer.toString(memoryClass));

第二个是GL_MAX_TEXTURE_SIZE 值,它限制给定设备的方形纹理的最大尺寸。这可能会有所不同,但现在的最小值似乎是 2048,因此您的纹理可以大到 2048x2048 像素。但唯一的建议是尺寸必须大于屏幕尺寸,实际尺寸由手机制造商决定。

我想你可以用下面的代码找出大小:

int[] maxTextureSize = new int[1];
GLES20.glGetIntegerv(GLES20.GL_MAX_TEXTURE_SIZE, maxTextureSize, 0);
Log.d("MyTag", "GL_MAX_TEXTURE_SIZE: " + Integer.toString(int[0]));

游戏可以在将大纹理分割成更小的纹理之前拥有令人印象深刻的图形,只加载需要的内容并尽可能多地重复使用。我制作了一款游戏,其中某些关卡通过 256x256 块组装而成,使得游戏即使在全高清平板电脑上也清晰可见。这些碎片分布在几个 2048x2048 纹理上。

【讨论】:

    猜你喜欢
    • 2012-02-01
    • 1970-01-01
    • 2016-08-13
    • 2017-02-23
    • 2013-12-19
    • 1970-01-01
    • 2013-03-06
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多