Q: 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:48 AM
Hello
Under 10.6.8, Watermark PDF Documents.action/Contents/Resources/tool.py works happily without any errors when invoked as follows with a.pdf and watermark.png in ~/desktop/test/ :
#!/bin/bash
py='/System/Library/Automator/Watermark PDF Documents.action/Contents/Resources/tool.py'
cd ~/desktop/test || exit
args=(
--input a.pdf
--output a_wm.pdf
--verbose
--over
--xOffset 0.0
--yOffset -150.0
--angle 300.0
--scale 0.3
--opacity 0.1
watermark.png
)
"$py" "${args[@]}"
If the said error – ValueError: depythonifying 'pointer', got 'str' – is raised at the line:
provider = CGDataProviderCreateWithFilename(imagePath)
I'd think it is because imagePath is not a C string pointer which the function expects but a CFStringRef or something which is implicitly converted from python string. Since I don't get this error with pyobjc 2.2b3 & python 2.6 under 10.6.8, it is caused by something introduced in later versions.
Anyway, the statement in question may be replaced with the following statements if it helps:
url = CFURLCreateFromFileSystemRepresentation(kCFAllocatorDefault, imagePath, len(imagePath), False) provider = CGDataProviderCreateWithURL(url)
I modified the tool.py with these changes along with other minor fixes and run it successfully under 10.6.8. I'm not sure at all whether it works under later OSes as well. And even if it does, editing tool.py will require the Automator action to be re-codesigned.
Here's the revised tool.py.
#!/usr/bin/python
# Watermark each page in a PDF document
import sys #, os
import getopt
import math
from Quartz.CoreGraphics import *
from Quartz.ImageIO import *
def drawWatermark(ctx, image, xOffset, yOffset, angle, scale, opacity):
if image:
imageWidth = CGImageGetWidth(image)
imageHeight = CGImageGetHeight(image)
imageBox = CGRectMake(0, 0, imageWidth, imageHeight)
CGContextSaveGState(ctx)
CGContextSetAlpha(ctx, opacity)
CGContextTranslateCTM(ctx, xOffset, yOffset)
CGContextScaleCTM(ctx, scale, scale)
CGContextTranslateCTM(ctx, imageWidth / 2, imageHeight / 2)
CGContextRotateCTM(ctx, angle * math.pi / 180)
CGContextTranslateCTM(ctx, -imageWidth / 2, -imageHeight / 2)
CGContextDrawImage(ctx, imageBox, image)
CGContextRestoreGState(ctx)
def createImage(imagePath):
image = None
# provider = CGDataProviderCreateWithFilename(imagePath) # FIXED: replaced by the following CGDataProviderCreateWithURL()
url = CFURLCreateFromFileSystemRepresentation(kCFAllocatorDefault, imagePath, len(imagePath), False)
provider = CGDataProviderCreateWithURL(url)
if provider:
imageSrc = CGImageSourceCreateWithDataProvider(provider, None)
if imageSrc:
image = CGImageSourceCreateImageAtIndex(imageSrc, 0, None)
if not image:
print "Cannot import the image from file %s" % imagePath
return image
def watermark(inputFile, watermarkFiles, outputFile, under, xOffset, yOffset, angle, scale, opacity, verbose):
images = map(createImage, watermarkFiles)
ctx = CGPDFContextCreateWithURL(CFURLCreateFromFileSystemRepresentation(kCFAllocatorDefault, outputFile, len(outputFile), False), None, None)
if ctx:
pdf = CGPDFDocumentCreateWithURL(CFURLCreateFromFileSystemRepresentation(kCFAllocatorDefault, inputFile, len(inputFile), False))
if pdf:
for i in range(1, CGPDFDocumentGetNumberOfPages(pdf) + 1):
image = images[i % len(images) - 1]
page = CGPDFDocumentGetPage(pdf, i)
if page:
mediaBox = CGPDFPageGetBoxRect(page, kCGPDFMediaBox)
if CGRectIsEmpty(mediaBox):
mediaBox = None
CGContextBeginPage(ctx, mediaBox)
if under:
drawWatermark(ctx, image, xOffset, yOffset, angle, scale, opacity)
CGContextDrawPDFPage(ctx, page)
if not under:
drawWatermark(ctx, image, xOffset, yOffset, angle, scale, opacity)
CGContextEndPage(ctx)
del pdf
CGPDFContextClose(ctx)
del ctx
def main(argv):
verbose = False
readFilename = None
writeFilename = None
under = False
xOffset = 0.0 # FIXED: changed to float value
yOffset = 0.0 # FIXED: changed to float value
angle = 0.0 # FIXED: changed to float value
scale = 1.0 # FIXED: added
opacity = 1.0
# Parse the command line options
try:
options, args = getopt.getopt(argv, "vutx:y:a:p:s:i:o:", ["verbose", "under", "over", "xOffset=", "yOffset=", "angle=", "opacity=", "scale=", "input=", "output=", ])
except getopt.GetoptError:
usage()
sys.exit(2)
for option, arg in options:
print option, arg
if option in ("-i", "--input") :
if verbose:
print "Reading pages from %s." % (arg)
readFilename = arg
elif option in ("-o", "--output") :
if verbose:
print "Setting %s as the output." % (arg)
writeFilename = arg
elif option in ("-v", "--verbose") :
print "Verbose mode enabled."
verbose = True
elif option in ("-u", "--under"):
print "watermark under PDF"
under = True
elif option in ("-t", "--over"): # FIXED: changed to "-t" from "t"
print "watermark over PDF"
under = False
elif option in ("-x", "--xOffset"):
xOffset = float(arg)
elif option in ("-y", "--yOffset"):
yOffset = float(arg)
elif option in ("-a", "--angle"):
angle = -float(arg)
elif option in ("-s", "--scale"):
scale = float(arg)
elif option in ("-p", "--opacity"):
opacity = float(arg)
else:
print "Unknown argument: %s" % (option)
if (len(args) > 0):
watermark(readFilename, args, writeFilename, under, xOffset, yOffset, angle, scale, opacity, verbose);
else:
shutil.copyfile(readFilename, writeFilename);
def usage():
print "Usage: watermark --input <file> --output <file> <watermark files>..."
if __name__ == "__main__":
print sys.argv
main(sys.argv[1:])
All the best,
H
Posted on Oct 23, 2014 3:11 AM



