-- Created by PhilHints - 2010. No re-publication without permission. global _alias, _aliasWithoutExtension, _dimensions, _rotation, _name, _nameExtension, _nameText, _imageType, _imageType2, _button, _atd, _textItems, _selection, _countOfSelection, _oldSelection, _newSelection, _container, _containerText, _answer, _pathToDesktop, _uPadOriginalImages, _delete_uPadOriginalImages, _formats, _conversionFormats, _selection2, _resolution, _colorSpace, _ratio, _pixels, _rotation, _width, _height, _colour, _colourList, _ratioToLongestSideCutOffPoint, _scalingLongestSide, _cropPadMaximumSize, _growlImage set _atd to "" -- For applescript's text item delimiters set _pathToDesktop to path to desktop set _delete_uPadOriginalImages to true -- Change this to false to keep the original images on the Desktop set _formats to {"jpeg", "jpg", "jp2", "png", "bmp", "tiff", "tif", "pdf", "pct", "PICT", "psd", "gif"} -- Formats that can be read - "QuickTime Image", "sgi", "MacPaint", "Photoshop" MIGHT work - I haven't tested any of these though… set _conversionFormats to {"jpeg", "jpg", "jp2", "png", "bmp", "tiff", "pct", "PICT", "psd"} -- Image Events can convert to these formats set _colour to "black" -- Default colour for padding images, if you change this, you might need to make a new _colourList (search for it) -- These limits help avoid overloading Image Events too much. Change them if they don't suit you. set _ratioToLongestSideCutOffPoint to 20 -- Value after which scaling is done by longest side instead of ratio set _scalingLongestSide to 5000 -- Longest side possible when scaling set _cropPadMaximumSize to 8000 -- longest side when cropping/padding set _answer to "" -- Text field text set _button to "" -- Window button value set _selection2 to {} -- Used if the selection is one folder -- Start routine _selectionProcess() on _selectionProcess() -- Checks the selection in Finder tell application "Finder" set _selection to selection if _selection = {} then return display dialog "Getting the files, please wait…" with title "uPad" buttons {"OK"} default button "OK" giving up after 1 activate set _container to container of item 1 of _selection set _containerText to _container as text set _checkAlias to item 1 of _selection as alias if (count of _selection) = 1 and kind of _checkAlias = "folder" then -- Gets files in one folder set _selection2 to _selection set _selection to every item of _checkAlias set _containerText to _checkAlias as text repeat with _item in _selection set _checkAlias to _item as alias set _checkExtension to name extension of _checkAlias if _checkExtension is in _formats then exit repeat -- Gets the first file that can be manipulated end repeat else repeat with i from 1 to count of _selection set _checkAlias to item i of _selection as alias set _checkExtension to name extension of _checkAlias if _checkExtension is in _formats then exit repeat -- Gets the first file that can be manipulated end repeat end if set _countOfSelection to count of _selection if _checkExtension is not in _formats then -- None of the selected files are valid images! -- Exits the script display dialog "Not a valid selection..." with title "uPad" buttons "Cancel" default button 1 without giving up after end if set _growlImage to _checkAlias -- If you use Growl… end tell activate tell application "Image Events" launch -- Use Image Events to get info about the FIRST useable image… set _image to open _checkAlias try set _name to displayed name of _checkAlias set _dimensions to dimensions of _image set _imageType to (file type of _image) as text set _resolution to resolution of _image set _imageType2 to kind of _checkAlias set _colorSpace to (color space of _image) as text close _image on error a number b close _image end try end tell -- For the variables below, I couldn't get good text strings without launching the script from AppleScript Editor, so this cleans them up… set AppleScript's text item delimiters to {"*", "»"} if (count of text items of _imageType) > 1 then set _imageType to text item -2 of _imageType if (count of text items of _colorSpace) > 1 then set _colorSpace to text item -2 of _colorSpace set AppleScript's text item delimiters to "" set _imageType to _imageType as text if _imageType = "PNGf" then set _imageType to "PNG" if _imageType = "" then set _imageType to _imageType2 set _colorSpace to _colorSpace as text _masterRoutine(_answer) end _selectionProcess on _masterRoutine(_textFieldTextForMainMenu) _mainMenu(_answer) if _answer is in {"q", "quit"} then -- Exit the script tell application "Finder" to activate return end if if _answer is in {"i", "info", "information"} then -- Information panel _displayButtons("CAUTION: Original images are put in the Trash! Scale: Enter one number. A number greater than " & (_ratioToLongestSideCutOffPoint - 1) & " becomes the longest side in pixels. Smaller than " & _ratioToLongestSideCutOffPoint & " scales the image by ratio. uPad will allow images up to " & _scalingLongestSide & " pixels on any side. Rotate: Any number above -360 and below 360 will work. When rotating by values other than multiples of 90, the image area will increase and there could be a lot of padding. Crop / Pad: '640x480' and '640 x 480' both work. Values higher than the image dimensions will pad the image. " & _cropPadMaximumSize & " pixels on the longest side is the maximum crop / pad. Padding colour will vary with format, so experiment! The default pad colour for JPGs is " & _colour & ". To use white, '640x480xwhite' and '640x480x white' both work. Valid colour presets are: red, blue, green, black, white and grey. Alternatively make any colour using the form '640x480x{65535, 0, 65535}' (This makes purple.) PDFs always pad in white. ORIGINAL PNG/TIFF/PSD/GIFs pad transparently. Convert: Type an image file extension to convert images. Valid inputs are: png, jpg, jp2, pct, bmp, tiff, and psd. ANY BUTTON works for this. Be careful when making big images, the 'sips' process can use a lot of memory and CPU, which can really slow down the system. If in doubt, try changing one image first before changing a big batch. Open Activity Monitor and force quit process 'Image Events' if you have big problems. Selecting multiple files works. If one folder is selected, uPad will act on every image in that folder. Acting on multiple folders is not possible. uPad will pass over non-image files without changing them. If a mistake is made, the original image will be in the Trash.", "uPad", {"Cancel", "Return"}, "Return", false) _masterRoutine(_answer) end if _MasterManipulationHandler(_answer, _button) _finish() end _masterRoutine on _mainMenu(_textFieldText) -- Generates the user window set {_fileText, _oneFileWarning} to {"files", "ONE of the files... "} set _answerText to _answer try if _countOfSelection = 1 then set {_fileText, _oneFileWarning} to {"file", ""} if _textFieldText = "" then set _answerText to "" & (item 1 of _dimensions as integer) & " x " & (item 2 of _dimensions as integer) -- Displays info for the FIRST useable image from the Finder selection… _displayDialog("Processing " & _countOfSelection & " " & _fileText & " CAUTION: Original images are put in the Trash! " & _oneFileWarning & "Name: " & _name & " Image type: " & _imageType & " Dimensions: " & (item 1 of _dimensions as integer) & " x " & (item 2 of _dimensions as integer) & " Resolution: " & (item 1 of _resolution as integer) & " x " & (item 2 of _resolution as integer) & " Color space: " & _colorSpace & " Enter 'q' to quit, enter 'i' for information, enter an extension to convert formats, e.g. 'png'. (Any button works for these.)", "uPad", _answerText, {"Scale", "Rotate", "Crop / Pad"}, 1, false) on error o number p -- Image Events can't read PICT files properly? try _displayDialog("Processing " & _countOfSelection & " files CAUTION: Original images are put in the Trash! " & _oneFileWarning & "Name: " & _name & " Image type: " & _imageType2 & " Enter 'q' to quit, enter 'i' for information, enter an extension to convert formats, e.g. 'png'. (Any button works for these.)", "uPad", _answerText, {"Scale", "Rotate", "Crop / Pad"}, 1, false) on error q number r set AppleScript's text item delimiters to _atd if r = -128 then return display dialog "Not a valid image..." with title "uPad" buttons "Cancel" default button 1 without giving up after return end try end try end _mainMenu on _MasterManipulationHandler(_answerToConvert, _buttonValue) try if _answerToConvert is in {"q", "quit"} then tell application "Finder" to activate return end if if _answerToConvert is in _conversionFormats then set {_button, _buttonValue} to {"Convert", "Convert"} -- No button for convert! -- Main crop / pad conditional if _buttonValue = "Crop / Pad" then _getText("x") _convertTextToValues() -- Add any colours you like here… if _colour = "black" then set _colourList to {0, 0, 0} if _colour = "white" then set _colourList to {65535, 65535, 65535} if _colour = "grey" then set _colourList to {32768, 32768, 32768} if _colour = "red" then set _colourList to {65535, 0, 0} if _colour = "green" then set _colourList to {0, 65535, 0} if _colour = "blue" then set _colourList to {0, 0, 65535} if item 1 of _colour = "{" then -- Looks for an rgb list in this form - {24000,15000,48000} set _rgbStrings to items 2 thru -2 of _colour as text set AppleScript's text item delimiters to "," set _rgbStrings to text items of _rgbStrings set _rgbValues to {(item 1 of _rgbStrings) as integer, (item 2 of _rgbStrings) as integer, (item 3 of _rgbStrings) as integer} set AppleScript's text item delimiters to "" set _colourList to _rgbValues end if set _width to item 1 of _textItems as integer set _height to item 2 of _textItems as integer if _width ≤ 0 or _height ≤ 0 then error "The crop must be bigger than 0 pixels…" number 1 if _width > _cropPadMaximumSize or _height > _cropPadMaximumSize then error "Sorry, the crop must be less than " & _cropPadMaximumSize & " pixels…" number 1 if _width < 64 or _height < 64 or _width > 5000 or _height > 5000 then -- Big images use a lot of processor / memory set _d to display dialog "Are you sure you want to crop to " & _width & " x " & _height & " pixels? That's quite extreme!" with title "uPad: Crop / Pad" buttons {"Error", "OK"} default button 2 if button returned of _d = "Error" then error "User cancelled…" number 1 end if end if -- "Crop / Pad" end -- Main "Rotate" conditional if _buttonValue = "Rotate" then set _rotation to _answerToConvert as integer if _rotation is in {0, 0, 360, -360} then error "No need to do anything then!" number 1 if _rotation > 359 or _rotation < -359 then error "Choose a value above -360 and below 360…" number 1 end if -- "Rotate" end -- Main "Scale" conditional if _buttonValue = "Scale" then set _ratio to 0 set _pixels to 0 set _scale to _answerToConvert as real if _scale ≤ 0 then error "Images can't be scaled at 0 or below…" number 1 if _scale = 1 then error "No need to do anything then!" number 1 if _scale > 0 and _scale < _ratioToLongestSideCutOffPoint then -- Scales image by ratio set _ratio to _scale if _dimensions ≠ {} then if ((_ratio * (item 1 of _dimensions)) > _scalingLongestSide) or ((_ratio * (item 2 of _dimensions)) > _scalingLongestSide) then error "Sorry, this will be more than " & _scalingLongestSide & " pixels…" number 1 end if if _ratio < 0.2 or _ratio > 10 then -- Guards against accidental over/undersizing set _d to display dialog "Are you sure you want a " & _ratio & " x image? That's a big change!" with title "uPad: Scale" buttons {"Error", "OK"} default button 2 if button returned of _d = "Error" then error "User cancelled…" number 1 end if end if if _scale ≥ _ratioToLongestSideCutOffPoint then -- Scales the image by longest side set _pixels to _scale if _pixels ≥ _scalingLongestSide then error "Sorry, this will be more than " & _scalingLongestSide & " pixels…" number 1 if _pixels < 64 or _pixels > 3000 then -- Guards against over/undersizing images set _d to display dialog "Are you sure you want " & (_pixels as integer) & " pixels? That's quite extreme!" with title "uPad: Scale" buttons {"Error", "OK"} default button 2 if button returned of _d = "Error" then error "User cancelled…" number 1 end if if {90, 180} contains _pixels then -- Common rotate values set _d to display dialog "Are you sure you don't want to rotate?" with title "uPad: Scale" buttons {"Error", "OK"} default button 2 if button returned of _d = "Error" then error "User cancelled…" number 1 end if end if end if -- "Scale" end -- create originals folder and selection conditional _createTemporaryFolder() set _newSelection to {} if _buttonValue = "Convert" then set _oldSelection to {} -- Conversions need to keep the files in the target folder else set _oldSelection to _selection -- Remember the original selection end if _messageHandler(_button) if _buttonValue ≠ "Convert" then -- One file will result in an alias, not an alias list… tell application "Finder" to set _selection to move _selection to _uPadOriginalImages if (count of _selection) = 0 then set _selection to {_selection} end if -- Repeat loop for selected files repeat with _item in _selection tell application "Finder" set _alias to _item as alias set _nameText to name of _alias set _nameExtension to name extension of _alias if _buttonValue = "Convert" then set _imageExtension to "." & _nameExtension if _buttonValue = "Convert" then set _aliasAsText to _alias as text end tell -- Main "Convert" conditional if _buttonValue = "Convert" then set _imageExtensionCount to count of _imageExtension if (items -1 thru -(_imageExtensionCount) of _aliasAsText) as text = _imageExtension then -- Alias without extension set AppleScript's text item delimiters to "." set _aliasWithoutExtension to text items 1 thru -2 of _aliasAsText set AppleScript's text item delimiters to "" set _aliasWithoutExtension to _aliasWithoutExtension as text else set _aliasWithoutExtension to _aliasAsText -- I'm not sure if alias always has an extension end if tell application "Finder" -- Check for files with same name and same extension as the target extension if (exists of alias (_aliasWithoutExtension & "." & _answerToConvert)) = true and _answerToConvert ≠ _nameExtension then try tell me to set _date to (current date) tell me to set _time to time of _date repeat set _time to _time + 1 if (exists of alias (_aliasWithoutExtension & " " & _time & "." & _answerToConvert)) ≠ true then set _aliasWithoutExtension to _aliasWithoutExtension & " " & _time exit repeat end if end repeat end try end if end tell end if -- "Convert" end -- Image Events _mainImageEventsHandler(_button, _answerToConvert) -- add converted files to new selection if _buttonValue = "Convert" then tell application "Finder" if _formats contains _nameExtension and _answerToConvert ≠ _nameExtension then try set end of _newSelection to alias (_aliasWithoutExtension & "." & _answerToConvert) -- Converted files set end of _oldSelection to _alias -- Files to delete on error a number b set end of _newSelection to _alias end try else set end of _newSelection to _alias -- Unconverted files end if end tell end if end repeat -- Repeat loop for selected files end set _answer to "" -- Delete originals and get selection if _buttonValue ≠ "Convert" then set _selection to _oldSelection if _buttonValue = "Convert" then tell application "Finder" to move _oldSelection to _uPadOriginalImages try if _delete_uPadOriginalImages = true then tell application "Finder" to delete _uPadOriginalImages end try try tell application "Finder" -- Set the selection to the converted files activate open _container delay 1 if _selection2 ≠ {} then set selection to _selection2 else if _buttonValue ≠ "Convert" then set selection to _selection if _buttonValue = "Convert" then set selection to _newSelection end if end tell on error a number b return end try -- Delete originals and get selection end on error a number b set AppleScript's text item delimiters to _atd if a = "Exit the manipulation…" then tell application "Finder" try set _filesToMoveBack to every item of _uPadOriginalImages repeat with _fileToMoveBack in _filesToMoveBack try move _fileToMoveBack to alias _containerText end try end repeat end try open _container delay 1 -- if _button = "Convert" then set selection to _selection if _button ≠ "Convert" then set selection to _oldSelection end tell else try if _delete_uPadOriginalImages = true then tell application "Finder" to delete _uPadOriginalImages end try display dialog a with title ("uPad: " & _buttonValue) default button 2 _masterRoutine(_answer) end if end try end _MasterManipulationHandler on _mainImageEventsHandler(_buttonValue2, _answerToManipulate) tell application "Image Events" -- main images launch if _formats contains _nameExtension then set _image to open _alias try if _buttonValue2 = "Crop / Pad" then try pad _image to dimensions {_width, _height} with pad color _colourList end try end if if _buttonValue2 = "Rotate" then try rotate _image to angle _rotation -- Rotations not in multiples of 90 can increase the image area significantly! end try end if if _buttonValue2 = "Scale" then if _ratio ≠ 0 then try set _dimensions to dimensions of _image if _dimensions = {} then tell me to display dialog "uPad can't scale some images (such as PICT) because the dimensions can't be found - try noting the dimensions in Finder and scaling by longest side." buttons {"OK"} default button "OK" with title "uPad: " & _buttonValue2 error a number b end if if (item 1 of _dimensions) * _ratio > _scalingLongestSide or (item 2 of _dimensions) * _ratio > _scalingLongestSide then tell me to display dialog "An Image has been passed over, it would be more than " & _scalingLongestSide & " pixels on one side." buttons {"OK"} default button "OK" with title "uPad: " & _buttonValue2 giving up after 3 error a number b else scale _image by factor _ratio end if end try end if if _pixels ≠ 0 then try scale _image to size _pixels end try end if end if if _buttonValue2 = "Convert" then set _formatsToSaveAs to {{"jpeg", JPEG}, {"jpg", JPEG}, {"jp2", JPEG2}, {"png", PNG}, {"bmp", BMP}, {"tiff", TIFF}, {"pct", PICT}, {"PICT", PICT}, {"psd", PSD}} -- link extension as text to Image Events property repeat with _formatToSaveAs in _formatsToSaveAs if _formatToSaveAs contains _answerToManipulate then set _formatToSaveAs to item 2 of _formatToSaveAs exit repeat end if end repeat if _answerToManipulate ≠ _nameExtension then save _image as _formatToSaveAs in _aliasWithoutExtension & "." & _answerToManipulate -- Won't save image as the SAME format if result = missing value then delay 1 tell application "Finder" to move _alias to alias _containerText error "uPad didn't manipulate this image - " & _nameText number 1 end if end if end if if _buttonValue2 ≠ "Convert" then save _image in _containerText & _nameText if result = missing value then error "uPad didn't manipulate this image - " & _nameText number 1 end if close _image on error a number b set _errorButton to "" tell me to display dialog a with title "uPad: " & _buttonValue2 buttons {"Exit", "OK"} default button "OK" set _errorButton to button returned of result try try close _image end try if _buttonValue2 ≠ "Convert" then tell application "Finder" to move _alias to alias _containerText end if end try if _errorButton = "Exit" then error "Exit the manipulation…" number 1 end try else if _buttonValue2 ≠ "Convert" then tell application "Finder" to move _alias to alias _containerText end if end tell end _mainImageEventsHandler on _messageHandler(_buttonValue3) set _messages to {{"Convert", "Converting files, please wait…"}, {"Crop / Pad", "Cropping/padding files, please wait…"}, {"Rotate", "Rotating files, please wait…"}, {"Scale", "Scaling files, please wait…"}} repeat with _message in _messages if item 1 of _message = _buttonValue3 then set _messageText to item 2 of _message exit repeat end if end repeat display dialog _messageText with title "uPad: " & _buttonValue3 buttons {"OK"} default button "OK" giving up after 1 end _messageHandler on _getText(_delimiter) -- Uses 'x' to separate the values in the text field set AppleScript's text item delimiters to _delimiter set _textItems to text items of _answer set AppleScript's text item delimiters to _atd end _getText on _convertTextToValues() -- Converts the first one or two text items into numbers try item 1 of _textItems as integer last character of item 1 of _textItems item 2 of _textItems as integer last character of item 2 of _textItems if item 1 of _textItems as integer = 0 or item 2 of _textItems as integer = 0 then error "0 is not a valid input…" number 1 if _button = "Crop / Pad" and (count of _textItems) > 2 then -- When padding, this looks for a pad colour value set _colour to item 3 of _textItems set AppleScript's text item delimiters to " " set _colour to text items of _colour set AppleScript's text item delimiters to "" set _colour to text items of _colour as text end if on error n number m set AppleScript's text item delimiters to _atd error n _masterRoutine(_answer) end try end _convertTextToValues on _displayDialog(_message, _title, _defaultAnswer, _buttons, _defaultButton, _givingUp) set _dialog to display dialog _message with title _title default answer _defaultAnswer buttons _buttons default button _defaultButton giving up after _givingUp set _button to button returned of _dialog set _answer to text returned of _dialog end _displayDialog on _createTemporaryFolder() set _date to (current date) set _time to time of _date tell application "Finder" try set _uPadOriginalImages to make new folder at _pathToDesktop with properties {name:"uPad original images"} on error a number b repeat try set _time to _time + 1 set _uPadOriginalImages to make new folder at _pathToDesktop with properties {name:("uPad original images " & _time)} exit repeat end try end repeat end try end tell end _createTemporaryFolder on _finish() if _answer is in {"q", "quit"} then tell application "Finder" to activate return end if -- Alter this if you have Growl down… (* try tell application "GrowlHelperApp" notify with name "Test" title "uPad" description "Manipulation complete" application name "Growl test" image from location _growlImage sticky no end tell end try *) set AppleScript's text item delimiters to _atd _selectionProcess() -- Launches the main user window again with the new images end _finish on _displayButtons(_message, _title, _buttons, _defaultButton, _givingUp) set _dialog to display dialog _message with title _title buttons _buttons default button _defaultButton giving up after _givingUp end _displayButtons