How to print onto virtual letter paper which exists as PDF

pdfprinting

How to print onto virtual letter paper which exists as PDF?

New to the Mac OS X world and with MACs. From the windows world I have a virtual letter paper with my e.g. logo, headers, footers existing as a PDF file.

I would need to be able to universally print onto this existing PDF, as if it were e.g. physically from a printing shop and inserted into my real physical printers paper tray.

Having now looked around in the Apple and MAC world, I kind of lack a way to use that "save pdf" or generate PDF file that is built-in to the OS X operating system itself, but pre-merge and mix it with my vector/pixels of my own supplied PDF virtual letter paper resulting in a nice official document e.g. for business cases and such stuff.

I read about OS X automator and even pdftk and all, and on Windows it is really simple by means for example of a virtual printer.

But on the Apple platform, it seems that there is just no way to put a background (my virtual letter paper coming from my own PDF) properly beneath anything I would like to print, as Apple or any application seems to put white pixels (instead of transparency) when they generate via their own OS X built-in means to generate that PDF.

What am I missing here? What if I wanted to for example print to a blue paper or a green paper as the most simple examples of this use-case? The Apple system or any app(lication) on it, seems to always generate a non-transparent and white-pixeled virtual paper, where my own virtual letter paper cannot compete with and cannot shine through.

Also via the automator I only found ways to stamp onto the saved PDF (thats fine for stamps saying such stuff as specimen, or example, or draft and such things) and printing below (underneath) of the actual document would be kind of near impossible because of that opaque white generated pixels/paper of the OS X system itself.

Also the automator only allows for images/pixel files to be used as stamp ontop/below, and my letter paper comes as PDF / vectorised already.

Is there really no concept on current MAC OS X to mix during the built-in way to generate PDFs with my own pre-defined document / PDF? Or is there no virtual printer driver software which would do this in its own way on the mac platform?

Any existing product for the MAC OS X platform I could buy? Thanks in advance.

Best Answer

The following python script will Merge one 'template' PDF onto the pages of any PDF file created in the Print dialog. You will need to supply the filepath to the template PDF in the script, then save it in your user Library, inside a folder called "PDF Services" e.g. ~/Library/PDF Services. (This may need to be created, if not already there.)

The script can then be called from the PDF button of the print dialog.

#!/usr/bin/python
# -*- coding: UTF-8 -*-
#
# Merge v. 0.1
# Merges two PDFs 

import sys
import os
import Quartz as Quartz
from Foundation import NSURL, kCFAllocatorDefault
from AppKit import NSSavePanel, NSApp

# OPTIONS
watermark = os.path.expanduser("~/Desktop/myTemplate.pdf")
destination = os.path.expanduser("~/Desktop") # Default destination
suffix = " wm.pdf" # Use ".pdf" if no actual suffix required.

# FUNCTIONS

def save_dialog(directory, filename):
    panel = NSSavePanel.savePanel()
    panel.setTitle_("Save PDF booklet")
    myUrl = NSURL.fileURLWithPath_isDirectory_(directory, True)
    panel.setDirectoryURL_(myUrl)
    panel.setNameFieldStringValue_(filename)
    NSApp.activateIgnoringOtherApps_(True)
    ret_value = panel.runModal()
    if ret_value:
        return panel.filename()
    else:
        return ''

# Loads in PDF document
def createPDFDocumentWithPath(path):
    return Quartz.CGPDFDocumentCreateWithURL(Quartz.CFURLCreateFromFileSystemRepresentation(kCFAllocatorDefault, path, len(path), False))

# Creates a Context for drawing
def createOutputContextWithPath(path, dictarray):
    return Quartz.CGPDFContextCreateWithURL(Quartz.CFURLCreateFromFileSystemRepresentation(kCFAllocatorDefault, path, len(path), False), None, dictarray)

# Gets DocInfo from input file to pass to output.
# PyObjC returns Keywords in an NSArray; they must be tupled.
def getDocInfo(file):
    file = file.decode('utf-8')
    pdfURL = NSURL.fileURLWithPath_(file)
    pdfDoc = Quartz.PDFDocument.alloc().initWithURL_(pdfURL)
    if pdfDoc:
        metadata = pdfDoc.documentAttributes()
        if "Keywords" in metadata:
            keys = metadata["Keywords"]
            mutableMetadata = metadata.mutableCopy()
            mutableMetadata["Keywords"] = tuple(keys)
            return mutableMetadata
        else:
            return metadata

def main(argv):
    (title, options, pathToFile) = argv[:]
    shortName = os.path.splitext(title)[0]
    # If you want to save to a consistent location, use:
    # writeFilename = os.path.join(destination, shortName + suffix)
    writeFilename = save_dialog(destination, shortName + suffix)
    writeFilename = writeFilename.encode('utf-8')
    shortName = os.path.splitext(pathToFile)[0]
    metaDict = getDocInfo(pathToFile)
    writeContext = createOutputContextWithPath(writeFilename, metaDict)
    readPDF = createPDFDocumentWithPath(pathToFile)
    mergePDF = createPDFDocumentWithPath(watermark)

    if writeContext != None and readPDF != None:
        numPages = Quartz.CGPDFDocumentGetNumberOfPages(readPDF)
        for pageNum in xrange(1, numPages + 1): 
            page = Quartz.CGPDFDocumentGetPage(readPDF, pageNum)
            mergepage = Quartz.CGPDFDocumentGetPage(mergePDF, 1)
            if page:
                mediaBox = Quartz.CGPDFPageGetBoxRect(page, Quartz.kCGPDFMediaBox)
                if Quartz.CGRectIsEmpty(mediaBox):
                    mediaBox = None         
                Quartz.CGContextBeginPage(writeContext, mediaBox)   
                Quartz.CGContextSetBlendMode(writeContext, Quartz.kCGBlendModeOverlay)
                Quartz.CGContextDrawPDFPage(writeContext, page)
                Quartz.CGContextDrawPDFPage(writeContext, mergepage)
                Quartz.CGContextEndPage(writeContext)
        Quartz.CGPDFContextClose(writeContext)
        del writeContext

    else:
        print "A valid input file and output file must be supplied."
        sys.exit(1)

if __name__ == "__main__":
    main(sys.argv[1:])

Currently, this uses the first page of the template PDF file and puts it on all pages of the output PDF.