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

Android Bitmap setPixels IllegalStateException:不可變 Bitmap 修改錯誤解決

     編輯:程式設計綜合問答

錯誤現象

Bitmap pic = ...; // 從資源解碼或網絡獲取
pic.setPixels(pix, 0, pic.getWidth(), 0, 0, pic.getWidth(), pic.getHeight());
// java.lang.IllegalStateException: bitmap is not mutable

根本原因

從資源、文件、網絡解碼得到的 Bitmap 默認不可變 (isMutable() == false)。setPixels()、setPixel() 要求 Bitmap 可變。

解決方案:創建可變副本

// 方案一:copy() 獲取可變副本 (推薦)
Bitmap mutableBitmap = pic.copy(Bitmap.Config.ARGB_8888, true); // true = mutable
// 現在可以修改
mutableBitmap.setPixels(pix, 0, width, 0, 0, width, height);

// 方案二:createBitmap 重繪 (適合需縮放/轉換)
Bitmap mutableBitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(mutableBitmap);
canvas.drawBitmap(pic, 0, 0, null);
// 再修改 mutableBitmap

// 方案三:解碼時直接獲取可變 Bitmap (API 19+ inBitmap 複用)
BitmapFactory.Options options = new BitmapFactory.Options();
options.inMutable = true; // 關鍵!
Bitmap mutableBitmap = BitmapFactory.decodeResource(res, R.drawable.xxx, options);

完整像素處理範例

public Bitmap processBitmap(Bitmap source) {
    if (source == null) return null;

    // 1. 確保可變
    Bitmap bitmap = source.isMutable() ? source : source.copy(Bitmap.Config.ARGB_8888, true);
    int width = bitmap.getWidth();
    int height = bitmap.getHeight();

    // 2. 獲取像素數組
    int[] pixels = new int[width * height];
    bitmap.getPixels(pixels, 0, width, 0, 0, width, height);

    // 3. 處理像素 (示例:灰度化)
    for (int i = 0; i < pixels.length; i++) {
        int color = pixels[i];
        int r = Color.red(color);
        int g = Color.green(color);
        int b = Color.blue(color);
        int gray = (int) (0.299 * r + 0.587 * g + 0.114 * b);
        pixels[i] = Color.argb(Color.alpha(color), gray, gray, gray);
    }

    // 4. 寫回
    bitmap.setPixels(pixels, 0, width, 0, 0, width, height);
    return bitmap;
}

記憶體與性能注意點

  • 大圖分塊處理:避免一次性分配巨大 int[] 導致 OOM,可用 getPixels/setPixels 分行處理
  • 及時 recycle():處理完成後釋放原始不可變 Bitmap
  • 考慮 RenderScript / OpenGL ES:大規模像素運算 GPU 加速遠快於 CPU
  • 現代替代:ImageDecoder (API 28+) + Bitmap.mutableCopy() (API 34+)

常見誤區

誤區事實
以為 decode 後直接能改資源/文件/網絡解碼 Bitmap 默認 immutable
用 createBitmap(src) 以為可變createBitmap 返回的也可能不可變,需指定 Config 且不共享內存
忽略 inMutable 選項API 19+ 解碼階段即可獲取可變 Bitmap,避免額外 copy 開銷
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved