4. Appendix: Going Further
4.1 Write Image-Manipulation Scripts with Cocoa
There are many useful things that can be done with Cocoa classes inside Ruby scripts. Here’s another simple example. I recently wanted to size some Photo Booth pictures down by 50%. With Ruby and RubyCocoa it was easy to get Cocoa to do the work for me.
require 'osx/cocoa' # magic to prevent a Cocoa warning when this is run from the command line # is this a "bug" (Apple's problem) or "abuse of the framework" (mine)? OSX::NSApplication.sharedApplication # use Ruby's open classes to add some new features to NSImage class OSX::NSImage def writeJPEG(filename) bits = OSX::NSBitmapImageRep.alloc.initWithData(self.TIFFRepresentation) data = bits.representationUsingType_properties(OSX::NSJPEGFileType, nil) data.writeToFile_atomically(filename, false) end def copyAndScale(factor) newWidth, newHeight = size.width*factor, size.height*factor newImage = OSX::NSImage.alloc.initWithSize [newWidth, newHeight] newImage.lockFocus drawInRect_fromRect_operation_fraction( [0, 0, newWidth, newHeight], [0, 0, size.width, size.height], OSX::NSCompositeSourceOver, 1.0) newImage.unlockFocus newImage end end def resizeImage(sourceFileName, scaledFileName) sourceImage = OSX::NSImage.alloc.initWithContentsOfFile(sourceFileName) scaledImage = sourceImage.copyAndScale 0.5 scaledImage.writeJPEG scaledFileName end resizeImage("image.jpg", "half-sized.jpg")
% ruby resize.rb 2006-06-29 08:06:40.372 ruby[536] _NXCreateWindow: error setting window property (1002) 2006-06-29 08:06:40.390 ruby[536] _NXTermWindow: error releasing window (1002)
I found a discussion of the problem on codecomments.com. Apparently, the AppKit code is a bit tangled, and it is necessary to have access to the window server to use NSImage. The needed initialization occurs when we call sharedApplication. Obvious? The discussion also contained an interesting comment by a Cocoa programmer: “Learning to program sometimes resembles blindly groping in dark.” To me, that’s a big disadvantage of working with a closed-source framework like Cocoa. Using Ruby to write quick scripts and explore interactively helps a lot, but doesn’t eliminate the problem.
Did you find an error? Is something missing? Post your comment or suggestion below!
Comments (1) post
Thanks for the tip. I had the same warnings when using App Kit from a non-GUI app written in C. The following function call probably does the same trick but is a bit more obvious what is happening. (And it is documented by Apple) NSApplicationLoad();