TeX Alchemist Online

TeX を使って化学のお仕事をしています。

pdfTeX による見開きPDFの結合・分割

先日の記事「既存PDFの最初数ページをローマ数字,残りをアラビア数字で,ページ番号を付け直す方法」で,「PDFを見開き 2in1 で並べたり,逆に裁断したりするために pdfTeX を使うこともできる」と述べました。

これについて,反響がありましたので,追加で解説しておくことにしましょう。

PDF加工ツールとしての pdfTeX の実力をとくとご覧ください。

【追記】後日,より良い方法を見つけましたので,改訂版記事を執筆しました。そちらの改良された方法をご利用ください。(本記事も,PDFのバウンディングボックス読み取り処理のサンプルコードおよび /Rotate 除去法のリンク集として残しておきます。)

目次

1. PDFを2-up結合して見開きPDFにする(例:A4x2枚 → A3x1枚)

f:id:doraTeX:20160610205722p:plain

例えば input.pdf を 2-up 結合して見開きPDFにしたい場合,次の pdfLaTeX ソースを作ります。

\def\target{input.pdf}%% 対象PDFファイル名

\documentclass{minimal}
%%% 先頭ページの読み込み
\pdfximage{\target}
%%% pdfTeX の機能で BoundingBox を取得
\dimen1=\pdfximagebbox\pdflastximage 1 %% 左下x
\dimen2=\pdfximagebbox\pdflastximage 2 %% 左下y
\dimen3=\pdfximagebbox\pdflastximage 3 %% 右上x
\dimen4=\pdfximagebbox\pdflastximage 4 %% 右上y
%%% 生成PDFのページサイズを決定
\usepackage[papersize={\dimexpr(\dimen3-\dimen1)*2\relax,\dimexpr\dimen4-\dimen2\relax}]{geometry}
\usepackage{pdfpages}

\begin{document}
\includepdf[nup=2x1,pages=-]{\target}
\end{document}

このソースを 2up.tex というファイルで保存したとすると,次のように pdfLaTeX でコンパイルすれば出来上がりです。

$ pdflatex 2up

2. PDFを裁断する(例:A3x1枚 → A4x2枚)

f:id:doraTeX:20160610204919p:plain

本を裁断せずにスキャナにかけると,次のように,見開き2ページずつのPDFが得られます。これを左右1ページずつに裁断したい状況を考えます。

f:id:doraTeX:20160610195559j:plain

(↑書籍版の「東京防災」をスキャンしたもの。このPDFを左右裁断したい。)

このようなときにも pdfTeX が役立ちます。

2.1 pdfTeX ソース

例えば input.pdf を左右裁断したいときは,次のような plain pdfTeX ソースを作成します。

% plain pdfTeX document
\pdfoutput=1
\def\target{input.pdf}%% 対象PDFファイル名
\def\ratio{0}%% 中央を何パーセント切り落とすか。負の数の場合は中央を両側に含める。-99〜99の百分率値を指定。
\pdfhorigin=0bp
\pdfvorigin=0bp
%
%%% CropBox をデフォルトのバウンディングボックスに指定(1=MediaBox, 2=CropBox, 3=BleedBox, 4=TrimBox, 5=ArtBox)
\pdfpagebox=2
%%% 先頭ページの読み込み
\pdfximage{\target}
%%% 総ページ数の取得
\newcount\pagecount
\pagecount=\pdflastximagepages
%%% BoundingBox の取得
\dimen1=\pdfximagebbox\pdflastximage 1 %% 左下x
\dimen2=\pdfximagebbox\pdflastximage 2 %% 左下y
\dimen3=\pdfximagebbox\pdflastximage 3 %% 右上x
\dimen4=\pdfximagebbox\pdflastximage 4 %% 右上y
%%% 生成PDFのページサイズを決定
\newdimen\originalwidth
\originalwidth=\dimexpr\dimen3-\dimen1\relax
\pdfpagewidth=\dimexpr\originalwidth*(100-\ratio)/200\relax
\pdfpageheight=\dimexpr\dimen4-\dimen2\relax
%%% 画像配置を実行
\newcount\thispage
\loop
\advance\thispage1\relax
\ifnum\thispage>1\relax
  \pdfximage page \thispage {\target}%% ページ読み込み
\fi
%%% 左ページの配置
\setbox0=\hbox to \pdfpagewidth{\pdfrefximage\pdflastximage}%
\ht0=\pdfpageheight\shipout\box0\relax
%%% 右ページの配置
\setbox0=\hbox to \pdfpagewidth{\kern\dimexpr\pdfpagewidth-\originalwidth\relax\pdfrefximage\pdflastximage}%
\ht0=\pdfpageheight\shipout\box0\relax
\ifnum\thispage<\pagecount\repeat
\end

これを split.tex というファイルで保存したとすると,次のように pdfTeX でコンパイルすれば出来上がりです。

$ pdftex split

なお,ソース中の

\def\ratio{0}%% 中央を何パーセント切り落とすか。負の数の場合は中央を両側に含める。-99〜99の百分率値を指定。

の部分は,ノド部分の影を切り落としたいときに,切り落としたい率(パーセント)を正の値で指定します。

f:id:doraTeX:20160610203031p:plain

逆に,この \ratio に負の値を指定すると,中央部が左右両ページに含まれるようになります。スキャン位置が毎回微妙に左右にぶれる場合,安全のために中央部は裁断時に両方に含めるようにしておくとよいでしょう。

2.2 原理

この「pdfTeX によるPDF裁断」は,本当にPDFを裁断しているわけではありません。同一ページを2回ずつ,左右にずらしてページに配置している感じです。ですから生成PDFのファイルサイズは激増してしまう点にご注意ください。

f:id:doraTeX:20160610205326p:plain:w250

3. 前提条件

いずれの方法も,読み込む PDF (input.pdf) が次の条件を満たしていることを仮定しています。

  • 全ページが同じページサイズを持つ。
  • /Rotate による回転がかかっていない。

入力 PDF に /Rotate による回転情報が付与されている場合は,事前に/Rotate を除去して回転情報を“確定”させておくとよいでしょう。

Ghostscript によって

$ gs -sDEVICE=pdfwrite -dBATCH -dNOPAUSE -dAutoRotatePages=/None -sOutputFile=input-norotate.pdf input.pdf

とすると,/Rotate を除去して回転情報を“確定”させた input-norotate.pdf が生成されます。それを pdfTeX から読み込むようにするとよいでしょう。

参考:PDF の /Rotate を除去して回転情報を“確定”させる様々な方法