如何使用 Java 裁剪图像而不将其加载到内存中

Posted

技术标签:

【中文标题】如何使用 Java 裁剪图像而不将其加载到内存中【英文标题】:How do I crop an image without loading it into memory using Java 【发布时间】:2015-10-28 19:49:47 【问题描述】:

有没有一种方法可以在不将整个图像加载到内存中然后对其进行裁剪的情况下裁剪图像?

场景是我有一个非常大的图像文件,并且我有一个直角坐标列表,我需要从大图像中裁剪出来。图像太大了,我无法直接将其加载到内存中。有没有一种技术可以流式传输图像并找到要裁剪的起点和终点?不要介意我是否必须为每组坐标多次执行此步骤。哦,是的,假设图像是 JPG/PNG/TIFF 格式,哪种最容易使用。

如果对本地库有任何依赖,应该能够在 Windows 和 Linux 上运行。

谢谢。

【问题讨论】:

查看 im4java 和 JMagick,它们都使用 ImageMagick。这个问题在 *** 上也得到了多次回答。 不确定在 Java 中是否有任何东西可以使用,但 LargeTIFFTools 实用程序是专门为此目的而设计的。 我忘了说这应该可以在 Windows 和 Linux 上工作,但幸运的是有一个 Windows 二进制文件 :) 【参考方案1】:

您可以使用libvips 执行此操作 - 它适用于 Linux、OSX 和 Windows。

为了进行设置,让我们使用 ImageMagick 创建一个难以压缩的大图像 (10,000x10,000),因为它充满了随机噪声:

convert -size 10000x10000 xc:gray +noise random  \
   -fill red  -draw "rectangle 0,0 100,100"      \
   -fill blue -draw "rectangle 9900,9900 10000,10000" BigBoy.tif

缩小后,它看起来像这样,如果仔细观察,左上角有一个红色矩形,右下角有一个蓝色矩形:

重量为 800 MB:

-rw-r--r--@  1 mark  staff  800080278  5 May 12:08 BigBoy.tif

现在让我们使用libvips(就在命令行中)提取左上角和右下角(很容易识别 - 你看到我在那里做了什么吗?):

vips im_extract_area BigBoy.tif topleft.jpg 0 0 200 200 --vips-leak
memory: high-water mark 118.85 MB

vips im_extract_area BigBoy.tif bottomright.jpg 9800 9800 200 200 --vips-leak
memory: high-water mark 118.85 MB

这两个命令都使用了大约 120MB 的内存。我不相信 libvips 有 Java 绑定,但我认为您可以使用 fork()exec() 的东西或使用类似 C 的 system() 函数。

【讨论】:

谢谢,太好了。是的,我绝对可以将 Java 中的命令作为一个进程运行,甚至可以创建自己的 JNI 类来访问它,这并不需要太多工作。

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

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

如何逐行读取大型文本文件,而不将其加载到内存中?

如何在xcode中使用图像文件作为启动图像而不将其名称更改为“Default.png”并将其重新导入到项目中?

如何使用 php gd 库加载动态图像,不将其保存在服务器上或使用 src="script.php"?

如何从 PHP 扩展返回数组,而不将其复制到内存中?

如何隐藏启动图像而不将其淡出? [复制]