我正在开发一个应用程序并在运行 Android 2.2 的设备上对其进行测试。在我的代码中,我使用了一个使用 BitmapFactory.decodeResource 检索的位图,并且我可以通过在其上调用 bitmap.setPixels()
来进行更改。当我在 friend 的运行 Android 1.6 的设备上对此进行测试时,我在对 bitmap.setPixels
的调用中得到了一个 IllegalStateException
。在线文档说,当位图不可变时,此方法会抛出 IllegalStateException
。文档没有说明 decodeResource
返回不可变位图的任何内容,但显然必须如此。
我可以进行不同的调用来可靠地从应用程序资源获取可变位图,而无需第二个 Bitmap
对象(我可以创建一个相同大小的可变位图并绘制到 Canvas 包装中它,但是这需要两个大小相同的位图,占用的内存是我预期的两倍)?
最佳答案
您可以将不可变位图转换为可变位图。
我找到了一个可接受的解决方案,它只使用一个位图的内存。
源位图被原始保存(RandomAccessFile)在磁盘上(没有内存),然后源位图被释放,(现在,内存中没有位图),然后,文件信息被加载到另一个位图。这种方式可以制作一个位图副本,每次只将一个位图存储在 RAM 内存中。
在此处查看完整的解决方案和实现:Android: convert Immutable Bitmap into Mutable
我对此解决方案进行了改进,现在可以使用任何类型的位图(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;
}
关于java - BitmapFactory.decodeResource 在 Android 2.2 中返回一个可变位图,在 Android 1.6 中返回一个不可变位图,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4349075/