裁剪图像而不加载到内存中

Posted

技术标签:

【中文标题】裁剪图像而不加载到内存中【英文标题】:Crop image without loading into memory 【发布时间】:2013-04-25 19:22:23 【问题描述】:

我想裁剪大尺寸的图像并尝试使用 Bitmap.createBitmap 但它给出了 OOM 错误。此外,围绕 createBitmap 尝试了多种技术,但均未成功。

现在我考虑将图像保存到文件系统并裁剪它而不将图像加载到内存中,这可能会解决问题。但是不知道怎么弄。

用户流程:每个快照用户可以手动裁剪后,用户将从应用内相机拍摄多张照片,或者应用会在某些预定义登录时静默裁剪,然后将这些图像发送到服务器。

谁能指导我如何实现这一目标?

【问题讨论】:

嗯,一种选择是选择性地将某些字节从现有文件复制到新文件中。但是,您需要了解现有格式以及如何将其映射到新文件。 @chirs 非常抽象,请您对您的解决方案进行更多说明。 我不得不说这是不可能的,但对于最简单的图像格式。如果您正在处理 JPEG 或 PNG 图像,据我所知,您必须将它们解压缩为位图,选择您想要的部分,然后从该部分生成一个新图像。 在这里读过吗? ***.com/questions/11275650/… 您是真的想裁剪它(即删除图片的一部分)还是只是想将其缩小到更小的尺寸?可以使用各种 Bitmap... 类进行收缩。 【参考方案1】:

有一个名为 BitmapRegionDecoder 的类可能会对您有所帮助,但它可从 API 10 及更高版本中获得。

如果你不能使用它:

许多图像格式都经过压缩,因此需要某种形式的加载到内存中。

您需要阅读适合您需要的最佳图像格式,然后自己阅读,仅使用您需要的内存。

一个更简单的任务是在 JNI 中完成这一切,这样即使您将使用大量内存,至少您的应用不会这么快进入 OOM,因为它不会被限制在最大值强加于普通应用的堆大小。

当然,由于android是开源的,你可以尝试使用BitmapRegionDecoder并将其用于任何设备。

【讨论】:

【参考方案2】:

我非常怀疑你能否用现有的 Android API 解决这个问题。

您需要做的是获取可用的图像访问库之一(libpng 可能是您最好的选择)并通过 jni 将其链接到您的应用程序(查看是否已有可用的 Java 绑定)。

使用低级 I/O 操作一次读取一个扫描线的图像。丢弃垂直裁剪区域之前或之后的任何扫描线。对于垂直裁剪区域内的那些扫描线,只取水平裁剪区域内的那些像素并将它们写入裁剪图像。

【讨论】:

对我来说,这里似乎付出了太多的努力和大量的砍伐,并在所有 API(从 8 开始)中管理它是一项艰巨的任务。在服务器端裁剪怎么样......用户只需显示图像并隐藏稍后将由服务器裁剪的部分。 在服务器上裁剪肯定是要走的路。通过在服务器上进行裁剪,您可以极大地节省带宽和加载时间。另外,在服务器端,只需安装 ImageMagick“转换”工具即可为您进行裁剪,几乎无需编写代码。

以上是关于裁剪图像而不加载到内存中的主要内容,如果未能解决你的问题,请参考以下文章

允许在 PHP 中裁剪和调整图像大小而不使用太多内存的图像功能 [关闭]

Android:旋转图像而不将其加载到内存中

C#如何在不使用大量内存的情况下裁剪图像? [复制]

保存/使用图像而不分配 300mb 内存

合并大文件而不将整个文件加载到内存中?

Gensim 构建字典而不将所有文本加载到内存中