On merging & thinning & adjusting pdfs



4 up of each page of the pdf
======================
http://pdfbooklet.sourceforge.net/
x copies / row: 2
no change + autoscale (otherwise it goes into A2 or bad quality reduction)

Merge pdf's in sharp quality
=====================
Considering that pdfunite is part of poppler it has a higher chance to be installed, usage is also simpler than pdftk:
pdfunite in-1.pdf in-2.pdf in-n.pdf out.pdf


4UP with psnup
================
pdf2ps photos.ebook.pdf - | \
psnup -p a4 -4 | \
ps2pdf - photos.4up.pdf


Changing the resolution of images in a PDF (to match an output device)
==========================================
SOURCE: http://tech-vaults.blogspot.be/2012/01/resampling-jpegs-inside-pdf-to.html

ebook is very a good setting for screen (better than the actual "screen" setting as it allows a little zooming in still)

In short, use ghostscript:

    gs -sDEVICE=pdfwrite -dPDFSETTINGS=/ebook -dNOPAUSE -dQUIET -dBATCH -sOutputFile=output.pdf input.pdf

The PDFSETTINGS presets equate to the following resolutions:

    /screen ... screen-view-only quality, 72 dpi images 
    /ebook ... low quality, 150 dpi images
    /printer ... high quality, 300 dpi images 
    /prepress ... high quality, color preserving, 300 dpi images
    /default ... similar to /screen

Other suggested command line arguments made various places:

    -dCompatibilityLevel=1.4 
    -dColorImageResolution=38 -dColorImageDownsampleType=/Average -dGrayImageDownsampleType=/Average -dGrayImageResolution=38 -dMonoImageResolution=38 -dMonoImageDownsampleType=/Average -dOptimize=true -dDownsampleColorImages=true -dDownsampleGrayImages=true -dDownsampleMonoImages=true -dUseCIEColor -dColorConversionStrategy=/sRGB
    -dMaxSubsetPct=100

More tips (very useful page)
http://www.peteryu.ca/tutorials/publishing/pdf_manipulation_tips


PHotobooks with Python + FLAT
=============================
Flat is a great pure python library that can make PDFs. NB: The resulting PDFs are not *exactly* Adobe standard compliant -- using the ghostscript resolution fix above is useful to "cleanup" / fix the outputs of these scripts.

First get FLAT:

   pip install flat

======================================
photobook.py
=====================================
from argparse import ArgumentParser
from flat import rgb, font, shape, strike, document, image
import glob

p = ArgumentParser("create a photo book pdf")
p.add_argument("--width", default=210, type=int, help="width in mm, default: 210 (A4)")
p.add_argument("--height", default=297, type=int, help="width in mm, default: 297 (A4)")
p.add_argument("--border", default=10, type=int, help="border in mm, default: 10")
p.add_argument("--input", help="input filenames in a text file")
p.add_argument("--output", default="output.pdf", help="output filename for PDF file, default: output.pdf")
p.add_argument("input", nargs="+", default=[], help="image filenames")
args = p.parse_args()

w = args.width # 210
h = args.height # 297
border = args.border # 10
d = document(w, h, 'mm')
hh = args.height / 2
page = None

paths = args.input
paths.sort()

def fitbox (image, placed, w, h):
        fit_h =  image.height * (float(w) / image.width)
        if fit_h > h:
                placed.fitheight(h)
        else:
                placed.fitwidth(w)

for impath in paths:
        print impath
        im = image.open(impath)
        if im.height > im.width:
                page = d.addpage()
                placed = page.place(im).frame(border, border, w-(border*2), h-(border*2))
                fitbox(im, placed, w-(border*2), h-(border*2))
                # placed.fitheight(h-(border*2))
                page = None
        else:
                # place in partial frame
                if page == None:
                        page = d.addpage()
                        placed = page.place(im).frame(border, border, w-(border*2), hh-(border*2))
                        fitbox(im, placed, w-(border*2), hh-(border*2))
                        # placed.fitheight(hh-(border*2))
                else:
                        placed = page.place(im).frame(border, hh+border, w-(border*2), hh-(border*2))
                        fitbox(im, placed, w-(border*2), hh-(border*2))
                        # placed.fitheight(hh-(border*2))
                        page = None

d.pdf(args.output)


======================================
photobook2.py (2x2 grid)
=====================================
from argparse import ArgumentParser
from flat import rgb, font, shape, strike, document, image
import glob
from random import shuffle

p = ArgumentParser("create a photo book pdf")
p.add_argument("--width", default=210, type=int, help="width in mm, default: 210 (A4)")
p.add_argument("--height", default=297, type=int, help="width in mm, default: 297 (A4)")
p.add_argument("--border", default=10, type=int, help="border in mm, default: 10")
p.add_argument("--input", help="input filenames in a text file")
p.add_argument("--output", default="output.pdf", help="output filename for PDF file, default: output.pdf")
p.add_argument("--shuffle", default=False, action="store_true", help="shuffle the order, default: False")
p.add_argument("input", nargs="+", default=[], help="image filenames")
args = p.parse_args()

w = args.width # 210
h = args.height # 297
border = args.border # 10
d = document(w, h, 'mm')
hw = args.width / 2.0
hh = args.height / 2.0
page = None

paths = args.input
paths.sort()
if args.shuffle:
        shuffle(paths)

def fitbox (image, placed, w, h):
        fit_h =  image.height * (float(w) / image.width)
        if fit_h > h:
                placed.fitheight(h)
        else:
                placed.fitwidth(w)

x, y = 0, 0

def newline():
        global page, x, y
        y += 1
        x = 0
        if y == 2:
                y = 0
                page = None

def ensurepage():
        global page
        if page == None:
                page = d.addpage()

border2 = 2*args.border

for impath in paths:
        print impath
        im = image.open(impath)

        if im.width > im.height:
                # place across 2 cells
                if x != 0:
                        newline()
                # px = x * hw
                py = y * hh
                ensurepage()
                placed = page.place(im).frame(0 + border, py + border, w - border2, hh - border2)
                fitbox(im, placed, w - border2, hh - border2)
                newline()
        else:
                px = x * hw
                py = y * hh
                ensurepage()
                placed = page.place(im).frame(px + border, py+border, hw-border2, hh-border2)
                fitbox(im, placed, hw-border2, hh-border2)

                x += 1
                if x == 2:
                        newline()

d.pdf(args.output)


makefile
=============
all: screenshots.prepress.pdf bookpdfs.prepress.pdf bookphotos.prepress.pdf

photobooks:
        python photobook.py pictures/photos/* --output photos.raw.pdf
        python photobook2.py pictures/bookphotos/* --shuffle --output bookphotos.raw.pdf
        python photobook2.py pictures/bookpdfs/*.jpg --shuffle --output bookpdfs.raw.pdf
        python photobook2.py pictures/screenshots/* --shuffle --output screenshots.raw.pdf

%.prepress.pdf: %.raw.pdf
        gs -sDEVICE=pdfwrite -dPDFSETTINGS=/prepress -dNOPAUSE -dQUIET -dBATCH -sOutputFile=$@ $<

%.ebook.pdf: %.raw.pdf
        gs -sDEVICE=pdfwrite -dPDFSETTINGS=/ebook -dNOPAUSE -dQUIET -dBATCH -sOutputFile=$@ $<

%.4up.pdf: %.ebook.pdf
        pdf2ps $< - | \
        psnup -p a4 -4 | \
        ps2pdf - $@

%.screen.pdf: %.pdf
        gs -sDEVICE=pdfwrite -dPDFSETTINGS=/screen -dNOPAUSE -dQUIET -dBATCH -sOutputFile=$@ $<