Le royaume de Eric Buist >> Informatique >> Quelques-unes de mes recherches personnelles | ||
Me contacter | Plan du site | |
<< Mon hypothèse actuelle sur le fonctionnement d'un gestionnaire de disques | Agrandissement de fichiers PDF | Problèmes avec Serial ATA >> |
En automne 2002, j'ai pris le cours Processus Cognitifs 1 (PSY1065), donné par Nathalie Gosselin, à l'Université de Montréal. J'ai choisi ce cours dans le cadre d'un cours à option complémentaire à mon baccalauréat en informatique. Le cours s'annonçait bien, moins pire que je ne le craignais. D'abord, il n'y aurait aucun travail pratique, encore moins de travail en équipe de quatre ou cinq nécessitant des rencontres en soirée ou la fin de semaine pour accomoder des étudiants qui travaillent. En plus, des notes disponibles en format PDF m'éviteraient de passer le cours à transcrire à toute vitesse ce que la prof dirait pour me retrouver au final avec un cahier rempli de gribouillis assez difficiles à lire pour ralentir l'étude. Ce que je ne savais pas, c'était que ces notes constitueraient l'objet d'une expérience personnelle informatique plutôt gourmande en ressources systèmes... et en temps. En effet, le texte de ces fichiers étaient écrit trop petit si bien que je dus me construire un outil pour l'agrandir. La tâche a été rendue difficile par le fait que les fichiers PDF ne peuvent pas être modifiés facilement.
Dimanche, le 15 septembre 2002, je parvins à obtenir les notes de cours via le système WebCT après avoir changé mon code initial (que je ne connaissais pas et qui semblait ardu à obtenir pour moi) en utilisant le profil informatique de la DGTIC. Au cours suivant cette petite victoire, le professeur affichait les noms des usagers avec les mots de passe initiaux; ma crainte que ces informations ne soient disponibles que sur un babillard, au pavillon Marie-Victorin, s'était avérée injustifiée. Heureusement, je n'ai pas perdu trop de temps à me forcer un accès. Les PDF se présentaient comme des produits de Adobe Distiller 3, inclus avec Adobe Acrobat 3. Puisque la présentation en classe tournait sous Microsoft PowerPoint, il était logique de penser que ces PDF avaient été produits à partir des diapositives PowerPoint.
Lorsque je remarquai les six diapositives par page, je regardai s'il n'y avait pas une autre version, et il n'en était rien. Une version à six diapositives par page est préférée par plusieurs étudiants en raison de l'économie de papier réalisée. Toutefois, dans mon cas, la petite taille des caractères me génait. Afin de pouvoir étudier dans des conditions optimales, sans devoir payer de maux de tête de bons résultats pour ce cours, un agrandissement s'avérait une bonne chose.
Malheureusement, contrairement aux formats éditables tels que le PowerPoint ou, mieux encore, le OpenOffice.org Impress ou le LaTeX Beamer, le PDF est difficile à modifier. Il est comparable à un document sur papier que l'on ne peut éditer ou reformater. Or il s'adonne que pour résoudre un problème d'adaptation comme un agrandissement, le reformatage est le meilleur moyen. Il me semblait compliqué d'obtenir les fichiers PowerPoint originaux, car il doit y avoir des droits d'auteur sur certains éléments de contenu. J'aurais peut-être dû m'essayer, mais je ne pouvais pas manquer cette occasion de m'amuser un peu avec les outils de Linux. J'ai donc développé ma propre solution que je présente sur cette page. Le procédé s'inspire de ce que j'aurais fait si je n'avais disposé d'aucune version électronique des documents pour en obtenir des agrandissements.
Si nous rencontrons un document papier avec des caractères trop petits, la seule solution consiste à le récrire au traitement de texte ou à le photocopier sur du papier plus grand. La méthode de récriture donnera certes d'excellents résultats, mais elle prendra beaucoup de temps. Des problèmes surgiront lors de l'importation des images qui devront, idéalement, être reconstruites de façon vectorielle ou au pire numériséee. La reconstruction est ardue, mais elle donnera une image qui pourra subir des agrandissements arbitraires. La numérisation exige un scanner et j'en possédais un, mais il faudrait aussi beaucoup de temps. Il était envisageable d'utiliser PowerPoint pour la lourde tâche, mais cela pourrait aussi se faire avec Word ou même LaTeX.
La photocopie, quant à elle, serait moins laborieuse, mais les résultats laisseraient à désirer. Un grossissement de 1.5x exigerait l'usage de papier de taille 32.385cm par 41.91cm, ce qui est non-standard. Il n'existe probablement pas un tel type de papier, encore moins un appareil qui pourra le traiter! Ce calcul a été obtenu en multipliant 8.5x11 pouces par 2.54cm/pouce puis par le facteur choisi, soit 1.5. Même si la photocopie était possible, la manipulation de ces gigantesques feuilles de papier, qui n'entreraient dans aucun cartable, serait très agaçante. Une solution alternative serait de diviser chaque page et d'agrandir chaque portion séparément, sur une feuille distincte; la page originale deviendrait plusieurs pages photocopiées. Avec cette méthode, la photocopie devrait se faire en multiples passes et un travail de calibrage important serait requis pour des résultats peu appréciables: du texte en oblique, l'apparition d'une partie de la page suivante ou précédente, des portions noires et d'autres artéfacts devront être prévus et tolérés.
La technique idéale consisterait à réaliser la photocopie agrandie sur une feuille de papier plus grande puis à utiliser une tranche pour découper les différentes diapositives. Ensuite, il faudrait réassembler les diapositives deux par deux sur des feuilles 8.5x11! Toutes ces solutions me semblaient longues à mettre en oeuvre et surtout très frustrantes. Ce cours ne valait pas la peine que j'y consacre autant de temps. Mais tout ce travail de moine bricoleur peut s'effectuer beaucoup plus facilement dans l'univers numérique et il établit la base du système informatique qui a résolu mon problème.
Il paraissait pour moi envisageable d'appliquer les différentes transformations évoquées dans la section précédente au fichier PDF et non à une version papier. Toutefois, un tel traitement pouvait vite devenir extrêmement fastidieux, frustrant et propice aux erreurs de manipulation. Il fallait donc utiliser des outils afin de l'automatiser et aucun logiciel ne permet de résoudre un problème aussi particulier. La solution résidait dans la combinaison de différents programmes qui seraient orchestrés par un script Perl, qui est un langage de programmation.
Cette étape est à la fois délicate et décisive, car elle déterminera la qualité et la lisibilité du produit fini. Si nous prenons une photographie numérisée et que nous lui appliquons un facteur d'agrandissement 1.5, le minimum pour rendre les diapositives utilisables efficacement pour moi, il s'ensuivra de l'aliasage, un fâcheux effet d'escalier. Sur du texte, ce sera un cauchemar pour la lecture ultérieure. Sans précautions, le fichier PDF agrandi sera encore plus difficile à lire que l'original!
La solution consiste à tirer parti des propriétés vectorielles du format PDF, et son cousin le PostScript. Le fichier PDF n'indique pas l'emplacement individuel de chacun des pixels mais plutôt comment afficher le document à l'aide de primitives (lignes, courbes, texte, etc.) de haut niveau. J'utilisai ici la commande pdf2ps de la version Linux de AFPL GhostScript afin d'obtenir le PostScript. PostScript est un langage de programmation destiné à contrôler des imprimantes du même type; la conversion ne viole pas les propriétés vectorielles du PDF. Le texte inscrit est toujours initié par des commandes et non un ensemble de pixels comme ce sera vite le cas après l'agrandissement.
GhostScript fournit un interpréteur PostScript logiciel à travers la commande gs. Malheureusement, la syntaxe de gs n'est pas simple et elle ne permet pas de spécifier une taille arbitraire pour un PostScript. Il fallut donc trouver une autre solution et ImageMagick me sembla approprié. Cet ensemble comprend des outils en ligne de commande pour réaliser des manipulations et appliquer des effets spéciaux de tous types sur différents formats d'images. Contrairement à des logiciels professionnels tels que Adobe PhotoShop, ImageMagick peut être facilement appelé depuis un script Perl.
Je décidai de convertir mes fichiers PDF agrandis vers le format Portable Network Graphics (PNG), car ce format permet une bonne compression sans perte de données. J'aurais aussi pu utiliser le Graphic Interchange Format (GIF) qui comporte la même qualité. Il est essentiel que les manipulations n'infligent pas de pertes de données en raison de décompressions et de recompressions successives. Le JPEG, qui est un format avec pertes, est donc ici à proscrire.
Après quelques recherches, je constatai avec soulagement que la commande convert de ImageMagick permet, grâce à son option -crop, de réaliser le découpage. Sans cette commande, il aurait fallu effectuer le travail manuellement avec un outil tel que The Gimp. La commande identify, de son côté, permet d'obtenir les dimensions de l'image. Un calcul numérique simple devait alors être utilisé pour déterminer des coordonnées de découpage, à savoir la position sur la page où débuter la coupure et la taille de la zone qui serait ainsi isolée, tout cela spécifié en pixels. L'étape précédente produit un fichier PNG par page tandis que cette nouvelle étape en produit six par pages, un par diapositive en fait.
Il me fallut un peu de temps pour découvrir une façon de réunir deux par deux les différents fichiers PNG obtenus à l'étape précédente. Finalement, je me rendis compte que l'option -append de la commande convert de ImageMagick permet d'empiler un ensemble d'images à la verticale, exactement ce qu'il fallait!
Nous avons alors deux fois moins de fichiers PNG puisqu'ils sont regroupés en paires, que nous appellerons ici pages finales. Toutefois, l'impression de tout cela devient astreignante, car chaque page exige des manipulations. Il fallait ainsi regrouper les fichiers, et convert semblait apte à réaliser la tâche.
Les grandes lignes de la technique mises au point, quelques détails demeuraient: que vont être les quantités numériques à utiliser? Quel est le facteur de grossissement maximal que l'on pourra tolérer? Le logiciel Adobe Acrobat Reader, après ouverture du PDF original, indiquait une largeur de papier de 8.26x11.69 pouces. Malheureusement, les pouces ne parlent pas à ImageMagick; la taille en pixels est requise. Par chance, il existe une règle simple: taillepouces*res=taillepixel, où res est la résolution en pixels par pouce de l'image. Mais nous ne connaissons pas la résolution...
L'application de pdf2ps produit un PostScript qui peut alors être traité par la commande identify de ImageMagick. Pour le premier cours de PSY1065, la commande donnait
cours1.ps[0] PS 560x806 PseudoClass 256c 8-bit 3085kb 0.1u 0:01 cours1.ps[1] PS 560x806 PseudoClass 256c 8-bit 3085kb 0.1u 0:01 cours1.ps[2] PS 560x806 PseudoClass 256c 8-bit 3085kb 0.1u 0:01 cours1.ps[3] PS 560x806 PseudoClass 256c 8-bit 3085kb 0.1u 0:01 cours1.ps[4] PS 560x806 PseudoClass 256c 8-bit 3085kb 0.1u 0:01 cours1.ps[5] PS 560x806 PseudoClass 256c 8-bit 3085kb 0.0u 0:01 cours1.ps[6] PS 560x806 PseudoClass 256c 8-bit 3085kb 0.0u 0:01
Ainsi, la taille en pixels s'élevait à 560 par 806. Nous pouvons alors calculer la résolution en dpi (dots per inch).
560px/8.5po | = | 65.88dpi |
806px/11po | = | 73.27dpi |
Cela ne cadre pas du tout puisqu'en général, la résolution est la même sur les deux axes. Il fallait donc tenter de se passer de cette information inconnue. Les PDF de PowerPoint comportent trois rangées de deux diapositives. Nous pouvons alors calculer que la taille d'une sous-page, en pouces, se chiffre à 8.5/2x11/3=4.25x3.67. Si nous doublons la taille des pages, nous obtenons des diapositives de taille 8.5x7.34 pouces, ce qui est trop grand pour en placer deux par page, à la verticale. La taille maximale verticale est de 5.5 pouces, donc 5.5/3.67=1.49 est le facteur maximal de grossissement que nous arrondirons à 1.5 pour plus de simplicité.
Mercredi, 16 octobre 2002, je tentai ma première conversion avec ImageMagick. La commande convert -size 840x1209 page.ps page.png fut mise en oeuvre pour chaque page. Malheureusement, la conversion ne tenait pas compte des propriétés vectorielles du PDF et nous obtenions une image aliasée, difficile à lire. gs est la seule et unique solution non commerciale et scriptable possible pour agrandir le PostScript, mais la résolution demandée par gs était manquante. Je me rendis heureusement compte d'une erreur de précision quant à la taille du papier et refis le calcul précédent avec les données d'Acrobat Reader plutôt que celle de identify.
560px/8.26po | = | 67.8dpi |
806px/11.69po | = | 68.9dpi |
Les valeurs sont nettement plus rapprochées et nous pouvons arrondir à 68 dpi. En multipliant la résolution par 1.5, nous obtiendrons 1.5 fois plus de pixels que la normale, ce qui est l'objectif. Ainsi, la résolution devra être gonflée à 102 dpi. Après consultation de la documentation de GhostScript et un peu de cogitation, j'obtins une commande semblable à une formule magique mais capable d'effectuer l'étape de grossissement.
gs -dNOPAUSE -dBATCH -sDEVICE=png16 -r102x102 -sOutputFile=out%02d.ps in.ps
Cette ligne indique à GhostScript de traiter tout le fichier passé en paramètre et puis s'arrêter. Il faut indiquer le format de la sortie ainsi que la résolution choisie. Le nom du fichier de sortie contient une variable qui sera remplacée par les numéros de pages. Nous obtiendrons des fichiers out01.png, out02.png, ... identify indique une taille de 843x1193 pour les PNG produits. Le facteur de grossissement est ainsi respecté.
Pour le découpage, convert fit le boulot sous l'effet de l'incantation
convert -crop w2xh3+x+y in.png in-sb.png
w2 signifie la moitié de la largeur de l'image PNG d'une sous-page (normalement 843 pixels) tandis que h3 représente le tiers de la hauteur d'une sous-page. x prendra les valeurs 0 et w2 tandis que y prendra les valeurs 0, h3 et 2*h3. Nous avons bien six sous-pages avec cette arithmétique.
Les pages initiales sont bien divisés en sous-pages qui sont lisibles, pas crénelées, mais le centre d'intérêt, à savoir la diapositive, n'était pas toujours localisé au même endroit selon les coordonnés (x,y) de début de la fenêtre de découpage. Il n'existe aucune façon mathématique et certaine d'obtenir les coordonnés des six cadres des diapositives, en supposant que leur position est uniforme d'une page à l'autre.
Heureusement, ImageMagick comporte la commande mogrify qui fournit une option -trim du plus grand intérêt: elle permet d'isoler la partie intéressante de l'image en retranchant les contours de couleur uniforme. La formule magique:
mogrify -trim in-sb.png
Le jumelage deux à deux se fait grâce à
convert -append in-sb1.png in-sb2.png out-pg.png
Puis toutes les pages finales sont jointes par
convert out-pg1.png out-pg2.png ... out-pgN.png out.ps
Le fichier PostScript final était volumineux et difficile à imprimer. Ceci s'explique par le fait que PostScript est un langage de programmation et qu'une commande doit être utilisée pour coder chaque ligne, voire chaque pixel, des images. Il vaut mieux produire un PDF qui compactera de nouveau les informations bitmaps. Cela peut se faire avec la commande
ps2pdf out.ps out.pdf
Mercredi, le 16 octobre 2002, au fur et à mesure que je testais, j'implantai dans le langage Perl le script reformat.pl qui servirait de chef d'orchestre des opérations. En effet, plusieurs commandes étaient requises pour accomplir la tâche et les saisir une à une devenait vite long.
Pour le cours 1, l'exécution se passa sans aucun problème, la vitesse était correcte et le PDF produit faisait dans les 100k. Comme il fallait s'en attendre, la taille a augmenté par rapport au PDF original, car nous avons perdu les propriétés vectorielles lors de l'agrandissement. Malheureusement, la qualité du PDF final laissait à désirer. L'impression d'une page donna un résultat illisible. La résolution devait ainsi être augmentée afin de compenser davantage la perte des propriétés vectorielles. J'essayai alors 360 dpi, mais une autre classe de problèmes survint: l'épuisement de la mémoire!
Avec l'accroissement de la résolution, l'exécution du script de reformatage ralentit de façon considérable et la quantité de mémoire utilisée était si grande qu'il finit par en manquer et le script s'arrêta brutalement, laissant en place ses fichiers temporaires. L'impression de l'un d'eux donna d'excellents résultats; plus d'aliasage intolérable sur le texte. Le manque de mémoire semblait se produire lors de la construction du PostScript final. Mais sans ce PostScript, il était nécessaire d'utiliser The Gimp pour imprimer un à un chacun des PNG représentant les pages finales.
Je découvris alors qu'il éait possible de joindre les étapes de découpage et d'isolement de la zone intéressante dans un même appel à convert. Ma première tentative dans ce sens s'était soldée par un échec, car j'avais utilisé le mauvais ordre dans les arguments. Il faut utiliser les options -crop et -trim dans cet ordre et non -trim puis -crop. Le second cas fait le trim sur tout le document puis isole la sous-page. Toutefois, l'arithmétique utilisée pour isoler les sous-pages devient erronée si les dimensions changent de cette façon imprévisible. L'usage d'un seul convert permet d'éviter que mogrify ne mobilise de la mémoire en rechargeant l'image et, à défaut de corriger le bogue mémoire au PostScript final, cette combinaison augmenta la performance du script. Je découvris également qu'il était possible de passer le PDF directement à gs, ce qui élimina pdf2ps du processus.
La commande convert permet heureusement de limiter la quantité de mémoire utilisable comme cache. Par exemple, l'option -cache 50 permet de limiter la cache à 50Mo, ce qui me permit d'obtenir un PDF de 500k pour le premier cours qui comportait six pages initiales, donc 18 pages finales. Toutefois, au cours de l'opération, la machine manqua de mémoire et transféra beaucoup de données sur le disque dur. L'ordinateur fut alors lent à répondre pendant les premières secondes suivant la conversion. Idéalement, il aurait fallu augmenter la mémoire à 512Mo (j'en possédais 256Mo au moment du projet) pour accroître l'efficacité du processus.
Le document de onze pages initiales du cours 2 me posa un nouveau problème: la dernière page ne contenait pas six diapositives si bien qu'ImageMagick produisait un message d'erreur lors de la tentative de découpage de la portion intéressante. Malheureusement, l'appel des commandes de ImageMagick ne permettait pas d'isoler la cause de l'erreur depuis le script et les bogues de mémoire sévissaient toujours. Solution: utiliser une solution plus perlish.
J'avais omis d'utiliser l'extension Perl Image::Magick parce que la documentation n'était pas disponible sur mon système et je n'avais pas trop envie de la rechercher. Je la trouvai sur le site Web de ImageMagick et je pus utiliser PerlMagic (extension Image::Magick) plutôt que des appels de commandes. Cela réduisit encore davantage les rechargements, mais la mémoire manquait toujours au PostScript final.
Après un essai, je constatai que a2ps permettait d'effectuer la fusion plus efficacement qu'ImageMagick, avec la commande
a2ps --columns=1 -R -o final.ps pagef1.png pagef2.png ... pagefN.png
D'après les informations en sortie, cette commande utilise toutefois ImageMagick, alors il semblait possible de réduire la quantité de logiciels à utiliser pour la solution. Hypothèse: une chaîne de convert.
convert page1.png final.ps convert final.ps page2.png final.ps .... convert final.ps pageN.png out.ps
Malheureusement, à chaque équivalent PerlMagick de convert, toutes les pages du PostScript étaient chargées en mémoire, peu importe si je réduisais le cache. Ainsi, il manquait toujours de mémoire. Seul a2ps semblait apte à réaliser la fusion des images, alors autant l'utiliser.
Pour le second cours, j'obtins un PDF de 1.2Mo! Ce 16 octobre 2002 fut un long après-midi de codage après quoi la solution fut relativement au point.
La première véritable tentative d'impression eut lieu jeudi, le 17 octobre 2002. Sans cartouche d'encre noire, l'opération fut impossible, si bien que je dus pour imprimer sous Linux interfacer SAMBA avec CUPS afin d'accéder à l'imprimante de l'ordinateur familial. L'impression fut longue en raison du mode graphique imposé par la forme bitmap du PDF. Le cadre autour des diapositives donna beaucoup de travail à l'imprimante. L'impression recto-verso causa elle aussi problème, car l'imprimante sauta des feuilles de temps en temps!
Il était aussi ardu de contrôler l'imprimante distante depuis Linux; il fallait me brancher sur la machine Windows XP pour annuler une tâche d'impression ayant dégénéré. Jeudi, le 17 octobre 2002, après beaucoup de problèmes et beaucoup de feuilles à recommencer, je parvins à imprimer les deux premiers cours de Processus Cognitifs 1!
Vendredi matin, le 18 octobre 2002, j'étudiai pour le cours et constatai que le texte était bien lisible. Étonnamment, les graphiques n'avaient pas subi de grandes altérations. Seules quelques images étaient devenues aliasées. L'après-midi même, encouragé par ces résultats enfin concluants, j'entamai l'impression d'autres cours. Lors de l'impression du cours 3, l'imprimante Epson sauta une feuille au début des versos, ce qui me força à tout reprendre depuis le début. Il était difficile de retrouver la page exacte qui avait raté dans le PDF, car la navigation dans le document bitmap s'avérait lente sous Linux. Je passai proche perdre espoir et abandonner.
Au lieu de faire ainsi, je modifiai le script et lui incorporai la génération de numéros de pages. Ce vendredi, je finis par me résoudre à fournir une par une chaque feuille à l'imprimante. Décidément, l'impression recto-verso est une affaire complexe!
Pourquoi donc m'acharner à imprimer ainsi? Pour des raisons d'économie d'espace. Avec une moyenne de trente pages par cours, recto seulement, j'obtiendrais pour les douze cours de la session un cartable contenant environ 360 pages! Un cartable un pouce risquait de ne pas suffire et je n'aimais pas trimbaler de gros cartables deux pouces. C'était donc un pur caprice personnel, rien de plus. Les numéros de pages ajoutés étaient trop petits, mais je décidai de m'en contenter. Je parvins ce jour-là à obtenir les PDF agrandis pour les cours 3 et 4.
Samedi, le 19 octobre 2002, je calculai avec la commande time que la conversion du PDF pour le cours 6 prenait 4min! Je parvins cet après-midi-là, sans trop d'incidents, à mettre sur papier les versions agrandies des cours 5 et 6! Les cours précédant l'examen intra étaient désormais traités. Je décidai d'attendre une nouvelle cartouche noire pour traiter les autres.
Samedi, le 26 octobre 2002, l'impression des cours 7 et 8 se passa sans incidents. J'appliquai aussi une variante sans agrandissement de la procédure développée pour traiter un PDF récalcitrant construit par le professeur de Technologie de l'Internet (IFT3220) avec le logiciel PDFWriter. L'impression s'avéra aussi rapide que l'impression d'un PDF normal, ce qui me fit croire que c'était la bordure noire des diapositives qui ralentissait le travail.
Le script prend deux paramètres sur la ligne de commande, soient le PDF à traiter et le nom du fichier PDF produit. Le traitement nécessite ImageMagick, son extension PerlMagick, GhostScript et a2ps. Adobe Reader ou tout autre lecteur PDF est utile pour visualiser le PDF final et l'imprimer.
Avantages | Inconvénients |
---|---|
|
|
Agrandissement |
|
Découpage |
Pour chaque page initiale en format PNG,
|
Fusion deux à deux |
Pour chaque groupe de deux sous-pages
|
PostScript final |
|
PDF final |
|
![]() |
Cette procédure est plutôt complexe et repartir des fichiers PowerPoint demeure la meilleure solution à ce problème. Toutefois, la procédure m'aura permis de résoudre le bogue et cette expérimentation restera gravé dans mes souvenirs pour bien longtemps.