Overlay text in PDF via command line

5,872

Solution 1

Well, I've come up with a solution using TikZ within a crafted LaTex document. The result is not exactly the same, but I think it is even nicer:

Solution output

This required having a tex document with placeholders that will be replaced by the arguments to a sh script.

% file: add_legend.tex

\documentclass{standalone}
\usepackage{graphicx}

\usepackage{tikz}
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% LaTeX Overlay Generator - Annotated Figures v0.0.1
% Created with (omitted http) ff.cx/latex-overlay-generator/
% If this generator saves you time, consider donating 5,- EUR! :-)
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%\annotatedFigureBoxCustom{bottom-left}{top-right}{label}{label-position}{box-color}{label-color}{border-color}{text-color}
\newcommand*\annotatedFigureBoxCustom[8]{\draw[#5,thick,rounded corners] (#1) rectangle (#2);\node at (#4) [fill=#6,thick,shape=circle,draw=#7,inner sep=4pt,font=\huge\sffamily,text=#8] {\textbf{#3}};}
%\annotatedFigureBox{bottom-left}{top-right}{label}{label-position}
\newcommand*\annotatedFigureBox[4]{\annotatedFigureBoxCustom{#1}{#2}{#3}{#4}{white}{white}{black}{black}}
\newcommand*\annotatedFigureText[4]{\node[draw=none, anchor=south west, text=#2, inner sep=0, text width=#3\linewidth,font=\sffamily] at (#1){#4};}
\newenvironment {annotatedFigure}[1]{\centering\begin{tikzpicture}
\node[anchor=south west,inner sep=0] (image) at (-0.75,-0.75) { #1};\begin{scope}[x={(image.south east)},y={(image.north west)}]}{\end{scope}\end{tikzpicture}}
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

\begin{document}  

  \begin{annotatedFigure}           
        {\includegraphics[width=1.0\linewidth]{_image_}}    
        \annotatedFigureBox{0,0}{0.000,0.0}{_letter_}{0,0}%bl
    \end{annotatedFigure}  

\end{document}

And the sh script:

#!/bin/sh
# Call this script with at least 2 parameters, for example
# sh scriptname <image_file> <letter_of_legend> 

cat add_legend.tex | sed "s/_image_/$1/g" | sed "s/_letter_/$2/g" | pdflatex

#rename output to match <letter_of_legend>_<image_file> format
mv texput.pdf $2_$1 

#clean up
rm texput.*

exit 0

Finnaly, by calling:

$> ./legend.sh online_gauss.pdf A

the output drawn in "A_online_gauss.pdf"!

Solution 2

For people that do not want to install a texlive distribution, you may prefer cpdf as explained here. However since cpdf has a strange license for commercial use, I tried to find an alternative. Here is one (you need to install enscript, ps2pdf and (pdftk or qpdf)).

The idea is just to use enscript to create a .ps from a text, then you convert this .ps into a .pdf using ps2pdf, and then you stack it on top of the original pdf with pdftk or qpdf...).

pdtfk version:

echo "I will be stamped on top of the page" | enscript -B -f Courier-Bold16 -o- | ps2pdf - | pdftk input.pdf stamp - output output.pdf

qpdf version:

If you want the text to repeat on all pages:

tmpfile=$(mktemp) && echo "I will be stamped on top of the page" | enscript -B -f Courier-Bold16 -o- | ps2pdf - "$tmpfile" && qpdf out_merge.pdf --overlay "$tmpfile" --repeat=1-z -- out_oneline.pdf

if you just want to put it on the first page:

tmpfile=$(mktemp) && echo "I will be stamped on top of the page" | enscript -B -f Courier-Bold16 -o- | ps2pdf - "$tmpfile" && qpdf out_merge.pdf --overlay "$tmpfile" -- out_oneline.pdf

See the documentation for more options.

NB: mktemp is just used to create a temporary file to provide a one-liner solution, since qpdf does not accept input from stdin

Unfortunately, I'm not sure to know how to set the position of the text, for not it's always on top left in a4 pages...

Share:
5,872

Related videos on Youtube

Bruno Silva
Author by

Bruno Silva

Updated on September 18, 2022

Comments

  • Bruno Silva
    Bruno Silva over 1 year

    The following command produced the result of the following image using convert, where an overlay box containing the letter "A" was layered over the PDF:

    convert online_gauss.pdf -fill white -undercolor '#00000080'
    -pointsize 40 -gravity South -annotate +0+5 ' A ' online_gauss_annot.pdf

    Desired result

    However, convert rasterizes the source. Since I would like to keep the original PDF format (vectorial) for publishing, is there a simple way of achieving this type of annotation via command line over a single PDF image? I would be happy just with the letter, even in the bottom left corner.

    I've seen some examples using Ghostscript, pdftk (stamp) but they involve several intermediate steps that are difficult to get right for different sized PDF images.

    • Admin
      Admin over 8 years
      I think pdfstamp is a good match for your problem. Perhaps you should detail your problems with it in case there is a solution.
    • Admin
      Admin over 8 years
      Thanks, but that requires generating a separate pdf file with the desired letter and then stamping it at the bottom; the generated pdf should also have proportional dimensions regarding the source.
    • Admin
      Admin almost 7 years
      @meuh I found pdfstamp thanks to your comment, and it is just what I need for MY problem, thanks! The only question is I don't seem to be able to overlay UTF8 text, even when doublechecking to have a font with Unicode support. Any ideas?
    • Admin
      Admin almost 7 years
      @Gnudiff I see the same problem, but I don't have an answer at the moment. Perhaps if you post a new question someone might know.
    • Admin
      Admin almost 7 years
      @meuh I ended up using pdftk and applying pdf over pdf
  • inye
    inye almost 7 years
    I have a lot of output text, I change a bit the script but is the same cat add_legend.tex | sed "s/_image_/$1/g" | sed "s/_letter_/$2/g" > texput.tex and pdflatex -interaction batchmode texput.tex