Das Erstellen von PDFs mit ImageMagick ist auf über 2 GB beschränkt

19

Ich benutze convert, um eine PDF-Datei aus ca. 2.000 Bildern zu erstellen:

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

Der Vorgang wird reproduzierbar beendet, wenn die Ausgabedatei mit der Meldung 2 ^ 31-1 Byte (2 GB −1) erreicht hat

convert: unknown `out.pdf'.

Die PDF-Dateispezifikation ermöglicht 10 GB . Ich habe versucht, mehr Informationen abzurufen -debug all, habe jedoch keine hilfreichen Informationen in der Protokollausgabe gefunden. Das Dateisystem ist ext3, das Dateien mit mindestens 16 GiB (möglicherweise mehr) zulässt . In Bezug auf ulimit, file sizeist unlimited. /etc/security/limits.confenthält nur auskommentierte Zeilen. Was kann das noch bewirken und wie kann ich das Limit erhöhen?

ImageMagick Version: 6.4.3 05.08.2016 Q16 OpenMP-
Distribution: SLES 11.4 (i586)

Matthias Ronge
quelle
4
Ist es möglich, dass Sie zwei Dateien mit der Hälfte der Bilder erstellen (oder was am besten zu Ihnen passt) und diese dann mit pdftk zusammenführen?
Gallifreyan
1
Haben Sie einen guten Grund, eine PDF-Datei mit mehr als 2 GB zu erstellen? Ich befürchte, dass viele PDF-Reader beim Versuch, sie zu öffnen, abstürzen würden.
dr01
Weil Ihre ImageMagick-Kopie ohne Unterstützung für große Dateien kompiliert wurde. Bitte melden Sie einen Fehler - es ist 2017.
Reinstate Monica - M. Schröder
@ dr01: Warum sollten sie? Large File Support gibt es schon seit Jahrzehnten.
Reinstate Monica - M. Schröder
@ MartinSchröder Und dennoch können einige Programme nicht mit zu großen Dateien umgehen. Wie auch immer, ich war neugierig, warum ich eine 2-GB-PDF-Datei (also ca. 150.000 A4-Seiten) erstellt habe.
dr01

Antworten:

24

Ihre Einschränkung beruht in der Tat nicht auf dem Dateisystem. oder von Paketversionen denke ich .

Das Limit von 2 GB wird von Ihnen mit einer 32-Bit-Version Ihres Betriebssystems festgelegt.

Die Option zum Vergrößern der Datei besteht darin, eine 64-Bit-Version zu installieren, wenn die Hardware dies unterstützt .

Siehe Unterstützung großer Dateien

Traditionell verwendeten viele Betriebssysteme und ihre zugrunde liegenden Dateisystemimplementierungen 32-Bit-Ganzzahlen, um Dateigrößen und -positionen darzustellen. Folglich kann keine Datei größer als 2 32 - 1 Byte (4 GB - 1) sein. In vielen Implementierungen wurde das Problem noch verschlimmert, indem die Größen als vorzeichenbehaftete Zahlen behandelt wurden, wodurch der Grenzwert weiter auf 2 31 - 1 Byte (2 GB - 1) gesenkt wurde .

Rui F Ribeiro
quelle
3
Randnotiz: Linux kann seit etwa einem Jahrzehnt 64-Bit-Dateigrößen und -Positionen auch auf 32-Bit-Dateien verwenden. Es ist zwar nicht sicher, dass dieses PDF-Generator-Tool diese Funktionalität verwenden kann.
Peterh sagt, dass er Monica
2
@peterh mit 64-Bit off_thilft nicht, wenn die Software versucht, die gesamte Datei im RAM zu erstellen und auf einmal auf die Festplatte zu schreiben.
Dmitry Grigoryev
2
Linux behandelt Größen nicht als signiert, aber der Kernel benötigt einen dedizierten Adressraum, um zu funktionieren, und in den alten Zeiten schien es viel, 2 GB dem Benutzerland zu überlassen, so dass der Kernel die anderen 2 GB reservierte.
Dmitry Grigoryev
2
@DmitryGrigoryev: Größen sind nicht signiert, aber Zeigerunterschiede ( ptrdiff_t) bedeuten, dass Größen effektiv auf den maximalen (signierten) Wert begrenzt werden müssen ptrdiff_t, sonst bekommen Sie wirklich wirklich böse UB- und UB-bezogene Fehler, die Anwendungen nicht haben gute Möglichkeit, umzugehen.
R ..
@DmitryGrigoryev In diesem Fall hat die Datei nicht genau 2 GB - 1 Byte, da das Programm mehr Speicher benötigt, um Dinge wie den ausführbaren Code zu speichern.
user23013
12

Versuchen Sie, den verwendeten Pixel-Cache convertauf z. B. 1 GB zu beschränken:

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

Hoffentlich zwingt dies ImageMagic, bereits verarbeitete Daten regelmäßig auf der Festplatte abzulegen, anstatt zu versuchen, mehr als 2 GiB in RAM-Puffer zu packen.

Übrigens wird die Menge an virtuellem Speicher, die einem einzelnen Prozess unter 32-Bit-Linux zur Verfügung steht, durch die VMSPLITKernel-Konfigurationseinstellung festgelegt. Dies kann entweder 2G / 2G (2 GB für Kernel + 2 GB für Userland) oder 1G / 3G (1 GB für Kernel + 3 GB für Userland) sein. Auf einem laufenden System kann die Einstellung über gefunden werden

zcat /proc/config.gz | grep VMSPLIT

Auf einigen Systemen wird /boot/config-$(uname -r)stattdessen die Kernel-Konfiguration gespeichert .

Dmitry Grigoryev
quelle
1

Wenn es nicht die große Anzahl von Fotos gäbe, könnten Sie TeX / LaTeX verwenden, um das PDF zu erstellen. Dann können Sie immer noch das gleiche Ergebnis (PDF-Bild) erzielen, ohne dass der Konverter abstürzt. Die Dateibeschränkungen unter TeX sollten nur Ihrem System (Hardware + Betriebssystem) entsprechen.

Aber ich denke, Sie könnten ein Shell-Skript verwenden, um das TeX zu schreiben:

0)

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

1) erstelle eine Vorlage

1.1) Ich bin mir sicher, dass es eine Möglichkeit gibt, diesen Schritt in einem Schritt durchzuführen, indem der Bildname durch eine Variable ersetzt und statt eines Anhängens eingefügt wird und $ FOO formatiert wird, um die richtigen führenden Nullen zu erhalten, aber das Folgende ist genau das, was ich weiß .

1.2) Die Vorlage muss geteilt werden, damit das Skript den Dateinamen einfügen kann

1.3) nano tmplt1 / * oder Editor Ihrer Wahl * /

/* 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) Ihre Dateien sind jedoch 0001.miff… 0010.miff… 0100.miff… 2000.miff. Dh eine variable Anzahl führender Nullen. Problemumgehung: 4 Versionen von tmplt1: tmplt1-9, tmplt10-99, tmplt100-999, tmplt1000-2000. Tmplt1-9 endet "... width] {000" (dh addiere 3 0's); tmplt10-99 endet "... width] {00" (dh addiere 2 0's). 100-999 addiert 1 Null und 1000-2000 ist dasselbe wie tmplt1

1.4) nächster Teil der Vorlage: nano tmplt2 / * OEOYC * /

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

1.5) nächster Teil der Vorlage: 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) nächste Vorlage: nano tmplt4 / * OEOYC * /

    }
\end{figure}

2) mach den Anfang der Datei: nano head / * OEOYC * /

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

3) mache das Ende der Datei: nano foot / * OEOYC * /

\end {document} 

4) Mach das Skript: 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) Skript ausführbar machen: chmod u + x loader

5.1) Nachdem ich dies getestet hatte, stellte ich fest, dass jedes Mal, wenn $ FOO eingefügt wurde, es über 3 Zeilen verteilt war. Ich kenne keine andere Möglichkeit, als das Skript aufzurufen und die Zeilenumbrüche manuell zu löschen. Zumindest sind es nur 36 für alle 2000 Fotos

6) Script aufrufen: Loader

7) kompiliere das TeX: pdflatex out.pdf

Dutzend Vocyemyorka
quelle