我正在开发应用程序并在运行Android 2.2的设备上对其进行测试。在我的代码中,我使用了一个通过BitmapFactory.decodeResource检索的位图,并且可以通过对其进行调用来进行更改bitmap.setPixels()。当我在运行Android 1.6的朋友的设备上进行测试时,我IllegalStateException接到的电话bitmap.setPixels。在线文档说,IllegalStateException当位图是不可变的时,从该方法抛出。该文档没有说明有关decodeResource返回不可变位图的任何内容,但显然必须如此。
BitmapFactory.decodeResource
bitmap.setPixels()
IllegalStateException
bitmap.setPixels
decodeResource
我是否可以进行另一个调用以从应用程序资源可靠地获取可变位图,而无需第二个Bitmap对象(我可以创建一个相同大小的可变位图并绘制到包装它的Canvas中,但这将需要两个相等大小的位图使用了两倍于我预期的内存)?
您可以将不可变位图转换为可变位图。
我找到了一种仅使用一个位图的内存的可接受解决方案。
将源位图原始保存(RandomAccessFile)到磁盘上(没有ram内存),然后释放源位图(现在,内存中没有位图),然后,文件信息将加载到另一个位图。通过这种方式,可以制作一次仅在内存中存储一个位图的位图副本。
在此处查看完整的解决方案和实现:Android:将不可变位图转换为可变
我对该解决方案进行了改进,现在可以与任何类型的位图(ARGB_8888,RGB_565等)一起使用,并删除临时文件。看我的方法:
/* * 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;
} 分