Obtenha mais de 2 GB de limite na criação de PDFs com o ImageMagick

19

Estou usando convertpara criar um arquivo PDF a partir de cerca de 2.000 imagens:

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

O processo termina reproduzível quando o arquivo de saída atinge 2 ^ 31-1 bytes (2 GB -1) com a mensagem

convert: unknown `out.pdf'.

A especificação do arquivo PDF permite ± 10 GB . Tentei obter mais informações -debug all, mas não vi nada útil na saída do log. O sistema de arquivos é ext3, que permite arquivos com pelo menos 16 GiB (pode ser mais) . Quanto a ulimit, file sizeé unlimited. /etc/security/limits.confcontém apenas linhas comentadas. O que mais pode causar isso e como posso aumentar o limite?

Versão do ImageMagick: 6.4.3-05-08 2016 Q16
Distribuição do OpenMP : SLES 11.4 (i586)

Matthias Ronge
fonte
4
É possível criar dois arquivos com metade das imagens (ou o que melhor lhe convier) e depois mesclá-los com o pdftk?
precisa
1
Você tem algum bom motivo para criar um arquivo PDF> 2 Gb? Receio que muitos leitores de PDF falhem ao tentar abri-lo.
dr01
Porque sua cópia do ImageMagick foi compilada sem o suporte a arquivos grandes. Por favor, registre um bug - é 2017.
Reinstate Monica - M. Schröder
@ dr01: Por que deveriam? O suporte a arquivos grandes existe há décadas.
Reintegrar Monica - M. Schröder
@ MartinSchröder E, no entanto, alguns programas não conseguem lidar com arquivos muito grandes. Enfim, fiquei curioso sobre o motivo da criação de um arquivo PDF de 2 Gb (ou seja, ~ 150.000 páginas A4).
dr01

Respostas:

24

Sua limitação não deriva de fato do sistema de arquivos; ou de versões de pacotes, eu acho .

Seu limite de 2 GB vem de você usando uma versão de 32 bits do seu sistema operacional.

A opção para aumentar o arquivo seria instalar uma versão de 64 bits se o hardware suportar .

Consulte Suporte a arquivos grandes

Tradicionalmente, muitos sistemas operacionais e suas implementações subjacentes de sistemas de arquivos usavam números inteiros de 32 bits para representar tamanhos e posições de arquivos. Conseqüentemente, nenhum arquivo pode ser maior que 2 32 - 1 bytes (4 GB - 1). Em muitas implementações, o problema foi agravado ao tratar os tamanhos como números assinados, o que reduziu ainda mais o limite para 2 31-1 bytes (2 GB-1).

Rui F Ribeiro
fonte
3
Nota lateral: o Linux pode usar tamanhos e posições de arquivos de 64 bits, mesmo em 32 bits, desde cerca de uma década atrás. Embora não seja certo, essa ferramenta geradora de pdf pode usar essa funcionalidade.
peterh diz restabelecer Monica 16/08/17
2
@peterh ter 64 bits off_tnão ajudará se o software tentar criar o arquivo inteiro na RAM e gravá-lo no disco de uma só vez.
Dmitry Grigoryev
2
O Linux não trata os tamanhos como assinados, mas o kernel precisa de algum espaço de endereço dedicado para funcionar, e antigamente, deixar 2 GB para a terra do usuário parecia muito, então o kernel reservaria os outros 2 GB.
Dmitry Grigoryev
2
@DmitryGrigoryev: Os tamanhos não são assinados, mas as diferenças de ponteiro ( ptrdiff_t) são, o que significa efetivamente que os tamanhos devem ser limitados ao valor máximo (assinado) ptrdiff_tpode representar, ou então você recebe bugs realmente desagradáveis ​​relacionados a UB e UB que os aplicativos não têm boa maneira de contornar.
R ..
@DmitryGrigoryev Nesse caso, o arquivo não terá exatamente 2 GB-1 bytes, pois o programa precisa de mais memória para armazenar itens como o código executável.
user23013
12

Tente limitar o cache de pixels usado por, convertpor exemplo, 1 GiB:

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

Espero que isso force o ImageMagic a despejar regularmente os dados já processados ​​no disco, em vez de tentar ajustar mais de 2 GiB nos buffers de RAM.

BTW, a quantidade de memória virtual disponível para um único processo no Linux de 32 bits é definida pela VMSPLITconfiguração do kernel. Pode ser 2G / 2G (2 GB para o kernel + 2 GB para a terra do usuário) ou 1G / 3G (1 GB para o kernel + 3 GB para a terra do usuário). Em um sistema em execução, a configuração pode ser encontrada via

zcat /proc/config.gz | grep VMSPLIT

Em alguns sistemas, a configuração do kernel é armazenada /boot/config-$(uname -r).

Dmitry Grigoryev
fonte
1

Se não fosse o grande número de fotografias, você poderia usar o TeX / LaTeX para criar o PDF. Então você ainda pode obter o mesmo resultado (pdf de imagens) sem o problema de falha do conversor. Os limites de arquivo no TeX devem ser apenas o seu sistema (hardware + SO)

Mas acho que você poderia usar um shell script para escrever o TeX:

0)

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

1) faça um modelo

1.1) Tenho certeza de que há uma maneira de executar essa etapa de uma só vez, substituindo o nome da imagem por variável e inserindo, em vez de anexando, e formatando $ FOO para ter os 0s iniciais corretos, mas a seguir é exatamente o que eu sei .

1.2) O modelo precisa ser dividido para que o script insira o nome do arquivo

1.3) nano tmplt1 / * ou editor de sua escolha * /

/* 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) No entanto, seus arquivos ficam 0001.miff… 0010.miff… 0100.miff… 2000.miff. Ou seja, um número variável de zeros à esquerda. Solução alternativa: 4 versões do tmplt1: tmplt1-9, tmplt10-99, tmplt100-999, tmplt1000-2000. Tmplt1-9 termina "... width] {000" (ou seja, adicione 3 0's); tmplt10-99 termina “... width] {00” (ou seja, adicione 2 0's). 100-999 adiciona 1 zero e 1000-2000 é o mesmo que tmplt1

1.4) próxima parte do modelo: nano tmplt2 / * OEOYC * /

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

1.5) próxima parte do modelo: 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) próximo modelo: nano tmplt4 / * OEOYC * /

    }
\end{figure}

2) faça o início do arquivo: nano head / * OEOYC * /

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

3) faça o final do arquivo: nano foot / * OEOYC * /

\end {document} 

4) faça o 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) torne o script executável: chmod u + x loader

5.1) Depois de testar isso, descobri que toda vez que $ FOO era inserido, ele se espalhava por três linhas. Não conheço nenhuma solução alternativa a não ser entrar no script e excluir manualmente os retornos de carro. Pelo menos são apenas 36 para todas as 2.000 fotos

6) script de chamada: carregador

7) compile o TeX: pdflatex out.pdf

DozenalVocyemyorka
fonte