0

我想从我的应用程序发送传真。传真文档的分辨率为 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 个字节),因为传真页面无论如何都是单色的。我需要这个分辨率,并且我需要访问像素进行编码。

什么是最好的方法?

4

3 回答 3

0

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

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

于 2013-05-02T15:53:59.373 回答
0

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

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

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

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

于 2013-05-02T15:48:33.977 回答
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);
}
于 2013-05-03T13:32:11.133 回答