EDRSPIHCRSSRSS

PDF Manipulation

PDF 파일을 편집하거나 수정하는 것은 보통 AdobeAcrobat을 이용하는 것이 일반적이다. 그러나 이 프로그램은 저렴하지 않은 상업용 프로그램이다. AdobeAcrobat을 이용하지 않고 PDF 파일을 편집하는 방법에 관한 팁을 모아본다.


1. PDF 파일 변환

1.1. n-up

PDF 파일을 한 페이지에 몇 쪽씩 들어가게 인쇄하는 것. PDFPages 패키지를 이용한다. KTUGOperate:4615

두 쪽을 마주보게 각 페이지를 축소해서 배열하는 경우, 즉 1x2 up의 경우를 예로 들어둔다. 원래의 PDF 파일이 testin.pdf라고 할 때, 다음과 같은 testout.tex을 작성한다.
\documentclass[a4paper]{article}
\usepackage{pdfpages}
\begin{document}
\includepdf[pages=-,nup=1x2,landscape,frame=false]{testin.pdf}
\end{document}

이 파일을 PDFLaTeX으로 실행한다.
#> pdflatex testout

이 방법은 pdfpages.sty가 제공하는 \includepdf 명령을 이용하는데, 사용례를 몇 가지 보이면 다음과 같다.
\includepdf[nup=1x2,landscape,pages=4-7]{foo.pdf}
\includepdf[nup=1x2,landscape,pages=4-7,turn=false]{foo.pdf}
\includepdf[nup=2x2,pages=1-4,column]{foo.pdf}

짝수쪽부터 시작하는 것을 방지하기 위하여 처음에 빈 쪽을 넣으려면
\includepdf[nup=2x2,pages={{},5-7}]{foo.pdf}

nup된 각 페이지에 프레임을 넣으려면
\includepdf[nup=2x2,pages=1-4,frame]{foo.pdf}

각 페이지의 일부를 trim함으로써 원래 페이지의 header나 footer를 제거하고 싶다면
\includepdf[nup=2x2,pages=1-4,
            trim= 0 40mm 0 40mm,
            clip]{foo.pdf}

nup된 페이지에 페이지 번호를 붙이고 싶다면
\includepdf[nup=2x2,pages=1-4,pagecommand={\thispagestyle{plain}}]{foo.pdf}

1.2. Merge

See PDFMerge.

1.3. PDF 파일 한쪽씩 합치기

두 개의 PDF 파일을 각각 한 페이지씩 교차하여 합쳐서 하나의 PDF 파일이 되도록 하는 방법 from KTUGOperate:4663 (by Karnes)

이 방법은 두 문서의 페이지수가 같고 마지막 페이지를 알고 있다고 가정했을 때 입니다. 각각의 문서를 컴파일해서 a.pdf와 b.pdf를 얻었고, 이 두 PDF의 페이지가 예를 들어 10페이지씩이라고 가정하겠습니다.

다음과 같은 total.tex을 작성합니다.
\documentclass{article}
\usepackage{pdfpages}
\makeatletter
\def\for#1#2#3{\@ifnextchar[{\@for@{#1}{#2}{#3}}{\@for@{#1}{#2}{#3}[1]}}
\long\def\@for@#1#2#3[#4]#5{\setcounter{#1}{#3}\addtocounter{#1}{1}%
        \edef\for@loopend{\arabic{#1}}%
        \setcounter{#1}{#2}%
        \loop
        \ifnum \expandafter\the\csname c@#1\endcsname < \for@loopend\relax
        #5\addtocounter{#1}{#4}\repeat}
\newcounter{repeatcnt}
\makeatother

\begin{document}
\for{repeatcnt}{1}{10}{%
        \includepdfmerge{a.pdf,\therepeatcnt,b.pdf,\therepeatcnt}
}
\end{document}

이제 pdflatex으로 total.tex을 컴파일하면 total.pdf를 얻을 수 있습니다. 페이지 수에 신경쓰시고, \includepdfmerge 명령 안에 모든 인자가 콤마로 분리되어 있다는 점에 주의하시면 될 것입니다. 이 예제에서는 for Loop를 구현하는 예도 보였습니다.

오래 전의 위의 샘플을 Expl3로 다시 써보았습니다.
\documentclass[a4paper]{article}
\usepackage{expl3,xparse}
\usepackage{pdfpages}
\usepackage{ksforloop}

\ExplSyntaxOn 

\int_new:N \lastlastpagenum

\NewDocumentCommand \numberofpdfpages { m }
{
        \luatex_if_engine:TF
        {
                \pdftex_pdfximage:D { #1 }
                \int_gset:Nn \g_tmpa_int { \pdftex_pdflastximagepages:D }
        }
        {
        \pdftex_if_engine:TF
        {
                \pdftex_pdfximage:D { #1 }
                \int_gset:Nn \g_tmpa_int { \pdftex_pdflastximagepages:D }
        }
        {
                \xetex_if_engine:T
                {
                        \int_gset:Nn \g_tmpa_int { \xetex_pdfpagecount:D "#1" }
                }
        }
        }
}

\NewDocumentCommand \pdffilestoprepare { m m }
{
        \numberofpdfpages { #1 } \int_set_eq:NN \l_tmpa_int \g_tmpa_int
        \numberofpdfpages { #2 } \int_set_eq:NN \l_tmpb_int \g_tmpa_int
        
        \int_compare:nTF { \l_tmpa_int > \l_tmpb_int }
        {
                \int_set_eq:NN \lastlastpagenum \l_tmpb_int
        }
        {
                \int_set_eq:NN \lastlastpagenum \l_tmpa_int
        }

        \tl_set:Nn \leftpdffile { #1 }
        \tl_set:Nn \rightpdffile { #2 }
}

\NewDocumentCommand \domerge { m m o }
{
        \pdffilestoprepare { #1 } { #2 }

        \IfValueT { #3 } { \int_set:Nn \lastlastpagenum { #3 } }

        \ksforloop{}{\lastlastpagenum}
        {
                \includepdfmerge{\leftpdffile,\ksfori,\rightpdffile,\ksfori}
        }
}

\ExplSyntaxOff 

\begin{document}

\domerge{a.pdf}{b.pdf}

\domerge{a.pdf}{b.pdf}[10]

\end{document}

이 예제에는 외부 pdf 파일의 마지막 페이지 번호를 얻어내는 방법이 들어 있습니다. (즉 각 pdf 파일의 최종 페이지 수를 미리 알고 있지 않아도 됩니다.) 두 파일의 최종 페이지를 비교하여 적은 쪽수를 가진 파일을 기준으로 합칩니다. 세 번째의 옵션 인자를 주면 1쪽부터 해당쪽까지 합칩니다.

2. PDF Cropping

PS 파일은 PS2Eps를 쓰면 Bounding Box를 조절해줍니다. PDF는 Bounding Box가 없지만 /MediaBox 지시자로 PS의 Bounding Box와 동일한 효과를 냅니다. PDF 파일의 Bounding Box를 정확하게 알고 싶으면 ebb를 실행해봅니다.

MediaBox가 잘못되어 있을 때 이를 수정하거나, 여백이 큰 PDF의 여백을 잘라내는 방법입니다.

2.1. pdfcrop.pl

Heiko Oberdiek 씨가 작성한 Perl 스크립트입니다.
CTAN CTAN:support/pdfcrop/

다음은 pdfcrop.pl --help 화면입니다.
PDFCROP 1.2, 2002/11/04 - Copyright (c) 2002 by Heiko Oberdiek.
Syntax:   pdfcrop [options] <input[.pdf]> [output file]
Function: Margins are calculated and removed for each page in the file.
Options:                                                    (defaults:)
  --help              print usage
  --(no)verbose       verbose printing                      (false)
  --(no)debug         debug informations                    (false)
  --gscmd _name_      call of ghostscript                   (gswin32c)
  --pdftexcmd _name_  call of pdfTeX                        (pdftex)
  --margins "left top right bottom"                 (0 0 0 0)
                      add extra margins, unit is bp. If only one number is
                      given, then it is used for all margins, in the case
                      of two numbers they are also used for right and bottom.
  --(no)clip          clipping support, if margins are set  (false)
  --(no)hires         using '%%HiResBoundingBox'            (false)
                      instead of '%%BoundingBox'
Examples:
  pdfcrop.pl --margins 10 input.pdf output.pdf
  pdfcrop.pl --margins '5 10 5 20' --clip input.pdf output.pdf

windows에서 TeX Live 2010을 사용할 경우 pdfcrop.pl 대신 pdfcrop 이라고 부르면 됩니다.

2.2. PDFTeX 파일을 작성하는 방법

from KTUGOperate:4284 (by 이공훈) 위의 유틸리티로 웬만한 PDF는 다 변환이 되지만, AdobeIllustrator에서 한글 Font를 포함하여 만들어진 PDF의 일부가 Ghostscript에서 읽어지지 않을 때가 있습니다. 이런 경우, 다음과 같은 .tex 파일을 작성하여 PDFTeX을 실행하면 PDF 파일을 원하는 크기만큼 잘라낼 수 있습니다. 원본 파일이 ainput.pdf인 경우,
\def\pdffile{ainput.pdf}                % <-- file 이름 수정
\def\page #1 [#2 #3 #4 #5]{%
  \count0=#1\relax
  \setbox0=\hbox{%
    \pdfximage page #1{\pdffile}%
    \pdfrefximage\pdflastximage
  }%
  \pdfhorigin=-#2bp\relax
  \pdfvorigin=#3bp\relax
  \pdfpagewidth=#4bp\relax
  \advance\pdfpagewidth by -#2bp\relax
  \pdfpageheight=#5bp\relax
  \advance\pdfpageheight by -#3bp\relax
  \ht0=\pdfpageheight
  \shipout\box0\relax
}
\page 1 [40 290 552 552]             % <-- 괄호 안의 BoundingBox 수정
\end
이 파일을 예를 들면 aoutput.tex으로 저장하고 다음과 같이 실행합니다.
#> pdftex aoutput

2.3. 예제

DVIPDFMx를 이용하여 다음과 같은 PDF 파일을 얻었습니다. ( Uploads:pdfcroptestinput.pdf )
#> perl pdfcrop.pl --clip pdfcroptestinput.pdf pdfcroptestoutput.pdf
그 결과 다음과 같은 PDF 파일이 만들어졌습니다. Uploads:pdfcroptestoutput.pdf

3. PDF Select (낱장추출)

3.1. ConTeXttexexec를 사용하는 방법

3.1.1. 일부 페이지만 추출

cf. KTUGOperate:7332 (by DohyunKim)

한 페이지만 추출하려면 texexec --pdfselect 방법을 쓴다. orig.pdf의 1페이지만을 test1.pdf로 쓰려면 다음과 같이 한다.
#> texexec --pdfselect --selection=1 --batch --result=test1.pdf orig.pdf

따라서, 1페이지부터 10페이지까지 별도의 PDF 파일로 만들려면, Perl을 이용하여,
for(1..10) {
  system("texexec --pdfselect --selection=$_ --batch --result=test$_.pdf orig.pdf");
}

3.1.2. 한 페이지만 추출하는 Shell 스크립트

위의 texexec로 한 페이지만 추출하는 것을 Shell Script로 만든 것.(Claus Gerhardt 씨)

#!/bin/sh
##
# pdfsel.sh
# pdfselect
#
# $1= selected pages either in form of a list x,y,z or in form of range x:y or as odd #resp. even
#filenename without suffix pdf, the resulting file is named filename-ext.pdf
# Claus Gerhardt
##


# EXTENSIONS : "*"
# OSTYPES    : "****"

for file; do
location=$(dirname "$file")
cd "${location}" && \
texexec --pdfselect --batch --silent --selection="$1" --result="${file}-ext.pdf" "${file}.pdf" \
&& rm -f "${file}-ext.tui" && rm -f "${file}-ext.tmp" && rm -f "texexec.tex" \
&& rm -f "texexec.tmp" && rm -f "texexec.tui" && rm -f "mprun.mp" rm -f "mpgraph.mp" \
&& rm -f "${file}-ext.log"
done

3.2. PDFPages를 이용하는 방법

3.2.1. 일부 페이지 추출

KTUGOperate:7342 (by 이공훈)

1페이지부터 10페이지까지 추출하는 방법.

#!/usr/bin/perl

for(1..10) {
open(OUT,">test$_.tex") or die "Cannot write 'test$_.tex'";
print OUT << "EOF";
\\documentclass[a4paper]{article}
\\usepackage{pdfpages}
\\begin{document}
\\includepdf[pages=$_]{orig.pdf}
\\end{document}
EOF
close OUT;
system("pdflatex --interaction batchmode test$_");
unlink "test$_.tex","test$_.log","test$_.aux";
}

3.2.2. 한 페이지만 추출하는 Shell Script

pdfsel.sh
#!/bin/sh

PAGENUM=$1
OUTFILE=$2-ext-$1.tex

echo '\documentclass{article}' > $OUTFILE
echo '\usepackage{pdfpages}' >> $OUTFILE
echo '\begin{document}' >> $OUTFILE
echo '\includepdf[pages='$PAGENUM']{'$2'.pdf}' >> $OUTFILE
echo '\end{document}' >> $OUTFILE
pdflatex --interaction=batchmode $OUTFILE

#> sh pdfsel.sh 13 test
(입력파일의 확장명 .pdf를 쓰지 않음. 첫번째 인자는 추출하려는 페이지, 두번째 인자는 입력파일. 결과는 test-ext-13.pdf와 같이 만들어진다.)

동일한 DOS Batchfile.
@echo off
rem pdfsel.bat
echo \documentclass{article} > %2-ext-%1.tex
echo \usepackage[pdftex]{graphicx} >> %2-ext-%1.tex
echo \usepackage{pdfpages} >> %2-ext-%1.tex
echo \begin{document} >> %2-ext-%1.tex
echo \includepdf[pages=%1]{%2.pdf} >> %2-ext-%1.tex
echo \end{document} >> %2-ext-%1.tex
pdflatex --interaction=batchmode %2-ext-%1
del %2-ext-%1.aux
rem del %2-ext-%1.log
del %2-ext-%1.tex

(!) 위의 pdfsel.bat를 이용하여 Windows 령행에서, 1페이지부터 10페이지까지 한 페이지씩 각각 하나의 PDF로 원본 test.pdf를 추출하는 방법.
#> for /L %i IN (1,1,10) DO call pdfsel.bat %i test


3.3. pdftk를 사용하는 방법

PDFtkhttps://www.pdflabs.com/ 에서 제공하며, 여기 설명하는 페이지 추출말고도 PDF Merge, 암호화 등의 다양한 기능들을 제공한다.

3.3.1. 일부 페이지만 추출

다음 예를 인풋 파일의 1쪽에서 12쪽까지 그리고 14쪽부터 끝까지를 추출하는 것이다.
pdftk A=in.pdf cat A1-12 A14-end output out.pdf
다음과 같은 파일 추출/병합도 가능하다.
pdftk A=in1.pdf B=in2.pdf cat B1 A1-7even A1-7odd output out1.pdf

3.3.2. 모든 페이지를 각 장씩 추출할려면

다음과 같은 명령어를 사용하면 된다.
pdftk input.pdf burst

3.3.3. 여러장의 PDF를 하나로 묶으려면

다음과 같은 명령어를 사용하면 된다. in1.pdf, in2.pdf 를 out1.pdf로 만들려면
pdftk in1.pdf in2.pdf cat output out1.pdf
or 
pdftk A=in1.pdf B=in2.pdf cat A B output out1.pdf
모든 *.pdf를 out1.pdf로 묶으려면
pdftk *.pdf cat output out1.pdf
  • 출처 : pdftk --help message

4. Booklet 만들기

PDF Booklet이란 한 쪽에 두 페이지씩 들어가게 인쇄하여 양면인쇄한 후 가운데를 철하면 소책자가 되도록 하는 것이다. PDFPages 패키지, \includepdf 명령의 signature 옵션을 이용한다. 주의할 점은, signature 값이 4의 배수가 되도록 하는 것이다. 11쪽 짜리 PDF가 하나 있고, 이것으로 소책자를 만들려는 경우를 생각해보자. 원 파일 이름이 doc.pdf라 하고, 다음과 같은 aout.tex을 작성한다.
%%-----------
\documentclass{article}
\usepackage[pdftex]{graphicx}
\usepackage{pdfpages}

\begin{document}
\pagestyle{empty}
\includepdf[pages=-,signature=12,landscape]{doc.pdf}
\end{document}
%%------------

이 원본 파일에 대하여 PDFLaTeX을 실행하면 aout.pdf가 만들어진다. 이 PDF를 양면인쇄하여 가운데를 접어서 철해보자.

signature 옵션을 주는 경우 nup 옵션은 무의미하다. 항상 1x2 또는 2x1로 PDF가 만들어질 것이다.

이 과정을 자동화해주는 DohyunKim 님의 Perl Script. KTUGBoard:3167

5. PDF 본문 복사 방지

KTUGOperate:12845 PDFEncryption

6. PDFJam

PDFJam = PDFPages의 명령행 유틸리티

7. 그밖의 유틸리티

TeX과 무관하지만 PDF를 다루는 유틸리티들은 많다.
  1. PDFill

  2. PDFTools
    PDF들을 합치는(Merge) pdcat, 페이지를 추출하는 pdsel, pdsplit, 텍스트를 PDF로 바꾸는 txt2pdf, 그밖에도 북마크 추가, 링크 추가 등을 할 수 있는 유틸리티를 제공한다.

  3. PDFtk
    PDF Toolkit. See PDFtk.

  4. Multivalent Tools
  5. KLDPBBS Windows에서 PostScript 파일로 프린트 하기, PS 파일을 PDF로

  6. pyPDF

CategoryFaq