IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Voir le flux RSS

blowagie

[Actualité] Comment créer un filigrane transparent en PDF?

Noter ce billet
par , 12/04/2015 à 14h01 (4371 Affichages)
QUESTION:
Je dois ajouter un filigrane à chaque page d'un fichier PDF. Le filigrane peut être du texte ou une image, mais doit surtout être transparent. Comment puis-je obtenir de de tels filigranes en PDF?
(Pour la version anglaise, voir How to watermark PDFs using text or images?)

REPONSE:
Jetons un oeil à l'exemple TransparentWatermark2. Dans cet example, on prend un document PDF existant et on ajoute un texte transparent sur chaque page impaire et une image transparente sur chaque page paire:

Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
public void manipulatePdf(String src, String dest) throws IOException, DocumentException {
    PdfReader reader = new PdfReader(src);
    int n = reader.getNumberOfPages();
    PdfStamper stamper = new PdfStamper(reader, new FileOutputStream(dest));
    // text watermark
    Font f = new Font(FontFamily.HELVETICA, 30);
    Phrase p = new Phrase("My watermark (text)", f);
    // image watermark
    Image img = Image.getInstance(IMG);
    float w = img.getScaledWidth();
    float h = img.getScaledHeight();
    // transparency
    PdfGState gs1 = new PdfGState();
    gs1.setFillOpacity(0.5f);
    // properties
    PdfContentByte over;
    Rectangle pagesize;
    float x, y;
    // loop over every page
    for (int i = 1; i <= n; i++) {
        pagesize = reader.getPageSizeWithRotation(i);
        x = (pagesize.getLeft() + pagesize.getRight()) / 2;
        y = (pagesize.getTop() + pagesize.getBottom()) / 2;
        over = stamper.getOverContent(i);
        over.saveState();
        over.setGState(gs1);
        if (i % 2 == 1)
            ColumnText.showTextAligned(over, Element.ALIGN_CENTER, p, x, y, 0);
        else
            over.addImage(img, w, 0, 0, h, x - (w / 2), y - (h / 2));
        over.restoreState();
    }
    stamper.close();
    reader.close();
}
Commençons avec un PdfReader (ligne 2) et un PdfStamper (ligne 4). L'object reader va lire le document existent et l'objet stamper va créer le document modifié.

Ensuite nous construisons
  • une Phrase avec le texte "My watermark (text)" (ligne 7) et une police Helvetica avec taille 30pt (ligne 6).
  • une Image dont on le chemin de fichier est IMG (ligne 9); w et h sont la largeur et la hauteur de l'image (line 10 et 11).
  • un objet PdfGState (ligne 13) qui contient la valeur de la transparence: une opacité de 50% (ligne 14). Ceci is l'état graphique (graphics state) du contenu d'une page PDF.

Une fois que nous avons ces objets, nous visitons chaque page (ligne 20). En général, nous utilisons l'objet reader pour obtenir des informations sur le document existant, par exemple les dimensions de chaque page (ligne 21). Nous utilisons l'objet PdfStamper quand nous voulons ajouter du contenu supplémentaire au document existant, par exemple l'ajout d'un filigrane.

Lors du changement du graphics state, il est toujours plus sûr d'effectuer saveState() avant de commencer et restoreState() une fois que vous avez terminé. Si vous supprimez ligne 25 et 31, l'application fonctionnera probablement sans fautes, mais croyez-moi: il vaut mieux d'avoir ces deux lignes afin d'éviter devoir déboger votre code en cas d'effets étranges avec un état graphique non-équilibré.

Nous appliquons la transparence en utilisant la méthode setGState() (ligne 26) et selon que la page est une page impaire ou paire, nous ajoutons:
  • le texte en utilisant ColumnText et le coordonnées (x, y) calculée de sorte que le texte est ajouté dans le milieu de chaque page (ligne 28), ou
  • l'image en utilisant la methode addImage() et les paramètres appropriés pour la matrice de transformation (ligne 30).

Une fois que nous avons executé ceci pour chaque page du document, nous fermons le stamper (ligne 33) et le reader (ligne 34).

Regardons le résultat: nous avions un fichier pages.pdf au quel nous avons ajouté ces filigranes. Le résultat est le fichier pages_watermarked.pdf dont la page 3 et 4 sont présentés dans la capture d'écran ci-dessous:

Nom : Untitled.png
Affichages : 5642
Taille : 9,7 Ko

Si vous examinez le fichier PDF de plus près, vous remarquerez que les pages 3 et 4 sont dans le format paysage, mais il ya une différence entre ces deux pages qui n'est pas visible du premier coup d'œil. Page 3 est en fait une page dont la taille est définie comme s'il s'agissait d'une page en mode portrait, mais la page est tourné de 90 degrés. Page 4 est une page dont la dimension est définie de telle sorte que la largeur est plus large que la hauteur (un vrai format paysage). Cette différence peut avoir des conséquences si vous ajoutez un filigrane.

En utilisant getPageSizeWithRotation(), iText s'adaptera, mais ceci n'est peut-être pas tout à fait ce que vous voulez: peut-être vous souhaitez que le filigrane tourne de la même façon que la page:
Nom : Untitled2.png
Affichages : 5280
Taille : 12,8 Ko

La capture d'écran nous montre que la page de gauche est en fait une page en format portrait, tournée de 90 degrees. En consequent, nous voulons peut-être que le filigrane est tourné aussi. (La page de droite est une page en format paysage, le filigrane ne doit pas être tourné.)

Comment obtenir ce résultat? Il suffit remplacer la méthode getPageSizeWithRotation() par la méthode getPageSize() et de forcer le PdfStamper de ne pas tenir compte de la rotation de la page: stamper.setRotateContents(false);

Voyons ligne 5 et ligne 22 de l'example TransparentWatermark3:

Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
public void manipulatePdf(String src, String dest) throws IOException, DocumentException {
    PdfReader reader = new PdfReader(src);
    int n = reader.getNumberOfPages();
    PdfStamper stamper = new PdfStamper(reader, new FileOutputStream(dest));
    stamper.setRotateContents(false);
    // text watermark
    Font f = new Font(FontFamily.HELVETICA, 30);
    Phrase p = new Phrase("My watermark (text)", f);
    // image watermark
    Image img = Image.getInstance(IMG);
    float w = img.getScaledWidth();
    float h = img.getScaledHeight();
    // transparency
    PdfGState gs1 = new PdfGState();
    gs1.setFillOpacity(0.5f);
    // properties
    PdfContentByte over;
    Rectangle pagesize;
    float x, y;
    // loop over every page
    for (int i = 1; i <= n; i++) {
        pagesize = reader.getPageSize(i);
        x = (pagesize.getLeft() + pagesize.getRight()) / 2;
        y = (pagesize.getTop() + pagesize.getBottom()) / 2;
        over = stamper.getOverContent(i);
        over.saveState();
        over.setGState(gs1);
        if (i % 2 == 1)
            ColumnText.showTextAligned(over, Element.ALIGN_CENTER, p, x, y, 0);
        else
            over.addImage(img, w, 0, 0, h, x - (w / 2), y - (h / 2));
        over.restoreState();
    }
    stamper.close();
    reader.close();
}
Maintenant le filigrane va suivre l'orientation de chaque page.

Si vous voulez plus d'exemples iText comme celui-ci, téléchargez le livre gratuit The Best iText Questions on StackOverflow.

Envoyer le billet « Comment créer un filigrane transparent en PDF? » dans le blog Viadeo Envoyer le billet « Comment créer un filigrane transparent en PDF? » dans le blog Twitter Envoyer le billet « Comment créer un filigrane transparent en PDF? » dans le blog Google Envoyer le billet « Comment créer un filigrane transparent en PDF? » dans le blog Facebook Envoyer le billet « Comment créer un filigrane transparent en PDF? » dans le blog Digg Envoyer le billet « Comment créer un filigrane transparent en PDF? » dans le blog Delicious Envoyer le billet « Comment créer un filigrane transparent en PDF? » dans le blog MySpace Envoyer le billet « Comment créer un filigrane transparent en PDF? » dans le blog Yahoo

Mis à jour 12/06/2015 à 10h33 par blowagie

Catégories
Java