Showing posts with label automator. Show all posts
Showing posts with label automator. Show all posts

Tuesday, June 9, 2009

Automator workflow for interleaving odd and even pages of PDF scans

I have made an Automator workflow that combines two PDFs, by shuffling (interleaving them), but after reversing the second one (second in terms of creation time). This means that you can scan a whole lot of pages (odd sides), turn them over and scan the other sides (even sides), then right click, choose an Automator workflow to combine them. They become Combined.pdf in the same folder - the originals are moved to the Trash.

Uses the python script automator action

This was something also wanted here.

The automator action starts with a Get Selected Finder Items action, then has a Run Python Script action with the following code.

import os
from CoreGraphics import *

def createPDFDocumentWithPath(path):
print path
return CGPDFDocumentCreateWithProvider(CGDataProviderCreateWithFilename(path))
def duplexPages(writeContext, oddfile, evenfile):
# open PDFDocuments for each of the files.
odd = createPDFDocumentWithPath( oddfile )
even = createPDFDocumentWithPath( evenfile )

# confirm that the number of pages is the same
maxPages = odd.getNumberOfPages()
if ( maxPages <> even.getNumberOfPages() ):
print "Documents do not have the same number of pages"
else:
# Shuffle the pages
for pageNum in xrange(1, maxPages + 1):
# start at first odd page
page = odd.getPage(pageNum)
print 'Page', pageNum, 'from', oddfile
if page != None:
mediaBox = odd.getMediaBox(pageNum)
writeContext.beginPage(mediaBox)
writeContext.drawPDFDocument(mediaBox, odd, pageNum)
writeContext.endPage()
# start at last even page
page = even.getPage(maxPages + 1 - pageNum)
print 'Page', maxPages + 1 - pageNum, 'from', evenfile
if page != None:
mediaBox = even.getMediaBox(maxPages + 1 - pageNum)
writeContext.beginPage(mediaBox)
writeContext.drawPDFDocument(mediaBox, even, maxPages + 1 - pageNum)
writeContext.endPage()
def realFilesOnly( item ):
return item.find(".") <> 0

# from http://stackoverflow.com/questions/249785/os-x-determine-trash-location-for-a-given-path
def get_trash_path(input_file):
    path, file = os.path.split(input_file)
    if path.startswith("/Volumes/"):
        # /Volumes/driveName/.Trashes/
        s = path.split(os.path.sep)
        # s[2] is drive name ([0] is empty, [1] is Volumes)
        trash_path = os.path.join("/Volumes", s[2], ".Trashes", str(os.getuid()))
        if not os.path.isdir(trash_path):
            raise IOError("Volume appears to be a network drive (%s could not be found)" % (trash_path))
    else:
        trash_path = os.path.join(os.getenv("HOME"), ".Trash")
    return trash_path
def main(input, *args, **kwargs):
dirname = os.path.dirname(input[0])    # extract folder to work in
# print dirname
files = input
# print files
# files = os.listdir( dirname )
# files = filter(realFilesOnly, files) # filter out special files
# print files # enable to see which files are selected
if ( len(files) == 2 ):
# files[0] = os.path.join(dirname,files[0]) # add path to files 
# files[1] = os.path.join(dirname,files[1])

# odd file is assumed to be the earlier one
if ( os.path.getctime(files[1]) > os.path.getctime(files[0]) ):
odd = files[0]
even = files[1]
else:
odd = files[1]
even = files[0]

print "Identified Odd: ", odd
print "Identified Even: ", even

outputFilename = os.path.join(dirname, "Combined.pdf")
print "Output to: ", outputFilename

pageRect = CGRectMake (0, 0, 612, 792)
writeContext = CGPDFContextCreateWithFilename(outputFilename, pageRect)

duplexPages(writeContext, odd, even)

# delete the original files
trashPath = get_trash_path( odd ) # find location of trash
os.rename( odd, os.path.join(trashPath,os.path.split(odd)[1]) )
os.rename( even, os.path.join(trashPath,os.path.split(even)[1]) )
else:
print "Incorrect number of files"

return files


It can be saved as a Finder Plugin to appear on the context menu for Finder items.

Tuesday, August 19, 2008

More about Automator

Looking for more info on Automator and Folder Actions, I found this page which explains it.

http://www.simplehelp.net/2007/01/30/folder-actions-for-os-x-explained-with-real-world-examples/

I also found this folder sync action which uses rsync in the background to synchronise two folders. Maybe useful in the future.

http://www.apple.com/downloads/macosx/automator/syncfoldersaction.html

I made an AppleScript that starts an Automator action and attached it to Proximity's In Range action - Proximity can't run an Automator action directly.

display dialog "In range"
tell application Automator

end tell

This apple page is a tutorial on how to create workflows using applescript.

http://developer.apple.com/documentation/AppleApplications/Conceptual/AutomatorTutorialAppleScript/WhatYouWillCreate/chapter_2_section_1.html#//apple_ref/doc/uid/TP40002010-CH202-BAJDHAEH

Proxi looks like it is the ideal tool for looking for hotkeys and triggers, such as tracks changing in iTunes and so on. It appears to be free as in beer.

http://proxi.griffintechnology.com/wiki/index.php/Main_Page

I found this page that helped provide advice about executing Automator actions from Applescript:

Basically you save the workflow as a plugin, and choose a Script menu plugin. Then it gets saved in /Users/xxxx/Library/Scripts/Bluetooth backup.app. I put that in, in quotes for a tell application line, and it asked me to browse to the application. Now it just appears like below (and runs okay):

tell application "Bluetooth backup"
open
end tell

Now I can have my phone automatically take a backup of my passwords when it comes in range. Unfortunately it does it all the time, I will have to set it up to only do it, say, once a week.

This article seems to say how to unmount TrueCrypt volumes using applescript - there isn't any proper applescript interface to it:

http://discussions.apple.com/thread.jspa?messageID=7750841

However, the right click menu of the TrueCrypt icon (sitting on my Dock) has options to mount all the favourite volumes, so it's quite easy to open the password wallet.