So I have over 4000 images that I need to square, and I dont want to stretch them. I want to open the image, check the width or height, then use the largest value as a variable in sips.
here is my script so far
--Open image
set this_file to choose file without invisibles
tell application "Image Events"
-- start the Image Events application
launch
-- open the image file
set this_image to open this_file
--Get width Height
copy dimensions of this_image to {W, H}
--What is the biggest?
if W is greater than H then
set padding_dimensions to H
else
set padding_dimensions to W
end if
--pass to sip
do shell script "/usr/bin/sips " & this_image & "-p " & padding_dimensions & padding_dimensions & " --padColor FFFFFF " & this_image
end tell
It runs right up to the sips bit. Then I get this error
I am sure I have do some POSIX stuff, but I am a bit stuck.
Classes
To terminal you may send only text. So, you must convert it to text. Analyze first line of my script.
Posix path.
Even after conversion to text, the path notation is not readable by terminal sips or any shell program. You must convert it to POSIX notation. Analyze second line.
Quoted form.
If you send a text command to sips or any terminal program, be aware to spaces in paths. Just because, the spaces is used to separate parameters in command line. To avoid this, put the paths in quote. Analyze create sips command line.
Spaces are necessary in commands
In your scripts, the words: “& padding_dimensions & padding_dimensions” create one big number. Put spaces between with & operand: & padding_dimensions & " " & padding_dimensions &
Return
Last line of my script saves sips response to text variable. You may use this for error catching.
And, for readability, put sips commands outside the tell block.
Here is my working script:
set this_file to (choose file without invisibles) as text
set Posix_filepath to (POSIX path of this_file)
tell application "Image Events"
-- start the Image Events application
launch
-- open the image file
set this_image to open this_file
--Get width Height
copy dimensions of this_image to {W, H}
--What is the biggest?
if W is greater than H then
set padding_dimensions to H
else
set padding_dimensions to W
end if
end tell
-- create sips command.
set sipscommand to "/usr/bin/sips " & quoted form of Posix_filepath & " -p " & padding_dimensions & " " & padding_dimensions & " --padColor FFFFFF " & quoted form of Posix_filepath
--pass to sip
set sipsanswer to do shell script sipscommand as text
The script you posted actually uses the smaller dimension, not the larger!
Image Events is essentially an AppleScript interface for sips. It provides a ‘pad’ command, so you could avoid multiple file-specifier types and the ‘do shell script’ overhead by staying with it:
set this_file to (choose file without invisibles)
tell application "Image Events"
-- start the Image Events application
launch
-- open the image file
set this_image to (open this_file)
--Get width Height
set {W, H} to dimensions of this_image
--What is the biggest?
if (W is greater than H) then
set padding_dimensions to W
else
set padding_dimensions to H
end if
pad this_image to dimensions {padding_dimensions, padding_dimensions} with pad color {65535, 65535, 65535} -- Pad with white.
save this_image -- This saves the edited image back to the original file, but it's possible to specify another destination.
close this_image -- Close the image afterwards to clear it from memory.
quit -- Quit Image Events afterwards for the same reason.
end tell
If you’ve got over 4000 images to process, you won’t want to run the script individually for each one, but repeat through a list of aliases between the ‘launch’ and ‘quit’ commands:
-- Somehow get a list of aliases to the image files. (Arrange this according to your own circumstances.)
set image_folder to (choose folder without invisibles)
tell application "Finder" to set image_files to (files of image_folder whose name ends with ".jpg") as alias list
tell application "Image Events"
-- start the Image Events application
launch
repeat with this_file in image_files
-- open the image file
set this_image to (open this_file)
--Get width Height
set {W, H} to dimensions of this_image
--What is the biggest?
if (W is greater than H) then
set padding_dimensions to W
else
set padding_dimensions to H
end if
pad this_image to dimensions {padding_dimensions, padding_dimensions} with pad color {65535, 65535, 65535} -- Pad out the smaller dimension with white.
save this_image -- This saves the edited image back to the original file, but it's possible to specify another destination.
close this_image -- Close the image afterwards to clear it from memory.
end repeat
quit -- Quit Image Events afterwards for the same reason.
end tell
beep 2
display dialog "Finished!" buttons {"OK"} default button 1 with icon note
Yugh! You’re right. And even my example Finder code for getting the list of aliases times out when there’s a really large number of files.
The version below incorporates weedinner’s ‘quit’ idea from the other thread, but only quits and relaunches Image Events after every tenth image processed. On my machine, it gets through a test folder of 6592 JPEGs in just over 36 minutes, including the time taken by the progress beeps:
on main()
script o
property image_paths : missing value
end script
-- Get a list of POSIX paths to the image files. (Arrange this according to your own circumstances.)
set image_folder to (choose folder without invisibles)
set o's image_paths to paragraphs of (do shell script ("find " & quoted form of POSIX path of image_folder & " \\( -type f -name '*.jpg' \\)"))
tell application "Image Events" to launch
repeat with i from 1 to (count o's image_paths)
set this_file to POSIX file (item i of o's image_paths)
tell application "Image Events"
-- open the image file
set this_image to (open this_file)
--Get width Height
set {W, H} to dimensions of this_image
--What is the biggest?
if (W is greater than H) then
set padding_dimensions to W
else
set padding_dimensions to H
end if
pad this_image to dimensions {padding_dimensions, padding_dimensions} with pad color {65535, 65535, 65535} -- Pad out the smaller dimension with white.
save this_image -- This saves the edited image back to the original file, but it's possible to specify another destination.
close this_image -- Close the image afterwards to clear it from memory.
end tell
-- After every tenth image, beep to indicate progress and quit and relaunch Image Events.
if (i mod 10 is 0) then
beep
tell application "Image Events" to quit
tell application "System Events"
repeat while (application process "Image Events" exists)
delay 0.2
end repeat
end tell
tell application "Image Events" to launch
end if
end repeat
tell application "Image Events" to quit
end main
main()
This one, using a single ‘do shell script’ for each image instead of Image Events, is about four minutes faster with an identical folder:
on main()
script o
property image_paths : missing value
end script
-- Get a list of POSIX paths to the image files. (Arrange this according to your own circumstances.)
set image_folder to (choose folder without invisibles)
set o's image_paths to paragraphs of (do shell script ("find " & quoted form of POSIX path of image_folder & " \\( -type f -name '*.jpg' \\)"))
repeat with i from 1 to (count o's image_paths)
set this_path to quoted form of item i of o's image_paths
do shell script ("w=$(sips -g pixelWidth " & this_path & " | egrep -o '\\d+$');
h=$(sips -g pixelHeight " & this_path & " | egrep -o '\\d+$');
padding_dimensions=$(echo \"$w\\n$h\" | sort -n | sed -n '$ p');
sips -p $padding_dimensions $padding_dimensions --padColor FFFFFF " & this_path)
if (i mod 10 is 0) then beep
end repeat
end main
main()
I’m sure seasoned shell scripters will know a better way to identify the larger dimension than the sort-sed sequence I’ve used here, but I don’t know it myself.