[couverture de Linux Magazine 97]

Perles de Mongueurs (35)

Article publié dans Linux Magazine 97, septembre 2007.

[+ del.icio.us] [+ Developers Zone] [+ Bookmarks.fr] [Digg this] [+ My Yahoo!]

La perle de ce mois-ci a été rédigée par Philippe "BooK" Bruhat (book@mongueurs.net), de Lyon.pm et Paris.pm.

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 fabriquant 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 gache 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 succinte 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 :

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 premiere 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 ! :-)

Références

À vous !

Envoyez vos perles à perles@mongueurs.net, elles seront peut-être publiées dans un prochain numéro de Linux Magazine.

[IE7, par Dean Edwards] [Validation du HTML] [Validation du CSS]