TeX Alchemist Online

TeX のこと,フォントのこと,Mac のこと

ページ数カウントの活用例:既存PDFの全ページに透かしを入れる

以前,LaTeX文書内から外部PDFファイルのページ数を取得する方法を解説しました。

doratex.hatenablog.jp

その中で,その典型的な用途として,次のように述べました。

LaTeX文書内から,外部PDFファイルのページ数を取得したい状況はよくあります。例えば,「外部PDFファイルの全ページにわたって○○を繰り返す」というような状況のとき,ループ回数を決めるにはそのページ数を取得せねばなりません。

この「外部PDFファイルの全ページにわたって○○を繰り返す」という用途の例として,既存PDFの全ページに透かしを入れたいという状況を考えましょう。

例えば,次のような,複数ページからなる既存のPDF(用紙サイズA4)があったとしましょう。

この文書の全ページの背景に「機密文書」という透かし(ウォーターマーク)を入れたいとします。

用意するもの

コード

(ここでは (u)pLaTeX 用のコードを示しますが,LuaLaTeX 等でもドキュメントクラスだけ変えれば使えます。)

%!uplatex
\documentclass[autodetect-engine,dvipdfmx,a4j]{jsarticle}
\usepackage{countpdfpages}% https://gist.github.com/doraTeX/99366548d6bf8f683328caf09accc74c
\usepackage{bxpgfcurpage}% https://gist.github.com/zr-tex8r/ee0998a76f90338c935ec8915c44d3d8
\usepackage{ifthen}
\usepackage{tikz}
\pagestyle{empty}

\makeatletter
\newcount\forEachPDFPage@count
\long\def\forEachPDFPage#1in#2\do#3{%
  \ifdefined#1\else\newcount#1\fi
  \CountPDFPages{#2}%
  \forEachPDFPage@count=\z@
  \whiledo{\forEachPDFPage@count<\PDFPageCount}{%
    #1=\forEachPDFPage@count
    \advance#1\@ne
    #3%
    \advance\forEachPDFPage@count\@ne
  }%
}
\makeatother

\begin{document}

% 透かしを入れる対象となるPDFのファイル名
\def\target{input.pdf}

% 現在のページ番号を \pageIndex に格納した状態で \target の全ページにわたって処理を繰り返す
\forEachPDFPage \pageIndex in \target \do{%
  \begin{tikzpicture}[remember picture,overlay]
    % 透かしを下に敷く
    \node[font=\sffamily,scale=12,rotate=5,text=pink!80!white,draw=pink!80!white,rectangle,line width=4pt,inner sep=1pt] at (current page.center) {機密文書};
    % その上にページを貼る
    \node at (current page.center) {\includegraphics[page=\the\pageIndex]{\target}};
  \end{tikzpicture}%
  \newpage
}

\end{document}

このLaTeXソースを(u)pLaTeXでコンパイル(2回コンパイルが必要です)すると,次のPDFが生成されます。

このように,ここで定義した \forEachPDFPage は,次のように使います。

\forEachPDFPage \ページカウンタ名 in ファイル名 \do {繰り返し処理}

繰り返し処理 の中では,現在のページ番号をTeXカウンタ \ページカウンタ名 で参照できます(1始まり)。主に,

\includegraphics[page=\the\ページカウンタ名]{ファイル名}

として,「○○ページを挿入」という形で使うことになるでしょう。

上記コードをテンプレートとして使えば,「外部PDFファイルの全ページにわたって○○を繰り返す」という処理に汎用的に応用することができるはずです。