当前位置: 首页 > 面试题库 >

BitmapFactory.decodeResource在Android 2.2中返回可变的位图,在Android 1.6中返回不可变的位图

柯凯旋
2023-03-14
问题内容

我正在开发应用程序并在运行Android 2.2的设备上对其进行测试。在我的代码中,我使用了一个通过BitmapFactory.decodeResource检索的位图,并且可以通过对其进行调用来进行更改bitmap.setPixels()。当我在运行Android 1.6的朋友的设备上进行测试时,我IllegalStateException接到的电话bitmap.setPixels。在线文档说,IllegalStateException当位图是不可变的时,从该方法抛出。该文档没有说明有关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;

}



 类似资料:
  • 问题内容: 我想知道是否存在一种实现类似于map getter的功能的方法:它返回返回值作为第一个参数,(可选地分配)第二个值作为第二个参数。因此,我需要可以通过以下方式调用的函数: 问题答案: 不,它无法完成,唯一的选择是返回一个指针并检查它是否为nil。

  • 我有一个包含水平回收视图的具有底部表行为的碎片。回收视图由SnapHelper调整以实现页面效果。它看起来像这样: 在片段中的onCreateView事件中,我设置了Adapter和LayoutManager: 在我设置适配器之后,在MyRecycorAdapter类对象中触发onCreateViewHolder事件,然后是onBindViewHolder: 当我第一次创建这个片段并配置Recyc

  • 我注意到,如果没有where(),returning()操作不可用。这是故意的吗? 这项工作: 这不起作用: 我应该考虑这个“黑客”吗?

  • 我希望我的类有一个字段,该字段返回所有公共访问的不可变列表,但在对象实例中,我希望列表是可变的,以便我可以向其添加元素。 我试过了,但不确定这是否被视为良好做法?

  • 问题内容: 我的android应用程序drawable文件夹中有一个jpg图像,分辨率为1000x600。我像这样将图像加载到位图 之后,我打电话返回1500。怎么回事?以及如何获得正确的图像宽度和高度? 问题答案: 这可能是因为密度不同。您的资源可能存储在中等密度的文件夹中,但设备为hdpi。中密度为160dpi,高密度为240dpi。因此,您的位图将缩放为原始大小的1.5倍。有关更多信息,请参

  • 以下是MyBitmapUtils.GetBitmapScaledToFitWidth: 我知道这是怎么发生的。这是因为图像的高度大于2048,而在Android系统中创建一个大于2048*2048的位图会导致OOM(奇怪的是,我的logcat没有报告这个错误)