在 Linux 上使用 ImageMagick 命令行批量转换时出现错误结果
Broken results on batch convert with ImageMagick command line on Linux
这是我的 IM 命令:
/usr/bin/convert
'src.tif'
-limit memory 0
-limit map 0
-limit file 0
-alpha transparent
-clip
-alpha opaque
-resize 800x600
'end.png'
2>&1
所以这将通过剪切文件中给定的路径来删除我的 TIFF 的白色背景。它将调整大小并保存为透明 PNG。
我从 IM 运行中没有收到任何错误。
但是如果我 运行 使用 PHP 这个命令对大约 13000 个文件执行它 - 我有时会遇到这些错误:
sh: line 1: 25065 Killed /usr/bin/convert \
'public_html/source_files/XXXX123/XXXX123/XXXX123.tif' \
-limit memory 0 -limit map 0 -limit file 0 -alpha transparent \
-clip -alpha opaque -resize 800x600 \
'public_html/converted/XXXX123/XXXX123/XXXX123_web.png' 2>&1
sh: line 1: 25702 Killed /usr/bin/convert \
'public_html/source_files/XXXX123/XXXX123/XXXX123.tif' \
-limit memory 0 -limit map 0 -limit file 0 -alpha transparent \
-clip -alpha opaque -resize 800x600 \
'public_html/converted/XXXX123/XXXX123/XXXX123_web.png' 2>&1
但更大的问题是:有些图片坏了。下面左边是 "bad" 图片,右边是 "good" 图片(ondrag/on 深色背景你看问题更清楚):
在 运行手动执行命令时,结果正常。只有在 运行 上,此 PHP 循环脚本才会提供损坏的结果。 ( PHP loop script )
我运行脚本是这样的:php55 run.php
。 find
作为 shell 脚本的简单循环提供了相同的结果。
所以我在 IM discourse server 和 运行 2 台不同分布的机器上搜索,询问这个程序(Debian Wheezy,Ubuntu Server 14.04)
Note/EDIT 1: 运行终端中相同文件的命令提供了完美的结果。
编辑 2: 添加了示例 TIFF 文件 here
我不确定这是否是答案。现在这纯粹是猜测。所以这里...
通过将限制设置为 0
值,您基本上是在告诉 ImageMagick:"Your resources are not limited at all. You do not need to care for any limits."
如果没有设置任何限制怎么办? 从命令中删除所有 -limit ... 0
部分.在这种情况下,ImageMagick 将使用其内置默认值或其他定义的设置(可能包含在 IM 安装的 policy.xml 文件中,或通过各种 环境变量)。您可以使用以下命令查询系统的当前限制:
identify -list resource
在我的系统上,我得到这些值:
File Area Memory Map Disk Thread Throttle Time
---------------------------------------------------------------------------
192 4.295GB 2GiB 4GiB unlimited 1 0 unlimited
如果您确实将这些限制设置为合理的值,与您系统的实际可用资源相匹配,会怎样?假设您有:8 GByte 的 RAM,50 GByte 的可用磁盘 space 和磁盘卷上的大量可用 inodes。然后尝试这样设置:-limit disk 10GB -limit memory 3GB -limit map 6GB
.
ImageMagick 资源管理
对于所有处理和中间步骤,ImageMagick 需要访问中间 像素缓存 memory/storage,然后才能提供最终结果。
这种对像素缓存存储的需求可以通过不同的资源来满足:
- 堆内存,
- 匿名内存映射,
- 基于磁盘的内存映射,
- 直接磁盘。
ImageMagick 逐步使用所有这些资源:
- 堆内存用完后,它会将像素存储在匿名地图中。
- 匿名内存映射用完后,它会在磁盘上创建像素缓存并尝试对其进行内存映射。
- 一旦内存映射内存耗尽,它就简单地使用标准磁盘I/O。
磁盘存储很便宜但也很慢:它比内存慢 3 个数量级(一千倍)。通过使用内存映射到基于磁盘的缓存可以获得一些速度提升(最多 5 倍)。
ImageMagick 知道控制这些资源数量的各种方法:
内置默认值。这些限制是:768 个文件、3GB 图像区域、1.5GiB 内存、3GiB 内存映射和 18.45EB 磁盘 space.
policy.xml
配置文件。请查看您自己的 policy.xml 文件中的内容。先用convert -list policy
找到这个文件的位置。然后使用 cat /some/path/policy.xml
查看其内容。 (该文件使用 XML 语法。不要忘记:包含在 <!--
和 -->
中的任何内容都是注释!)它还包含解释各种细节的注释。 policy.xml 可以定义比可用限制资源更多的东西。 policy.xml 中的设置优先于内置默认值(如果在此处定义)。
环境变量。以下是可以限制 IM 资源的环境变量列表:MAGICK_AREA_LIMIT
(图像区域限制),MAGICK_DISK_LIMIT
(磁盘 space 限制),MAGICK_FILE_LIMIT
(最大打开数文件限制)、MAGICK_MEMORY_LIMIT
(堆内存限制)、MAGICK_MAP_LIMIT
(内存映射限制)、MAGICK_THREAD_LIMIT
(最大线程数限制)和 MAGICK_TIME_LIMIT
(最大运行时间秒)。如果设置了这些环境变量,则优先于 policy.xml 配置文件。
-limit <name> <value>
命令行设置。以下 <names>
被识别:
width
(图像的最大宽度)。超过限制时,抛出异常并停止处理。
height
(图像的最大高度)。超过限制时,抛出异常并停止处理。
area
(任何单个图像驻留在像素缓存内存中的最大字节数)。当超过限制时,自动缓存到磁盘(可能是内存映射)设置。
memory
(从匿名映射内存或堆中为像素缓存分配的最大内存)。
map
(为像素缓存分配的内存映射的最大数量)。
disk
(像素缓存允许使用的最大磁盘量 space)。超过限制时,不会创建像素缓存并抛出致命异常。
files
(打开像素缓存文件的最大数量)。当超过限制时,缓存到磁盘的所有后续像素将关闭并根据需要重新打开。
thread
(最大并行线程数)
time
(允许进程执行的最长时间,以秒为单位)。当超出此限制时,将引发异常并停止处理。
命令行上的 -limit
设置优先并覆盖所有其他设置。
这是我的 IM 命令:
/usr/bin/convert
'src.tif'
-limit memory 0
-limit map 0
-limit file 0
-alpha transparent
-clip
-alpha opaque
-resize 800x600
'end.png'
2>&1
所以这将通过剪切文件中给定的路径来删除我的 TIFF 的白色背景。它将调整大小并保存为透明 PNG。
我从 IM 运行中没有收到任何错误。
但是如果我 运行 使用 PHP 这个命令对大约 13000 个文件执行它 - 我有时会遇到这些错误:
sh: line 1: 25065 Killed /usr/bin/convert \
'public_html/source_files/XXXX123/XXXX123/XXXX123.tif' \
-limit memory 0 -limit map 0 -limit file 0 -alpha transparent \
-clip -alpha opaque -resize 800x600 \
'public_html/converted/XXXX123/XXXX123/XXXX123_web.png' 2>&1
sh: line 1: 25702 Killed /usr/bin/convert \
'public_html/source_files/XXXX123/XXXX123/XXXX123.tif' \
-limit memory 0 -limit map 0 -limit file 0 -alpha transparent \
-clip -alpha opaque -resize 800x600 \
'public_html/converted/XXXX123/XXXX123/XXXX123_web.png' 2>&1
但更大的问题是:有些图片坏了。下面左边是 "bad" 图片,右边是 "good" 图片(ondrag/on 深色背景你看问题更清楚):
在 运行手动执行命令时,结果正常。只有在 运行 上,此 PHP 循环脚本才会提供损坏的结果。 ( PHP loop script )
我运行脚本是这样的:php55 run.php
。 find
作为 shell 脚本的简单循环提供了相同的结果。
所以我在 IM discourse server 和 运行 2 台不同分布的机器上搜索,询问这个程序(Debian Wheezy,Ubuntu Server 14.04)
Note/EDIT 1: 运行终端中相同文件的命令提供了完美的结果。
编辑 2: 添加了示例 TIFF 文件 here
我不确定这是否是答案。现在这纯粹是猜测。所以这里...
通过将限制设置为 0
值,您基本上是在告诉 ImageMagick:"Your resources are not limited at all. You do not need to care for any limits."
如果没有设置任何限制怎么办? 从命令中删除所有
-limit ... 0
部分.在这种情况下,ImageMagick 将使用其内置默认值或其他定义的设置(可能包含在 IM 安装的 policy.xml 文件中,或通过各种 环境变量)。您可以使用以下命令查询系统的当前限制:identify -list resource
在我的系统上,我得到这些值:
File Area Memory Map Disk Thread Throttle Time --------------------------------------------------------------------------- 192 4.295GB 2GiB 4GiB unlimited 1 0 unlimited
如果您确实将这些限制设置为合理的值,与您系统的实际可用资源相匹配,会怎样?假设您有:8 GByte 的 RAM,50 GByte 的可用磁盘 space 和磁盘卷上的大量可用 inodes。然后尝试这样设置:
-limit disk 10GB -limit memory 3GB -limit map 6GB
.
ImageMagick 资源管理
对于所有处理和中间步骤,ImageMagick 需要访问中间 像素缓存 memory/storage,然后才能提供最终结果。
这种对像素缓存存储的需求可以通过不同的资源来满足:
- 堆内存,
- 匿名内存映射,
- 基于磁盘的内存映射,
- 直接磁盘。
ImageMagick 逐步使用所有这些资源:
- 堆内存用完后,它会将像素存储在匿名地图中。
- 匿名内存映射用完后,它会在磁盘上创建像素缓存并尝试对其进行内存映射。
- 一旦内存映射内存耗尽,它就简单地使用标准磁盘I/O。
磁盘存储很便宜但也很慢:它比内存慢 3 个数量级(一千倍)。通过使用内存映射到基于磁盘的缓存可以获得一些速度提升(最多 5 倍)。
ImageMagick 知道控制这些资源数量的各种方法:
内置默认值。这些限制是:768 个文件、3GB 图像区域、1.5GiB 内存、3GiB 内存映射和 18.45EB 磁盘 space.
policy.xml
配置文件。请查看您自己的 policy.xml 文件中的内容。先用convert -list policy
找到这个文件的位置。然后使用cat /some/path/policy.xml
查看其内容。 (该文件使用 XML 语法。不要忘记:包含在<!--
和-->
中的任何内容都是注释!)它还包含解释各种细节的注释。 policy.xml 可以定义比可用限制资源更多的东西。 policy.xml 中的设置优先于内置默认值(如果在此处定义)。环境变量。以下是可以限制 IM 资源的环境变量列表:
MAGICK_AREA_LIMIT
(图像区域限制),MAGICK_DISK_LIMIT
(磁盘 space 限制),MAGICK_FILE_LIMIT
(最大打开数文件限制)、MAGICK_MEMORY_LIMIT
(堆内存限制)、MAGICK_MAP_LIMIT
(内存映射限制)、MAGICK_THREAD_LIMIT
(最大线程数限制)和MAGICK_TIME_LIMIT
(最大运行时间秒)。如果设置了这些环境变量,则优先于 policy.xml 配置文件。-limit <name> <value>
命令行设置。以下<names>
被识别:width
(图像的最大宽度)。超过限制时,抛出异常并停止处理。height
(图像的最大高度)。超过限制时,抛出异常并停止处理。area
(任何单个图像驻留在像素缓存内存中的最大字节数)。当超过限制时,自动缓存到磁盘(可能是内存映射)设置。memory
(从匿名映射内存或堆中为像素缓存分配的最大内存)。map
(为像素缓存分配的内存映射的最大数量)。disk
(像素缓存允许使用的最大磁盘量 space)。超过限制时,不会创建像素缓存并抛出致命异常。files
(打开像素缓存文件的最大数量)。当超过限制时,缓存到磁盘的所有后续像素将关闭并根据需要重新打开。thread
(最大并行线程数)time
(允许进程执行的最长时间,以秒为单位)。当超出此限制时,将引发异常并停止处理。
命令行上的
-limit
设置优先并覆盖所有其他设置。