Pagine divise in pdf


67

Ho un file pdf scansionato che ha scansionato due pagine su una pagina virtuale (pagina in file pdf).

La risoluzione è di buona qualità. Il problema è che devo ingrandire durante la lettura e trascinare da sinistra a destra.
C'è qualche comando ( convert, pdftk, ...) o uno script che può convertire il file pdf con le pagine normali (una pagina dal libro = una pagina nel file pdf)?


1
Anche se non è la risposta più votata, questa mi ha davvero sorpreso. È semplice, corto, veloce ed elegante. Ho pensato che valesse la pena menzionarlo qui, perché a volte siamo troppo pigri per scorrere fino ad altre risposte ...
Peque

Per i record, l'operazione inversa (che unisce più pagine) può essere ottenuta dalla riga di comando (anziché "stampa su file") con pdfnup, dalla pdfjamsuite.
Skippy le Grand Gourou,

Risposte:


46

Ecco un piccolo script Python che utilizza la libreria PyPdf che svolge il lavoro in modo ordinato. Salvalo in uno script chiamato un2up(o come preferisci), rendilo eseguibile ( chmod +x un2up) ed eseguilo come filtro ( un2up <2up.pdf >1up.pdf).

#!/usr/bin/env python
import copy, sys
from pyPdf import PdfFileWriter, PdfFileReader
input = PdfFileReader(sys.stdin)
output = PdfFileWriter()
for p in [input.getPage(i) for i in range(0,input.getNumPages())]:
    q = copy.copy(p)
    (w, h) = p.mediaBox.upperRight
    p.mediaBox.upperRight = (w/2, h)
    q.mediaBox.upperLeft = (w/2, h)
    output.addPage(p)
    output.addPage(q)
output.write(sys.stdout)

Ignora eventuali avvisi di ammortamento; solo i manutentori di PyPdf devono preoccuparsene.

Se l'input è orientato in modo insolito, potrebbe essere necessario utilizzare coordinate diverse quando si troncano le pagine. Vedi Perché il mio codice non ha suddiviso correttamente ogni pagina in un PDF scansionato?


Nel caso sia utile, ecco la mia risposta precedente che utilizza una combinazione di due strumenti più un intervento manuale:

  • Pdfjam (almeno versione 2.0), basato sul pacchetto LaTeX di pdfpages , per ritagliare le pagine;
  • Pdftk , per rimettere insieme le metà sinistra e destra.

Entrambi gli strumenti sono necessari perché, per quanto ne so, pdfpages non è in grado di applicare due diverse trasformazioni alla stessa pagina in un flusso. Nella chiamata a pdftk, sostituire 42 con il numero di pagine nel documento di input ( 2up.pdf).

pdfjam -o odd.pdf --trim '0cm 0cm 14.85cm 0cm' --scale 1.141 2up.pdf
pdfjam -o even.pdf --trim '14.85cm 0cm 0cm 0cm' --scale 1.141 2up.pdf
pdftk O=odd.pdf E=even.pdf cat $(i=1; while [ $i -le 42 ]; do echo O$i E$i; i=$(($i+1)); done) output all.pdf

Se non hai pdfjam 2.0, è sufficiente avere un'installazione PDFLaTeX con il pacchetto pdfpages (su Ubuntu: hai bisogno di texlive-latex-consigliati Installa texlive-latex-raccomandato e forse (su Ubuntu: texlive-fonts-raccomandato Installa texlive-fonts-consigliato ), e usa il seguente driver file driver.tex:

\batchmode
\documentclass{minimal}
\usepackage{pdfpages}
\begin{document}
\includepdfmerge[trim=0cm 0cm 14.85cm 0cm,scale=1.141]{2up.pdf,-}
\includepdfmerge[trim=14.85cm 0cm 0cm 0cm,scale=1.141]{2up.pdf,-}
\end{document}

Quindi eseguire i seguenti comandi, sostituendo 42 con il numero di pagine nel file di input (che deve essere chiamato 2up.pdf):

pdflatex driver
pdftk driver.pdf cat $(i=1; pages=42; while [ $i -le $pages ]; do echo $i $(($pages+$i)); i=$(($i+1)); done) output 1up.pdf

La libreria PyPdf funziona perfettamente. L'ho modificato solo un po ' ed eseguito con python conv_pdf.py res.pdf . Come eseguiresti la tua sceneggiatura da linea di comando?
xralf,

Vorrei provare anche la versione con pdfjam (a causa del leggero ridimensionamento), ma dopo l'installazione del pacchetto pdfjam la mia shell non riconoscerà il pdfjamcomando.
xralf,

@xralf: il mio script Python legge solo dallo standard input e scrive sullo standard output. La versione pdfjam richiede pdfjam 2.0; è solo un piccolo involucro attorno alle pagine PDF e ho aggiunto il bit di LaTeX che genera in modo da poterlo utilizzare direttamente. Il problema del ridimensionamento è probabilmente risolvibile con pypdf, potrebbe essere un problema di dimensioni della pagina (potrei o meno essere in grado di aiutarti se fornisci maggiori dettagli su ciò che sta accadendo e in particolare le dimensioni della pagina coinvolte).
Gilles 'SO- smetti di essere malvagio'

Grazie, la differenza sta nella risoluzione leggermente peggiore, ma questo non ha importanza. Ci tornerò quando ne saprò di più sul Latex (è troppo complesso per me ora e la soluzione è davvero buona con PyPdf).
xralf,

1
@Gilles Versy script utile. Mi aspettavo di vedere qualcosa del genere in pdfjam, pdftk. Ad ogni modo, alcune persone potrebbero desiderare alcune modifiche per dividere le pagine su un altro asse e utilizzare ordini diversi. Questo è possibile con il cambiamento poche righe e conq.mediaBox.lowerRight = (w, h/2)
ony

52

Solo un'aggiunta da quando ho avuto problemi con lo script Python (e diverse altre soluzioni): per me ha mutoolfunzionato alla grande. È un'aggiunta semplice e piccola fornita con l'elegante mupdflettore. Quindi puoi provare:

mutool poster -y 2 input.pdf output.pdf

Per divisioni orizzontali, sostituire ycon x. E ovviamente puoi combinare le due soluzioni più complesse.

Sono davvero felice di averlo trovato (dopo anni di utilizzo quotidiano di mupdf :)

mutoolviene spedito con mupdf a partire dalla versione 1.4: http://www.mupdf.com/news


Installazione mupdfe mutooldalla fonte:

wget http://www.mupdf.com/downloads/mupdf-1.8-source.tar.gz
tar -xvf mupdf-1.8-source.tar.gz
cd mupdf-1.8-source
sudo make prefix=/usr/local install

Oppure vai alla pagina dei download per trovare una versione più recente.


3
Ho avuto un djvu ... l'ho trasformato in un poscritto (abbastanza veloce), poi in un pdf (tartaruga lenta) - e finalmente mutool lo ha tagliato così velocemente che pensavo non avesse funzionato - aveva!
Julien Puydt,

2
sì, sono stato anche molto contento della velocità.
martz,

3
Questo è il più semplice e migliore. mutoolè stato fatto per questo. Inoltre, attenzione -y, penso che nella maggior parte dei casi ciò che vuoi è -x.
fiatjaf,

2
Questa utility è molto veloce, tuttavia ho un problema con l'ordine delle pagine. Il comando alloca la pagina destra nella prima posizione e la pagina sinistra nella seconda. Qualcuno può aiutarmi con questo problema?
garciparedes,


16

Imagemagick può farlo in un solo passaggio:

$ convert in.pdf -crop 50%x0 +repage out.pdf

1
Grazie. Se aggiungo il -density 400parametro` ha una qualità ancora migliore.
xralf,

11
Sembra che convert utilizzi il raster come formato intermedio. Ciò provoca un aspetto sfocato anche quando il PDF originale contiene oggetti vettoriali.
ony

Qualcuno conosce un modo per farlo senza rasterizzare i contenuti della pagina lungo la strada ... o almeno per impostare una risoluzione più elevata?
Tomislav Nakic-Alfirevic,

questo ha reso i testi in immagini e creato pdf dalle immagini. Forse bello per le foto ma inutile per l'estrazione del testo.
andrej,

6

Il comando Converti di ImageMagick può aiutarti a ritagliare il tuo file in 2 parti. Vedi http://www.imagemagick.org/Usage/crop/

Se fossi in te, scriverei uno script (shell) come questo:

  1. Dividi il tuo file con pdfsam : 1 pagina = 1 file su disco (il formato non ha importanza. Scegli uno che ImageMagick conosce. Vorrei solo prendere PS o PDF.
  2. Per ogni pagina, ritaglia la prima metà e inseriscila in un file chiamato $ {PageNumber} A

  3. Ritaglia la seconda metà e inseriscila in un file chiamato $ {PageNumber} B.

    Ottieni 1A.pdf, 1B.pdf, 2A.pdf, 2B.pdf, ecc.

  4. Ora, assembla di nuovo in un nuovo PDF. Esistono molti metodi per farlo.

1
L'uso di ImageMagick non rasterizzerebbe i file? E dovresti spiegare l'ultima parte in linea, soprattutto a beneficio dei non francofoni nel pubblico.
Gilles 'SO- smetti di essere malvagio'

Perché non hai bisogno di capire il francese. Mostra semplicemente come utilizzare ImageMagick convert, pdftk o ghostscript (gs) da solo per raggiungere questo obiettivo. Mi piace usare pdftk. Il "rastering" non ha importanza in quanto si tratta di un documento scansionato.
Tiktak,

6

Basato sulla risposta di Gilles e su come trovare il conteggio delle pagine PDF che ho scritto

#!/bin/bash

pdforiginal=$1
pdfood=$pdforiginal.odd.pdf
pdfeven=$pdforiginal.even.pdf
pdfout=output_$1
margin=${2:-0}
scale=${3:-1}

pages=$(pdftk $pdforiginal dump_data | grep NumberOfPages | awk '{print $2}')

pagesize=$(pdfinfo $pdforiginal | grep "Page size" | awk '{print $5}')
margin=$(echo $pagesize/2-$margin | bc -l)

pdfjam -o $pdfood --trim "0cm 0cm ${margin}pt 0cm" --scale $scale $pdforiginal
pdfjam -o $pdfeven --trim "${margin}pt 0cm 0cm 0cm" --scale $scale  $pdforiginal

pdftk O=$pdfood E=$pdfeven cat $(i=1; while [ $i -le $pages ]; do echo O$i E$i; i=$(($i+1)); done) output $pdfout

rm $pdfood $pdfeven

Quindi posso correre

./split.sh my.pdf 50 1.2

dove 50 per regolare il margine e 1,2 per la scala.


4

Ecco una variante del codice PyPDF pubblicato da Gilles. Questa funzione funzionerà indipendentemente dall'orientamento della pagina:

import copy
import math
import pyPdf

def split_pages(src, dst):
    src_f = file(src, 'r+b')
    dst_f = file(dst, 'w+b')

    input = pyPdf.PdfFileReader(src_f)
    output = pyPdf.PdfFileWriter()

    for i in range(input.getNumPages()):
        p = input.getPage(i)
        q = copy.copy(p)
        q.mediaBox = copy.copy(p.mediaBox)

        x1, x2 = p.mediaBox.lowerLeft
        x3, x4 = p.mediaBox.upperRight

        x1, x2 = math.floor(x1), math.floor(x2)
        x3, x4 = math.floor(x3), math.floor(x4)
        x5, x6 = math.floor(x3/2), math.floor(x4/2)

        if x3 > x4:
            # horizontal
            p.mediaBox.upperRight = (x5, x4)
            p.mediaBox.lowerLeft = (x1, x2)

            q.mediaBox.upperRight = (x3, x4)
            q.mediaBox.lowerLeft = (x5, x2)
        else:
            # vertical
            p.mediaBox.upperRight = (x3, x4)
            p.mediaBox.lowerLeft = (x1, x6)

            q.mediaBox.upperRight = (x3, x6)
            q.mediaBox.lowerLeft = (x1, x2)

        output.addPage(p)
        output.addPage(q)

    output.write(dst_f)
    src_f.close()
    dst_f.close()

2

La soluzione migliore era mutool, vedi sopra:

sudo apt install mupdf-tools pdftk

la divisione:

mutool poster -y 2 input.pdf output.pdf

ma poi devi ruotare le pagine a sinistra:

pdftk output.pdf cat 1-endleft output rotated.pdf

Ancora nessuna sovrapposizione ...
MUY Belgio,

1

Sulla base della risposta di Benjamin ad AskUbuntu, consiglierei di usare lo strumento GUI chiamato gscan2pdf .

  1. Importa il file di scansione PDF in gscan2pdf. Si noti che i file PDF non di immagine potrebbero non funzionare. Le scansioni vanno bene, quindi non devi preoccuparti.

    inserisci qui la descrizione dell'immagine

  2. Potrebbe volerci un po 'di tempo a seconda delle dimensioni del documento. Aspetta che si carichi.

  3. Premi Ctrl + A per selezionare tutte le pagine e quindi ruotale (Ctrl + Maiusc + C) se necessario.

    inserisci qui la descrizione dell'immagine

  4. Vai su Strumenti >> Pulizia . Seleziona Layout come doppio e # pagine di output = 2 .

    inserisci qui la descrizione dell'immagine

  5. Premi OK e attendi fino al termine del lavoro.

    inserisci qui la descrizione dell'immagine

  6. Salva il file PDF. Fatto.


Testato, fallito con documenti pdf complessi con un enorme numero di immagini.
MUY Belgio,

0

la soluzione di moraes non ha funzionato per me. Il problema principale era il calcolo x5 e x6. Qui si deve considerare un offset, ovvero se lowerLeft non è su (0,0)

Quindi ecco un'altra variante, con adattamenti aggiuntivi per usare PyPDF2 e python 3:

import copy
import math
import PyPDF2
import sys
import io 

def split_pages(src, dst):
    src_f = io.open(src, 'r+b')
    dst_f = io.open(dst, 'w+b')

    input = PyPDF2.PdfFileReader(src_f)
    output = PyPDF2.PdfFileWriter()

    for i in range(input.getNumPages()):
        p = input.getPage(i) 
        q = copy.copy(p)
        q.mediaBox = copy.copy(p.mediaBox)

        x1, x2 = p.cropBox.lowerLeft
        x3, x4 = p.cropBox.upperRight        

        x1, x2 = math.floor(x1), math.floor(x2)
        x3, x4 = math.floor(x3), math.floor(x4)

        x5 = math.floor((x3-x1) / 2 + x1)
        x6 = math.floor((x4-x2) / 2 + x2)

        if x3 > x4:        
            # horizontal
            p.mediaBox.upperRight = (x5, x4)
            p.mediaBox.lowerLeft = (x1, x2)

            q.mediaBox.upperRight = (x3, x4)
            q.mediaBox.lowerLeft = (x5, x2)
        else:
            # vertical        
            p.mediaBox.lowerLeft = (x1, x6)
            p.mediaBox.upperRight = (x3, x4)

            q.mediaBox.upperRight = (x3, x6)
            q.mediaBox.lowerLeft = (x1, x2)

        output.addPage(p)
        output.addPage(q)

    output.write(dst_f)
    src_f.close()
    dst_f.close()

if __name__ == "__main__":
    if ( len(sys.argv) != 3 ):
        print ('Usage: python3 double2single.py input.pdf output.pdf')
        sys.exit(1)

    split_pages(sys.argv[1], sys.argv[2])
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.