Hello,
My goal would be to merge picture files nested in sub-folders into a PDF file.
I’ve a lot of sub-folders which picture files needs to be merged, so doing it manually or with automator isn’t exactly the way wanna go…
I found 2 articles related to my research, but unfortunately, the first post is outdated, at least for me as I installed my Os fresh over snow leopard… The second posts merges just PDF files, and fails with picture files.
Some suggestion?
use AppleScript version "2.4" -- Yosemite (10.10) or later
use scripting additions
use framework "Foundation"
use framework "AppKit" -- for NSImage
use framework "Quartz" -- required for PDF stuff
set inFiles to (choose file of type {"public.image", "com.adobe.pdf"} with prompt "Choose your files:" with multiple selections allowed)
set destPosixPath to POSIX path of (choose file name default name "Combined.pdf" with prompt "Save new PDF to:")
my combineFiles:inFiles savingToPDF:destPosixPath
on combineFiles:inFiles savingToPDF:destPosixPath
-- make URL of the first file
set inNSURL to current application's |NSURL|'s fileURLWithPath:(POSIX path of item 1 of inFiles)
-- make PDF document from the URL
if (inNSURL's pathExtension()'s isEqualToString:"pdf") as boolean then
set theDoc to current application's PDFDocument's alloc()'s initWithURL:inNSURL
else
set theDoc to my pdfDocFromImageURL:inNSURL
end if
-- loop through the rest
set oldDocCount to theDoc's pageCount()
set inFiles to rest of inFiles
repeat with aFile in inFiles
-- make URL of the next PDF
set inNSURL to (current application's |NSURL|'s fileURLWithPath:(POSIX path of aFile))
-- make PDF document from the URL
if (inNSURL's pathExtension()'s isEqualToString:"pdf") as boolean then
set newDoc to (current application's PDFDocument's alloc()'s initWithURL:inNSURL)
else
set newDoc to (my pdfDocFromImageURL:inNSURL)
end if
-- loop through, moving pages
set newDocCount to newDoc's pageCount()
repeat with i from 1 to newDocCount
-- get page of PDF
set thePDFPage to (newDoc's pageAtIndex:(i - 1)) -- zero-based indexes
-- insert the page into main PDF
(theDoc's insertPage:thePDFPage atIndex:oldDocCount)
set oldDocCount to oldDocCount + 1
end repeat
end repeat
set outNSURL to current application's |NSURL|'s fileURLWithPath:destPosixPath
-- save the main PDF
(theDoc's writeToURL:outNSURL)
end combineFiles:savingToPDF:
on pdfDocFromImageURL:inNSURL
set theImage to current application's NSImage's alloc()'s initWithContentsOfURL:inNSURL
set theSize to theImage's |size|()
set theRect to {{0, 0}, theSize}
set theImageView to current application's NSImageView's alloc()'s initWithFrame:theRect
theImageView's setImage:theImage
set theData to theImageView's dataWithPDFInsideRect:theRect
return current application's PDFDocument's alloc()'s initWithData:theData
end pdfDocFromImageURL:
Great Shane,
Works exactly as expected.
I tried to modify your previous script by myself but that kind of coding isn’t yet in my reach. Still I read your code with interest.
Doing the same with Automator requires a lot of fiddling, some 3rd party actions and then the results aren’t optimal.
Thanks for sharing AppleScriptObjC with us all! (PDF is always useful)
Shane’s suggestion is excellent and clearly the script to use.
I have no knowledge of scripting additions and thought I would try to do this with basic Applescript using utilities included with macOS. I’ve copied my script below.
A significant flaw of my script is that it uses join.py to merge PDF files, and it is very slow. Substituting another utility–such as PDFtk Server, cpdf, or Ghostscript–is easily done and would eliminate this flaw (although Shane’s script is still preferred). My script has been tested on Sierra only.
--Set variable to temp folder.
set tempFolder to "/Users/bob/Temp/"
--Prompt for picture folder.
choose folder default location (path to home folder)
set pictureFolder to quoted form of (text 1 thru -2 of POSIX path of result)
--Set variable to picture files.
try
do shell script "find " & pictureFolder & " -type f -iname *.png -or -iname *.jpg"
set pictureFiles to paragraphs of result
on error errorMessage
display dialog "The Find utility reported an error while searching for picture files." buttons {"View Error Message", "OK"} ¬
cancel button 2 default button 2 with title "Picture Merge" with icon stop
display dialog errorMessage buttons {"OK"} ¬
cancel button 1 default button 1 with title "Picture Merge"
end try
--Notify if no or a large number of picture files in the selected Folder.
set pictureCount to (count pictureFiles)
if pictureCount = 0 then
display dialog "No picture files in selected folder." buttons {"OK"} ¬
cancel button 1 default button 1 with title "Picture Merge" with icon stop
else if pictureCount > 200 then
display dialog (pictureCount as text) & " picture files in selected folder." buttons {"Cancel", "Continue"} ¬
cancel button 1 default button 1 with title "Picture Merge" with icon stop
end if
--Prompt for PDF file name.
choose file name with prompt "" default name "Merged Picture Files.pdf" default location (path to desktop folder)
set pdfFile to result as text
--Set variable to PDF file name.
if pdfFile does not end with ".pdf" then set pdfFile to pdfFile & ".pdf"
set pdfFile to quoted form of POSIX path of pdfFile
--Convert picture files to PDF format.
set fileNumber to 0
repeat with aFile in pictureFiles
set tempFile to "Picture_merge_temp_" & (text -4 thru -1 of ("000" & fileNumber)) & ".pdf"
do shell script "sips --setProperty format pdf " & (quoted form of aFile) & " --out " & tempFolder & tempFile
set fileNumber to fileNumber + 1
end repeat
--Merge temporary files.
set pdfUtility to "'/System/Library/Automator/Combine PDF Pages.action/Contents/Resources/join.py'"
do shell script pdfUtility & " -o " & pdfFile & " " & tempFolder & "*.pdf"
--Delete temporary files.
tell application "System Events" to ¬
delete (every file in folder tempFolder whose name begins with "Picture_merge_temp_")