Skip to content

Instantly share code, notes, and snippets.

@sparr
Last active March 17, 2025 14:24
Show Gist options
  • Save sparr/e83079ca02edb33fb791121b64eeb892 to your computer and use it in GitHub Desktop.
Save sparr/e83079ca02edb33fb791121b64eeb892 to your computer and use it in GitHub Desktop.
Postscript script to add page numbers to an existing document
%!PS
% originally from https://stackoverflow.com/a/57162167/13675
% Usage to concatentate multiple PDFs, number all the pages sequentially, and output a single PDF:
% gs \
% -dBATCH -dNOPAUSE \
% -sDEVICE=pdfwrite -dPDFSETTINGS=/prepress \
% -sOutputFile=/path/to/merged.pdf \
% -f add_page_numbers.ps -f input1.pdf -f input2.pdf
% modifications by Clarence "Sparr" Risher <[email protected]>
% to add centered page numbers with prefix and suffix
% Note: Page dimensions are expressed in units of the default user space (72nds of an inch).
% inspired by https://www.ghostscript.com/pipermail/gs-devel/2005-May/006956.html
globaldict /MyPageCount 1 put % initialize page counter
% String concatenation function from ghostscript Resource/Init/gs_init.ps
/concatstrings % (str1) (str2) concatstrings (str1str2)
{ exch dup length 2 index length add string % str2 str1 new
dup dup 4 2 roll copy % str2 new new new1
length 4 -1 roll putinterval
} bind def
% executed at the end of each page. Before calling the procedure, the interpreter
% pushes two integers on the operand stack:
% 1. a count of previous showpage executions for this device
% 2. a reason code indicating the circumstances under which this call is being made:
% 0: During showpage or (LanguageLevel 3) copypage
% 1: During copypage (LanguageLevel 2 only)
% 2: At device deactivation
% The procedure must return a boolean value specifying whether to transmit the page image to the
% physical output device.
<< /EndPage {
exch pop % remove showpage counter (unused)
0 eq dup { % only run and return true for showpage
MyPageCount 0 lt % starting page of "later pages" below
{
/Courier 8 selectfont % select font and size for early pages
}
{
/Courier 12 selectfont % select font and size for later pages
}
ifelse
MyPageCount =string cvs % get page counter as string
(PREFIX) exch concatstrings % add prefix to page number string
(SUFFIX) concatstrings % add suffix to page number string
dup % need it twice (width determination and actual show)
stringwidth pop % get width of page counter string ...
2 div % halve the width of the string
currentpagedevice /PageSize get 0 get % get width from PageSize on stack
2 div % halve the width of the page
exch sub % pagewidth/2 - stringwidth/2
18 moveto % move to calculated x and y=18 (0/0 is the bottom left corner) (18 units is 1/4")
show % finally show the page counter
globaldict /MyPageCount MyPageCount 1 add put % increment page counter
} if
} bind >> setpagedevice
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment