-- Leo's gemini proxy

-- Connecting to bwog-notes.chagratt.site:1965...

-- Connected

-- Sending request

-- Meta line: 20 text/gemini

Ajouter un filigrane dans PDF avec ghostscript


Rédigé le 24 mars 2021 - modifié le 15 avril 2021. Étiquettes : pdf ghostscript


Si vous avez déjà les outils ghostscript installés sur votre machine, voici un moyen d'ajouter un filigrane sur chaque page d'un PDF.




La démarche est simple, mais la mise en œuvre ne l'est pas tant, surtout quand on ne veut ou peut pas installer des outils en plus.

Notamment de grosses suites logicielles, souvent propriétaires.

À noter que LibreOffice Draw permet de le faire facilement (via le mode masque, dans le sous-menu affichage), mais j'ai remarqué sur mes documents de test que certains textes étaient décalés et donc dénaturaient, voire rendaient illisibles le document final.


J'ai donc cherché une solution à base de ligne de commande et de ghostscript.

C'était long et laborieux, mais pas impossible. Avec toutefois quelques subtilités à prendre en compte.


Sans plus attendre : des solutions.


#!/usr/bin/env bash
readonly WATERMARK_FILE=$(mktemp /tmp/watermark.XXXXXXX.ps)

filename=${1:-}
watermark=${2:-}

cat > "${WATERMARK_FILE}" << HERE
<<
  /BeginPage
   {
     2 eq { pop false }
     {
         0.65 .setfillconstantalpha
         /Helvetica_Bold 50 selectfont
         .40 setgray
         gsave
         130 70 moveto 50 rotate (${watermark}) show
         grestore
         true
     } ifelse
   } bind
>> setpagedevice
HERE

gs -dBATCH -dALLOWPSTRANSPARENCY -dNOPAUSE -q -sDEVICE=pdfwrite -sOutputFile="watermarked_${filename}" "${WATERMARK_FILE}" "${filename}"

Il est assez facile de trouver ce bout de ghostscript un peu partout, à peu de choses près.

Mais avec les versions actuelles, il faut penser à ajouter -dALLOWPSTRANSPARENCY, sans quoi la génération échouera avec une erreur cryptique.


Dans le script également, j'ai (quasiment) toujours vu /EndPage, d'où l'envie de beaucoup de monde de jouer avec la transparence,

car ainsi le texte est généré _par dessus_ le texte original.

Or nous voulons le mettre _dessous_.

La bonne solution pour ça est d'utiliser en fait /BeginPage.


La transparence devient optionnelle du coup, mais le texte plein est ainsi moins prononcé ce qui ne gêne pas la lecture du document.


Les éléments notables


Pour personnaliser un peu tout ça, vous pouvez jouer avec les paramètres suivants :


- selectfont : le nombre avant indique la taille du texte. Plus la valeur est élevée, plus le texte sera grand.

- moveto : les coordonnées de départ du texte. La première valeur correspond aux abscisses, la seconde aux ordonnées. L'origine se situe en bas à gauche du document.

- rotate : l'angle du texte par rapport à l'horizontale. En valeur positive, le texte tourne dans le sens contraire des aiguilles d'une montre.

- .setfillconstantalpha : la transparence. Plus celle valeur est faible, plus le texte sera estompé.

- setgray : l'intensité du gris. Plus la valeur est proche de 1, plus il sera clair.


Bonus : un style « contour » pour le texte


cat > "${WATERMARK_FILE}" << HERE
<<
  /BeginPage
   {
     2 eq { pop false }
     {
         gsave
         /Helvetica findfont 48 scalefont setfont
         .45 setgray
         newpath
         130 70 moveto 50 rotate
         (${watermark}) false  charpath
         1 setlinewidth stroke
         grestore
         true
     } ifelse
   } bind
>> setpagedevice
HERE

Pour avoir plusieurs lignes


En reprenant les deux exemples précédents, si l'on veut faire plusieurs lignes, il suffit de dupliquer les blocs gsave et grestore

puis de changer les coordonnées des instructions moveto de chaque ligne pour éviter qu'elles se superposent.


Style plein :


cat > "${WATERMARK_FILE}" << HERE
<<
  /BeginPage
   {
     2 eq { pop false }
     {
         /Helvetica_Bold 48 selectfont
         0.65 .setfillconstantalpha
         0.40 setgray
         gsave
         100 350 moveto 50 rotate (${line_1}) show
         grestore
         gsave
         100 250 moveto 50 rotate (${line_2}) show
         grestore
         gsave
         100 150 moveto 50 rotate (${line_3}) show
         grestore
         true
     } ifelse
   } bind
>> setpagedevice
HERE

Style contour :


cat > "${WATERMARK_FILE}" << HERE
<<
  /BeginPage
   {
     2 eq { pop false }
     {
         /Helvetica findfont 48 scalefont setfont
         .45 setgray
         gsave
         newpath
         100 350 moveto 50 rotate
         (${line_1}) false  charpath
         1 setlinewidth stroke
         grestore
         gsave
         newpath
         100 250 moveto 50 rotate
         (${line_2}) false  charpath
         1 setlinewidth stroke
         grestore
         gsave
         newpath
         100 150 moveto 50 rotate
         (${line_3}) false  charpath
         1 setlinewidth stroke
         grestore
         true
     } ifelse
   } bind
>> setpagedevice

Conclusion


Ça n'est pas optimal (surtout au niveau du code ghostscript), ni forcément bien placé mais ça fait le boulot.


À noter que pour les textes longs, ce n'est pas auto-adaptatif et donnera donc un débordement hors du PDF, d'où mon bricolage avec les lignes multiples.


Sources


Tous en anglais hélas :


Le script d'origine, avec la transparence qui fait planter la compilation


Pour le style « contour des lettres »


Le post stackoverflow, surtout son commentaire, pour le BeginPage



-------------------------------

← Plus récent : Le retour du thème clair

→ Plus ancien : Migration de i3wm (Xorg) à Sway (Wayland)

Aléatoire : Le Heredoc

Retour à l'accueil


Contenu sous licence CC-BY-SA


-- Response ended

-- Page fetched on Sat May 18 08:16:01 2024