我正在开发一个应用程序,并在我运行Android 2.2的设备上进行测试。在我的代码中,我使用了一个使用BitmapFactory.decodeResource检索的位图,并且我能够通过调用bitmap.setPixels()
对它进行更改。当我在朋友运行Android 1.6的设备上进行测试时,我在调用bitmap.setPixels
时得到了一个IllegalStateException
。在线文档说当位图是不可变的时,这个方法会抛出一个IllegalStateException
。文档没有提到decodeResource
返回一个不可变的位图,但很明显,这是必须的。
是否有其他调用可以从应用程序资源中可靠地获取可变位图,而不需要第二个Bitmap
对象(我可以创建一个相同大小的可变位图,并将其绘制到Canvas中进行 Package ,但这将需要两个相同大小的位图,占用的内存是我预期的两倍)?
7条答案
按热度按时间llycmphe1#
可以将不可变位图转换为可变位图。
我找到了一个可以接受的解决方案,它只使用一个位图的内存。
一个源位图被原始保存(RandomAccessFile)在磁盘上(没有内存),然后源位图被释放,(现在内存中没有位图),然后文件信息被加载到另一个位图中。这种方法可以使位图副本每次只在内存中存储一个位图。
在此处查看完整的解决方案和实施:Android: convert Immutable Bitmap into Mutable
我对这个解决方案做了改进,现在可以处理任何类型的位图(ARGB_8888,RGB_565等),并删除了临时文件。
6mw9ycah2#
使用mutable选项true将位图复制到自身。这样既不需要额外的内存消耗也不需要长代码行。
cmssoen23#
我们可以先通过示例化BitmapFactory.Options类来设置BitmapFactory的选项,然后将名为“inMutable”的选项字段设置为true,然后将此选项示例传递给decodeResource。
x33g5p2x4#
下面是我创建的一个解决方案,它使用内部存储,不需要任何新的权限,基于“Derzu”的想法,以及从Hive开始,这是内置的事实:
另一种方法是使用JNI将数据放入其中,回收原始位图,并使用JNI数据创建一个新位图,该位图将是(自动)可变的,因此与my JNI solution for bitmaps一起,可以执行以下操作:
不过,我不确定API级别的最低要求是什么。它在API 8和更高版本上运行得很好。
vm0i2vca5#
我知道我迟到了,但这就是我们如何避免这个痛苦恼人的Android问题,并裁剪和修改一个图像只有一个副本在内存中。
情况
我们要处理保存到文件中的图像的裁剪版本的像素。2由于内存需求很高,我们不希望在任何给定时间在内存中拥有该图像的多个副本。
本应成功却失败了
使用
BitmapRegionDecoder
打开图像子部分(我们想要裁剪到的位),使用inMutable = true
传入BitmapFactory.option
,处理像素,然后保存到文件。尽管我们的应用程序声明API最小值为14,目标值为19,但
BitmapRegionDecoder
返回的是一个不可变的位图,实际上忽略了我们的BitMapFactory.options
"什么行不通"
BitmapFactory
(这与我们的inMutable
选项有关)打开可变图像并裁剪它:所有裁剪技术都是非强制性的(要求整个图像的副本同时存在于内存中,即使在覆盖和回收之后立即收集垃圾)BitmapRegionDecoder
(有效裁剪)打开不可变图像并将其转换为可变图像;所有可用的技术再次需要存储器中的副本。2014年最佳解决方案
BitmapFactory
打开全尺寸图像作为可变位图,并执行我们的像素操作BitmapRegionDecoder
打开保存的位图,只打开要裁剪的区域(现在我们不关心位图是否不可变)使用这种方法,我们可以裁剪位图并在位图上执行像素处理,而内存中只有一个副本(因此我们可以尽可能避免那些讨厌的OOM错误),因为我们必须执行额外的(缓慢的)文件IO,所以用RAM来换取时间。
gzszwxb46#
这是因为您希望通过调用
setHeight()
或setWidth()
来调整位图的大小调整任何位图或可绘制对象(Png、Svg、矢量等)的大小
用法示例:
yqyhoc1h7#
我知道这个问题已经解决了,但是:
第一个月