0

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)

Automator Screenshot

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:]) 
4
  • A few questions...how are you associating the watermark file with the PDF file? Do you need to watermark each page of the PDF or just the first page? Where does this watermark have to be placed?
    – Allan
    CommentedNov 28, 2020 at 21:20
  • Each PDF has only one page, each watermark has to be placed on the center of the page. Usually, I can achieve this by doing the watermarks one by one. But doing this for 400 files takes a considerable amount of time. The problem is that the watermark scripts were written to use only one watermark for multiple files, or for one PDF file with multiple pages.CommentedNov 29, 2020 at 11:28
  • Do the watermark image files and the corresponding image files have the same name ( for e.g. 1.png for 1.pdf etc.)?
    – sfxedit
    CommentedNov 30, 2020 at 21:02
  • Yes they all have corresponding names, I put the files in two different folders.CommentedDec 1, 2020 at 4:30

1 Answer 1

1

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 PDFdocuments and graphic image files for the watermark, where the files are in different locations. It works for me as coded.

The following exampleshell scriptcode assumes that for each PDFdocument 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 and fqp2pyf, while the rest of the values from the original script are maintained except where they have already been modified.

In the Automatorworkflow, using a Get Specified Finder Itemsaction for the PDFdocuments and a Run Shell Scriptaction set as shown in your OP:

  • Shell: [/bin/bash]
  • Pass input: [as arguments]

Replace any existing code in the Run Shell Scriptaction, default or otherwise, with:

 # Path to watermark files. # Example: "${HOME}/Pictures/Watermarks" # Watermark file extension, e.g.: png # Fully qualified pathname to python 'tool.py' file. # Example: "${HOME}/bin/tool.py" p2wf="${HOME}/Pictures/Watermarks" wext="png" fqp2pyf="${HOME}/bin/tool.py" # f = fully qualified pathname # d = directory pathname # fn = filename with extension # n = filename without extension # e = filename extension for f in "$@"; do d="${f%/*}" fn="${f##*/}" n="${fn%.*}" e="${fn##*.}" "${fqp2pyf}" \ --over \ --xOffset 56 \ --yOffset 58 \ --angle 0 \ --scale 0.11 \ --opacity 1 \ --input "${f}" \ --output "${d}/${n} (COPY).${e}" \ "${p2wf}/${n}.${wext}" done 

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.

2

You must log in to answer this question.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.