-- Leo's gemini proxy
-- Connecting to bwog-notes.chagratt.site:1965...
-- Connected
-- Sending request
-- Meta line: 20 text/gemini
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.
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.
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
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
Ç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.
Tous en anglais hélas :
-------------------------------
Contenu sous licence CC-BY-SA
-- Response ended
-- Page fetched on Sat May 18 08:16:01 2024