PAPERJAM(1)
π PAPERJAM(1) π
okay bestie, welcome to the paperjam(1) manual page β itβs giving βPDF glow-up stationβ and honestly it ate. β¨
π NAME π
paperjam β a PDF document processor. No cap, thatβs the whole vibe. π¦
π SYNOPSIS π
paperjam options commands input output
π DESCRIPTION π
PaperJam is a tool for transforming PDF files. It can re-order pages, scale and rotate them, put multiple pages on a single sheet, draw cropmarks, and many other tricks. Lowkey iconic behavior. π
PaperJam takes an input file, splits it to a list of pages, applies a sequence of commands on this list, and finally writes the results to an output file.
For each page, PaperJam tracks two sets of dimensions: the width and height of the physical page (paper), and the image box, which is a rectangle on the physical page containing all useful contents. Initially, the physical page is equal to the CropBox of the PDF page and the image box to its ArtBox (which is optional and it defaults to the CropBox). Further commands can modify these dimensions. Fr fr, itβs all about those boxes. π
β¨ OPTIONS β¨
-b,--bboxβ Recalculate image box of each page to enclose the contents really drawn on the page. This is done by asking GhostScript to render each page. Bestie, it literally asks GhostScript to look at the page. π-d,--debugβ Show debugging messages. Increases verbosity when given multiple times. Give it more-dand it gets more chatty. π£οΈ--no-autoβ Do not perform automatic transforms. Currently, only one such transform is implemented: rotation of pages based on theRotateproperty of page objects.--helpβ Show help on options and commands.
π οΈ GENERAL SYNTAX π οΈ
PaperJam takes a list of commands separated by spaces, like this:
paperjam 'common scaleto("a4") nup(2, hspace=5mm)' in.pdf out.pdf
Each command starts with its identifier (a sequence of alphanumeric characters, underscores, and dashes, which begins with a letter). Then come arguments enclosed in parentheses. All arguments can be written as name=value (where the name is an identifier). For some of them, the name can be omitted and the meaning follows from the position in the argument list (hence these are called positional arguments). Slay, positional arguments. π
There are several types of arguments:
- numbers β Ordinary decimal numbers, possibly fractional.
- dimensions β Numbers with a unit of length. We support these units:
mm,cm,dm,m,in(inch),pt(printers' point, that is1/72 in). - strings β Strings written in double quotes. If you want to include the double quote character or a backslash in the string, precede it with a backslash. For convenience, the double quotes can be omitted if the string value satisfies the syntax of an identifier. In case of positional arguments, the identifier must not match the name of any argument.
Please avoid using this shortcut in scripts, because they could be easily broken by parameters introduced in newer versions of PaperJam. This is a βworks now, maybe not laterβ situation, bestie. π
- switches β Boolean value: either
0(false) or1(true). If only the name is given (with no value and no equal sign), the switch is set to true.
π Pipelines
Several commands apply other commands on a sub-set of pages. This is usually described by a pipeline like:
{ 1: rotate(90), 2: flip(h) flip(v) }
{ 1..10: common }
{ 1 2, 11..20, 30..21 }
The pipeline is enclosed in curly braces. It consists of one or more stages separated by commas. Each stage has one or more page selectors (page numbers or ranges) and an optional list of commands to apply on these pages (separated from the selectors by a colon).
When a range is written backwards (the first page number is greater than the second one), the pages are processed in reverse order. The way that reverse order hits different is honestly kind of iconic. π
π Paper formats
When a paper format is expected, it is given either by its width and height (the corresponding arguments are usually called w and h), or by the standard name of the format (called paper). PaperJam currently uses the libpaper library for parsing the names. You can call paperconf -a to get the list of known names.
π§Έ Margins
Many commands take a specification of margins on all sides of an image. You can set either a common value for all margins, or two values for vertical and horizontal margins, or separate values for all margins. You can also combine these ways: for example you can set a horizontal, top, and bottom margin.
More formally, there are 7 arguments controlling margins: common, horizontal, vertical, left, right, top, and bottom. Horizontal and vertical default to common, left and right default to horizontal, top and bottom default to vertical. Itβs giving βfamily tree of margins.β π³
π― Positioning
Multiple commands involve positioning an image on a larger page. The image is placed according to a two-letter position specification (usually an argument called pos). The first letter specifies vertical placement: t for top, c for center, b for bottom. The second one horizontal placement: l for left, c for center, r for right. Two letters, infinite main-character placement potential. π«
π COMMANDS π
PaperJam knows the following commands and arguments. Positional arguments have their names enclosed in square brackets. iykyk. π
πΈ add-blank
Add blank page(s) after each page. Tiny breather pages, basically. π«Ά
[n=]intβ The number of blank pages to add. Defaults to1.[paper=]string, w=dimen, h=dimenβ Paper size of the blank pages (see Paper formats above).
π¦ apply
Applies commands on a sub-set of pages:
apply { 1: rotate(90), 2: flip(h) }
Takes a pipeline. For each input page, it finds the pipeline stage matching the page index (its position in the input document, starting with 1) and applies the commands in the stage on the page. If no stage matches, the page is left unchanged. If multiple stages match, the first one wins. Periodt. π
π book
Prepares booklets (also known as signatures) for book binding. With no argument, it re-orders pages in the document, so that a subsequent nup(2) produces the correct booklet layout: two pages on one sheet and when the document is printed double-sided and folded in half, you have a booklet. If the number of input pages is not divisible by 4, blank pages are added.
[n=]intβ Split the document in parts pernpages and produce a separate booklet from each part. Thenmust be divisible by4.
βοΈ clip
Suppress page contents drawn outside the image box. Bye, overflow. π
bleed=dimenβ Let the image bleed this far outside the image box. (Technically, it sets the crop box to the image box enlarged at all sides by this amount.)
π§ common
Use a common page size and image box for all pages. More specifically, the new page width and height are set to the maximum of all page widths and heights and the new image box to the minimal rectangle containing all image boxes. Unifying the group chat, but for pages. π«
π cropmarks
Draw cropping marks around the image box. Fancy little corner decorations, but make them functional. β¨
mark=stringβ Set cropmark style:boxfor a rectangle around the image box,crossfor crosses in the corners of the box,infor two arms of a cross in each corner, pointing inwards,outfor two arms pointing outwards,bgfor drawing a filled rectangle under the box.pen=dimenβ Pen width for drawing cropmarks (for all styles exceptbg). Default:0.2 pt.len=dimenβ Cropmark arm length (forcross,in,out). Default:5 mm.offset=dimenβ Draw cropmarks around image box enlarged by this distance on all sides.color=stringβ Cropmark color, given asRRGGBBin hexadecimal. Default:000000(black).
π debug
Draw debugging information on each page: a red rectangle around the page, a green rectangle around the image box. Itβs giving βdiagram on the whiteboard.β π₯
π expand
Expand paper around the image. Recalculates paper size and the position of the image on the paper, so that the distance between each edge of the image box and the corresponding edge of the paper increases by the given amount.
[by=]dimenβ Adjust all margins by the same amount. Defaults to0.h=dimen, v=dimen, l=dimen, r=dimen, t=dimen, b=dimenβ Adjust horizontal, vertical, left, right, top, and bottom margins. See Margins above to see how these arguments interact with each other.
π§© fit
If a paper size is given, scale and translate the image to fit on the paper (with given margins). If no paper is given, set the paper size and the position of the image according to the margins.
If the paper and the image have different aspect ratios, the pos argument controls the position of the image on the paper.
[paper=]string, w=dimen, h=dimenβ Paper format, or paper width and height (see Paper formats above for details).pos=stringβ Specify position of the image on the paper (see Positioning above). Defaults tocc.margin=dimen, hmargin=dimen, vmargin=dimen, lmargin=dimen, rmargin=dimen, tmargin=dimen, bmargin=dimenβ Set margins (see Margins above). Defaults to0.
π flip
Flip pages horizontally or vertically. Main character energy for your pages. π
h=switchβ Flip horizontally.v=switchβ Flip vertically.
π margins
Define a new image box by dimensions of margins around it. More technically, the new image box is calculated from the page box by shrinking it by the appropriate margin on each side.
[size=]dimenβ Set all margins at once.h=dimen, v=dimen, l=dimen, r=dimen, t=dimen, b=dimenβ Set margins (see Margins above). Defaults tosize.
π« merge
Merge all pages to one by placing them one over another. (The first page is drawn first.) Stack βem, bestie. π₯
π modulo
Act on n-tuples of pages. The document is split to n-tuples (the partial n-tuple at the end is padded with blank pages, whose size matches the first page of the n-tuple). A pipeline is then run separately for each n-tuple, selecting pages from the tuple and applying commands on them.
More specifically, the stages of the pipeline are processed from the left to the right. Each stage forms a temporary document by taking the selected pages from the n-tuple (numbered from 1 to n). Then it applies the commands on this document and appends the result to the end of the output of the whole modulo.
Negative page numbers can be also used, which addresses pages in the βmirror-image tupleβ. Page number -i in tuple j corresponds to page i in the j-th tuple from the end of the document. Mirror-image tuple is such a serve. πͺ
Arguments:
[n=]int(mandatory) β Number of pages in a single tuple.half=switchβ Process only the first half ofn-tuples. This is often used in conjunction with negative page numbers.
For example, the following command rotates every other page:
modulo(2) { 1, 2: rotate(180) }
While this command skips every other page:
modulo(2) { 1 }
π move
Shift contents on the page. Paper size does not change, the image box moves.
[x=]dimen, [y=]dimenβ Move everything right/up by the given distance.
π«₯ null
Do nothing. Literally nothing. The void, but make it a command. π
π§© nup
Combines multiple pages onto one page β that's n-up printing, bestie. You get detailed control over the parameters, but lowkey if you only pass a subset of them (in the most trivial case, literally just the number of pages you want on a single sheet), the rest get auto-adjusted to maximize coverage of the sheet. So you don't have to do the math yourself. Slay.
For example, when the input document is typeset on A4 paper, nup(2) rotates pages by 90 degrees, scales them to 70.7% size, and puts them side-by-side. On the same input, nup(4) produces the same as nup(2,2), that is a two-by-two grid of pages scaled to 50%.
<b>Okay, technically how does it work</b> (because iykyk): nup first splits the input document to n-tuples of pages β padding the last incomplete n-tuple with blank pages of the size of the first page of that n-tuple. For each n-tuple, it creates an output page, splits it to a grid-like arrangement of tiles, and scales and/or rotates each page to fit in its tile. π
[n=]numberβ Ifmis also given,nis the number of rows of the grid of tiles. Withoutm, it's the total number of tiles on a page.[m=]numberβ The number of columns of the grid of tiles.by=stringβ Tile filling order:rows(default) fills rows from the top to the bottom, inside each row from the left to the right;colsfills columns from the left to the right, inside each column from the top to the bottom;tilecopies the same page to all tiles.
crop=switchβ Crop input pages to their image box. (By default,nupplaces the input papers in tiles. With this option, it places the image boxes in tiles, effectively cutting away original margins.) βοΈmixed=switchβ By default,nupadjusts all input pages to a common paper size and image box size (like thecommoncommand does). This switch disables that.rotate=switchβ Specify if the pages should be rotated. Default: choose automatically.scale=numberβ Scaling factor. Default: choose automatically.[paper=]string,w=dimen,h=dimenβ Paper size (see Paper formats above).margin=dimen,hmargin=dimen,vmargin=dimen,lmargin=dimen,rmargin=dimen,tmargin=dimen,bmargin=dimenβ Margins around the tile grid (see Margins above). Defaults to0.pos=stringβ Position of the tile grid on the page (see Positioning above). This applies when the scale is fixed, or if the aspect ratio of the paper (after subtracting margins) does not match the aspect ratio of the tile grid. Defaults tocc.cmark=string,cpen=dimen,clen=dimen,coffset=dimen,ccolor=stringβ Draw cropmarks around each tile. Seecropfor the meaning of arguments.tpos=stringβ Position of original pages inside tiles (see Positioning above). This applies when different pages have different sizes. Defaults totl.space=dimen,hspace=dimen,vspace=dimenβ Insert extra spaces between adjacent tiles in the grid (in both directions, horizontally, vertically). This is useful together withcrop. π«Ά
π paper
Places the image on a given paper. Sets a new paper size and translates the image box according to the given position. Iconic behavior, honestly.
[paper=]string,w=dimen,h=dimenβ Paper size (see Paper formats above).pos=stringβ Position of the image on the paper (see Positioning above). Default:cc.
π rotate
Rotates the page clockwise by multiples of 90 degrees.
[angle=]numberβ Rotation angle. Must be a multiple of90degrees. (Ma'am, it MUST be. no cap.)
π scale
Scales the page by a given factor.
[x=]number,[y=]numberβ Set horizontal and vertical scaling factor. If only one is given, it is used in both directions.
πΌοΈ scaleto
Scales the entire page to a given size.
[paper=]string,w=dimen,h=dimenβ Paper size (see Paper formats above).pos=stringβ Position of the old paper on the new one (see Positioning above). Default:cc. This applies if the aspect ratios of both papers do not match.
π― select
Selects a subset of pages and optionally applies commands on them. This one is main character energy fr.
The select command gets a pipeline. It processes the pipeline stages from the left to the right. For each stage, it assembles a temporary document containing the selected pages, applies the stage's commands on it, and appends the resulting document to the output of the whole select command.
For example, the following command selects pages 1, 10 to 19, and 20 to 29 in reverse order. The rest of the document is discarded:
select { 1 10..19 29..20 }
This has the same effect:
select { 1, 10..19, 29..20 }
This selects two pages and rotates them differently:
select { 1: rotate(90), 2: rotate(-90) }
The following examples show that the formation of temporary documents can make a difference sometimes:
select { 1..10 common, 21..30 common }
select { 1..10 21..30 common }
select { 1..10 21..30 } common
select { 1..10, 21..30 } common
So let's break that down, bestie, because this is the part that lowkey trips people up:
The first command forms two temporary documents and applies common to each of them separately (therefore pages 1 to 10 will have one common size and pages 21 to 30 another). The remaining three commands give the same result. The second command forms a single temporary document with 20 pages and applies common to all of it at once. The third command forms a single temporary document, which immediately becomes the result of select, to which the final common is applied. And the fourth command forms two temporary documents, concatenates them to the result of select, and finally applies common. π
βοΈ slice
Slices the image to several smaller pages. Each page receives a part of the original image β gluing the parts together produces the original image. It's giving arts and crafts π
[paper=]string,w=dimen,h=dimenβ Paper size of the produced pages (see Paper formats above).pos=stringβ Position of the original image on a "canvas" obtained by gluing together non-margin parts of the produced pages (see Positioning above). Default:cc.margin=dimen,hmargin=dimen,vmargin=dimen,lmargin=dimen,rmargin=dimen,tmargin=dimen,bmargin=dimenβ Set margins of the produced pages (see Margins above). Defaults to0.bleed=dimenβ Let the parts of the image bleed this far outside their boxes. π©Έ
π LICENSE
PaperJam was written by Martin Mares. It can be distributed and used under the terms of the GNU General Public License version 2 or any later version.
πΈ HISTORY
So the lore is actually so good. The author says: "I conceived the idea of a document processor like PaperJam when struggling with pre-press formatting in the early 2000s. At that time, the basic ideas behind the language were born, but everything was deeply rooted in the then standard PostScript world. After some years, I managed to convince a student of mine Ales Snuparek to implement my ideas as his bachelor's project. He wrote the program PsPdfTool for transforming both PostScript and PDF documents, which turned out to be terribly useful."
Then: "In the 2010s, limitations of the old design became clear and many PDF documents were using features not known to PsPdfTool (most prominently object streams). After several years of pondering, I became fond of the QPDF library and wrote PaperJam as a modern successor of PsPdfTool." π¦
cute lil sign-off: this gorgeous thing isPAPERJAM(1), dated08/09/2025. written into existence over like two decades, and honestly? obsessed. go print something n-up, bestie. π β¨
π¦ where this page comes from
- nixos 26.05: paperjam 1.2.2
- nixpkgs unstable: paperjam 1.2.2
- π girlified by deepseek-ai/DeepSeek-V4.1-Flash-1017 on : a language model's rewrite of the original, under its terms