Script per uniformare i PDF

Pubblicato da Nicola Rainiero il 12-06-2012 (aggiornato il 11-08-2016)

Un grave difetto del mio eBook reader, l'Asus DR900, è l'impossibilità di ingrandire le pagine oltre il 200%, in genere non è un problema così grave ma quando cerco di leggere PDF che contengono anche pagine affiancate come quotidiani o documenti in formato A4 con inserti in A3, allora sono cavoli amari! Per sopperire a questa lacuna ho realizzato set-uniform-pagination.sh, uno script bash che illustrerò nell'articolo.

Uno dei motivi che mi ha spinto a comprare questo apparecchio è stata anche la presunzione di poter finalmente leggere in santa pace e senza stare attaccato al monitor del PC il Fatto Quotidiano, giornale di cui ho un abbonamento PDF annuale. Il loro sito offre due possibilità per scaricarlo:

  1. Tramite ActivePaper Daily di Olive Software, che permette di leggerlo on-line e di salvarlo sul proprio PC. Questa versione è molto pesante e contiene alcune pagine affiancate. Le specifiche del file scaricato indicano che è stato realizzato con Acrobat Distiller 7.0 in versione 1.6
  2. Tramite il link diretto disponibile nella pagina abbonati. Questa versione è tre volte più piccola della precedente e non contiene pagine affiancate. Leggendo le specifiche del PDF salvato si scopre che è stato realizzato con PDFsharp 1.2.1269-g, in versione 1.4.

Sul computer non ho mai avuto problemi con le due tipologie di file sopra descritte, ma sul lettore purtroppo tanti: le pagine affiancate del primo caso anche ingrandendole al 200% sono illeggibili, il secondo invece di tanto in tanto mi fa piantare il dispositivo o per lo meno devono passare svariati minuti per passare da una pagina all'altra.

Fermo restando che sono testardo di natura e taccagno per definizione, ho voluto trovare una soluzione a questo problema, dapprima cercando su internet e poi provando a scrivere qualche riga di codice. Alla fine ne è uscito uno script bash che mi consente di uniformare la prima versione e ridurla in un formato più digeribile all'eBook reader. Le specifiche finali recitano: GPL Ghostscript 8.71, versione 1.4 e formato in tutti i casi portato ad ISO A4 per tutte le pagine. Per quanto riguarda la dimensione del file posso scegliere se ottimizzarlo come “ebook” e allora si riduce della metà rispetto al PDF più pesante (possibilità 1) oppure con l'opzione “screen” si riduce di oltre un terzo, ma foto, diagrammi e soprattutto le vignette diventano troppo sgranati.

 

Il funzionamento

Prima di passare allo script ne mostro il funzionamento con un esempio pratico:

  • doppia_facciata.pdf è un documento che contiene 3 pagine: la seconda è in doppia facciata;
  • da shell lancio lo script in questo modo:
    ./set-uniform-pagination.sh doppia_facciata.pdf
  • ottenendo come file finale doppia_facciata_ebook.pdf.
File in ingresso:File restituito:
File PDF con inserti doppiFile PDF con inserti doppi divisi opportunamente

 

Lo script set-uniform-pagination.sh

Per poterlo usare bisogna avere i seguenti prerequisiti:

  • shell testuale bash, per poter eseguire lo script;
  • pdfinfo, per leggere il numero di pagine complessive che costituiscono il PDF e le dimensioni orizzontali e verticali di ogni pagina;
  • awk, per estrapolare le variabili prodotte da pdfinfo;
  • LaTeX con i pacchetti pdfpages per includere pagine PDF nei documenti e ifthen per poter inserire comandi condizionali;
  • Ghostscript per ottimizzare il file pdf ottenuto;
  • Se la prima pagina del PDF è in doppia facciata, bisogna editare lo script e sostituirla con un'altra singola.

Senza entrare troppo nei dettagli tecnici (basta editarlo e leggere i commenti inseriti) il suo funzionamento si può descrivere in questo modo: lettura delle informazioni che costituiscono il PDF di input (numero totale e dimensioni delle singole pagine), scrittura di un opportuno file LaTeX che si occupa di dividere le pagine eccedenti la dimensione orizzontale della prima (presa come riferimento) a metà, compilazione del file generato con il comando pdflatex e ottimizzazione con il comando gs di ghostscript.

Ecco l'archivio zip con lo script per il download: Script_to_PDF_uniform.zip

Ovviamente si può modificare a seconda delle proprie esigenze cambiando per esempio: il formato (A4 nello script), l'orientazione della carta ad orizzontale (da “portrait” a “landscape”), la pagina di riferimento, e molto altro.

Per i più pigri ecco il codice dello script:

#!/bin/bash
# Script written by Nicola Rainiero
# Available at http://rainnic.altervista.org
#
# This work is licensed under the Creative Commons Attribution 3.0 Italy License.
# To view a copy of this license, visit http://creativecommons.org/licenses/by/3.0/it/
#
# Requirements: pdfinfo, awk, LaTex with pdfpages and ifthen packages,ghostcript
# Usage: set-uniform-pagination.sh INPUT_FILE.pdf
#
if [ -n "$1" ]
then
	document=$1 # check if exist an input PDF file
else
	echo Missing input PDF 'file'!!
	exit 0
fi

echo $document
# read the exact number of page in the PDF file and write it in "pagine" variable
echo `pdfinfo $document | awk ' $1=="Pages:" {print $2}'` > input.txt 
pagine=$(cat input.txt | awk '{ SUM += $1} END { print SUM }')

echo $pagine
echo '% File di conversione' > latex.tex
# initialize the latex document: the default page layout is "portrait"
# to have the whole document pages changed to "landscape"
echo '\documentclass[a4paper,portrait]{minimal}' >> latex.tex;
echo '\usepackage[pdftex,portrait]{geometry}' >> latex.tex;
echo '\usepackage{pdfpages}' >> latex.tex;
echo '\usepackage{ifthen}' >> latex.tex;
echo '\newcounter{pg}' >> latex.tex;
echo '\begin{document}' >> latex.tex;

# read the horizontal dimension of the first page ("-f 1" option) and save it in: rifh
echo `pdfinfo -f 1 -box $document | awk ' $1=="MediaBox:" {print $4}'` > input.txt
rifh=$(cat input.txt | awk '{ SUM += $1} END { print SUM }')
echo $rifh
# read the vertical dimension of the first page ("-f 1" option) and save it in: rifv
echo `pdfinfo -f 1 -box $document | awk ' $1=="MediaBox:" {print $5}'` > input.txt
rifv=$(cat input.txt | awk '{ SUM += $1} END { print SUM }')
echo $rifv
echo

# check for every page the corresponding horizontal dimension
# and compare it with the "rifh" variable
for i in `seq 1 $pagine`
do
   echo `pdfinfo -f $i -box $document | awk ' $1=="MediaBox:" {print $4}'` > input.txt
   h=$(cat input.txt | awk '{ SUM += $1} END { print SUM }')
    echo $h
    if [[ "$h" -gt "$rifh+200" ]]
	then
		echo 'split' page
		echo '   \includepdf[pages='$i',viewport=0 0 '$rifh' '$rifv']{'$document'} ' >> latex.tex;
		echo '   \includepdf[pages='$i',viewport='$rifh' 0 '$h' '$rifv']{'$document'} ' >> latex.tex;
	else
		echo 'do' not 'split' page
		echo '   \includepdf[pages='$i',viewport=0 0 '$rifh' '$rifv']{'$document'} ' >> latex.tex;
	fi
done

# close the latex document and make pdf --> latex.pdf
echo '\end{document} ' >> latex.tex;
pdflatex latex.tex

# save in "nomefile" variable the exact name of the input file
nomefile=${1%%.*}
echo $nomefile

# optimize latex.pdf and rename it in "nomefile" plus the ebook label
gs -sDEVICE=pdfwrite -dCompatibilityLevel=1.4 -dPDFSETTINGS=/ebook -dNOPAUSE -dQUIET -dBATCH -sOutputFile="$nomefile"_ebook.pdf latex.pdf

# clean up useless files
rm input.txt
rm latex*
exit 0



Potrebbero interessarti anche:

Nicola Rainiero

Ingegnere civile specializzato in geotecnica con l'ambizione di facilitare la propria attività lavorativa usando e creando software libero per un sapere condiviso e collettivo. Mi occupo anche di energie rinnovabili ed in particolare di geotermia a bassa entalpia. Sono da sempre appassionato di web design e modellazione 3D.

Commenti