8

I need to add annotations to large PDF file. The method suggested in this answer does not scale well:

\documentclass[12pt]{article}
\usepackage{pdfpages}
\usepackage{tikz}
\begin{document}
\includepdf[pagecommand=
{\begin{tikzpicture}[remember picture,overlay]
 \node at (current page.center) {overlayed text};
 \end{tikzpicture}},pages=1]{filename.pdf}
\includepdf[pages=2-]{filename.pdf}
\end{document}

My PDF file is 700 pages long. I annotate the file at random pages (50+ annotations). Now my source has the following structure:

annotationion of page X

\includepdf[pages=(X+1)-(Y-1)]{filename.pdf}

annotationion of page Y

\includepdf[pages=(Y+1)-(Z-1)]{filename.pdf}

annotationion of page Z

The extra \includepdf are both annoying and error prone. Is there a way to automate this procedure?

  • 1
    For the future casual reader: if you just need to overlay text, tikz is overkill. You are better off with textpos. – Primo Petri Apr 4 '18 at 7:54
4

Update: Package now released on CTAN

I finally got around to tidying up my pdfoverlay package and releasing it on to CTAN. It's also in TeXLive and MikTeX. See https://ctan.org/pkg/pdfoverlay.

I re-implemented it in expl3 and wrote some proper documentation. The syntax is slightly different taking into account some of the feedback from the comments below.

The MWE example below now becomes:

\documentclass{article}
\usepackage{pdfoverlay}
\pdfoverlaySetPDF{filename.pdf}
\begin{document}
Annotation on page 1.
\pdfoverlayIncludeToPage{10}
Annotation on page 10.
\pdfoverlayIncludeToPage{50}
Annotation on page 50.
\pdfoverlayIncludeToLastPage
\end{document}

Original Answer

I have written a package that is exactly for this kind of thing. It's not documented except with a few comments and isn't in CTAN. (I could add it, though not for a couple of weeks.) It probably also needs some error checking to be a bit more robust.

It allows for this kind of thing:

\documentclass{article}
\usepackage{pdfoverlay}
\pdfoverlaySetPDF{filename.pdf}
\begin{document}
Annotation on page 1.
\pdfoverlayMoveToPage{10}
Annotation on page 10.
\pdfoverlayMoveToPage{50}
Annotation on page 50.
\pdfoverlayMoveToLastPage
\end{document}

Just save this as pdfoverlay.sty and put it in the same directory as your tex file.

%%
%% This file is pdfoverlay.sty'
%% 
%% Copyright (c) 2017-2018
%% by David Purton <dcpurton@marshwiggle.net>
%%
%% This work may be distributed and/or modified under the conditions of
%% the LaTeX Project Public License, either version 1.3c of this license
%% or (at your option) any later version. The latest version of this
%% license is in
%%    http://www.latex-project.org/lppl.txt
%% and version 1.3c or later is part of all distributions of LaTeX
%% version 2005/12/01 or later.
%% 
%% This work is "maintained" (as per the LPPL maintenance status)
%% by David Purton.
%% 
%% This work consists of the file pdfoverlay.sty.
%% 
\NeedsTeXFormat{LaTeX2e}
\ProvidesPackage{pdfoverlay}
  [2018/04/04 Package for overlaying text on an existing PDF document (DCP)]

\RequirePackage{everypage}
\RequirePackage{graphicx}
\RequirePackage{etoolbox}
\RequirePackage{pdfpages}

\newcounter{pdfoverlay@page}

\newtoggle{pdfoverlay@outputpage}
\toggletrue{pdfoverlay@outputpage}

\newcommand{\pdfoverlay@setpdf}{%
  \iftoggle{pdfoverlay@outputpage}
    {\ifcsvoid{pdfoverlay@pdf}
      {\PackageError{pdfoverlay}
         {No PDF file set}
         {Set a PDF file using \protect\pdfoverlaySetPDF}}
      {\AddToShipoutPictureBG*{%
         \ifnum \thepdfoverlay@page>\z@
           \unless\ifnum \thepdfoverlay@page>\pdfoverlay@pagecount
             \includegraphics[page=\thepdfoverlay@page,
                              width=\paperwidth,
                              height=\paperheight]{\pdfoverlay@pdf}%
           \fi
         \fi}}%
       \stepcounter{pdfoverlay@page}}
    {}}

\def\pdfoverlay@pdf{}

% set the PDF to output in the background
% \pdfoverlaySetPDF{filename.pdf}
\newcommand{\pdfoverlaySetPDF}[1]{%
  \IfFileExists{#1}
    {\gdef\pdfoverlay@pdf{#1}%
     \edef\AM@currentdocname{#1}%
     \AM@getpagecount
     \xdef\pdfoverlay@pagecount{\AM@pagecount}}
    {\PackageError{pdfoverlay}
       {PDF file #1 not found}
       {}}}

\setcounter{pdfoverlay@page}{0}%
\AddEverypageHook{\pdfoverlay@setpdf}

% jump to page in background PDF without outputting pages in between
% \pdfovrlaySetPage{n}
% where n is an integer
% NOTE: The page will not actually be outputted
%       unless there is some text overlayed on it
\newcommand{\pdfoverlaySetPage}[1]{%
  \setcounter{pdfoverlay@page}{#1}%
  \addtocounter{pdfoverlay@page}{-1}}

% Move through the PDF to the specified page
% \pdfoverlayMoveToPage{n}
% where n is an integer
% NOTE: The page will not actually be outputted
%       unless there is some text overlayed on it
\newcommand{\pdfoverlayMoveToPage}[1]{%
  \whileboolexpr
    {test {\ifnumcomp{\value{pdfoverlay@page}}<{#1-1}}}
    {\null
     \clearpage}}

% Move through the PDF to the last page
% NOTE: Any further text will be output on the next page
\newcommand{\pdfoverlayMoveToLastPage}{%
  \whileboolexpr
    {test {\ifnumcomp{\value{pdfoverlay@page}}<{\pdfoverlay@pagecount-1}}}
    {\null
     \clearpage}%
   \null}

% Toggle outputting the PDF
\newcommand{\pdfoverlayOutputToggle}{%
  \iftoggle{pdfoverlay@outputpage}
    {\togglefalse{pdfoverlay@outputpage}}
    {\toggletrue{pdfoverlay@outputpage}}}

% Resume outputting the PDF
\newcommand{\pdfoverlayOutputToggleTrue}{%
  \toggletrue{pdfoverlay@outputpage}}

% Pause outputting the PDF
\newcommand{\pdfoverlayOutputToggleFalse}{%
  \togglefalse{pdfoverlay@outputpage}}

% Set page style to empty
\pagestyle{empty}

\endinput
  • It works very well! – Primo Petri Apr 4 '18 at 7:51
  • I tested your package for a couple of days. It works smoothly. A minor comment if you decide to put it on CTAN. Adding \setcounter{page}{#1} to the definition of \pdfoverlaySetPage helps when you skip many pages of the original file (requires hyperref). – Primo Petri Apr 6 '18 at 16:32
  • An even lesser comment: I find the names \pdfoverlaySetPage and \pdfoverlayMoveToPage counter-intuitive. What you really mean is\pdfoverlaySkipToPage and \pdfoverlayIncludeUptoPage or something like that. – Primo Petri Apr 6 '18 at 16:57
4

Assuming that your statement about scalability refers only to the fact that it is tedious and error prone to do it by hand and not to the efficiency on large pdf files, I propose you an idea that can be used to implement your own commands for your specific case.

In words, it is about taking advantage of a counter to keep track of which page was annotated and build a command that make an annotation on a given page, printing all the previous not annotated ones.

Disadvantage: You have to put the \makeAnnotation commands in order (with respect to the annotated page), but it should not be a big deal and I think you will do it anyway.

\documentclass{article}
\usepackage{etoolbox}

\newcounter{PageOfPdf}

\newcommand{\makeAnnotation}[1]{%
    \ifnumequal{#1}{1}{}{%
        \stepcounter{PageOfPdf}%
        \ifnumequal{#1}{\thePageOfPdf}{}{
            \thePageOfPdf-\the\numexpr #1-1 \\
        }
    }%
    annotate on #1 \\
    \addtocounter{PageOfPdf}{\numexpr #1-\thePageOfPdf}
}
\newcommand{\lastAnnotation}[1]{%
    \makeAnnotation{#1}
    {\the\numexpr #1 +1}- \\
}

\begin{document}
    \noindent
    \makeAnnotation{1}
    \makeAnnotation{11}
    \makeAnnotation{12}
    \lastAnnotation{16}
\end{document}

enter image description here

Few additional remarks:

  • The external if clause in the \makeAnnotation command is necessary in case you need to annotate the first page of your pdf file
  • The internal if clause, instead, is needed to avoid to print the range of unannotated pdf pages in case two following annotations are on consecutive pages
  • The \lastAnnotation command should print the remaining bunch of pages

And few more remarks:

  • Here I added later the etoolbox package for the if clauses; it is very powerful and it could be used to improve the code
  • It could be that there are additional cases I did not consider, but the main idea is here and you should be able to cope with them in case
  • Better ideas/approaches probably exist and feel free to suggest them :)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.