Image Events Resize

Hey,

It was simple enough to make a script to resize an image using Image Events but I find I need
to resize images in both the vertical and horizontal dimensions…which is where I’m
having trouble getting anything to work.

I need a fixed final size of 460 x 300 regardless of the dimensions of the original.
I realize this will distort some images but that’s fine for my purpose.
Not really cropping the image at all, just forcing it to new dimensions.

So far I have:

set fs to "/Library/Application Support/Perceptive Automation/Images/Sonos/Living Room_art.jpg"


property pngFile : "/Library/Application Support/Perceptive Automation/Indigo 6/IndigoWebServer/images/controls/variables/photo+sonos.png"
property targetSize : 460

tell application "Image Events"
	launch
	set theImageReference to open fs
	-- create the png file
	scale theImageReference to size targetSize
	save theImageReference as PNG in pngFile with icon
	close theImageReference
end tell

Any help getting this to work would be greatly appreciated!

Thanks,

Carl

Hi ckeyes888,

What if you rotate the image, then scale? This might scale by height. Then rotate it back.

Edited: that doesn’t work. I forgot what app I used to script to scale both height and width with distortion.

gl,
kel

Hi.

Image Events scales the longer dimension to the target size and scales the shorter one proportionately. You can scale the shorter dimension to a particular size by calculating what the longer one needs to be scaled to to get the required result, but you can’t change the ratio between the dimensions.

Preview can scale without proportion if you want to use ui scripting.

That all makes sense. Have to look into scripting Preview.
Odd that Image Events lacks that ability.

Thanks a bunch!

Carl

It looks like you can do it with NSImage also from Cocoa-AppleScript.

And possibly with “sips” in shell script.

So far sips looks the most promising. Having a hard time understanding how to make it resize a file
in one directory and save it with a new name in another directory.

Thanks,

Carl

Yes, although it’s a bit more complex than cropping. You basically make a new bitmap of the required size (using one of the longest Cocoa methods there is), and draw from the original bitmap into it. This is untested, but should work:

script scalePic
	set {thisFile, exportFile, theWidth, theHeight} to current application's NSApp's passedValue() as list
	set theImage to current application's NSImage's alloc()'s initWithContentsOfFile_(thisFile)
	set {width:x1, height:y1} to theImage's |size|() -- get size
	-- make new bitmap rep 
	set newRep to current application's NSBitmapImageRep's alloc()'s initWithBitmapDataPlanes_pixelsWide_pixelsHigh_bitsPerSample_samplesPerPixel_hasAlpha_isPlanar_colorSpaceName_bitmapFormat_bytesPerRow_bitsPerPixel_(missing value, theWidth, theHeight, 8, 4, true, false, current application's NSCalibratedRGBColorSpace, current application's NSAlphaFirstBitmapFormat, 0, 32)
	current application's NSGraphicsContext's saveGraphicsState() -- save graphics context state
	current application's NSGraphicsContext's setCurrentContext_(current application's NSGraphicsContext's graphicsContextWithBitmapImageRep_(newRep)) -- set current graphics context to new image rep
	theImage's drawInRect_fromRect_operation_fraction_({origin:{x:0, y:0}, |size|:{width:theWidth, height:theHeight}}, current application's NSZeroRect, current application's NSCompositeSourceOver, 1.0) -- draw from old rep into graphics context
	current application's NSGraphicsContext's restoreGraphicsState() -- restore graphics state
	set theData to newRep's representationUsingType_properties_(current application's NSJPEGFileType, {NSImageCompressionFactor:0.9})
	theData's writeToFile_atomically_(exportFile, true)
end script

set thisFile to POSIX path of "Macintosh HD:Users:TL:desktop:Ski Images:whitefishT.jpg"
set exportFile to POSIX path of "Macintosh HD:Users:TL:desktop:Ski Images:whitefish.jpg"
set theWidth to 460
set theHeight to 300
tell application "ASObjC Runner" to run the script {scalePic} passing {thisFile, exportFile, theWidth, theHeight}

Hi Shane,

I didn’t understand what the representation is about, so I just resized the image which seems to work. Don’t know if something is wrong with this.

script resizePic
	set {thisFile, exportFile} to current application's NSApp's passedValue() as list
	set theImage to current application's NSImage's alloc()'s initWithContentsOfFile_(thisFile)
	set newSize to {width:460, height:300}
	theImage's setSize_(newSize)
	set theSize to (theImage's |size|()) as record
	set theHeight to height of theSize
	set theWidth to width of theSize
	set newRect to {{x:0, y:0}, {width:theWidth, height:theHeight}}
	theImage's lockFocus()
	set theRep to current application's NSBitmapImageRep's alloc()'s initWithFocusedViewRect_(newRect)
	theImage's unlockFocus()
	set theData to theRep's representationUsingType_properties_(current application's NSJPEGFileType, {NSImageCompressionFactor:0.9})
	theData's writeToFile_atomically_(exportFile, true)
end script

set thisFile to POSIX path of (choose file)
set exportFile to POSIX path of (choose file name)
tell application "ASObjC Runner" to run the script {resizePic} passing {thisFile, exportFile}

Hope it’s not wasting memory or something.

No, that’s fine. In fact the method I posted is overkill – but you’d use it if, say, you wanted to resize and crop at the same time. (In which case you’d use the rect you want to capture instead of NSZeroRect.)

I think I see it. In my script you can’t crop first then scale.

Thanks,
kel

I believe that will work perfectly. Problem I have is turning up a version of ASObjC Runner that will run in
10.5.8

Many thanks,

Carl

Alas, AppleScriptObjC was introduced in 10.6 – it’s not going to work with anything earlier.

Now I really must get upgraded :slight_smile:

thanks,

Carl

That’s right. The other version is essentially saying take this rectangular part of the original and draw it in another rectangle on the new bitmap, squishing it size and shape. You can use the same technique to blend images, using different compositing operations.

This seems to work, assuming both directories already exist:

property targetW : "460"
property targetH : "300"

set fs to "/Library/Application Support/Perceptive Automation/Images/Sonos/Living Room_art.jpg"
set pngFile to "/Library/Application Support/Perceptive Automation/Indigo 6/IndigoWebServer/images/controls/variables/photo+sonos.png"

do shell script ("sips --setProperty format png --resampleHeightWidth " & targetH & space & targetW & space & quoted form of fs & " --out " & quoted form of pngFile)

Hi Nigel,

Great script. I was a little mixed up at first thinking that the file specification (fs) was the file that is being written to. You were just quoting the original file references.

kel

Hello.

I found This blogpost using Image Magick for resizing and sharpening images. I haven’t come around to use it yet, but here it is in case anybody is interested. You’ll have to install ImageMagick, from Macports, or elsewhere, as Image Magick isn’t included in OS X.