BitmapFactory.decodeResource returns a mutable Bitmap in Android 2.2 and an immutable Bitmap in Android 1.6 BitmapFactory.decodeResource returns a mutable Bitmap in Android 2.2 and an immutable Bitmap in Android 1.6 java java

BitmapFactory.decodeResource returns a mutable Bitmap in Android 2.2 and an immutable Bitmap in Android 1.6


You can convert your immutable bitmap to a mutable bitmap.

I found an acceptable solution that uses only the memory of one bitmap.

A source bitmap is raw saved (RandomAccessFile) on disk (no ram memory), then source bitmap is released, (now, there's no bitmap at memory), and after that, the file info is loaded to another bitmap. This way is possible to make a bitmap copy having just one bitmap stored in ram memory per time.

See the full solution and implementation here: Android: convert Immutable Bitmap into Mutable

I add a improvement to this solution, that now works with any type of Bitmaps (ARGB_8888, RGB_565, etc), and deletes the temp file. See my method:

/** * 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;}


Copy the bitmap to itself with mutable option true. This way neither extra memory consumption nor long lines of codes are needed.

Bitmap bitmap= BitmapFactory.decodeResource(....);bitmap= bitmap.copy(Bitmap.Config.ARGB_8888, true);


We can first set options for BitmapFactory by instantiating an BitmapFactory.Options class and then set the options field named 'inMutable' as true and and then pass this options instance to decodeResource.

 BitmapFactory.Options opt = new BitmapFactory.Options(); opt.inMutable = true; Bitmap bp = BitmapFactory.decodeResource(getResources(), R.raw.white, opt);