java - Android:内存友好的图像字节修改

标签 java android bitmap bitmapfactory

我目前正在制作一个 Android 应用程序来修改图像的一些字节。为此,我编写了以下代码:

Bitmap bmp = BitmapFactory.decodeStream(new FileInputStream(path));
ByteBuffer buffer = ByteBuffer.allocate(bmp.getWidth()*bmp.getHeight());
bmp.copyPixelsToBuffer(buffer);
return buffer.array();

问题是这种方式使用了过多的堆内存,并抛出OutOfMemoryException。 我知道我可以让应用程序的堆内存更大,但这似乎不是一个好的设计选择。

是否有更内存友好的方式来更改图像的字节?

最佳答案

看起来托管堆上有两个像素数据副本:

  • Bitmap中的未压缩数据
  • ByteBuffer 中数据的副本

通过将数据保留在位图中并使用getPixel(),可以将内存需求减半。/setPixel() (或者可能使用“批量”变体一次编辑一行),但这会增加一些开销。

根据图像的性质,您也许可以使用不太精确的格式(例如 RGB 565 而不是 8888),从而将内存需求减半。

正如评论之一所述,您可以将数据解压缩到文件,并使用 java.nio.channels.FileChannel#map() 对其进行内存映射。 ,并通过 MappedByteBuffer 访问它。这会增加加载和保存的相当大的开销,并且可能会很烦人,因为您必须完成 ByteBuffer而不是byte[] .

另一个选项是使用 android:largeHeap 扩展堆。 ( documented here ),尽管在某些方面您只是推迟了不可避免的事情:您可能会被要求编辑对于“大”堆来说太大的图像。此外,“大”堆的容量因设备而异,就像“正常大小”堆一样。这是否有意义部分取决于您加载的图像有多大。

在执行任何操作之前,我建议使用堆分析工具(例如 this blog post )来查看内存的去向。另外,查看内存不足异常上面的logcat;它应该识别失败的分配的大小。确保它看起来“合理”,即您不会无意中分配比您想象的多得多的资金。

关于java - Android:内存友好的图像字节修改,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17217652/

相关文章:

java - Java 中线程的不同操作需要多长时间?

Java:为什么迭代器不可复制

android - 如何在 Android 中设置背景图像并将该图像适合整个卡片以用于卡片 View ?

Android:如何在不加载完整位图的情况下即时将流式图像渲染到 ImageView?

android - 如何减小透明位图大小(不是尺寸)

java - Eclipse:如何将单词设置为代码完成的自动激活触发器

java - Netty:如何限制每秒的Websocket channel 消息数?

java - Android 应用程序从网站解析 JSON

Android 位图移位/移动问题

c# - 从 RGB 格式的文件加载位图(无 Alpha)