【问题标题】:How to Combine Images without loading them into RAM in Java如何在不将图像加载到 Java 中的 RAM 的情况下组合图像
【发布时间】:2017-01-19 05:52:25
【问题描述】:

我正在尝试生成一个非常大(大约十亿像素)的图像,到目前为止,在出现内存不足错误之前,我只能在 BufferedImage 中创建最大约 40 兆像素的图像。我想一块一块地构建图像,然后组合这些块而不将图像加载到内存中。我也可以通过将每个片段写入文件来做到这一点,但 ImageIO 不支持。

【问题讨论】:

  • 为什么不增加应用程序的可用内存呢?
  • 我做到了,这将我的阈值提高到了 100 兆像素,但我的内存快用完了。另外,我希望我的程序可以扩展到更高的分辨率。这是一个mandelbrot集的分形生成程序。
  • 你能用外部工具剪切图像,将碎片与你的程序组合,然后重新组合图像吗?
  • 这是一个选项,但如果不强制用户下载外部工具,我将无法分发该程序。
  • 如果每个像素包含 R、G、B 和 A 的每个字节,则 40 MPix 图像将消耗 160 Meg 的内存。即使没有 alpha 分量,它也会达到 120 Meg。您是否对 100 Meg 失败的原因有所了解? O_o 至于9000的建议,你可以部署应用程序。使用 Java Web Start 并让它安装外部应用程序。适用于 Mac、*nix 或 Windows。就用户而言,只需在出现提示时单击“确定”即可 - 工具的安装是自动的。

标签: java image memory bufferedimage


【解决方案1】:

我认为JAI 可以帮助您构建您想要的东西。我建议查看JAI 提供的数据结构和流。

另外,看看这些问题,可能会对您有所帮助。

  1. How to save a large fractal image with the least possible memory footprint
  2. How to create a big image file from many tiles
  3. Appending to an Image File

你基本上想把 2 倒过来。
祝你的项目好运;)

【讨论】:

  • 这些几乎都描述了我的问题。他们也都推荐 JAI。我找到了一个不错的 JAI API here
  • 是的,JAI 有点被忽视了,好几年没有更新了。一部分现在是javax.ImageIO
  • 嗯。从 RAM 中组合图像的可能性看起来不太好。有谁知道如何追加到文件?
【解决方案2】:

不是一个合适的解决方案,只是一个草图。

当图像被压缩时,解压一张图像并不容易。您可以通过外部工具将图像解压缩为一些简单的格式(xpm,未压缩的 tiff)。然后,您可以将此图像的片段加载为字节数组,因为格式非常简单,并从这些原始数据中创建 Image 实例。

【讨论】:

  • 这仍然需要将所有图像加载到内存中。
  • 这需要将图像加载到内存中,而不是一次加载整个图像!您将能够加载正确大小的块,因为像素数据只是一个线性数组。一些seek()s 将是必需的,但其他不多。
  • 如何创建一个包含所有图像数据的图像文件?
【解决方案3】:

我看到了两个简单的解决方案。为您的图像创建自定义二进制格式。为了保存,一次只生成一个部分,seek() 到文件中的适当位置,然后卸载您的数据。对于加载,seek() 到文件中的适当位置,然后加载您的数据。

另一种解决方案是自己学习图像格式。 bmp 是未压缩的,但它是唯一容易学习的。一旦学会,上述步骤工作得很好。

记得将你的图片转换成字节数组以便于存储。

【讨论】:

    【解决方案4】:

    如果没有办法在 Java 中内置(为了您的利益,我希望不是这种情况,并且有人这样回答),那么您将需要自己实现一个算法,就像其他人在这里评论说的那样所以。

    您不一定需要自己了解整个算法。如果您采用预先存在的算法,您可以修改它以将文件作为字节流加载,创建一个字节缓冲区以继续读取文件的块,并修改算法以一次接受该数据块。

    某些算法,例如 jpg,可能无法以这种方式使用文件块的线性流来实现。正如@warren 建议的那样,bmp 可能是最容易以这种方式实现的,因为该文件格式只有一个包含这么多字节的标头,然后它只是以二进制格式直接转储 RGBA 数据(以及一些填充)。因此,如果您要加载需要组合的子图像,一次在逻辑上加载 1 个(尽管您实际上可以多线程处理这个东西并同时加载下一个数据以加快速度,因为这个过程需要很长一段时间),读取下一行数据,将其保存到二进制输出流中,等等。

    您甚至可能需要多次加载子图像。例如,假设要保存的图像由 2x2 网格中的 4 个子图像组成。您可能需要加载图像 1,读取其第一行数据,将其保存到新文件,释放图像 1,加载图像 2,读取其第一行数据,保存,释放 2,加载 1 以读取其第二行数据等。如果您使用压缩图像格式进行保存,则更有可能需要这样做。

    再次建议一个 bmp,因为 bmp 没有被压缩,你可以以任何你想要的格式保存数据(假设文件是​​以提供随机访问的方式打开的),你可以在你的文件中跳过'重新保存,以便您可以完全读取 1 个子图像并保存其所有数据,然后再继续下一个。这可能会节省运行时间,但也可能会节省可怕的文件大小。

    我可以继续。可能存在多个陷阱、优化等。

    如果您创建一个仅由元数据组成的新图像文件格式,而不是保存 1 个巨大的文件,它是组合其他文件的结果,它允许它以一种逻辑上组合它们的方式引用其他文件,而无需实际创建 1 个大型文件?是否可以选择创建新的图像文件格式取决于您的软件;如果您希望人们将这些图像用于其他软件,那么这是行不通的 - 至少,除非您可以让您的新图像文件格式流行并成为标准。

    【讨论】:

      猜你喜欢
      • 2015-09-17
      • 2018-05-26
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-02-17
      • 2016-03-25
      • 1970-01-01
      • 2016-12-02
      相关资源
      最近更新 更多