You can make a difference in the Apple Support Community!

When you sign up with your Apple Account, you can provide valuable feedback to other community members by upvoting helpful replies and User Tips.

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

Automator Render PDF Pages as Images with Annotations

I am trying to convert a PDF to Image using Automator. When I use "Render PDF Pages as Images", all the annotations are gone in the resulting image.

How could I convert pdf to images using Automator but also include all pdf annotations in the resulting images?

MacBook Pro 15″, macOS 10.14

Posted on Feb 28, 2022 5:11 AM

Reply
Question marked as Top-ranking reply

Posted on Feb 28, 2022 7:05 AM

Because that Automator action is not coded by Apple to preserve Annotations when converting to an image (e.g. png).


Apple's Preview application will preserve annotation when exporting to an image (e.g. png, tiff).





11 replies

Mar 1, 2022 1:56 PM in response to akalbat

The issue in this thread is that the Automator Render PDF pages as images action does not flatten PDF, and thus, excludes any PDF annotation in the resulting images. The second issue is that the Apple Preview AppleScript dictionary support does not allow saving flattened PDFs. The goal here is to use available Apple technology to get this done in a practical workflow.


It is possible to save a flattened PDF using AppleScript/Objective-C using features from a few Apple frameworks and programmatically printing that annotated PDF to a file, instead of to the printer. This simulates the Print panel's PDF > Save As PDF feature. Here is that code that when pasted into the Script Editor, compiled, and ran, prompts for a PDF and then saves as that pdfname_flattened.pdf in the original PDF location:


use framework "Foundation"
use framework "AppKit"
use framework "PDFKit"
use AppleScript version "2.4"
use scripting additions

property SUFFIX : "_flattened"
property NSString : a reference to current application's NSString
property NSURL : a reference to current application's NSURL
property PDFDocument : a reference to current application's PDFDocument
property NSDictionary : a reference to current application's NSDictionary
property NSPrintInfo : a reference to current application's NSPrintInfo

set thisPDF to POSIX path of (choose file of type "com.adobe.pdf" default location (path to desktop) without invisibles) as text
set {status, flatPDF} to my flatten_PDF(thisPDF)

if status = true then
	display dialog "Flattened PDF created" & return & return & flatPDF with title "Print Operation Results"
else
	display dialog "Flattened PDF operation failed." with title "Print Operation Results"
end if
return

on flatten_PDF(thisPDF)
	set basename to (NSString's stringWithString:thisPDF)'s stringByDeletingPathExtension()
	set basename_sfx to basename's stringByAppendingString:SUFFIX
	set outPDF to basename_sfx's stringByAppendingPathExtension:"pdf"
	set outURL to NSURL's fileURLWithPath:outPDF
	set inURL to NSURL's fileURLWithPath:thisPDF
	set pdf to PDFDocument's alloc()'s initWithURL:inURL
	
	# make assumption that first page of PDF has same MediaBox as rest of the PDF
	set {{x, y}, {w, h}} to (pdf's pageAtIndex:0)'s boundsForBox:(current application's kPDFDisplayBoxMediaBox)
	
	set pdict to (NSDictionary's dictionaryWithObject:outURL forKey:(current application's NSPrintJobSavingURL))'s mutableCopy()
	pdict's setObject:(current application's NSPrintSaveJob) forKey:(current application's NSPrintJobDisposition)
	pdict's setObject:outURL forKey:(current application's NSPrintJobSavingURL)
	set printInfo to NSPrintInfo's alloc()'s initWithDictionary:pdict
	
	printInfo's setVerticalPagination:(current application's NSPrintingPaginationModeAutomatic)
	printInfo's setJobDisposition:(current application's NSPrintSaveJob)
	printInfo's setPaperSize:(current application's NSMakeSize(w, h))
	
	set printOp to pdf's printOperationForPrintInfo:printInfo scalingMode:0 autoRotate:false
	printOp's setShowsPrintPanel:false
	printOp's setShowsProgressPanel:false
	set status to printOp's runOperation()
	return {status as boolean, (outPDF's stringByAbbreviatingWithTildeInPath()) as text}
	
end flatten_PDF


Now, based on the OPs situation, how to incorporate this PDF flattening process prior to the Render PDF Pages as Images Automator action and pass the flattened PDF into that action. Here is that Automator workflow in sequential actions:


Automator actions (in order) for an Automator Application:

  1. Files & Folders : Ask for Finder Items
    1. Start At: Desktop
    2. Type: Files ☐ Allow multiple selection
  2. Files & Folders: Filter Finder Items
    1. All Kind is PDF
  3. Utilities: Run AppleScript
    1. Remove all of the default content, and replace with the code show below that you copy/paste into this action
    2. Passes the path of the flattened PDF into next action
  4. PDF: Render PDF Pages as Images
    1. Choose these settings to your goal
  5. Files & Folders: Rename Finder Items
    1. Add the copy finder items when asked
      1. Set to the destination folder for your images
    2. Rename Finder Items
      1. Make Sequential
      2. Add number to existing item name
      3. Place number after name and start numbers at 1
      4. Separated by underscore and make all numbers 2 (or 3) digits long (eg. someimage_01.jpg)
      5. This action does not operate as it suggests. Instead of someimage_01.jpg, it will create someimage 1_1.jpg instead. No fix for this if using sequential numbering.
  6. Save to Desktop and Quit Automator


Code for 3.1 (exceeded 5000 characters, see Reply to this post for code to paste into Run AppleScript action.


Mar 2, 2022 8:24 AM in response to akalbat

The Quartz framework includes PDFKit, though in my testing, that use framework "PDFKit" worked just fine on Big Sur and Monterey.


I would have to modify and test this solution as a Quick Action. Essentially the AppleScript would need to be altered to form a loop on the passed in PDFs and call the flatten_PDF handler for each PDF.


The following Quick Action (e.g. Flatten PDF) with one action works with multiple selected PDFs in the Finder:


Feb 28, 2022 7:12 AM in response to VikingOSX

Is there any way to flatten a pdf within Automator? I tried to "save as pdf" within preview and it turn out that the resulted pdf is flattened and when I apply "Render PDF Pages as Images" to the flattened pdf, the annotations are preserved and shown in the images.


I have PDFWriter on my system and when I tried to use "" Print Finder Items" and chose the PDFWriter as the printer, it turned out the resulted pdf is not flattened.


Is there any way to print to pdf by using Shell Script?

Mar 2, 2022 7:18 AM in response to VikingOSX

Thanks a lot for the detailed reply.


When I tried to run the code, I got an error that "PDFKit" is not available. I fixed this by replacing (use framework "PDFKit") with (use framework "Quartz").


Based on your explanation, the previous is an Automator Application. Is it possible to turn the above method into a Quick Action in which I just need to highlight a group of pdf files and then right click and apply the Quick Action and then the resulted pdf files which are flattened will go to a specific folder like Downloads with the same name as the original files. No need for any dialog to select files or the completion of the conversion.


I am very new to the Apple Script and sorry for asking these simple questions.

Mar 2, 2022 8:52 AM in response to VikingOSX

To achieve writing the same name of the selected PDF into the ~/Downloads folder, do the following:


Remove:


property SUFFIX : "_flattened"


In flatten_PDF(thisPDF):


set basename to (NSString's stringWithString:thisPDF)'s stringByDeletingPathExtension()
set basename_sfx to basename's stringByAppendingString:SUFFIX
set outPDF to basename_sfx's stringByAppendingPathExtension:"pdf"



Replace in the same locations:


property newFolder : "~/Downloads"


In flatten_PDF(thisPDF):


set newPath to (NSString's stringWithString:newFolder)'s stringByStandardizingPath()
set basename to (NSString's stringWithString:thePDF)'s lastPathComponent()
set outPDF to newPath's stringByAppendingPathComponent:basename


Thus, when you select a PDF with the Quick Action (e.g. ~/Desktop/P51_Preview.pdf), it will be written into your Downloads folder with the same name as a flattened PDF.

Mar 2, 2022 3:51 PM in response to VikingOSX

Thanks for your reply. I followed your instructions and wrote the final script shown below. When I select a pdf file and apply the quick action, I am getting the following error:


The action “Run AppleScript” encountered an error: “The variable thePDF is not defined.”


I am not sure what am I doing wrong.


use framework "Foundation"
use framework "AppKit"
use framework "Quartz"
use AppleScript version "2.4"
use scripting additions


property newFolder : "~/Downloads"
property NSString : a reference to current application's NSString
property NSURL : a reference to current application's NSURL
property PDFDocument : a reference to current application's PDFDocument
property NSDictionary : a reference to current application's NSDictionary
property NSPrintInfo : a reference to current application's NSPrintInfo


on run {input, parameters}
	
	repeat with aPDF in input
		set thePDF to POSIX path of aPDF as text
		my flatten_PDF(thePDF)
	end repeat
	
	return input
end run


on flatten_PDF(thisPDF)
	set newPath to (NSString's stringWithString:newFolder)'s stringByStandardizingPath()
	set basename to (NSString's stringWithString:thePDF)'s lastPathComponent()
	set outPDF to newPath's stringByAppendingPathComponent:basename
	set outURL to NSURL's fileURLWithPath:outPDF
	set inURL to NSURL's fileURLWithPath:thisPDF
	set pdf to PDFDocument's alloc()'s initWithURL:inURL
	
	# make assumption that first page of PDF has same MediaBox as rest of the PDF
	set {{x, y}, {w, h}} to (pdf's pageAtIndex:0)'s boundsForBox:(current application's kPDFDisplayBoxMediaBox)
	
	set pdict to (NSDictionary's dictionaryWithObject:outURL forKey:(current application's NSPrintJobSavingURL))'s mutableCopy()
	pdict's setObject:(current application's NSPrintSaveJob) forKey:(current application's NSPrintJobDisposition)
	pdict's setObject:outURL forKey:(current application's NSPrintJobSavingURL)
	set printInfo to NSPrintInfo's alloc()'s initWithDictionary:pdict
	
	printInfo's setVerticalPagination:(current application's NSPrintingPaginationModeAutomatic)
	printInfo's setJobDisposition:(current application's NSPrintSaveJob)
	printInfo's setPaperSize:(current application's NSMakeSize(w, h))
	
	set printOp to pdf's printOperationForPrintInfo:printInfo scalingMode:0 autoRotate:false
	printOp's setShowsPrintPanel:false
	printOp's setShowsProgressPanel:false
	printOp's runOperation()
	return
	
end flatten_PDF




Automator Render PDF Pages as Images with Annotations

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