Obtenez plus de 2 Go de création de fichiers PDF avec ImageMagick

19

J'utilise convertpour créer un fichier PDF à partir d'environ 2000 images:

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

Le processus se termine reproductible lorsque le fichier de sortie a atteint 2 ^ 31-1 octets (2 Go -1) avec le message

convert: unknown `out.pdf'.

La spécification du fichier PDF autorise ≈10 Go . J'ai essayé d'extraire plus d'informations -debug all, mais je n'ai rien vu d'utile dans la sortie de journalisation. Le système de fichiers est ext3 qui permet des fichiers d'au moins jusqu'à 16 Gio (peut-être plus) . Quant à ulimit, file sizeest unlimited. /etc/security/limits.confne contient que des lignes commentées. Quoi d'autre peut provoquer cela et comment puis-je augmenter la limite?

Version d'ImageMagick: 6.4.3 2016-08-05
Distribution OpenMP Q16 : SLES 11.4 (i586)

Matthias Ronge
la source
4
Est-il possible de créer deux fichiers avec la moitié des images (ou ce qui vous convient le mieux), puis de les fusionner avec pdftk?
Gallifreyan
1
Avez-vous une bonne raison de créer un fichier PDF> 2 Go? Je crains que de nombreux lecteurs PDF ne plantent en tentant de l'ouvrir.
dr01
Parce que votre copie d'ImageMagick a été compilée sans prise en charge des fichiers volumineux. Veuillez signaler un bug - c'est 2017.
Réinstallez Monica - M. Schröder
@ dr01: Pourquoi devraient-ils? La prise en charge des fichiers volumineux existe depuis des décennies.
Rétablir Monica - M. Schröder
@ MartinSchröder Et pourtant, certains programmes ne sont pas capables de gérer des fichiers trop volumineux. Quoi qu'il en soit, j'étais curieux de savoir pourquoi créer un fichier PDF de 2 Go (soit environ 150 000 pages A4).
dr01

Réponses:

24

Votre limitation ne provient pas en effet du système de fichiers; ou à partir des versions de package, je pense .

Votre limite de 2 Go provient de vous en utilisant une version 32 bits de votre système d'exploitation.

L'option pour augmenter le fichier serait d'installer une version 64 bits si le matériel le prend en charge .

Voir Prise en charge des fichiers volumineux

Traditionnellement, de nombreux systèmes d'exploitation et leurs implémentations de système de fichiers sous-jacentes utilisaient des entiers 32 bits pour représenter les tailles et les positions des fichiers. Par conséquent, aucun fichier ne peut dépasser 2 32 - 1 octets (4 Go - 1). Dans de nombreuses implémentations, le problème a été exacerbé en traitant les tailles comme des numéros signés, ce qui a encore abaissé la limite à 2 31 - 1 octets (2 Go - 1).

Rui F Ribeiro
la source
3
Note latérale: Linux peut utiliser des tailles et des positions de fichiers 64 bits même sur 32 bits depuis une dizaine d'années. Bien qu'il ne soit pas sûr, que cet outil générateur de pdf puisse utiliser cette fonctionnalité.
peterh
2
@peterh ayant 64 bits off_tn'aidera pas si le logiciel essaie de créer tout le fichier en RAM et de l'écrire sur le disque en une seule fois.
Dmitry Grigoryev
2
Linux ne traite pas les tailles comme signées, mais le noyau a besoin d'un espace d'adressage dédié pour fonctionner, et dans le passé, laisser 2 Go au userland semblait beaucoup, donc le noyau réservait les 2 Go restants.
Dmitry Grigoryev
2
@DmitryGrigoryev: les tailles ne sont pas signées, mais les différences de pointeur ( ptrdiff_t) le sont, ce qui signifie effectivement que les tailles doivent être limitées à la valeur maximale (signée) ptrdiff_tpeut représenter, sinon vous obtenez des bogues UB et UB vraiment très désagréables que les applications n'ont pas bonne façon de contourner.
R ..
@DmitryGrigoryev Dans ce cas, le fichier n'aura pas exactement 2 Go-1 octets, car le programme a besoin de plus de mémoire pour stocker des éléments tels que le code exécutable.
user23013
12

Essayez de limiter le cache de pixels utilisé par convertexemple à 1 Gio:

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

Espérons que cela forcera ImageMagic à vider régulièrement les données déjà traitées sur le disque au lieu d'essayer de placer plus de 2 Gio dans les tampons RAM.

BTW, la quantité de mémoire virtuelle disponible pour un seul processus sous Linux 32 bits est définie par le VMSPLITparamètre de configuration du noyau. Cela peut être soit 2G / 2G (2 Go pour le noyau + 2 Go pour l'espace utilisateur) ou 1G / 3G (1 Go pour le noyau + 3 Go pour l'espace utilisateur). Sur un système en cours d'exécution, le paramètre peut être trouvé via

zcat /proc/config.gz | grep VMSPLIT

Sur certains systèmes, la configuration du noyau est stockée à la /boot/config-$(uname -r)place.

Dmitry Grigoryev
la source
1

Si ce n'était pas pour le grand nombre de photographies, vous pourriez utiliser TeX / LaTeX pour créer le PDF. Ensuite, vous pouvez toujours obtenir le même résultat (pdf d'images) sans le problème de crash du convertisseur. Les limites de fichiers sur TeX devraient être simplement votre système (matériel + OS)

Mais je pense que vous pourriez utiliser un script shell pour écrire le TeX:

0)

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

1) créez un modèle

1.1) Je suis sûr qu'il existe un moyen de faire cette étape en une seule fois, en remplaçant le nom de l'image par une variable et en l'insérant plutôt qu'en l'ajoutant, et à formater $ FOO pour avoir les bons 0 en tête, mais ce qui suit est exactement ce que je sais .

1.2) Le modèle doit être divisé pour que le script insère le nom du fichier

1.3) nano tmplt1 / * ou éditeur de votre choix * /

/* 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) Cependant, vos fichiers vont 0001.miff… 0010.miff… 0100.miff… 2000.miff. C'est-à-dire un nombre variable de zéros non significatifs. Solution: 4 versions de tmplt1: tmplt1-9, tmplt10-99, tmplt100-999, tmplt1000-2000. Tmplt1-9 termine «... largeur] {000» (c'est-à-dire ajouter 3 0); tmplt10-99 termine "... largeur] {00" (c'est-à-dire ajouter 2 0). 100-999 ajoute 1 zéro et 1000-2000 est le même que tmplt1

1.4) partie suivante du modèle: nano tmplt2 / * OEOYC * /

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

1.5) partie suivante du modèle: 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) modèle suivant: nano tmplt4 / * OEOYC * /

    }
\end{figure}

2) faire le début du fichier: nano head / * OEOYC * /

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

3) faire la fin du fichier: nano pied / * OEOYC * /

\end {document} 

4) faire le script: 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) Rendre le script exécutable: chmod u + x loader

5.1) Après avoir testé cela, j'ai constaté que chaque fois que $ FOO était inséré, il était réparti sur 3 lignes. Je ne connais pas d'autre solution que d'entrer dans le script et de supprimer manuellement les retours chariot. Au moins, c'est seulement 36 pour les 2000 photos

6) script d'appel: chargeur

7) compiler le TeX: pdflatex out.pdf

DozenalVocyemyorka
la source