Monday, November 23, 2009
  • Index
  •  » Code Exchange
  •  » Create image sequences from still images without QuickTime Pro

#1 2008-05-16 01:26:06 pm

Martin Michel
Administrator
From: Berlin, Germany
Registered: 2008-03-03
Posts: 530
Website

Create image sequences from still images without QuickTime Pro

Panic in the laboratory! On a Friday...

Just shortly after I entered my office this morning, my colleagues from the R&D lab approached me with a request to write an AppleScript for them. They needed to create image sequences from 3000 still images generated by a device measuring stress values in electroplated deposits and they definitely did not want to do that manually. Especially not on a Friday...

http://files.macscripter.net/joy/images/openimagesequence.jpg

QuickTime Pro allows you to create image sequences...


Well, I knew that you could easily create custom slide shows with QuickTime Pro, but why spent hard-earned $29.99 when you can get the same functionality free of charge by using built-in Mac OS X 10.5 technologies? [Okay, just ignore my hourly rate in this calculation big_smile]

And here is how: Mac OS X 10.5 already contains PyObjC, which allows to work directly with the excellent QTKit using the Python scripting language. This way I was able to quickly write a Python script that creates an empty QuickTime movie and then adds images to it. Combined with a convenient AppleScript droplet, that calls the Python script located in its own Application bundle, this made for a nice and efficient workflow wink At least, my colleagues were more than satisfied...

As always, I invite you to download and inspect the AppleScript on your fine Mac:



Requirements
• Mac OS X 10.5 Leopard
• QuickTime 7.2.1

Installation & Usage
Download and extract the ZIP archive. Then open the script with a double click or drop a bunch of image files onto its icon. The script will then ask you to specify a file name and location for the new QuickTime movie. After you provided certain settings for your image sequence (e.g. frames per second/seconds per frame), your image sequence will be produced.

Supported Image Formats
jpg, jpeg, gif, png, tiff, tif, psd, pict, bmp, pdf
>>> only the first page of a PDF document is recognized

Notes
Sequimago currently uses the JPEG image format for the image sequence, which results in a smaller file size of the QuickTime movie. But you can easily edit the Python script to use alternative image formats (e.g. TIFF). The Python script is located at: «Sequimago.app/Contents/Resources/crtimgseq.py».

Moreover the script does not yet offer advanced export settings. But you can study this excellent article to modify the Python script yourself.

Important: Opening and saving the below script code in Script Editor won't result in a usable AppleScript! That is because the AppleScript internally relies on a little Python script, which is located inside its Application bundle. Therefor please download the complete script here.

Applescript:


-- author: Martin Michel
-- created: 16.05.2008
-- requires:
-- • Mac OS X 10.5 Leopard
-- • QuickTime 7.2.1

-- This AppleScript will create an image sequence (QuickTime movie) from
-- selected or dropped image files.
--
-- The script will ask you to specify a file name and location for the new
-- QuickTime movie and lets you select specific settings for the image sequence
-- (frames per second/seconds per frame). Moreover you can choose to sort the
-- image files by their file names before creating the QuickTime movie.
--
-- The image sequence itself is created by a Python script using QTKit.
--
-- YOU DO NOT NEED QuickTime Pro to use this script :D
--
-- Supported image formats: jpg, jpeg, gif, png, tiff, tif, psd, pict, bmp, pdf

-- the AppleScript's name
property mytitle : "Sequimago"

-- I am called when the user opens the AppleScript with a double-click
on run
   set finderitems to choose file with prompt "Please choose image files for the image sequence:" with multiple selections allowed without showing package contents and invisibles
   my main(finderitems)
end run

-- I am called when the user drops Finder items onto the AppleScript's icon
on open finderitems
   my main(finderitems)
end open

-- |--|--|--|--|--|--|--|--|--|--|--|--|--|
-- | Main Routine
-- |--|--|--|--|--|--|--|--|--|--|--|--|--|

-- I am the main function controlling the script flow
-- I demand a list of Finder items to process
on main(finderitems)
   try
       -- searching the given Finder items for image files that can be processes
       set imgpaths to my getimgpaths(finderitems)
       -- no image files found...
       if imgpaths is {} then
           set errmsg to "The dropped/selected items did not contain any image files to process." & return & return & "Supported image formats: jpg, jpeg, gif, png, tiff, tif, psd, pict, bmp, pdf"
           my dsperrmsg(errmsg, "--")
           return
       end if
       -- asking the user to provide a file path for the new QuickTime movie
       set newmoviepath to my getnewmoviepath()
       if newmoviepath is missing value then
           return
       end if
       -- asking the user to select certain settings for the image sequence
       set imgseqsettings to my getimgseqsettings()
       if imgseqsettings is missing value then
           return
       end if
       -- does the user want to sort the image files by their file names?
       set sortimgfiles to my getsortimgfiles()
       -- creating the image sequence
       my crtimgsequence(newmoviepath, imgpaths, sortimgfiles, imgseqsettings)
       -- catching unexpected errors
   on error errmsg number errnum
       my dsperrmsg(errmsg, errnum)
   end try
end main

-- I am searching the given list of Finder items for image files
-- that can be used to create an image sequence
-- >>> I return a list of image file paths, that might be empty, if not image files are found
-- Note: I am currently searching for image files by simply looking at the file's name
-- extension. That is not the best approach...File types in the future?
on getimgpaths(finderitems)
   set imgpaths to {}
   repeat with finderitem in finderitems
       set iteminfo to info for finderitem
       if not folder of iteminfo then
           set suffix to name extension of iteminfo
           if suffix is not missing value then
               if suffix is in {"jpg", "jpeg", "gif", "png", "tiff", "tif", "psd", "pict", "bmp", "pdf"} then
                   set imgpaths to imgpaths & (finderitem as Unicode text)
               end if
           end if
       end if
   end repeat
   return imgpaths
end getimgpaths

-- I am asking the user to specify a file name and location for a new QuickTime movie
-- >>> I return the chosen file path as Unicode text [Mac path, not Posix path] or
-- >>> missing value in case the user cancels the dialog
on getnewmoviepath()
   try
       set newmoviepath to choose file name default name "imagesequence.mov" with prompt "Please specify a file name and location for the new QuickTime movie:"
       return (newmoviepath as Unicode text)
   on error
       return missing value
   end try
end getnewmoviepath

-- I am asking the user to select specific settings for the image sequence
-- (frames per second vs. seconds per frames)
-- >>> I return a special list containing a time code used by QuickTime
-- >>> {time value, time scale} or missing value in case the user cancels the dialog
on getimgseqsettings()
   try
       tell me
           activate
           display dialog "Please select a timing mode for the image sequence:" with title mytitle buttons {"Cancel", "Frames per second", "Seconds per frame"} default button 1
       end tell
       set dlgresult to result
       if button returned of dlgresult is "Frames per second" then
           set fpsvalue to my gettimingvalue("fps")
           if fpsvalue is not missing value then
               return {1, fpsvalue}
           else
               return missing value
           end if
       else if button returned of dlgresult is "Seconds per frame" then
           set spfvalue to my gettimingvalue("spf")
           if spfvalue is not missing value then
               return {spfvalue, 1}
           else
               return missing value
           end if
       end if
   on error
       return missing value
   end try
end getimgseqsettings

-- I am asking the user to enter the number of frames per second or the duration of
-- each frame in seconds based on the given mode ("fps" or "spf")
-- >>> I return a real or missing value in case the user cancels the dialog
on gettimingvalue(mode)
   -- getting the system's decimal separator (comma or dot)
   set decseparator to my getdecseparator()
   if mode is "fps" then
       set dlgmsg to "Please enter the number of desired frames per second:" & return & "(decimal separator: »" & decseparator & "«)"
   else
       set dlgmsg to "Please enter the duration of each frame in seconds:" & return & "(decimal separator: »" & decseparator & "«)"
   end if
   set defansw to "1" & decseparator & "0"
   try
       tell me
           activate
           display dialog dlgmsg default answer defansw buttons {"Cancel", "Enter"} default button 2 with title mytitle
       end tell
       set dlgresult to result
       set usrinput to text returned of dlgresult
       -- no input, empty string
       if usrinput is "" then
           my gettimingvalue(mode)
       else
           -- can we convert the user input into a real?
           try
               set fpsvalue to usrinput as real
               if fpsvalue is greater than 0 then
                   return fpsvalue
               end if
           on error errmsg number errnum
               -- no, we cannot...try again
               my dsperrmsg(errmsg, errnum)
               my getfpsvalue()
           end try
       end if
   on error
       return missing value
   end try
end gettimingvalue

-- I am asking the user if he wants to sort the image files by their file names
-- before creating the image sequence
-- >>> I return true or false
on getsortimgfiles()
   tell me
       activate
       display dialog "Do you want to sort the image files by their file names before processing them?" buttons {"Yes", "No"} default button 2 with icon note with title mytitle
   end tell
   set dlgresult to result
   if button returned of dlgresult is "No" then
       return false
   else if button returned of dlgresult is "Yes" then
       return true
   end if
end getsortimgfiles

-- I am creating an image sequence using the given parameters and a Python script
on crtimgsequence(newmoviepath, imgpaths, sortimgfiles, imgseqsettings)
   -- file path of the Python script responsible for creating the image sequence
   -- using the QTKit and the newly introduced Scripting Bridge
   set mypath to ((path to me) as Unicode text)
   set pyscriptpath to POSIX path of (mypath & "Contents:Resources:crtimgseq.py")
   -- we need to use a dot as the decimal separator when passing these two real numbers
   -- to the Python script on the command line, therefore we search and replace any commas
   set timevalue to my searchnreplace(",", ".", (item 1 of imgseqsettings) as Unicode text)
   set timescale to my searchnreplace(",", ".", (item 2 of imgseqsettings) as Unicode text)
   set newmoviepath to (POSIX path of newmoviepath)
   -- creating a large string containing all image file paths, so that we can easily
   -- pass them on to the Python script
   set strpaths to ""
   repeat with imgpath in imgpaths
       set strpaths to strpaths & space & quoted form of (POSIX path of imgpath)
   end repeat
   -- creating the complete command
   set command to "python " & quoted form of pyscriptpath & space & quoted form of newmoviepath & space & timevalue & space & timescale & space & sortimgfiles & strpaths
   log command
   set command to command as «class utf8»
   -- there we go...BUMM
   do shell script command
end crtimgsequence

-- I am returning the currently used decimal separator
on getdecseparator()
   set strnum to 0.1 as Unicode text
   set decseparator to character 2 of strnum
   return decseparator
end getdecseparator

-- I am returning the text items of the given text (delimited by the given delimiter)
on gettxtitems(txt, delchar)
   considering case, diacriticals and punctuation
       set olddelims to AppleScript's text item delimiters
       set AppleScript's text item delimiters to {delchar}
       set txtitems to text items of txt
       set AppleScript's text item delimiters to olddelims
   end considering
   return txtitems
end gettxtitems

-- I am a very old search & replace function
on searchnreplace(searchstr, replacestr, txt)
   considering case, diacriticals and punctuation
       if txt contains searchstr then
           set olddelims to AppleScript's text item delimiters
           set AppleScript's text item delimiters to {searchstr}
           set txtitems to text items of txt
           set AppleScript's text item delimiters to {replacestr}
           set txt to txtitems as Unicode text
           set AppleScript's text item delimiters to olddelims
       end if
   end considering
   return txt
end searchnreplace

-- I am displaying error messages to the user
on dsperrmsg(errmsg, errnum)
   tell me
       activate
       display dialog "Sorry, an error occured:" & return & return & (errmsg & " (" & errnum & ")") buttons {"OK"} default button 1 with icon stop with title mytitle giving up after 60
   end tell
end dsperrmsg


Never thought to make a living by automating Macs…

Offline

 

#2 2009-10-16 10:51:01 am

chrislarson
Member
Registered: 2009-10-14
Posts: 4

Re: Create image sequences from still images without QuickTime Pro

Thansk a ton! I incorporated some of your script in to a Photoshop script I've been playing around with.

This really helped me a ton!

Offline

 
  • Index
  •  » Code Exchange
  •  » Create image sequences from still images without QuickTime Pro

Board footer

Powered by FluxBB

[ Generated in 0.418 seconds, 8 queries executed ]

RSS (new topics) RSS (active topics)