创建位图时OutOfMemoryError

时间:2013-05-01 23:24:32

标签: android encoding bitmap fax

我想从我的应用发送传真。 传真文档的分辨率为1728 x 2444像素。 所以我创建了一个位图,添加文本和/或图片并将其编码为CCITT(Huffman):

Bitmap image = Bitmap.createBitmap(1728, 2444, Config.ALPHA_8);
Canvas canvas = new Canvas(image);
canvas.drawText("This is a fax", 100, 100, new Paint());
ByteBuffer buffer = ByteBuffer.allocateDirect(image.getWidth() * image.getHeight());
image.copyPixelsToBuffer(buffer);
image.recycle();
encodeCCITT(buffer, width, height);

这适用于我的Galaxy SII(64 MB堆大小),但不适用于模拟器(24 MB)。在创建第二个传真页面后,我在分配缓冲区时得到“4223232字节外部分配对于此过程来说太大了...... java.lang.OutOfMemoryError”。

我已经将ARGB_8888(每像素4个字节)的颜色深度减少到ALPHA_8(1个字节),因为无论如何传真页面都是单色的。 我需要这个分辨率,我需要访问像素进行编码。

最好的方法是什么?

3 个答案:

答案 0 :(得分:0)

Android不支持1-Bpp位图,而Java堆大小限制为24/32 / 48MB是Android的一部分。无论有多少RAM,真实设备都不能分配超过Java堆限制。似乎只有两种可能的解决方案:

1)在Java堆的限制范围内工作。

2)使用本机代码(NDK)。

在本机代码中,您可以分配设备的整个可用RAM。唯一的缺点是你需要编写自己的代码来编辑和编码你的位图。

答案 1 :(得分:0)

除了BitBank已经很好的答案之外,如果您希望垃圾收集器实际清理Bitmap的引用,则必须使引用为空。该方法的The documentation表明:

  

这是一个高级调用,通常不需要调用,因为   正常的GC过程将在没有更多时释放这个内存   对此位图的引用。

答案 2 :(得分:0)

而不是将所有像素复制到ByteBuffer,您可以逐步复制。这里有一个int []数组。所以,你需要更少的内存:

int countLines = 100;
int[] pixels = new int[width * countLines];
for (int y = 0; y < heigth; y += countLines) {
    image.getPixels(line, 0, width, 0, y, width, countLines);
    // do something with pixels...
    image.setPixels(line, 0, width, 0, y, width, countLines);
}