Cortar páginas de un PDF en varias páginas [cerrado]


16

Tengo un montón de archivos PDF que contienen dos páginas "reales" en una sola página PDF; Me gustaría cortarlos por la mitad y poner cada mitad en una página separada. Esencialmente, necesito algo que haga exactamente lo contrario de pdfnup(o psnup). ¿Cómo se puede lograr esta hazaña?

La plataforma es Linux, se prefiere el código abierto; ya que tengo una gran cantidad de estos para hacer algo que puede ser programado (en lugar de una GUI) sería bueno, así que puedo darle una lista de ellos y hacer que los elimine.

Un script preexistente tampoco es la única opción; Si hay un código de muestra para manipular archivos PDF de manera similar con una biblioteca de terceros, probablemente pueda hackearlo para que haga lo que quiera.


Respuestas:


22

Puede resolver esto con la ayuda de Ghostscript. pdftksolo no puedo hacer eso (que yo sepa). Te daré los pasos de la línea de comandos para hacer esto manualmente. Será fácil escribir esto como un procedimiento, también con diferentes parámetros para tamaños de página y números de página. Pero dijiste que puedes hacerlo tú mismo ;-)

Cómo resolver esto con la ayuda de Ghostscript ...

... y por diversión, lo he hecho recientemente no con un archivo de entrada con páginas "dobles", sino uno con "agudos". Puede leer la respuesta para este caso aquí .

Tu caso es aún más simple. Parece que tienes algo similar a esto:

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

Desea crear 1 PDF con 4 páginas, cada una de las cuales tiene un tamaño de 421 pt x 595 pt.

Primer paso

Primero extraigamos las secciones izquierdas de cada una de las páginas de entrada:

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

¿Qué hicieron estos parámetros?

Primero, sepa que en PDF 1 pulgada == 72 puntos . Entonces el resto es:

  • -o ...............:Nombre de archivo de salida. Implícitamente también utiliza -dBATCH -dNOPAUSE -dSAFER.
  • -sDEVICE=pdfwrite : Queremos PDF como formato de salida.
  • -g................:establece el tamaño del medio de salida en píxeles. La resolución predeterminada de pdfwrite es 720 ppp. Por lo tanto, multiplique por 10 para obtener una coincidencia para PageOffset.
  • -c "..............:le pide a Ghostscript que procese el fragmento de código PostScript dado justo antes del archivo de entrada principal (que debe seguir -f).
  • <</PageOffset ....:establece el desplazamiento de la imagen de la página en el medio. (Por supuesto, para las páginas izquierdas, el desplazamiento [0 0]no tiene ningún efecto real).
  • -f ...............: procesar este archivo de entrada.

¿Qué resultado logró el último comando?

Éste:

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 paso

A continuación, las secciones correctas:

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

Tenga en cuenta el desplazamiento negativo ya que estamos desplazando la página hacia la izquierda mientras mantenemos el área de visualización estacionaria.

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 paso

Ahora combinamos las páginas en un archivo. También podríamos hacer eso con ghostscript, pero lo usaremos pdftken su lugar, porque es más rápido para este trabajo:

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

Hecho. Aquí está el resultado deseado. 4 páginas diferentes, tamaño 421x595 pt.

Resultado:

+------------+ +------------+ +------------+ +------------+   ^
|            | |            | |            | |            |   |
|     1      | |     2      | |     3      | |     4      |   |
|            | |            | |            | |            |5595 pt
|            | |            | |            | |            |   |
|            | |            | |            | |            |   |
|            | |            | |            | |            |   |
+------------+ +------------+ +------------+ +------------+   v
<-- 421 pt --> <-- 421 pt --> <-- 421 pt --> <-- 421 pt -->

@ Desconocido: ¡Gracias por el voto negativo! ¿Le gustaría escribir un comentario indicando alguna razón para esto?
Kurt Pfeifle

+1 para un uso asombroso del arte ASCII e instrucciones muy claras. Solo porque soy un CLI n00b, el \ s escapa de las líneas para que sea más fácil de leer, ¿verdad?
Journeyman Geek

@mullhausen: gracias por corregir el error tipográfico ( 421-> -421). ;-)
Kurt Pfeifle

6

Existe una herramienta pdfposter que se puede utilizar para crear archivos PDF con varias páginas para una página de entrada (en mosaico o cortando las páginas). Es similar a la herramienta poster, que hace lo mismo para los archivos PostScript.


pdfposter no maneja la impresión de contenido superpuesto en los bordes, para facilitar el ensamblaje del póster. Sin embargo, es un script de Perl, por lo que es bastante fácil de agregar.
Matthias Urlichs

3

Entonces, después de mucha más búsqueda (parece que "cortar páginas PDF" es una búsqueda mucho mejor), encontré un pequeño script llamado unpnupque utiliza poster, conversión de PDF / PS, y pdftkhacer exactamente lo que necesito. Es un poco largo, pero es muy superior a los otros métodos que encontré (como usar imagemagick) porque no rasteriza las páginas antes de escupirlas.

En caso de que mobileread desaparezca por alguna razón, el núcleo del script (licenciado bajo la GPLv2 o posterior por Harald Hackenberg <hackenberggmx.at>) es el siguiente:

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

1
Me encanta cuando las personas responden sus propias preguntas. Sin embargo, si necesita hacerlo con una GUI, especialmente si los tamaños de las páginas no son uniformes o si desea recortar aún más cada lado, consulte Briss: briss.sourceforge.net
frabjous

Debería poder hacer lo que quiera con PDFTK por sí mismo, sin todas las conversiones.
CarlF

@CarlF: pensé que sería posible, pero no puedo ver nada en la página de manual de PDFTK para manipular el contenido de las páginas. ¿Tienes alguna sugerencia para mí?
womble

@frabjous: ¿Qué hay de malo en responder tus propias preguntas?
Kurt Pfeifle

1
@womble: tus conversiones se realizan a través de PS / EPS. Esto está destinado a provocar pérdidas de calidad (fuentes incrustadas, transparencias, etc.). Mi sugerencia evita la PDF => EPS => PDFruta arriesgada y va por el PDF => PDF => PDFcamino más seguro .
Kurt Pfeifle

2

La respuesta de Kurt Pfeifle me pareció muy útil para mi situación similar. Pensé que podría compartir mi modificación de la solución con otros ...

Yo también tenía un PDF escaneado que tenía 2 páginas en cada hoja. Era un escaneo de 11 x 8,5 (pulgadas) de un folleto cosido en el lomo que quedó grapado cuando se escaneó originalmente, por lo tanto: página 1 del PDF = parte posterior y portada; PDF página 2 = páginas 2 y 3, etc. Esto se lee bien en pantalla pero no puede imprimirlo y luego engraparlo para hacer más copias del folleto.

Necesitaba poder imprimir esto en una copiadora dúplex; es decir, conviértalo de nuevo en un PDF "impuesto", listo para imprimir. Entonces, usando la solución de Kurt, hice este (ejem) "one-liner" para convertirlo nuevamente en medias páginas, en el orden correcto de página nuevamente. Funcionará para cualquier ALTURA y ANCHO, y también para cualquier número de páginas. En mi caso, tenía un folleto de 40 páginas (20 páginas escaneadas en el 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"

Solo necesita modificar los primeros parámetros en este comando para especificar HEIGHT y WIDTH y ORIG_FILE_PATH. El resto del comando calcula los diversos tamaños y llama a gs dos veces, luego pdftk. Incluso contará las páginas en su escaneo y luego producirá la especificación de clasificación correcta (para el escenario que di).

Produce algún progreso sobre lo que está haciendo, que se verá así:

+++ 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

Luego, para obtener la imposición de página que necesita para un folleto impreso, simplemente "imprima" pedida.pdf en un tamaño de página personalizado exactamente del tamaño que necesita (en mi ejemplo, 5.5 x 8.5), enviándolo a una "creación de folletos" "(en mi caso, utilicé Crear folleto de Christoph Vogelbusch para Mac en http://download.cnet.com/Create-Booklet/3000-2088_4-86349.html ).

El PDF resultante ahora volverá al tamaño de página original de 11 x 8.5 con 2 páginas por hoja, pero el pedido será tal que pueda imprimirlo a doble cara, encuadernación de borde corto y ¡listo! tendrá una copia impresa que puede fotocopiar y doblar y coser, reproduciendo el folleto original sin desarmar (o incluso necesariamente ver) el original.

¡Espero que esto ayude a alguien!

-C


1

Basado en la respuesta anterior de piptas :

En Windows, para dividir archivos PDF de tamaño carta con una sola imagen de portada al principio, lo siguiente funcionó muy bien para mí (tenga en cuenta el uso de [-612 0] en el segundo paso, un valor positivo creó páginas en blanco porque empujó en la dirección incorrecta .)

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

Tenga en cuenta el uso de -dFirstPage=2que le indica a gs que comience a procesar en la página 2.

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

Esto crea right-secciones.pdf de la misma manera. Y ahora la imagen de portada:

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

Luego, como no quería fusionarme con pdftk usando la entrada de página manual, dividí las secciones izquierda y derecha en archivos PDF separados en un nuevo directorio.

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

Luego me uno a los PDF en ese directorio, alfabéticamente (¡y afortunadamente eso significa que están ordenados en el orden correcto!) Y también ejecuto el resultado a través de ghostscript nuevamente para corregir "Advertencia: número de generación fuera del rango 0..65535, suponiendo 0. " errores producidos por pdftk que ghostscript llamó "itext-paulo-155 (itextpdf.sf.net-lawagie.com)" - también se redujo el tamaño del archivo a la mitad en mi uso. Con un original de 4.5MB, el resultado de pdftk fue de 6.7MB y el reprocesamiento de gswin32c lo redujo a 3.2 MB.

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

¡Y hemos terminado! Siéntase libre de eliminar la carpeta input_file, cover.pdf, input_temp.pdf, right_sections.pdf y left_sections.pdf. ;-)


1

si solo necesita imprimir los archivos PDF del lado izquierdo en un solo documento, y los archivos PDF del lado derecho en un solo documento, entonces el siguiente script basado en la respuesta de Kurt Pfeifle hará el truco (funciona para cualquier altura y anchura):

$ 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"

luego ejecútelo así:

$ ./split.sh thepdftosplit.pdf
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.