android picture is not mutable解决!

先上Log:

转载文章如下:

Bitmap的mutable属性引发的血案

  最近做的一个项目,需要获取图片中每个像素点的信息,然后再进行一定顺序的重新排列。一开始,将需要处理的图片放到了Drawable中,通过getPixels()方法获取了整张图片的信息,然后处理完之后直接通过setPixels()就得到了新的图片。很好,然后抽风将图片放到了sdcard中,用同样的方法处理后报异常:java.lang.IllegalStateException……

  最后发现Bitmap中有一个isMutable的字段,我的理解就是是否可变,也不知道对不对。而通过BitmapFactory.decodeResource(Resources res, int id)获取到的bitmap是mutable的,而BitmapFactory.decodeFile(String path)获取到的是immutable的,因此导致了前面所说的异常。(查看源码时看到走了好多方法,并没有仔细研究为什么两者生成的bitmap一个是mutable,一个是immutable的,如果哪位大虾能说清楚些希望指点一下…)

  通过查找资料,stackoverflow有位大神给出了如下的方法,将immutable的bitmap转为了mutable的:

复制代码
/**
 * Converts a immutable bitmap to a mutable bitmap. This operation doesn't allocates
 * more memory that there is already allocated.
 * 
 * @param imgIn - Source image. It will be released, and should not be used more
 * @return a copy of imgIn, but muttable.
 */
public static Bitmap convertToMutable(Bitmap imgIn) {
    try {
        //this is the file going to use temporally to save the bytes. 
        // This file will not be a image, it will store the raw image data.
        File file = new File(Environment.getExternalStorageDirectory() + File.separator + "temp.tmp");

        //Open an RandomAccessFile
        //Make sure you have added uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"
        //into AndroidManifest.xml file
        RandomAccessFile randomAccessFile = new RandomAccessFile(file, "rw");

        // get the width and height of the source bitmap.
        int width = imgIn.getWidth();
        int height = imgIn.getHeight();
        Config type = imgIn.getConfig();

        //Copy the byte to the file
        //Assume source bitmap loaded using options.inPreferredConfig = Config.ARGB_8888;
        FileChannel channel = randomAccessFile.getChannel();
        MappedByteBuffer map = channel.map(MapMode.READ_WRITE, 0, imgIn.getRowBytes()*height);
        imgIn.copyPixelsToBuffer(map);
        //recycle the source bitmap, this will be no longer used.
        imgIn.recycle();
        System.gc();// try to force the bytes from the imgIn to be released

        //Create a new bitmap to load the bitmap again. Probably the memory will be available. 
        imgIn = Bitmap.createBitmap(width, height, type);
        map.position(0);
        //load it back from temporary 
        imgIn.copyPixelsFromBuffer(map);
        //close the temporary file and channel , then delete that also
        channel.close();
        randomAccessFile.close();

        // delete the temp file
        file.delete();

    } catch (FileNotFoundException e) {
        e.printStackTrace();
    } catch (IOException e) {
        e.printStackTrace();
    } 

    return imgIn;
}
复制代码

  用这个方法转一下,解决了异常。后来查找每个生成bitmap的方法,发现只有Bitmap createBitmap(int width, int height, Config config) 和Bitmap createBitmap(int width, int height,Config config, boolean hasAlpha)是Returns a mutable bitmap。(前者就是hasAlpha为true的后者,你懂得),故在进行setPixels前重新通过createBitmap(width, height, Config.ARGB_8888)创建了一个bitmap(他是mutable的),然后再setPixels(),也解决了异常,不过感觉后者的效率能够高些,看第一个方法还创建了个临时文件,感觉可能会很卡,但测试是两个都挺卡……准备做个像ViewPager一样的缓存,这样可能不会那么卡吧……

  参考资料:

http://stackoverflow.com/questions/4349075/bitmapfactory-decoderesource-returns-a-mutable-bitmap-in-android-2-2-and-an-immu


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值