Catégorie : Bureautique     Tags : ,      

    Retrouvez cet article dans : Linux Magazine 97

    Depuis le numéro 59, les Mongueurs de Perl vous proposent tous les mois de découvrir les scripts jetables qu’ils ont pu coder ou découvrir dans leur utilisation quotidienne de Perl. Bref, des choses trop courtes pour en faire un article, mais suffisamment intéressantes pour mériter d’être publiées. Ce sont les perles de Mongueurs.

    Supprimer une page d’un fichier PDF

    C’est avec beaucoup d’intérêt que j’ai suivi la série Heroes (qui est passée cet été en France). La chaîne NBC, qui produit celle-ci, utilise beaucoup Internet pour garder vivace l’intérêt des spectateurs pendant les périodes de pause de la série (parfois plus d’un mois !). Ainsi, les blogs des personnages sont mis à jour, certains envoient même des emails aux spectateurs inscrits, etc.
    La chaîne NBC propose également en téléchargement gratuit sur son site web des comic-books qui racontent des histoires de quelques pages qui se passent entre les épisodes de la série et rentrent dans les détails d’événements vus à la télévision.
    Le premier numéro de cette bande dessinée annexe est disponible à l’adresse suivante : http://www.nbc.com/Heroes/novels/downloads/Heroes_novel_001.pdf. Vous devriez arriver à trouver les autres épisodes (il y en a plus de trente à l’heure où j’écris ces lignes) sans difficulté, si cela vous intéresse. ;-)
    Pour ceux qui n’avaient pas remarqué en regardant la série, il y a un fabricant d’automobiles qui a sûrement beaucoup payé pour être cité dans quasiment chaque épisode... C’est également le cas du comic-book, qui commence par une énorme page de pub (beaucoup plus grosse que les pages du reste du PDF), ce qui gâche un peu la lecture (certains lecteurs ne sachant pas zoomer correctement pour afficher les pages suivantes au mieux).
    Cette page de publicité me gêne et me gâche la lecture. Voici comment je m’en suis débarrassé.

    PDF::API2

    Le module PDF::API2 permet de créer, lire, manipuler et sauvegarder des fichiers PDF. La documentation est très succincte et ne suffit pas forcément pour arriver à produire ses premiers PDF. Le module a une interface d’assez bas niveau, et il vaut mieux avoir quelques connaissances de PostScript ou de PDF pour s’en servir au mieux.
    Je vais créer un document PDF qui contient toutes les pages du PDF original, sauf la première. Afin de ressembler au document original, je vais de plus créer des bookmarks qui permettent d’accéder directement à chaque page.
    Dans le script qui suit, seules quelques méthodes de PDF::API2 seront utilisées :

    • open() et new(), qui permettent respectivement d’ouvrir un document PDF existant et d’en créer un vide.
    • importpage(), qui permet d’importer une page d’un document dans un autre, en donnant le numéro de la page à importer et celui de la page à ajouter dans le nouveau document.
    • info() et preferences() permettent de manipuler les informations associées au document, et les préférences à l’ouverture.
    • La méthode outlines() permet de créer un objet représentant les marque-pages (bookmarks) permettant d’accéder aux pages individuelles du document. PDF::API2 ne semble pas donner accès aux marque-pages d’un document existant (ou, en tout cas, je n’ai pas trouvé comment faire). Nous nous contenterons donc de liens titrés « Page 1 », « Page 2 », etc.
      L’objet outlines créé avec la méthode outlines() (au pluriel) contiendra les marque-pages créés avec la méthode outline(). Les paramètres de ces marque-pages sont définis avec title() et dest().
    • end() permet de libérer la mémoire occupée par le document. C’est important ici, car le script permet de traiter des fichiers en boucle.

    Voici le programme complet :

        #!/usr/bin/env perl
        use strict;
        use warnings;
        use PDF::API2;
        use Getopt::Long;
        my %conf;
        GetOptions( \%conf, ‚verbose!‘, ‚clobber!‘ )
            or die „Usage: remove_ad [ --verbose ] [ --clobber] file ...\n”;
        # traite tous les fichiers passés sur la ligne de commande
        for my $file (@ARGV) {
            # ouvre l’ancien PDF et affiche le nombre de pages
            my $old_pdf = PDF::API2->open($file);
            print «$file: «, $old_pdf->pages - 1, « pages, « if $conf{verbose};
            my $old_size = -s $file;
            # ouvre le nouveau PDF
            my $new_pdf  = PDF::API2->new();
            my $outlines = $new_pdf->outlines();
            # copie les pages en boucle, à partir de la page 2
            for my $page_num ( 2 .. $old_pdf->pages ) {
                # importe la page à la fin du document
                my $page = $new_pdf->importpage( $old_pdf, $page_num );
                # ajoute un lien vers la page 
    
                my $outline = $outlines->outline();
                $outline->title( «Page « . ( $page_num - 1 ) );
                $outline->dest($page);
            }
            # copie la structure d’information (Author, etc)
            $new_pdf->info( $old_pdf->info() );
            # le lecteur ouvrira le document sur la première page
            # qui remplira la page au mieux
            $new_pdf->preferences(
                -singlepage => 1,
                -firstpage  => [ $new_pdf->openpage(1), -fit => 1 ],
            );
            # sauve le nouveau fichier en écrasant l’ancien
            $file =~ s/\.pdf$/-noad.pdf/ if !$conf{clobber};
            $new_pdf->saveas($file);
            # statistiques de gain de taille
            print int( 100 * ( ( -s $file ) - $old_size ) / $old_size ), «%\n»
                if $conf{verbose};
            # détruit les objets en mémoire
            $new_pdf->end();
            $old_pdf->end();
        }

    J’en ai profité pour faire des calculs sur la différence de taille entre la version avec et sans publicité.
    À l’exécution, cela donne :

        $ ./remove_pdf_ad -v Heroes_novel_*.pdf
        Heroes_novel_001.pdf: 6 pages, -14%
        Heroes_novel_002.pdf: 6 pages, -21%
        Heroes_novel_003.pdf: 6 pages, -10%
        ...

    L’option --clobber que j’ai ajoutée permet d’écraser l’ancien fichier par le nouveau.

    Bilan

    La suppression de cette première publicité a permis un gain entre 15% et 30% sur la taille des divers PDF, ce qui est appréciable quand l’original pèse entre 10 et 20 mégaoctets (pour 6 à 9 pages).
    Et la lecture est beaucoup plus agréable ! :-)

    Posté par Philippe Bruhat (BooK) | Signature : Philippe « BooK » Bruhat | Article paru dans Creative Commons License

    Laissez une réponse

    Vous devez avoir ouvert une session pour écrire un commentaire.


    • Il y a actuellement

    • 465 articles/billets en ligne.