【发布时间】:2014-10-26 16:31:12
【问题描述】:
首先是重要的代码行:
Bitmap bitmap = BitmapFactory.decodeResource(context.getResources(), getDrawableForLvl(drawable));
int []pixels = new int[bitmap.getWidth()*bitmap.getHeight()];
bitmap.getPixels(pixels, 0, bitmap.getWidth(), 0, 0, bitmap.getWidth(), bitmap.getHeight());
//..
pixels = null; // please gc remove this huge data
System.gc();
所以我正在开发一个具有多个级别的 Android 应用(游戏)。每个级别都是我在级别开始时作为位图加载的图像。然后我必须分析每个像素(第 3 行)。为此,我创建了一个数组(第 2 行)。图像为 1280x800,因此数组的大小超过一百万个整数。这里没有问题,因为它是一个局部变量,它应该在方法返回时被销毁。但它是 java,所以它不是 -.- 取决于设备,垃圾收集器是否及时运行得足够快。因此,当用户非常快速地启动和关闭关卡时,它会在第 2 行产生 java.lang.OutOfMemoryError。我猜是因为旧数组还没有/没有被删除,现在我有多个填充内存。
我可以使数组成为静态成员。因此,它创建一次并且始终可用。那么不可能有它的多个实例。但我认为这是一种糟糕的编码风格,因为它在不需要时也可用 (4 MB)。
我不需要同时使用所有像素。我将图像分割成一百多个矩形,所以我可以使用更小的数组并用像素一个接一个地填充它。但是我对方法参数can someone help me here的理解有问题? 还有一种方法可以只获取one pixel at position x,y,但我想一百万个函数调用很慢。
有人有更好的主意吗?在java中没有办法强制对象超出内存,是吗?
更新1: 正如 vzoha 建议的那样,只获得第一季度:
int []pixels = new int[bitmap.getWidth()/2*bitmap.getHeight()/2];
bitmap.getPixels(pixels, 0, bitmap.getWidth(), 0, 0, bitmap.getWidth()/2, bitmap.getHeight()/2);
给出一个 ArrayIndexOutOfBound。我认为函数调用只是获取第一季度的像素,但仍希望完整大小的数组和其他字段保持不变。
Update2:我想我可以逐行进行(第一季度半行半行):
int []pixels = new int[bitmap.getWidth()/2*bitmap.getHeight()/2];
for(int row = 0; row < bitmap.getHeight()/2; ++row)
bitmap.getPixels(pixels, bitmap.getWidth()/2, bitmap.getWidth(), 0, row, bitmap.getWidth()/2, 1);
但是,当我为 20x10 部分执行此操作时,它并不比单独获取每个像素好多少。好吧,它要好得多,但是该方法仍然应该能够通过一次调用来做到这一点,不是吗?我只是没有得到这个“步幅”参数:“在行之间跳过的像素 [] 中的条目数(必须 >= 位图的宽度)。可以是负数。” >= width 怎么会是负数?
【问题讨论】:
-
我也遇到了位图和 outOfMemoryError 的问题。尝试观察 DDMS 中的堆是否在增加,或者在不使用位图后减少。对我来说,帮助拨打了
bitmap.recycle(); bitmap = null;,但我没有使用getPixels。试试看,让我记下。 -
好吧,错误在于巨大数组的声明。但我猜 Bitmap 的内存大小应该更大,所以这是一个很好的建议。当一个关卡关闭时,我会尝试回收位图,所以它应该是下一个关卡的更大的可用内存缓冲区。 bitmap.recycle 是我需要的数组,因为我不能依赖垃圾收集器来运行它。
-
我刚刚注意到:回收不会释放像素数据,它只是允许它被垃圾收集。所以这并没有什么区别,因为我只在放弃保存位图的对象时才使用回收,所以无论我是否调用回收,它都可用于 GC。
-
好的,对我来说,在某些设备上也有帮助
imageView.setImageDrawable(null);,但这不是你的问题。正如您所说,您可以将bitmap.getPixels(pixels, 0, bitmap.getWidth(), 0, 0, bitmap.getWidth(), bitmap.getHeight());用于部分图像。我认为,第一季度应该是:bitmap.getPixels(pixels, 0, bitmap.getWidth(), 0, 0, bitmap.getWidth()/2, bitmap.getHeight()/2);,第二季度:bitmap.getPixels(pixels, 0, bitmap.getWidth(), bitmap.getWidth()/2, 0, bitmap.getWidth(), bitmap.getHeight()/2);等等。 -
这就是我已经尝试过的,因为它完全有道理,但它不起作用。 (我将其添加到我的问题描述中)
标签: android arrays bitmap pixel