Requires Photoshop CS4.
Had a need to batch-convert Photoshop files (PSD, EPS, TIFF, JPEG) and AI files (as long as PDF Preview is turned on) for a web site. Also a similar need to convert these formats to certain “don’t exceed this size” JPEGs.
Started simple”just trying to work-around the fact that Actions have no if/then logic to them (for "resizing not to exceed a given height and width), then of course we thought of more things it should do.
So I wrote this, with a little help from MacScripter folks. Converts to RGB, resizes based on given dimensions, takes inches and pixels, strips extra channels, strips color profiles, flattens, and let’s you choose a basic JPEG quality level.
A little tedious with all the dialogs.will be converting this to a FaceSpan project for a better UI, but not sure when I’ll get to it.
--
-- DECLARE PROPERTIES
--
-- debugging on?
property g_debug : false
--basic file path and names
property g_home_folder_path : path to home folder
property g_log_file_name : "Convert Images to JPEG.txt"
--
-- UTILITY HANDLERS
--
--Log Entry Generation
-- With help from StephanK of MacScripter
-- http://bbs.applescript.net/viewtopic.php?pid=76607#p76607
--
on logMe(log_string, indent_level)
if g_debug is true then --allows turning the debugger on and off so my logMe's can be left in final version
set log_target to (g_home_folder_path & "Library:Logs:" & g_log_file_name) as text
try
set log_file_ref to open for access file log_target with write permission
repeat indent_level times
write tab to log_file_ref starting at eof
end repeat
write ((log_string as text) & return) to log_file_ref starting at eof
close access log_file_ref
return true
on error
try
close access file log_target
end try
return false
end try
end if
end logMe
--
-- MAIN SCRIPT
--
on open actionItems
-- remove folders from list
--
-- courtesy of Adam Bell of MacScripter
-- http://bbs.applescript.net/viewtopic.php?pid=77739#p77739
--
set dropped_items to {}
repeat with current_actionItem in actionItems
tell application "Finder"
if (contents of current_actionItem as text) ends with ":" then
try
set dropped_items to dropped_items & (files of (entire contents of current_actionItem) as alias list)
on error -- only one file inside (works around bug)
set dropped_items to dropped_items & (files of (entire contents of current_actionItem) as alias as list)
end try
else
set dropped_items to dropped_items & current_actionItem
end if
end tell
end repeat
--gather user-entered parameters
set u to display dialog "Units?" buttons {"inches", "pixels"} default button "pixels"
set working_units to button returned of u
set h to display dialog "Height:" default answer ""
set new_height to text returned of h
set w to display dialog "Width:" default answer ""
set new_width to text returned of w
set p to display dialog "Pad to provided dimensions?" buttons {"Yes", "No"} default button "No"
set pad_image to button returned of p
set j to display dialog "JPEG Quality:" buttons {"Medium", "High", "Maximum"} default button "Maximum"
set JPEG_quality to button returned of j
set n to display dialog "File Suffix:" default answer "_web"
set file_suffix to text returned of n
set r to display dialog "Resolution:" default answer "72"
set file_res to text returned of r
set save_location to choose folder with prompt "Choose a location to save converted files:"
--convert user answer to JPEG quality to Photoshop's numeric notation
if JPEG_quality = "Medium" then
set JPEG_quality to 5
else
if JPEG_quality = "High" then
set JPEG_quality to 8
else
if JPEG_quality = "Maximum" then
set JPEG_quality to 12
end if
end if
end if
--step through files
repeat with i from 1 to number of items of dropped_items
set parseMeString to (item i of dropped_items) as string
set parseMeStringPOSIX to POSIX path of parseMeString
--get file name without extension
tell (info for item i of dropped_items without size) to set {file_name, file_extension} to {name, name extension}
set file_name to text 1 thru -((count file_extension) + 2) of file_name
--rename file to indicate it was converted by script
set new_file_name to file_name & file_suffix & ".jpg"
try
tell application "Adobe Photoshop CS4"
activate
open file (parseMeStringPOSIX as text)
--set document units to pixels (resize command only uses ppi)
set ruler units of settings to pixel units
--fix pixel aspect ratio
set pixel aspect ratio of current document to 1.0
tell current document
--get height and width of current document
set current_height to height
set current_width to width
--flatten image
flatten
--set image resolution
resize image resolution file_res resample method none
--if user requested inches, convert dimensions in-place
if working_units is "inches" then
set new_height to (new_height * file_res)
set new_width to (new_width * file_res)
end if
--change to RGB (CMYK not web compatible)
change mode to RGB
end tell
--set background for padding (canvas resize)
set background color to {class:RGB color, red:255, green:255, blue:255}
--remove extra channels
set safe_channels to {"Red", "Green", "Blue"}
set channel_names to name of channels of current document
repeat with c from 1 to number of items in channel_names
if (item c of channel_names) is not in safe_channels then
delete channel (item c of channel_names) of current document
end if
end repeat
--figure out reduction percentages
set height_ratio to new_height / current_height
set width_ratio to new_width / current_width
--make sure is not enlargement
if (height_ratio < 1) or (width_ratio < 1) then
--pick out smallest reduction and use that
if height_ratio ≤ width_ratio then
resize image current document height new_height resample method bicubic
else
if width_ratio < height_ratio then
resize image current document width new_width resample method bicubic
end if
end if
end if
--pad image if required
if pad_image is "Yes" then
resize canvas current document width new_width height new_height anchor position middle center
end if
--create path to destination
set new_file_location to ((save_location as Unicode text) & new_file_name)
--create reference (required for Photoshop saves)
set new_file_reference to (a reference to file new_file_location)
--save and close file
save current document appending lowercase extension as JPEG in new_file_reference with options {embed color profile:false, format options:optimized, quality:JPEG_quality}
close current document
--set completed file label to green
tell application "Finder" to set label index of (item i of dropped_items) to 6
end tell
on error
activate
display alert file_name message "Unable to process this file, it will be skipped."
--set uncompleted file label to red
tell application "Finder" to set label index of (item i of dropped_items) to 2
end try
end repeat
end open
I added some features (ability to handle Inches input being the key one) and added a user interface, but only after I turned it into a FaceSpan project.
This is FaceSpan “project AppleScript” so won’t work without modification in plain-Jane AppleScript anymore:
(the key problem is path handling and UI elements that are different/won’t work in plain AppleScript)
--
-- DECLARE PROPERTIES & GLOBAL VARIABLES
--
-- debugging on?
property g_debug : false
--basic file path and names
property g_home_folder_path : path to home folder
property g_desktop_folder_path : path to desktop folder
property g_log_file_name : "Convert Images to JPEG.txt"
--global variables
global g_dropped_items
--
-- UTILITY HANDLERS
--
--Log Entry Generation
-- With help from StephanK of MacScripter
-- http://bbs.applescript.net/viewtopic.php?pid=76607#p76607
--
on logMe(log_string, indent_level)
if g_debug is true then --allows turning the debugger on and off so my logMe's can be left in final version
set log_target to (g_home_folder_path & "Library:Logs:" & g_log_file_name) as text
try
set log_file_ref to open for access file log_target with write permission
repeat indent_level times
write tab to log_file_ref starting at eof
end repeat
write ((log_string as text) & return) to log_file_ref starting at eof
close access log_file_ref
return true
on error
try
close access file log_target
end try
return false
end try
end if
end logMe
--
-- FACESPAN HANDLERS (interface)
--
-- Display mainInterface window
--
on displayMainInterface(preset_name)
--close other windows that might be open
hide window "progressWindow"
--display version number of app
tell current application to set cfr_version to version
set string value of text field "textVersion" of window "mainInterface" to ("Version " & cfr_version)
--initialized fields (leave relevant pre-entered data except on reset)
if preset_name is "web" then
set current column of matrix "radioUnits" of window "mainInterface" to 2 --set units to pixels by default
set string value of text field "textFillRes" of window "mainInterface" to "72"
set current column of matrix "radioQuality" of window "mainInterface" to 2 --set quality to "High" by default
else if preset_name is "high" then
set current column of matrix "radioUnits" of window "mainInterface" to 1 --set units to inches by default
set string value of text field "textFillRes" of window "mainInterface" to "300"
set current column of matrix "radioQuality" of window "mainInterface" to 3 --set quality to "Maximum" by default
else if preset_name is "reset" then
--reset all fields
set string value of text field "textFillHeight" of window "mainInterface" to ""
set string value of text field "textFillWidth" of window "mainInterface" to ""
set current column of matrix "radioUnits" of window "mainInterface" to 2 --set units to pixels by default
set current column of matrix "radioPad" of window "mainInterface" to 2 --set padding to "no" by default
set string value of text field "textFillRes" of window "mainInterface" to ""
set current column of matrix "radioQuality" of window "mainInterface" to 3 --set quality to "Maximum" by default
set string value of text field "textFillSuffix" of window "mainInterface" to ""
set save_location to g_desktop_folder_path
set string value of text field "textSaveLoc" of window "mainInterface" to save_location
end if
--display main window
show window "mainInterface"
center window "mainInterface"
tell application "Convert Images to JPEG" to activate
end displayMainInterface
-- Button handler
--
on clicked theObject
set button_clicked to name of theObject
if button_clicked is "buttonStart" then
logMe("¢ Start Button clicked", 0)
processFiles()
end if
if button_clicked is "buttonWeb" then
displayMainInterface("web")
end if
if button_clicked is "buttonHigh" then
displayMainInterface("high")
end if
if button_clicked is "buttonReset" then
displayMainInterface("reset")
end if
if button_clicked is "buttonBrowse" then
set save_location to choose folder with prompt "Choose a location to save converted files:"
set string value of text field "textSaveLoc" of window "mainInterface" to save_location
end if
end clicked
-- Progress window
--
on displayProgress()
hide window "mainInterface"
show window "progressWindow"
center window "progressWindow"
end displayProgress
--
-- MAIN SCRIPT (kick-off application and interface only)
--
on open actionItems
logMe("Open Handler Started", 0)
--convert UNIX paths "in place" to alias (FaceSpan droplet outputs UNIX paths, AppleScript droplets output alias paths)
repeat with an_item in actionItems
set contents of an_item to alias (POSIX file an_item)
end repeat
-- remove folders from list
--
-- courtesy of Adam Bell of MacScripter
-- http://bbs.applescript.net/viewtopic.php?pid=77739#p77739
--
set g_dropped_items to {}
repeat with current_actionItem in actionItems
tell application "Finder"
if (contents of current_actionItem as text) ends with ":" then
try
set g_dropped_items to g_dropped_items & (files of (entire contents of current_actionItem) as alias list)
on error -- only one file inside (works around bug)
set g_dropped_items to g_dropped_items & (files of (entire contents of current_actionItem) as alias as list)
end try
else
set g_dropped_items to g_dropped_items & current_actionItem
end if
end tell
end repeat
--set mainInterface
displayMainInterface("reset")
end open
--
-- MAIN SCRIPT (handler from clicking "Start")
--
on processFiles()
logMe("processFiles Started", 0)
logMe("¢ Files to Process: " & g_dropped_items, 1)
logMe("¢ Number of Items: " & (count of items of g_dropped_items), 1)
--display progress window
displayProgress()
--collect parameters from interface
set new_height to get string value of text field "textFillHeight" of window "mainInterface"
set new_width to get string value of text field "textFillWidth" of window "mainInterface"
set working_units to get title of current cell of matrix "radioUnits" of window "mainInterface"
set pad_image to get title of current cell of matrix "radioPad" of window "mainInterface"
set file_res to get string value of text field "textFillRes" of window "mainInterface"
set JPEG_quality to get title of current cell of matrix "radioQuality" of window "mainInterface"
set file_suffix to get string value of text field "textFillSuffix" of window "mainInterface"
set save_location to get string value of text field "textSaveLoc" of window "mainInterface"
logMe("User Parameters Collected", 1)
--convert user answer to JPEG quality to Photoshop's numeric notation
if JPEG_quality = "Medium" then
set JPEG_quality to 5
else
if JPEG_quality = "High" then
set JPEG_quality to 8
else
if JPEG_quality = "Maximum" then
set JPEG_quality to 12
end if
end if
end if
logMe("JPEG Quality Notation Converted", 1)
--step through files
repeat with i from 1 to count of items of g_dropped_items
logMe("Step Through Files: Loop " & i, 2)
(* Needed only outside FaceSpan?
set parseMeString to (item i of g_dropped_items) as string
set parseMeStringPOSIX to POSIX path of parseMeString
logMe("¢ POSIX Conversion Completed", 2)
*)
--get file name without extension
tell (info for item i of g_dropped_items without size) to set {file_name, file_extension} to {name, name extension}
set file_name to text 1 thru -((count file_extension) + 2) of file_name
logMe("¢ File name without extension: " & file_name, 2)
--rename file to indicate it was converted by script
set new_file_name to file_name & file_suffix & ".jpg"
logMe("¢ File name with extension: " & new_file_name, 2)
try
tell application "Adobe Photoshop CS4"
my logMe("Photoshop Work Started", 3)
activate
open file (item i of g_dropped_items as string)
--open file (parseMeStringPOSIX as text) --for outside FaceSpan
--set document units to pixels (resize command only uses ppi)
set ruler units of settings to pixel units
--fix pixel aspect ratio
set pixel aspect ratio of current document to 1.0
tell current document
--get height and width of current document
set current_height to height
set current_width to width
--flatten image
flatten
--set image resolution
resize image resolution file_res resample method none
--if user requested inches, convert dimensions to ppi in-place (resize command needs ppi)
if working_units is "Inches" then
set new_height to (new_height * file_res)
set new_width to (new_width * file_res)
end if
--change to RGB (CMYK not web compatible)
change mode to RGB
end tell
--set background for padding (canvas resize)
set background color to {class:RGB color, red:255, green:255, blue:255}
--remove extra channels
set safe_channels to {"Red", "Green", "Blue"}
set channel_names to name of channels of current document
repeat with c from 1 to number of items in channel_names
if (item c of channel_names) is not in safe_channels then
delete channel (item c of channel_names) of current document
end if
end repeat
--figure out reduction percentages
set height_ratio to new_height / current_height
set width_ratio to new_width / current_width
--make sure is not enlargement
if (height_ratio < 1) or (width_ratio < 1) then
--pick out smallest reduction and use that
if height_ratio ≤ width_ratio then
resize image current document height new_height resample method bicubic
else
if width_ratio < height_ratio then
resize image current document width new_width resample method bicubic
end if
end if
end if
--pad image if required
if pad_image is "Yes" then
resize canvas current document width new_width height new_height anchor position middle center
end if
my logMe("¢ Image Padded (if needed)", 3)
--create path to destination
my logMe("¢ Build File Path and Name", 3)
set new_file_location to ((save_location as Unicode text) & "/" & new_file_name)
my logMe("¢ Destination Path Built: " & new_file_location, 4)
--create reference (required for Photoshop saves)
set new_file_reference to (a reference to file new_file_location)
my logMe("¢ File Reference Created", 4)
--save and close file
save current document appending lowercase extension as JPEG in new_file_reference with options {embed color profile:false, format options:optimized, quality:JPEG_quality}
close current document
my logMe("¢ Save Completed", 3)
--set completed file label to green
tell application "Finder" to set label index of (item i of g_dropped_items) to 6
end tell
on error
activate
display alert file_name message "Unable to process this file, it will be skipped. Report problem to Kevin (x7060)."
--set uncompleted file label to red
tell application "Finder" to set label index of (item i of g_dropped_items) to 2
end try
end repeat
logMe("processFiles Ended", 0)
quit application
end processFiles