Created
January 8, 2011 04:30
-
-
Save jpertino/770544 to your computer and use it in GitHub Desktop.
sort pdf pages for book-like two-page print
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
@GrabResolver(name='itextpdf', root='http://maven.itextpdf.com/') | |
@Grab('com.itextpdf:itextpdf:5.0.5') | |
import static com.itextpdf.text.PageSize.A4 | |
import com.itextpdf.text.Document | |
import com.itextpdf.text.pdf.PdfReader | |
import com.itextpdf.text.pdf.PdfWriter | |
def cli = new CliBuilder().with { | |
usage = 'preparePdf [options] <source file path>' | |
s args:1, longOpt: 'select', 'Select pages (e.g. -s "1,X,4..7,2,3,X,8..10")' | |
t args:1, longOpt: 'target', 'Target path' | |
parse(args) | |
} | |
assert cli.arguments().size() == 1 && cli.arguments()[0].endsWith('.pdf') | |
def sourcePath = cli.arguments()[0] | |
def targetPath = cli.t ?: sourcePath.replace('.pdf', '-sorted.pdf') | |
def reader = new PdfReader(new File(sourcePath).newInputStream()) | |
// if no -s selection use full document | |
def selected = parseSelection(cli.s) ?: [*1..reader.numberOfPages] | |
// we need to fill missing pages to be divisible by 4 | |
// 'X' is a blank page btw | |
selected += ['X'] * (-selected.size() & 3) | |
def doc = new Document(A4, 0, 0, 0, 0) | |
def writer = PdfWriter.getInstance(doc, new File(targetPath).newOutputStream()) | |
doc.open() | |
sort(selected).eachWithIndex {it, i-> | |
if (i) doc.newPage() | |
if (it.is("X")) { | |
writer.@pdf.@pageEmpty = false // hacky but works | |
doc.newPage() | |
} else { | |
def page = writer.getImportedPage(reader, it) | |
// find the most appropiate scale and offsets for the page | |
float scale = [A4.width / page.width, A4.height / page.height].min() | |
float shiftright = (A4.width - page.width * scale) / 2 | |
float shiftup = (A4.height - page.height * scale) / 2 | |
writer.directContent.addTemplate page, scale, 0f, 0f, scale, shiftright, shiftup | |
} | |
} | |
doc.close() | |
writer.close() | |
def parseSelection(input) { | |
if (input) { | |
def tokens = input.tokenize(',').collect{it.tokenize('..')} | |
assert tokens.every{it.size() in [1,2] && it.every{it.integer || it.is('X')}} | |
tokens.collect { | |
it.size() == 2? (it[0] as int)..(it[1] as int) : | |
it[0].is('X')? 'X' : it[0] as int | |
}.flatten() | |
} | |
} | |
def sort(pages) { | |
// sort pages for those that don't have a smart printer | |
pages[(0..<(pages.size()>>1)).step(2).sum { | |
[pages.size() - it - 1, it, it + 1, pages.size() - it - 2]}] | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment