applescript to split multipage tiff - macos

I'm trying to make a pdf of a multipage tiff file.
I managed to do that in windows with image magick.
In a project we are working together with a macbook with OSX (new to me).
And there should it be possible to.
Is there a script/automator... to do this.
Now I split the multipage tiff (2pages) in preview manually: open the tiff, drag each page to a folder and than I run a script to make a pdf.
Can that be done in a script?

I greet every user who tries to do without third-party applications where possible. The question asked by the OP is much more interesting than many of the trivial questions popping up in this section. Moreover, I do not understand the minuses put down by two users to the question asked. Here's the solution:
use AppleScript version "2.4"
use scripting additions
use framework "Foundation"
use framework "QuartzCore"
use framework "Quartz"
use framework "AppKit"
property |NSURL| : a reference to current application's |NSURL|
property NSString : a reference to current application's NSString
property PDFPage : a reference to current application's PDFPage
property NSImage : a reference to current application's NSImage
property PDFDocument : a reference to current application's PDFDocument
property NSBitmapImageRep : a reference to current application's NSBitmapImageRep
-- select TIFF
set anAlias to choose file of type {"public.tiff"} with prompt "Select Multi-page tiff file"
-- get selected TIFF's name and base name
tell application "Finder"
set pathString to NSString's stringWithString:(name of anAlias)
set baseName to (pathString's stringByDeletingPathExtension()) as text
end tell
-- make new destination folder (if it doesn't exist already)
tell application "Finder"
try
set destinationFolder to (make new folder at desktop with properties {name:baseName}) as text
on error
set destinationFolder to "" & (path to desktop folder) & baseName
end try
end tell
set destinationFolder to POSIX path of destinationFolder
--Read Multi-Page TIFF
set aURL to |NSURL|'s fileURLWithPath:(POSIX path of anAlias)
set aImage to NSImage's alloc()'s initWithContentsOfURL:aURL
set aRawimg to aImage's TIFFRepresentation()
set eachTiffPages to (NSBitmapImageRep's imageRepsWithData:aRawimg) as list
-- extract each tiff page as PDF file
set pageNum to 1
repeat with curPage in eachTiffPages
set thisImage to contents of curPage
set aImg to (NSImage's alloc()'s initWithSize:(thisImage's |size|()))
(aImg's addRepresentation:thisImage)
--Make Blank PDF
set aPDFdoc to PDFDocument's alloc()'s init()
-- set PDF first page's content to next image
(aPDFdoc's insertPage:(PDFPage's alloc()'s initWithImage:aImg) atIndex:0)
-- write PDF to destination
set outPutPath to destinationFolder & "/Page_" & pageNum & ".pdf"
(aPDFdoc's writeToFile:outPutPath)
set pageNum to pageNum + 1
end repeat

Related

MacOS render images from PDFs (no third party render lib)

I'm trying to render 50k images using a Mac Mini. I don't know much about the system, but I need to use the built-in renderer like the Preview.app.
I currently tested to set up an Automator script that could take files selected in the Finder window, render images, and move them to another directory.
But running that script with 50k single-page PDFs does not work. Instead, it seems to use the memory to store the PDFs or something like that.
I have never written any AppleScript, Swift, or similar code, but I'm well versed in Bash and Java, so if I could do this from the command line, then it would be ideal, but if someone has a suggestion on an AppleScript that could solve this issue I'm all ears.
Thank you for reading this.
-- 1) Create --> **Quick Action** (that is, service)
-- 2) Set: **Workflow receives current PDFs in Finder.app**
-- 3) Add action **Run AppleScript** with following content.
-- 4) Save this service with name like "Render images from single_page PDFs".
use scripting additions
use framework "Foundation"
use framework "AppKit"
use framework "Quartz"
use framework "QuartzCore"
on run {input, parameters}
set destinationFolder to (choose folder with prompt "Please, choose Destination Folder")
set destFolderPosixPath to POSIX path of destinationFolder
repeat with aPDF in (get input)
(my rasterPDF:aPDF savingToFolder:destFolderPosixPath)
end repeat
return input
end run
on rasterPDF:aPDF savingToFolder:destFolderPosixPath
set aURL to (|NSURL|'s fileURLWithPath:(POSIX path of aPDF))
set fileName to aURL's lastPathComponent()
set baseName to fileName's stringByDeletingPathExtension()
set aPDFdoc to PDFDocument's alloc()'s initWithURL:aURL
set doc to (NSImage's alloc()'s initWithData:((aPDFdoc's pageAtIndex:0)'s dataRepresentation()))
if doc = missing value then error "Error in getting image from PDF"
set theData to doc's TIFFRepresentation()
set aNSBitmapImageRep to (NSBitmapImageRep's imageRepsWithData:theData)'s objectAtIndex:0
set outNSURL to |NSURL|'s fileURLWithPath:(destFolderPosixPath & baseName & ".png")
set outputPNGData to aNSBitmapImageRep's representationUsingType:NSPNGFileType |properties|:{NSImageCompressionFactor:0.8, NSImageProgressive:false}
outputPNGData's writeToURL:outNSURL atomically:true
end rasterPDF:savingToFolder:
NOTE: 1) the script renders image from first page of multiple_page PDFs as well. 2) with using repeat loop and with changing pageAtIndex property, someone can adapt my script to render images from all PDF pages.

How do get last downloaded image to insert into object placeholder of current keynote slide?

Images are key to my work.
I am trying to find a quick way to automate image insertion to keynote. The script I am drafting is to get the last created/downloaded image, and insert it into the current slide on Keynote as a replacement of the master's object placeholder.
Error from applescript:
"Keynote got an error: Can’t set file name of slide 2 of document id \"B1054797-9A07-4642-AE79-166D1DE72674\" to alias." number -10006 from file name of slide 2 of document id "B1054797-9A07-4642-AE79-166D1DE72674" to alias
set myFolder to "/Users/Mingyu/Desktop/UpperEchelon"
tell application "Finder" to set latestFile to item 1 of (sort files of (POSIX file myFolder as alias) by creation date) as alias
tell application "Keynote"
activate
tell the front document
tell the current slide
set thisPlaceholderImageItem to item 1
set file name of thisPlaceholderImageItem to ¬
alias
end tell
end tell
end tell
I expect the script will insert last download image in the folder "UpperEchelon" to a current open slide in Keynote
Two issues:
You have to set thisPlaceholderImageItem to image 1 rather than to item 1
You have to set the file name to latestFile rather than just to alias. That's what the error is telling you.
And if the folder is a subfolder of the desktop there is a much shorter syntax
set myFolder to "UpperEchelon"
tell application "Finder" to set latestFile to item 1 of (sort files of folder myFolder by creation date) as alias
tell application "Keynote"
activate
tell the front document
tell the current slide
set thisPlaceholderImageItem to image 1
set file name of thisPlaceholderImageItem to latestFile
end tell
end tell
end tell

How to show composite icons using Display Dialog

Is there any way to display Display Dialog icons like macOS does, I tried looking for the icon below in /System/Library/CoreServices/CoreTypes.bundle
but I didn't find it.
set myIcon to (path to resource "myIcon.icns")
display dialog "this is my icon" buttons {"OK"} default button "OK" with icon myIcon
All of the standard Apple icons are stored here:
`/System/Library/CoreServices/CoreTypes.bundle/Contents/Resources`
You can access them directly, as in the following.
set iconFIle to choose file "Choose an icon file" of type {"com.apple.icns"} ¬
default location POSIX file "/System/Library/CoreServices/CoreTypes.bundle/Contents/Resources"
display dialog "This is a test" with icon iconFIle
Note that the Finder sometimes does composite icons by using one icon as an overlay or badge applied to another icon. For instance, I believe the image you posted above is the file "KEXT.icns" overlaid with the file "AlertCautionBadgeIcon.icns." You can mimic that behavior with the following script.
set basePath to POSIX path of (path to library folder from system domain) & "CoreServices/CoreTypes.bundle/Contents/Resources/"
set tempStoragePath to POSIX path of (path to temporary items from user domain)
-- set the name of the main idon, and the overlay icon
set mainName to "KEXT"
set overlayName to "AlertCautionBadgeIcon"
set kextImgPath to basePath & mainName & ".icns"
set alertImgPath to basePath & overlayName & ".icns"
set tempSetPath to quoted form of (tempStoragePath & mainName & ".iconset" as text)
set tempOverlayPath to quoted form of (tempStoragePath & overlayName & ".iconset" as text)
-- decompose the icns into iconsets, so that we can do the overlays by hand
do shell script "iconutil -c iconset -o " & tempSetPath & " " & kextImgPath
do shell script "iconutil -c iconset -o " & tempOverlayPath & " " & alertImgPath
tell application "System Events"
set mainFolder to folder (mainName & ".iconset") of folder tempStoragePath
set overlayFolder to folder (overlayName & ".iconset") of folder tempStoragePath
set theFiles to (files of mainFolder whose name extension is "png")
(*
iconsets are folders with files named (e.g.) 'icon_16x16.png', 'icon_128x128#2x.png'
this loop runs through and finds matching sized elements of the set, then sends
them to the script object's handler for processing with ASOC
*)
repeat with thisFile in theFiles
set fileName to name of thisFile
if exists file (name of thisFile) of overlayFolder then
asocBits's mungePNGs(POSIX path of thisFile, POSIX path of (file fileName of overlayFolder))
end if
end repeat
end tell
-- convert the iconset folders back to icns files, then send the file to display dialog
do shell script "iconutil -c icns " & tempSetPath
display dialog "This is a test" with icon POSIX file (tempStoragePath & mainName & ".icns")
script asocBits
use framework "Foundation"
use framework "AppKit"
property NSImage : class "NSImage"
property NSBitmapImageRep : class "NSBitmapImageRep"
on mungePNGs(mainImg, overlay)
-- get respective images
set mainImgObj to NSImage's alloc's initWithContentsOfFile:mainImg
set overlayObj to NSImage's alloc's initWithContentsOfFile:overlay
-- create a destination image
set newImage to NSImage's alloc's initWithSize:(mainImgObj's |size|)
newImage's lockFocus()
-- set up apprpriate drawing rects, then draw the two images into the new image.
set newRect to current application's CGRectZero as list
set imgSize to mainImgObj's |size| as list
set item 2 of newRect to item 1 of imgSize
set h to (height of item 1 of imgSize)
(*
these were trial and error. remember that (0,0) is the bottom left,
not the top left (y goes from bottom to top).
placementRect is supposed to be where the overlay is placed.
cropRect is the part of the overlay that's pasted.
different badges have their effective images in different quadrants.
*)
set placementRect to current application's CGRectMake(0.5 * h, 0.0, h, h)
set cropRect to current application's CGRectMake(0.5 * h, 0.5 * h, h, h)
mainImgObj's drawInRect:newRect
set op to current application's NSCompositeSourceOver
overlayObj's drawInRect:placementRect fromRect:cropRect operation:op fraction:1.0
-- create a bitmap representation and save it back to the main iconset file
set bitmapRep to NSBitmapImageRep's alloc's initWithFocusedViewRect:newRect
newImage's unlockFocus()
set PNGType to current application's NSBitmapImageFileTypePNG
set imgData to (bitmapRep's representationUsingType:PNGType |properties|:(missing value))
imgData's writeToFile:mainImg atomically:false
end mungePNGs
end script
The script is on the slow side, but it gets the job done. In the long run, it might be more efficient simply to use the script object to create icns files that you can store in the bundle and call at need.
Technical detail: I've used a script object to isolate the ASOC routines from the rest of the script. ASOC and osax commands don't always play well together. In this case, display dialog with icon always seems to throw an error if any frameworks have been invoked. I suppose I could have used tell framework "..." blocks instead, but the script object appealed to me...
As Ted correctly answered you can't display compound icons.
But you can do the opposite, displaying your application icon with a caution or stop badge.
To do so omit the reference to the icon and use the other – enumerated – with icon parameter
display dialog "this is my icon" buttons {"OK"} default button "OK" with icon caution
display dialog "this is my icon" buttons {"OK"} default button "OK" with icon stop

How can I automate a keynote workflow to flatten slides into image slides for export to .ppt

I always design my presentation slides in keynote (because I find it easier and more pleasant to work with), though they often need to be presented on a windows machine running PowerPoint.
In order to avoid issues with fonts, formatting, etc., I always use the following effective workflow:
Design the slides in keynote, often using images and text.
Export the slides as jpg files to a folder on the desktop.
Open a new keynote presentation.
Drag the jpg files into the slide navigator. This creates an image slide of each jpg.
export the new presentation to a .ppt file.
Is there a way I can automate this workflow? I'd love to collapse steps 2-5 into a single step!
Here's the AppleScript that does this (work on Keynote version 6.2, not on version 5):
tell application "Finder" to set f to (make new folder) as text -- create a temp folder to export images
tell application "Keynote"
tell front document
export to (file f) as slide images with properties {image format:JPEG, compression factor:95}
set {h, w, fPath} to {height, width, file of it}
end tell
tell (fPath as string) to if it ends with ".key:" then
set newFile to (text 1 thru -6) & ".ppt"
else
set newFile to it & ".ppt"
end if
set jpegs to my getImages(f)
set newDoc to make new document with properties {width:w, height:h}
tell newDoc
set mSlide to last master slide -- blank
repeat with thisJPEG in jpegs
set s to make new slide with properties {base slide:mSlide}
tell s to make new image with properties {file:thisJPEG}
end repeat
delete slide 1
export to (file newFile) as Microsoft PowerPoint
close saving no
end tell
end tell
tell application "Finder" to delete folder f -- delete the temp folder
on getImages(f)
tell application "Finder" to return (files of folder f) as alias list
end getImages
Important:
the slideshow must be already open in Keynote before running the script.
And the slideshow must be already saved, because the script use the path of the front document to save the PPT file in the same folder.
--
Updated: to choose location of the new file
set v to ("Volumes" as POSIX file) as alias
tell application "Finder" to set f to (make new folder) as text -- create a temp folder to export images
tell application "Keynote"
tell front document
export to (file f) as slide images with properties {image format:JPEG, compression factor:95}
set {h, w, tName} to {height, width, name of it}
end tell
tell tName to if it ends with ".key" then
set newName to (text 1 thru -5) & ".ppt"
else
set newName to it & ".ppt"
end if
set jpegs to my getImages(f)
activate
set newFile to choose file name default name newName default location v with prompt "Select the folder to save the PPT file"
set newDoc to make new document with properties {width:w, height:h}
tell newDoc
set mSlide to last master slide -- blank
repeat with thisJPEG in jpegs
set s to make new slide with properties {base slide:mSlide}
tell s to make new image with properties {file:thisJPEG}
end repeat
delete slide 1
export to (newFile) as Microsoft PowerPoint
close saving no
end tell
end tell
tell application "Finder" to delete folder f -- delete the temp folder
on getImages(f)
tell application "Finder" to return (files of folder f) as alias list
end getImages

AppleScript: Organize images based on image dimensions

I'm brand new to AppleScript and I'm trying to write a basic script that does the following:
Finds images (PNGs) in the folder ~/Dropbox/Camera Uploads that are exactly 640x1136 (iPhone 5 screenshots) and moves them to ~/Dropbox/Camera Uploads/Screenshots.
This seems pretty straightforward, but so far I haven't been able to figure it out.
Here's how I would do it. I wouldn't worry about performance. I ran the Image Events section on 200 files, and it only took 1 second.
set picFolder to alias "Path:to:Dropbox:Camera Uploads:"
set screenshotFolder to alias "Path:to:Dropbox:Camera Uploads:screenshots:"
tell application "System Events"
set photos to path of files of picFolder whose kind is "Portable Network Graphics image"
end tell
set screenshots to {}
repeat with imgPath in photos
set imgAlias to alias imgPath
tell application "Image Events"
set img to open imgPath
if dimensions of img = {640, 1136} then
set end of screenshots to imgAlias
end if
close img
end tell
end repeat
tell application "Finder"
move screenshots to screenshotFolder
end tell
You need to have an AppleScript-aware application that can act based on the dimensions of an image file. I don’t think the Finder can do this, despite its ability to show the dimensions of images in Finder views.
iPhoto should be able to do this. The iPhoto dictionary indicates that “photos” have both the width and height of images. So you should be able to write an AppleScript that imports them into iPhoto first, then selects those that match your criteria, and then saves them to the appropriate Dropbox folder.
Depending on your needs, you might also look at Automator. It contains iPhoto actions as well, including one to “Filter iPhoto items”. If you create a Folder Action you should be able to create an Automator script that starts up whenever something new is added to your Camera Uploads folder, adds them to iPhoto, and then copies them to your Screenshots folder.
If nothing else, you should be able to use Image Events to get all images in the folder, and then act only on the ones that match your criteria. Something like:
tell application "Image Events"
tell folder "Macintosh HD:Users:colin:Dropbox:Camera Uploads"
copy (files where kind is "JPEG image") to potentialScreenshots
repeat with potentialFile in potentialScreenshots
set potentialScreenshot to open potentialFile
set imageDimensions to dimensions of potentialScreenshot
if item 1 of imageDimensions is 640 then
set fileName to name of potentialFile
tell me to display dialog fileName
end if
end repeat
end tell
end tell
There ought to be a way to tell Image Events to only look at files whose dimensions match what you want, but I can’t see it.
Try:
set folderPath to POSIX path of (path to home folder) & "Dropbox/Camera Uploads"
set screenshotsPath to POSIX path of (path to home folder) & "Dropbox/Camera Uploads/Screenshots"
try
do shell script "mdfind -0 -onlyin " & quoted form of folderPath & " \"kMDItemPixelWidth == 640 && kMDItemPixelHeight == 1136\" | xargs -0 -I {} mv {} " & quoted form of screenshotsPath
end try

Resources