Recherche sur le blog

mardi 16 juin 2015

[WD19] Filigrane sur un PDF déjà généré

Ayant des fichiers PDF déjà générés, je cherchais une solution pour rajouter un filigrane du style "Duplicata" pour une réimpression. Travaillant en Windev, je suis tombé sur la solution de Jurassic Pork sur les forums de PC SOFT, où il conseille d'utiliser ITextSharp, un assemblage .NET qui permet en gros de générer des PDF ou de les manipuler (séparer en plusieurs documents, fusionner, ajouter un filigrane ou un tampon, remplir des formulaires, etc).

Pour une question de licence, il recommande d'utiliser une ancienne version, soit la 4.1.6 (qu'on peut télécharger à l'adresse suivante : http://pdfviewernet.googlecode.com/svn-history/r55/trunk/PDFView/PDFView/lib/itextsharp.dll) et qui est sous licence MGPL/LGPL... Mais attention, d'après plusieurs sources, celle-ci est deprecated (considérée comme obsolète). Si vous souhaitez travailler avec une version plus récente, vous retrouverez l'assemblage sur Sourceforge (projet ITextSharp). Notez que la version 5 est passée sous licence AGPL. Pour savoir ce que cela implique, consultez le site GNU.org, section "Licences". 

Intégrer l'assemblage .NET 

Si vous ne vous rappelez pas comment intégrer un assemblage dans votre projet, voici comment il faut procéder : 
  • Dans l'explorateur de projets, clic droit sur "Assemblages .NET". 
  • Choisissez l'option "Utiliser un assemblage .NET dans le projet".
  • Cliquez sur le bouton "Parcourir" dans la fenêtre qui s'ouvre.
  • Sélectionnez le fichier "itextsharp.dll" puis cliquez sur OK.
  • Validez et recompilez le projet.

Procédure pour ajouter le filigrane

La procédure écrite par "JP" recevra en paramètre trois éléments : l'emplacement du fichier source, l'emplacement (complet - avec le nom de fichier et l'extension de celui-ci) pour le fichier de destination, et le texte qu'on souhaite afficher.


En début de procédure on va déclarer les premières variables :
  • Une variable de type entier pour contenir l'index de page, qui sera en fait utilisée dans une boucle en partant de la valeur 1. Il sera nommé "pageIndex".
  • Un objet de type PdfReader, qui va servir à charger le fichier source (on passe l'emplacement du fichier en paramètre du constructeur). Il sera nommé "MonFichierPDF".
  • Un objet de type FileStream pour initialiser un flux pour la création du fichier de destination (les paramètres du constructeur, sont, dans l'ordre : l'emplacement du futur fichier, et le mode de création - ex : FileMode.OpenOrCreate). Il sera nommé "fluxSortie".
  • Un objet de type PdfStamper qui sera utilisé pour ajouter du contenu supplémentaire au fichier source. Les paramètres du constructeur sont : l'objet PdfReader précédemment instancié, et le flux de sortie). Il sera nommé tout simplement "pdfStamper".
La fameuse boucle dont il était question ci-dessus est de type "POUR variable = x _A_ y". Dans ce cas-ci on réutilise notre entier - nommé "pageIndex" qu'on initialise à 1 en début de boucle, pour aller jusqu'à "MonFichierPDF.NumberOfPages"(inclus).


Ensuite dans la boucle il va falloir effectuer plusieurs choses :
  • D'abord la création d'un objet dynamique de type "itextsharp.text.rectangle". Il s'agit d'une représentation d'une forme géométrique. Dans ce cas-ci l'objet contiendra la représentation géométrique d'une page. Cela nous permettra de récupérer sa longueur et sa largeur afin de plus tard, placer le filigrane au bon endroit.
  • On va instancier un objet dynamique de type "PdfContentByte". Il va en fait contenir les images et le contenu textuel de la page renvoyée par notre objet "pdfStamper". Pour obtenir cela on appelle la fonction GetOverContent() en passant en paramètre le numéro de la page.
  • On va configurer la police et la taille pour le futur filigrane.

Mais ce n'est pas tout !


Toujours dans la boucle qui parcourt les différentes pages de notre document PDF, on va commencer à créer le filigrane. Tout d'abord à l'aide d'un objet "PdfGState" - qu'on va nommer "graphicsState" -, on va définir son opacité (à 0.4 dans l'exemple). Pour cela il faut écrire :

graphicsState.FillOpacity = 0.4

Ensuite, à l'aide de la fonction SetGState() de l'objet "PdfContentByte", on va appliquer cette caractéristique d'opacité au contenu existant. On définit ensuite la couleur de l'écriture - à l'aide de SetColorFill() -, puis on indique qu'on va commencer à saisir du texte - en utilisant BeginText().

La méthode suivante - ShowTextAligned() - va recevoir en paramètre la position du texte (ex : Element.ALIGN_CENTER), le texte à afficher, sa position sur la page - qui sera calculée en divisant respectivement la hauteur et la largeur par 2, et la valeur de la rotation. Si vous avez bien compté, cela fait au total 5 paramètres.

Dernière ligne de la boucle, il faut appeler la fonction EndText() de notre objet "PdfContentByte". Tous ces traitements se répéteront donc pour chacune des pages présentes dans le PDF. Cela peut prendre du temps en fonction du nombre de pages à traiter.


Ensuite il faut appeler la méthode Close() sur nos deux objets, "pdfStamper" et "fluxSortie". C'est très important pour que le fichier soit correctement sauvegardé et pour que le programme libère tous les descripteurs de fichiers ouverts.

Bon développement !

Sources

Forums PC-SOFT

Aucun commentaire: