2013-05-01 66 views
0

我想從我的應用程序發送傳真。 傳真文檔的分辨率爲1728 x 2444像素。 所以我創建位圖,添加文本和/或圖片,並將其編碼爲CCITT(霍夫曼):創建位圖時OutOfMemoryError

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個字節)的顏色深度,因爲無論如何傳真頁面都是單色的。 我需要這個分辨率,我需要訪問像素進行編碼。

什麼是最好的方法?

回答

0

Android不支持1-Bpp位圖,並且Java堆大小限制爲24/32/48MB是Android的一部分。無論他們擁有多少RAM,實際設備都不能分配超過Java堆的限制。似乎只有兩種可能的解決方案:

1)在Java堆的限制內工作。

2)使用本機代碼(NDK)。

在本機代碼中,您可以分配設備的全部可用RAM。唯一的缺點是您需要編寫自己的代碼來編輯和編碼位圖。

0

除了BitBank已經很好的答案之外,如果您希望垃圾收集器實際清理您的位圖的引用,則必須將該引用歸爲空。 The documentation該法規定:

這是一種先進的呼叫,並且通常不需要叫,因爲 正常GC過程中會釋放此內存時,有沒有更多的 引用此位圖。

+0

我解決了它與重用Bitmap對象。使用recycle()或設置爲null不起作用。 – almisoft 2013-05-02 19:37:17

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); 
}