Apple Event: May 7th at 7 am PT

Looks like no one’s replied in a while. To start the conversation again, simply ask a new question.

Automator Watermark PDF Workflow

Seems with every major upgrade, Apple breaks the Automator Watermark PDF Workflow.

Can someone test this workflow in Yosemite so I know if the problem I'm having is with OS X 10.10.

OS X Yosemite (10.10)

Posted on Oct 22, 2014 9:43 AM

Reply
Question marked as Best reply

Posted on Oct 22, 2014 11:04 AM

I may agree with you. 😠 Can't get it to work as drag/drop application, with a rename after the watermark — or as a Printer plugin as below.


I create a Print plugin in Automator. Two actions:

  • Watermark PDF Documents

    Image: draft.jpg (will not allow you to select a draft.pdf with the chooser, but you can drag/drop one in the well - doesn't work either)

  • Set Application for Files - Preview


Print > PDF > myDraft


User uploaded file

53 replies

Aug 13, 2016 9:56 AM in response to benwiggy

I am unaware of an automatic process for matching objects and their associated constants to their respective class import statements. It is just grunt work, with occasional trips to the class/object declarations and contant definitions to be certain.


This is why you see alot of Python code with the convenient import splat — and its cost to performance. PEP8 (last bullet under Import section) discourages the use of the splat as it pollutes the name space.


I use the Anaconda plug-in in Sublime Text 3, and it syntax checks, and alerts when PEP8 is transgressed. Good habit building tool.

Aug 13, 2016 4:30 PM in response to benwiggy

My pleasure! And feel free to adapt it to your project, for it is trivial sample code with nothing special but series of framework function calls. Only that I have accommodated the code to tool.py located at (under OS X 10.6.8):


/System/Library/Automator/Watermark PDF Documents.action/Contents/Resources/tool.py



so if you feel uneasy or uncertain about using the code as is, arrange it as you see fit. 😉



Regarding PyObjC, it is part of standard installation of OS X 10.5 through 10.11 if I'm not mistaken. Under OS X 10.6.8, for instance, it is installed in the following directories.


/System/Library/Frameworks/Python.framework/Versions/2.6/Extras/lib/python/PyObjC /System/Library/Frameworks/Python.framework/Versions/2.5/Extras/lib/python/PyObjC



Regarding PyObjC performance, unfortunately, Python's importing PyObjC modules is blooming slow as compared to Ruby's importing RubyCocoa modules which is so quick and almost instant. In recent PyObjC's implementation, however, module importing performance can be improved reportedly either by specifying symbols selectively as VikingOSX described or by importing module in separate name space by means of 'as' qualifier of import statement, such as:


import Quartz.CoreGraphics as CG



and qualify symbols with CG prefixed such as:


CG.CGPDFContextCreateWithURL(url)



(Sadly, these techniques gain nothing under OS X 10.6.8 I'm using...)



Anyway, I'd employ the following variation for faster importing pyobjc modules, where I use single OSX name space for simplicity. Framework's symbols are well distinguished by framework-specific names, so there should be no problem, any more than 'from Framework import *'.




#!/usr/bin/python # coding: utf-8 import math import CoreFoundation as OSX import Quartz.CoreGraphics as OSX import CoreText as OSX def drawWatermarkText(ctx, line, xOffset, yOffset, angle, scale, opacity): # CGContextRef ctx # CTLineRef line # float xOffset, yOffset, angle ([degree]), scale, opacity ([0.0, 1.0]) if line: rect = OSX.CTLineGetImageBounds(line, ctx) imageWidth = rect.size.width imageHeight = rect.size.height OSX.CGContextSaveGState(ctx) OSX.CGContextSetAlpha(ctx, opacity) OSX.CGContextTranslateCTM(ctx, xOffset, yOffset) OSX.CGContextScaleCTM(ctx, scale, scale) OSX.CGContextTranslateCTM(ctx, imageWidth / 2, imageHeight / 2) OSX.CGContextRotateCTM(ctx, angle * math.pi / 180) OSX.CGContextTranslateCTM(ctx, -imageWidth / 2, -imageHeight / 2) OSX.CGContextSetTextPosition(ctx, 0.0, 0.0); OSX.CTLineDraw(line, ctx); OSX.CGContextRestoreGState(ctx) # parameters ifile = 'input.pdf' ofile = 'output.pdf' text = 'Watermark Sample' xOffset, yOffset, angle, scale, opacity = 0.0, 400.0, 60.0, 2.0, 0.2 # create CoreText line (CTLine) font = OSX.CTFontCreateWithName('Helvetica', 36.0, None) astr = OSX.CFAttributedStringCreate(OSX.kCFAllocatorDefault, text, { OSX.kCTFontAttributeName : font }) line = OSX.CTLineCreateWithAttributedString(astr) # create output pdf context ourl = OSX.CFURLCreateFromFileSystemRepresentation(OSX.kCFAllocatorDefault, ofile, len(ofile), False) ctx = OSX.CGPDFContextCreateWithURL(ourl, None, None) # create input pdf document iurl = OSX.CFURLCreateFromFileSystemRepresentation(OSX.kCFAllocatorDefault, ifile, len(ifile), False) pdf = OSX.CGPDFDocumentCreateWithURL(iurl) if pdf: for i in range(0, OSX.CGPDFDocumentGetNumberOfPages(pdf)): page = OSX.CGPDFDocumentGetPage(pdf, i + 1) if page: mbox = OSX.CGPDFPageGetBoxRect(page, OSX.kCGPDFMediaBox) if OSX.CGRectIsEmpty(mbox): mbox = None OSX.CGContextBeginPage(ctx, mbox) OSX.CGContextDrawPDFPage(ctx, page) # elementary test OSX.CGContextSetTextPosition(ctx, 10.0, 10.0) OSX.CTLineDraw(line, ctx) # using general function drawWatermarkText(ctx, line, xOffset, yOffset, angle, scale, opacity) OSX.CGContextEndPage(ctx) del pdf OSX.CGPDFContextClose(ctx) del ctx




All the best,

Hiroto

Aug 13, 2016 4:48 PM in response to Hiroto

Hiroto,


Aha! I like your name space alternative, and it is just as quick to watermark a 179 page input.pdf as my earlier laborious import naming efforts. I am sold, and thanks again.


I think what may confuse people is that there is the Python Scripting Bridge inherent to OS X, which we alternatively refer to as PyObjC, and then there is that other third-party PyObjC solution that installs the PyObjC bridging solution into Python releases other than supplied by OS X.

Aug 13, 2016 6:23 PM in response to VikingOSX

Oops. I thought importing multiple frameworks into single OSX name space by those import statements works but indeed does not. The previous code happens to work because CoreText module internally imports CoreFoundation and Quartz.


In other words, the following:


import CoreFoundation as OSX import Quartz.CoreGraphics as OSX import CoreText as OSX



is effectively equivalent to:


import CoreText as OSX




If you change the import statements order such as:


import Quartz.CoreGraphics as OSX import CoreText as OSX import CoreFoundation as OSX



code to access CoreText or CoreGraphics symbols should fail...



Sorry for confusion.


Hiroto

Aug 14, 2016 2:00 AM in response to Hiroto

Thanks once more for your further comments. Yes, I've used the python script tool.py, as well as the other three python scripts hidden inside Automator actions for Combining PDF Pages, Extracting pages and making graph paper.


Yes, I was confused by the third-party PyObjC software. I don't think there's any need for that, unless you're building GUI apps.??


I'll try using the name space idea, as it is otherwise easy to miss one out! My library of python scripts to work with PDFs is now looking pretty comprehensive, thanks to you and various other bits of code I've gleaned.

Automator Watermark PDF Workflow

Welcome to Apple Support Community
A forum where Apple customers help each other with their products. Get started with your Apple ID.