Divida as páginas de um PDF em várias páginas [fechado]

16

Eu tenho vários arquivos PDF que contêm duas páginas "reais" em uma única página PDF; Eu gostaria de cortá-las ao meio e colocar cada metade em uma página separada. Essencialmente, preciso de algo que faça exatamente o oposto de pdfnup(ou psnup). Como esse feito pode ser alcançado?

A plataforma é Linux, preferencialmente de código aberto; como eu tenho uma grande pilha deles para fazer algo que possa ser script (ao contrário de uma GUI) seria bom, então eu posso apenas dar uma lista deles e fazer com que eles sejam eliminados.

Um script pré-existente também não é a única opção; se houver um código de exemplo para manipular PDFs de maneira semelhante a uma biblioteca de terceiros, provavelmente eu posso invadir o arquivo para fazer o que eu quero.

womble
fonte
Possível duplicata de Como posso dividir as páginas de um PDF no meio?
Skippy le Grand Gourou

Respostas:

22

Você pode resolver isso com a ajuda do Ghostscript. pdftksozinho não pode fazer isso (tanto quanto sei). Darei a você as etapas da linha de comando para fazer isso manualmente. Será fácil escrever isso como um procedimento, também com parâmetros diferentes para tamanhos e números de páginas. Mas você disse que pode fazer isso sozinho ;-)

Como resolver isso com a ajuda do Ghostscript ...

... e, por diversão, recentemente fiz isso não com um arquivo de entrada com páginas "dobradas", mas com um "triplo". Você pode ler a resposta para este caso aqui .

Seu caso é ainda mais simples. Você parece ter algo parecido com isto:

+------------+------------+   ^
|            |            |   |
|      1     |      2     |   |
|            |            | 595 pt
|            |            |   |
|            |            |   |
|            |            |   |
+------------+------------+   v
             ^
            fold
             v
+------------+------------+   ^
|            |            |   |
|      3     |      4     |   |
|            |            | 595 pt
|            |            |   |
|            |            |   |
|            |            |   |
+------------+------------+   v
<---------- 842 pt -------->

Você deseja criar 1 PDF com 4 páginas, cada uma com o tamanho de 421 pt x 595 pt.

Primeiro passo

Vamos primeiro extrair as seções esquerdas de cada uma das páginas de entrada:

gs \
    -o left-sections.pdf \
    -sDEVICE=pdfwrite \
    -g4210x5950 \
    -c "<</PageOffset [0 0]>> setpagedevice" \
    -f double-page-input.pdf

O que esses parâmetros fizeram?

Primeiro, saiba que no PDF 1 polegada == 72 pontos . Então o resto é:

  • -o ...............:Nomeia o arquivo de saída. Implicitamente também usa -dBATCH -dNOPAUSE -dSAFER.
  • -sDEVICE=pdfwrite : queremos PDF como formato de saída.
  • -g................:define o tamanho da mídia de saída em pixels. A resolução padrão do pdfwrite é 720 dpi. Portanto, multiplique por 10 para obter uma correspondência para o PageOffset.
  • -c "..............:solicita ao Ghostscript que processe o snippet de código PostScript fornecido antes do arquivo de entrada principal (que precisa ser seguido -f).
  • <</PageOffset ....:define o deslocamento da imagem da página no meio. (É claro que, para as páginas da esquerda, a troca por [0 0]não tem efeito real.)
  • -f ...............: processe esse arquivo de entrada.

Qual resultado o último comando alcançou?

Este:

Output file: left-sections.pdf, page 1
+------------+  ^
|            |  |
|     1      |  |
|            |595 pt
|            |  |
|            |  |
|            |  |
+------------+  v

Output file: left-sections.pdf, page 2
+------------+  ^
|            |  |
|     3      |  |
|            |595 pt
|            |  |
|            |  |
|            |  |
+------------+  v
<-- 421 pt -->

Segundo passo

A seguir, as seções corretas:

gs \
    -o right-sections.pdf \
    -sDEVICE=pdfwrite \
    -g4210x5950 \
    -c "<</PageOffset [-421 0]>> setpagedevice" \
    -f double-page-input.pdf

Observe o deslocamento negativo, pois estamos deslocando a página para a esquerda enquanto mantemos a área de visualização estacionária.

Resultado:

Output file: right-sections.pdf, page 1
+------------+  ^
|            |  |
|     2      |  |
|            |595 pt
|            |  |
|            |  |
|            |  |
+------------+  v

Output file: right-sections.pdf, page 2
+------------+  ^
|            |  |
|     4      |  |
|            |595 pt
|            |  |
|            |  |
|            |  |
+------------+  v
<-- 421 pt -->

Último passo

Agora combinamos as páginas em um arquivo. Poderíamos fazer isso com o ghostscript também, mas usaremos em pdftkvez disso, porque é mais rápido para este trabalho:

pdftk \
  A=right-sections.pdf \
  B=left-sections.pdf \
  shuffle \
  output single-pages-output.pdf
  verbose

Feito. Aqui está o resultado desejado. 4 páginas diferentes, tamanho 421x595 pt.

Resultado:

+------------+ +------------+ +------------+ +------------+   ^
|            | |            | |            | |            |   |
|     1      | |     2      | |     3      | |     4      |   |
|            | |            | |            | |            |5595 pt
|            | |            | |            | |            |   |
|            | |            | |            | |            |   |
|            | |            | |            | |            |   |
+------------+ +------------+ +------------+ +------------+   v
<-- 421 pt --> <-- 421 pt --> <-- 421 pt --> <-- 421 pt -->
Kurt Pfeifle
fonte
@Desconhecido: Obrigado pela votação! Você gostaria de escrever um comentário indicando algum motivo para isso?
Kurt Pfeifle
+1 para uso impressionante da arte ASCII e instruções muito claras. Só porque eu sou um CLI n00b, eles escapam das linhas e ficam mais fáceis de ler, certo?
Journeyman Geek
@ Müllhausen: obrigado por corrigir o erro de digitação ( 421-> -421). ;-)
Kurt Pfeifle
6

Existe uma ferramenta pdfposter que pode ser usada para criar PDFs com várias páginas para uma página de entrada (lado a lado ou cortando as páginas). É semelhante à ferramenta poster, que faz o mesmo para arquivos PostScript.

Philipp Wendler
fonte
O pdfposter não lida com a impressão de conteúdo sobreposto nas bordas, para facilitar a montagem do pôster. Porém, é um script Perl, por isso é bastante fácil de adicionar.
Matthias Urlichs
3

Então, depois de muito mais pesquisa (parece que "páginas cortadas em PDF" é uma pesquisa muito melhor), encontrei um pequeno script chamado unpnupque usa poster, conversão de PDF / PS e pdftkpara fazer exatamente o que preciso. É um pouco longo, mas é muito superior aos outros métodos que encontrei (como usar o imagemagick) porque não rasteriza as páginas antes de cuspi-las.

Caso o mobileread desapareça por algum motivo, o núcleo do script (licenciado sob a GPLv2 ou mais recente por Harald Hackenberg <hackenberggmx.at>) é o seguinte:

pdftk "$1" burst
for file in pg*.pdf;
do
    pdftops -eps $file
    poster -v -pA4 -mA5 -c0% `basename $file .pdf`.eps > `basename $file .pdf`.tps
    epstopdf `basename $file .pdf`.tps
done
pdftk pg*.pdf cat output ../`basename $1 .pdf`_unpnuped.pdf
womble
fonte
11
Tem que amar quando as pessoas respondem suas próprias perguntas. No entanto, se for necessário para fazê-lo com uma GUI, especialmente se os tamanhos de páginas não estavam mesmo ou você queria mais cultura cada lado, veja Briss: briss.sourceforge.net
frabjous
Você deve poder fazer o que quiser com o PDFTK por si só, sem todas as conversões.
CarlF 22/09/10
@CarlF: Eu pensei que seria possível, mas não consigo ver nada na página do manual PDFTK para manipular o conteúdo das páginas. Tem alguma dica para mim?
womble 23/09/10
@frabjous: O que há de errado em responder suas próprias perguntas?
Kurt Pfeifle
11
@ womble: suas conversões são feitas via PS / EPS. Isso pode levar a perdas de qualidade (fontes incorporadas, transparências etc.). Minha sugestão evita a PDF => EPS => PDFrota arriscada e segue o PDF => PDF => PDFcaminho mais seguro .
Kurt Pfeifle
2

Achei a resposta de Kurt Pfeifle muito útil para minha situação semelhante. Pensei em compartilhar minha modificação da solução com outras pessoas ...

Eu também tinha um PDF digitalizado com 2 páginas em cada folha. Foi uma digitalização de 11 x 8,5 (polegadas) de um livreto costurado na sela que foi grampeado quando digitalizado originalmente; portanto: página 1 do PDF = contracapa e capa; Página 2 do PDF = páginas 2 e 3, etc. Isso lê bem na tela, mas você não pode imprimi-lo e grampá-lo para fazer mais cópias do livreto.

Eu precisava imprimir isso em uma copiadora duplex; ou seja, transformá-lo em um PDF "imposto", pronto para impressão. Então, usando a solução de Kurt, criei esse (ahem) "one-liner" para convertê-lo novamente em meia página, na ordem correta da página novamente. Ele funcionará para qualquer altura e largura e também para qualquer número de páginas. No meu caso, eu tinha um livreto de 40 páginas (20 páginas digitalizadas no PDF).

HEIGHT=8.5 WIDTH=11 ORIG_FILE_PATH="original.pdf" \
count=$(set -xe; \
gs -o left.pdf -sDEVICE=pdfwrite \
-g$(perl -e "print(($WIDTH / 2) * 720)")x$(perl -e "print($HEIGHT * 720)") \
-c "<</PageOffset [0  0]>> setpagedevice" \
-f "$ORIG_FILE_PATH" >/dev/null; \
gs -o right.pdf -sDEVICE=pdfwrite \
-g$(perl -e "print(($WIDTH / 2) * 720)")x$(perl -e "print($HEIGHT * 720)") \
-c "<</PageOffset [-$(perl -e "print(($WIDTH / 2) * 72)")  0]>> setpagedevice" \
-f "$ORIG_FILE_PATH" | grep Page | wc -l ); \
echo '>>>>>' Re-ordering $count pages...; \
(set -xe; pdftk A=right.pdf B=left.pdf cat \
A1 `set +xe; for x in $(seq 2 $count); do echo B$x A$x; done` B1 \
output ordered.pdf); \
echo "Done. See ordered.pdf"

Você só precisa alterar os primeiros parâmetros neste comando para especificar HEIGHT, WIDTH e ORIG_FILE_PATH. O restante do comando calcula os vários tamanhos e chama gs duas vezes, depois pdftk. Contará até as páginas em sua digitalização e produzirá a especificação de classificação correta (para o cenário que eu dei).

Ele produz algum progresso sobre o que está fazendo, que será assim:

+++ perl -e 'print((11 / 2) * 720)'
+++ perl -e 'print(8.5 * 720)'
++ gs -o left.pdf -sDEVICE=pdfwrite -g3960x6120 -c '<</PageOffset [0  0]>> setpagedevice' -f original.pdf
++ wc -l
++ grep Page
+++ perl -e 'print((11 / 2) * 720)'
+++ perl -e 'print(8.5 * 720)'
+++ perl -e 'print((11 / 2) * 72)'
++ gs -o right.pdf -sDEVICE=pdfwrite -g3960x6120 -c '<</PageOffset [-396  0]>> setpagedevice' -f original.pdf
>>>>> Re-ordering 20 pages...
++ set +xe
+ pdftk A=right.pdf B=left.pdf cat A1 B2 A2 B3 A3 B4 A4 B5 A5 B6 A6 B7 A7 B8 A8 B9 A9 B10 A10 B11 A11 B12 A12 B13 A13 B14 A14 B15 A15 B16 A16 B17 A17 B18 A18 B19 A19 B20 A20 B1 output ordered.pdf
Done. See ordered.pdf

Em seguida, para obter a imposição de página necessária para um livreto impresso, basta "imprimir" pedidos.pdf em um tamanho de página personalizado exatamente do tamanho que você precisa (no meu exemplo, 5,5 x 8,5), enviando-o para uma "criação de livreto" "(no meu caso, usei o Create Booklet for Mac de Christoph Vogelbusch em http://download.cnet.com/Create-Booklet/3000-2088_4-86349.html ).

O PDF resultante agora estará de volta ao tamanho da página original de 11 x 8,5 com 2 páginas por folha, mas a ordem será tal que você poderá imprimi-lo em frente e verso, encadernação pela borda curta e pronto! você terá uma impressão que poderá fotocopiar, dobrar e encadernar, reproduzindo o livreto original sem nunca desmontar (ou mesmo necessariamente ver) o original.

Espero que isso ajude alguém!

-c

Chris Thorman
fonte
1

Com base na resposta dos piptas acima:

No Windows, para dividir PDFs em tamanho de carta com uma única imagem de capa no início, o seguinte funcionou muito bem para mim (observe o uso de [-612 0] na segunda etapa, um valor positivo criou páginas em branco porque era errado. .)

gswin32c -o left-sections.pdf -sDEVICE=pdfwrite -dFirstPage=2 -g6120x7920 -c "<</PageOffset [0 0]>> setpagedevice" -f input.pdf

Observe o uso do -dFirstPage=2qual instrui o gs a iniciar o processamento na página 2.

gswin32c -o right-sections.pdf -sDEVICE=pdfwrite -dFirstPage=2 -g6120x7920 -c "<</PageOffset [-612 0]>> setpagedevice" -f input.pdf

Isso cria seções-direita.pdf da mesma maneira. E agora a imagem da capa:

gswin32c -o cover.pdf -sDEVICE=pdfwrite -dLastPage=1 -g6120x7920 -c "<</PageOffset [0 0]>> setpagedevice" -f input.pdf

Em seguida, como não queria mesclar com o pdftk usando a entrada manual de páginas, divida as seções esquerda e direita em PDFs separados em um novo diretório.

mkdir input_file
copy cover.pdf input_file\0000.pdf
pdftk left-sections.pdf burst output input_file\%04d_A.pdf
pdftk right-sections.pdf burst output input_file\%04d_B.pdf

Então, ingresso nos PDFs nesse diretório, em ordem alfabética (e felizmente isso significa que eles estão classificados na ordem certa!) E também executo o resultado no ghostscript novamente para corrigir "Aviso: Número da geração fora do intervalo de 0..65535, assumindo 0. " erros produzidos pelo pdftk, que o ghostscript chamou "itext-paulo-155 (itextpdf.sf.net-lawagie.com)" - também passou a reduzir pela metade o tamanho do arquivo em meu uso. Com um original de 4,5 MB, o resultado do pdftk foi de 6,7 MB e o reprocessamento do gswin32c reduziu para 3,2 MB.

pdftk input_file\*.pdf cat output input_temp.pdf
gswin32c -o final_output.pdf -sDEVICE=pdfwrite -f input_temp.pdf

E nós terminamos! Sinta-se à vontade para excluir a pasta input_file, cover.pdf, input_temp.pdf, right_sections.pdf e left_sections.pdf. ;-)

Louis
fonte
1

se você só precisa imprimir os PDFs do lado esquerdo em um documento e os PDFs do lado direito em um documento, o script a seguir, com base na resposta de Kurt Pfeifle, fará o truque (funciona para qualquer altura e largura):

$ cat split.sh
#!/bin/bash                                                                     

dims=$(pdfinfo "$1" | grep -i "page size:" | cut -d ":" -f2)                    
width=$(echo "$dims" | cut -d " " -f7)                                          
height=$(echo "$dims" | cut -d " " -f9)                                         
half_width=$(echo "$width * 0.5" | bc -l | cut -d "." -f1)                      
half_widthtt=$(echo "$width * 5" | bc -l | cut -d "." -f1)                      
heighttt=$(echo "$height * 10" | bc -l | cut -d "." -f1)                        

echo "pdf $1 has height $height and width $width"                               

gs -o "left-$1" -sDEVICE=pdfwrite -g"$half_widthtt"x"$heighttt" -c "<</PageOffset [0 0]>> setpagedevice" -f "$1"
gs -o "right-$1" -sDEVICE=pdfwrite -g"$half_widthtt"x"$heighttt" -c "<</PageOffset [-$half_width 0]>> setpagedevice" -f "$1"

em seguida, execute-o assim:

$ ./split.sh thepdftosplit.pdf
Mulllhausen
fonte