1. 程式人生 > >bitmap setPixels報java.lang.IllegalStateException異常解決方法

bitmap setPixels報java.lang.IllegalStateException異常解決方法

int w = 352;

int h = 288;
int[] pixels = new int[w * h * 10];
ImageView iv = (ImageView) findViewById(R.id.fImageView);
Bitmap bitmap = BitmapFactory.decodeResource(getResources(),R.drawable.icon2);// 建立物件
bitmap.getPixels(pixels, 0, bitmap.getWidth(), 0, 0, bitmap.getWidth(),bitmap.getHeight());// 放入
bitmap.setPixels(pixels, 0, bitmap.getWidth(), 0, 0, bitmap.getWidth(),bitmap.getHeight());// 取出

iv.setImageBitmap(bitmap);// 顯示

在bitmap.setPixels(pixels, 0, bitmap.getWidth(), 0, 0, bitmap.getWidth(),bitmap.getHeight());出現了一下以下異常:
AndrodRuntime Caused by:java.lang.IllegalStateException
AndrodRuntime at android.graphics.Bitmap.setPixels(Bitmap.java:853)
AndrodRuntime at com.phd.canwasDemo.CanvasDemoF.onCreate(CanvasDemoF.java:37)

AndrodRuntime at android.app.Instrumentation.allActivityOnCreate(Instrumentation.java:1123)
AndrodRuntime at android.app.ActivityThread.performLaunchActivity(ActivityThread.java.2233)
AndrodRuntime ...11 more

但我執行
ImageView iv = (ImageView) findViewById(R.id.gImageView);
Bitmap b = Bitmap.createBitmap(2, 2, Bitmap.Config.ARGB_8888);// 建立bitmap物件

int[] pixels = new int[b.getWidth() * b.getHeight()];// 建立畫素陣列
b.setPixel(0, 0, 0xFF00FF00);
b.setPixel(0, 1, 0x8000FF00);
b.setPixel(1, 0, 0x0000FF00);
b.getPixels(pixels, 0, b.getWidth(), 0, 0, b.getWidth(), b.getHeight());
b.setPixels(pixels, 0, b.getWidth(), 0, 0, b.getWidth(), b.getHeight());
iv.setImageBitmap(b);
可正常執行並顯示
請各位幫我分析下,該如何解決!

------解決方案--------------------
這個問題我測試過了,如果再建立一個
Bitmap bitmap2=Bitmap.createBitmap(w, h, Config.ARGB_8888);
然後使用
bitmap2.setPixels(pixels, 0, bitmap2.getWidth(), 0, 0, bitmap2.getWidth(),
bitmap2.getHeight());// 取出

顯示
iv.setImageBitmap(bitmap2);// 顯示
就可以了,我分析會不會是記憶體處理上的問題。 
------解決方案--------------------
我查了下,第一個錯誤應該是the bitmap is not mutable 
------解決方案--------------------
Bitmap bitmap = BitmapFactory.decodeResource(getResources(),R.drawable.icon2);//返回的估計是一個immutalbe的bitmap;所以不能用setpixels

而Bitmap b = Bitmap.createBitmap(2, 2, Bitmap.Config.ARGB_8888);//返回的是一個mutable的bitmap,可以用setpixels


------解決方案--------------------
從Bitmap.createBitmap可以看到有的返回immutable bitmap,有的返回 mutable bitmap

1。static Bitmap createBitmap(Bitmap src)
Returns an immutable bitmap from the source bitmap.

2.static Bitmap createBitmap(int[] colors, int width, int height, Bitmap.Config config)
Returns a immutable bitmap with the specified width and height,

3.static Bitmap createBitmap(int[] colors, int offset, int stride, int width, int height, Bitmap.Config config)
Returns a immutable bitmap with the specified width and height,  

4.static Bitmap createBitmap(Bitmap source, int x, int y, int width, int height, Matrix m, boolean filter)
Returns an immutable bitmap from subset of the source bitmap,  

5.static Bitmap createBitmap(int width, int height, Bitmap.Config config)
Returns a mutable bitmap with the specified width and height.

6.static Bitmap createBitmap(Bitmap source, int x, int y, int width, int height)

Returns an immutable bitmap from the specified subset of the source bitmap.

引用例項:

//實現類似錄音時,動態變化的錄音圖片

package com.app.bigbang;


import java.util.Random;


import android.annotation.SuppressLint;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.drawable.BitmapDrawable;
import android.util.AttributeSet;
import android.view.View;

//自定義view後在佈局檔案裡面呼叫
public class RecordView extends View {
    
Paint mPaint;
Bitmap mBitmap;
int mBitmapWidth = 0;
int mBitmapHeight = 0;
int mArrayColorLengh = 0; 
int mArrayColor[] = null;  
long startTime = 0; 
int mBackVolume = 0; 
Bitmap bmp;

public RecordView(Context context) {
super(context);
init(context);
// TODO Auto-generated constructor stub
}
public RecordView(Context context, AttributeSet attrs) {
super(context, attrs);
init(context);
// TODO Auto-generated constructor stub
}
public RecordView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init(context);
// TODO Auto-generated constructor stub
}
@SuppressLint("NewApi")
@SuppressWarnings("deprecation")
private void init(Context context){
mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
bmp = BitmapFactory.decodeResource(getResources(), R.drawable.jiangfeilv);//獲取資原始檔裡面的圖片,返回immutable的Bitmap
mBitmapWidth = bmp.getWidth();
mBitmapHeight = bmp.getHeight();
mBitmap = Bitmap.createBitmap(mBitmapWidth, mBitmapHeight, Bitmap.Config.ARGB_8888);//建立資原始檔圖片大小的圖片,返回mutable
mArrayColorLengh = mBitmapWidth * mBitmapHeight;
mArrayColor = new int[mArrayColorLengh];
int count = 0;
for (int i = 0; i < mBitmapHeight; i++) {  
       for (int j = 0; j < mBitmapWidth; j++) {
        //獲得Bitmap 圖片中每一個點的color顏色值  
           int color = bmp.getPixel(j, i);  
           mBitmap.setPixel(j, i, color);  //給mutable的Bitmap設定畫素點,使其顯示成資原始檔裡面的圖片
           //將顏色值存在一個數組中 方便後面修改  
           mArrayColor[count] = color;  
           //如果你想做的更細緻的話 可以把顏色值的R G B 拿到做響應的處理 筆者在這裡就不做更多解釋 
           int r = Color.red(color);
           int g = Color.green(color);
           int b = Color.blue(color);
           count++;
       }
}
setBackground(new BitmapDrawable(mBitmap));
startTime = System.currentTimeMillis();
}

//返回隨機數
int UtilRandom(int bottom,int top){
return ((Math.abs(new Random().nextInt())%(top+1-bottom))+bottom);
}
@Override
protected void onDraw(Canvas canvas) {
// TODO Auto-generated method stub
super.onDraw(canvas);
if(System.currentTimeMillis() - startTime >= 100){
startTime = System.currentTimeMillis();
setVolum(UtilRandom(0,100));
}
//用於重新整理螢幕  
       invalidate();
}
private void setVolum(int volume) {
// TODO Auto-generated method stub
int  startY = 0;
int endY = 0;
boolean isAdd = false;
//判斷當前應該填充新區域 還是還原舊的區域 
if(mBackVolume > volume ){
isAdd = false;
startY = getValue(mBackVolume);
endY = getValue(volume);
}else{
isAdd = true;
startY = getValue(volume);
endY = getValue(mBackVolume);
}
//沒必要每次都迴圈圖片中的所有點,因為這樣會比較耗時。  
        int count = startY * mBitmapWidth;  
        //從圖片須要填充或者還原 顏色的起始點 開始 到 終點   
        for (int i = startY; i < endY; i++) {  
        for (int j = 0; j < mBitmapWidth; j++) {  
            if (isAdd) {  
            //將需要填充的顏色值如果不是  
            //在這說明一下 如果color 是全透明 或者全黑 返回值為 0  
            //getPixel()不帶透明通道 getPixel32()才帶透明部分 所以全透明是0x00000000   
            //而不透明黑色是0xFF000000 如果不計算透明部分就都是0了  
            int color = mBitmap.getPixel(j, i);  
            if (color != 0) {  
                mBitmap.setPixel(j, i, Color.BLACK);  
            }  
            } else {  
            //如果是還原顏色 把現在點的顏色 賦值為之前儲存顏色的陣列  
            mBitmap.setPixel(j, i, mArrayColor[count]);  
            }  
            count++;  
        }  
        }  
        mBackVolume = volume; 

}

//通過百分比 根據圖片寬高算出實際填充 高度  
    public int getValue(int volume) {  
        return mBitmapHeight - (mBitmapHeight * volume / 100);  
    }  


}