I am trying to create a script to watermark a group a PDF files in a folder, each PDF has to have a unique watermark.
All the PDFs are in one folder, all the watermarks are in .png located in another folder.
I currently have watermark script which I found on Apple Forums, but this was made to watermark all files with one watermark only.
What I need is a way to watermark each PDF file with it's own different watermark (there are 400 pdfs and 400 different watermarks)
Here is the contents of the watermark 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:])
Best Answer
I tested this under macOS Catalina using the code from the
tool.py
in the OP and the value of the options shown for it, while using PDF documents and graphic image files for the watermark, where the files are in different locations. It works for me as coded.The following example shell script code assumes that for each PDF document there is a corresponding graphic image file of the same name with a different extension with all watermark files being in a different directory.
You will need to set the value of three variables at the top of the script,
p2wf
,wext
andfqp2pyf
, while the rest of the values from the original script are maintained except where they have already been modified.In the Automator workflow, using a Get Specified Finder Items action for the PDF documents and a Run Shell Script action set as shown in your OP:
Replace any existing code in the Run Shell Script action, default or otherwise, with:
Note: From past experience, I never use
~
for the home directory in scripts. I use e.g.,$HOME
or${HOME}
as~
can actually be problematic in some situations.