首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 更多程式語言 >> 程式設計綜合問答

Android Bitmap.createBitmap 內存溢出 (OOM) 解決方案

     編輯:程式設計綜合問答

問題場景

調用 Bitmap.createBitmap(bitmap, 0, 0, width, height, matrix, true) 時頻繁拋出 java.lang.OutOfMemoryError。這通常發生在對大圖片進行旋轉、縮放、裁剪等變換操作時,因為該方法會在內存中創建一個全新的 Bitmap 副本,瞬間佔用雙倍內存。

解決思路

  1. 降低輸入圖片尺寸: 使用 BitmapFactory.Options.inSampleSize 在解碼階段就縮小圖片,避免將超大原圖載入內存。
  2. 避免創建副本,改用 Canvas 繪製: 不生成新 Bitmap,而是創建目標 Bitmap(可配置 inMutable=true),然後用 Canvas.drawBitmap(source, matrix, paint) 直接繪製變換後的圖像。這樣同一時間只有一張位圖在內存中。
  3. 使用 inBitmap 復用內存 (API 19+): 設置 options.inMutable = true 和 options.inBitmap 指向一個可復用的舊 Bitmap,減少 GC 壓力。
  4. 檢查矩陣操作必要性: 若只是簡單旋轉 90/180/270 度,可用 ExifInterface 讀取方向標籤,在繪製時處理,避免矩陣變換開銷。

代碼示例:Canvas 替代 createBitmap

// 目標尺寸
int targetW = bitmap.getWidth();
int targetH = bitmap.getHeight();

// 創建可變的目標 Bitmap (ARGB_8888 每像素 4 字節)
Bitmap target = Bitmap.createBitmap(targetW, targetH, Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(target);

// 設置變換矩陣
Matrix matrix = new Matrix();
matrix.postRotate(90); // 例如旋轉 90 度

// 直接繪製到目標 Bitmap,無中間副本
Paint paint = new Paint();
paint.setFilterBitmap(true); // 雙線性過濾,質量更好
canvas.drawBitmap(bitmap, matrix, paint);

// 如果原 bitmap 不再需要,可回收
// bitmap.recycle();

最佳實踐總結

「能不創建新 Bitmap 就不創建」。優先使用 inSampleSize 降低分辨率,變換時用 Canvas 直接繪製到目標緩衝區,並善用 inBitmap 復用內存塊。大圖處理時考慮分塊或使用 BitmapRegionDecoder。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved