使用ImageMagick创建PDF超过2 GB的限制


19

我正在使用convert约2,000张图像创建PDF文件:

convert 0001.miff 0002.miff ... 2000.miff -compress jpeg -quality 80 out.pdf

当输出文件达到2 ^ 31-1字节(2 GB -1)的消息时,该过程可重复终止

convert: unknown `out.pdf'.

PDF文件规范允许≈10GB。我试图从中获取更多信息-debug all,但是在日志输出中没有发现任何有用的信息。文件系统是ext3,它允许至少16 GiB(可能更多)的文件。至于ulimitfile sizeunlimited/etc/security/limits.conf仅包含注释行。还有什么会导致此问题,如何增加限额?

ImageMagick版本:6.4.3 2016-08-05 Q16 OpenMP
发行版:SLES 11.4(i586)


4
是否可以用一半的图像(或最适合您的图像)创建两个文件,然后将它们与pdftk合并?
Gallifreyan

1
您是否有充分的理由创建一个大于2 Gb的PDF文件?我担心许多PDF阅读器会在尝试打开它时崩溃。
dr01

因为您的ImageMagick副本是在没有大文件支持的情况下编译的。请提交错误-这是2017
。–恢复莫妮卡-M.Schröder17年

@ dr01:为什么要这样?大文件支持已经存在了数十年。
恢复莫妮卡-M.Schröder17年

@MartinSchröder但是,有些程序无法处理太大的文件。无论如何,我对创建2 Gb(即约150'000 A4页)PDF文件的原因感到好奇。
dr01

Answers:


24

您的限制实际上并非来自文件系统;或从我认为的软件包版本开始。

您的2GB限制来自使用32位版本的OS。

如果硬件支持,则增加文件的选项是安装64位版本。

请参阅大文件支持

传统上,许多操作系统及其底层文件系统实现使用32位整数来表示文件大小和位置。因此,任何文件都不能大于2 32 − 1字节(4 GB − 1)。在许多实现中,通过将大小视为带符号的数字使问题更加严重,这进一步将限制降低到2 31 − 1字节(2 GB − 1)。


3
旁注:大约十年前,Linux甚至可以在32位上使用64位文件大小和位置。尽管不确定,该pdf生成器工具可以使用此功能。
彼得说恢复莫妮卡的时间

2
off_t如果软件尝试在RAM中一次性创建整个文件并将其一次写入磁盘,则具有64位的@peterh 不会有所帮助。
德米特里·格里戈里耶夫

2
Linux不会将大小视为已签名,但是内核需要一些专用的地址空间来运行,并且在过去,将2GB留给用户空间似乎很多,因此内核会保留其他2GB。
德米特里·格里戈里耶夫

2
@DmitryGrigoryev:大小不是带符号的,但指针差(ptrdiff_t)是带符号的,这实际上意味着大小必须限制为ptrdiff_t可以表示的最大(带符号)值,否则您会得到真正讨厌的 UB和与UB相关的错误,而应用程序则没有解决的好方法。
R.,

@DmitryGrigoryev在这种情况下,文件将不完全具有2GB-1字节,因为程序需要更多的内存来存储诸如可执行代码之类的东西。
user23013

12

尝试将使用的像素缓存限制convert为例如1 GiB:

convert 0001.miff ... 2000.miff -limit memory 1GiB -limit map 1GiB -compress jpeg -quality 80 out.pdf

希望这将迫使ImageMagic定期将已处理的数据转储到磁盘上,而不是尝试在RAM缓冲区中容纳2 GB以上的GiB。

顺便说一句,由VMSPLIT内核配置设置定义了32位Linux上单个进程可用的虚拟内存量。可以是2G / 2G(内核2GB +用户空间2GB)或1G / 3G(内核1GB +用户空间3GB)。在运行的系统上,可以通过以下方式找到设置

zcat /proc/config.gz | grep VMSPLIT

在某些系统上,内核配置存储在 /boot/config-$(uname -r)


1

如果不是大量照片,则可以使用TeX / LaTeX创建PDF。然后,您仍然可以获得相同的结果(图像pdf),而不会出现转换器崩溃的问题。TeX上的文件限制应仅是您的系统(硬件+ OS)

但是我认为您可以使用Shell脚本编写TeX:

0)

mkdir convert
pushd convert
PATH=convert:$PATH /* keep everything in one directory for tidyness.*/

1)制作一个模板

1.1)我敢肯定,有一种方法可以通过使用变量替换图像名称并插入而不是追加来一次性完成此步骤,并格式化$ FOO使其具有正确的前导0,但是以下正是我所知道的。

1.2)模板需要拆分以便脚本插入文件名

1.3)nano tmplt1 / *或您选择的编辑器* /

/* white space line */ 
\begin{figure}[h!]
    \includegraphics[width=0.5\linewidth]{
/* at this point the script will insert $FOO, the file name variable */

1.3.1)但是,您的文件转到0001.miff…0010.miff…0100.miff…2000.miff。即可变数量的前导零。解决方法:tmplt1的4个版本:tmplt1-9,tmplt10-99,tmplt100-999,tmplt1000-2000。Tmplt1-9以“ ... width] {000”结尾(即加3 0);tmplt10-99以“ ... width] {00”结尾(即加2 0)。100-999加1零,而1000-2000与tmplt1相同

1.4)模板的下一部分:nano tmplt2 / * OEOYC * /

.miff}
   \caption{ /* if you want to caption, otherwise skip to  tmplt3.
Same again, script will insert $FOO here */

1.5)模板的下一部分:nano tmplt3 / * OEOYC * /

}
\label{f:   /*if you want them labelled which is actually
a index/reference for the text to refer to, not a caption.
Same again, the script will insert $FOO here. If you do not
want labels, skip to tmplt4*/

1.6)下一个模板:nano tmplt4 / * OEOYC * /

    }
\end{figure}

2)开始文件:nano head / * OEOYC * /

\documentclass{article} /* Or more suitable class */
 \usepackage{graphicx}
 \begin{document}
  /* white space line*/

3)结束文件:nano foot / * OEOYC * /

\end {document} 

4)编写脚本:nano loader / * OEOYC * /

#! /bin/bash

cat head > out.pdf

for FOO in {1...9}
do
    cat tmplt1-9 >> out.pdf
    echo "$FOO" | cat >> out.pdf
    cat tmplt2 >> out.pdf
    echo "$FOO" | cat >> out.pdf
    cat tmplt3 >> out.pdf
    echo "$FOO" | cat >> out.pdf
    cat tmplt4 >> out.pdf
done

for FOO in {10...99}
do
    cat tmplt10-99 >> out.pdf /* this looks like a lot but
is actually copy-paste of first block, just add relevant 0's and 9's */
    echo "$FOO" | cat >> out.pdf
    cat tmplt2 >> out.pdf
    echo "$FOO" | cat >> out.pdf
    cat tmplt3 >> out.pdf
    echo "$FOO" | cat >> out.pdf
    cat tmplt4 >> out.pdf
done

for FOO in {100...999}
do
    cat tmplt100-999 >> out.pdf
    echo "$FOO" | cat >> out.pdf
    cat tmplt2 >> out.pdf
    echo "$FOO" | cat >> out.pdf
    cat tmplt3 >> out.pdf
    echo "$FOO" | cat >> out.pdf
    cat tmplt4 >> out.pdf
done

for FOO in {1000...2000}
do
    cat tmplt1000-2000 >> out.pdf
    echo "$FOO" | cat >> out.pdf
    cat tmplt2 >> out.pdf
    echo "$FOO" | cat >> out.pdf
    cat tmplt3 >> out.pdf
    echo "$FOO" | cat >> out.pdf
    cat tmplt4 >> out.pdf
done

cat foot >> out.pdf

5)使脚本可执行:chmod u + x loader

5.1)经过测试之后,我发现每次插入$ FOO时,它就会分布在3行中。除了进入脚本并手动删除回车符外,我不知道其他解决方法。至少所有2000张照片中只有36张

6)调用脚本:加载程序

7)编译TeX:pdflatex out.pdf

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.