For the past couple years, I’ve been using the Python CoreGraphics bindings to do some of my image manipulation. While a bit more complex than I would have liked for setup (dealing w/ context rotations and other scaling math was a bit of the pain), it otherwise worked great (and more importantly, right out of the box) on Leopard. Unfortunately, with Snow Leopard, the CoreGraphics library was unceremoniously (as far as I know, without any sort of announcement or acknowledgement) deprecated. It’d only work in 32-bit mode and more troubling, certain Context calls that used to take floats now required CGFloats. Not so much of a problem… besides the fact that even after much research and poking, I found no way to instantiate a CGFloat (there’s an undocumented CGFloatArray call, but that just gives you uninitialized CGFloats w/o a good way to assign them).
As has been the trend, I’ve been isolating/switching more and more of my code from anything that touches Apple libraries. I’ve come to the conclusion that they just don’t give a shit about breaking your code (much less care about fixing or even responding what they’ve broken). It’s incredibly off-putting. In this case, it’s unfortunate, as the CoreGraphics code performs much better than both PIL and ImageMagick (I would have tested GraphicsMagick as well, but it doesn’t support the chaining features I needed for my particular resizing/layout operations).
CoreGraphics Python w/ kCGInterpolationHigh real 0m1.885s user 0m1.456s sys 0m0.400s PIL w/ Bilinear Filter Resize real 0m3.380s user 0m2.981s sys 0m0.365s 32-bit Static ImageMagick real 0m7.125s user 0m9.730s sys 0m0.652s 32-bit Static ImageMagick w/ Box Filter Resize real 0m4.237s user 0m4.438s sys 0m0.636s 64-bit Shared ImageMagick real 0m6.080s user 0m8.495s sys 0m0.366s 64-bit Shared ImageMagick w/ Box Filter Resize real 0m3.268s user 0m3.599s sys 0m0.331s
A few things worth noting:
- I try to use the system Python. After all the problems w/ 10.5->10.6 though, I am reconsidering.
- PIL seemed to easy_install well (w/ a binary egg no less) on my 10.6 – I’ll have to test on a clean system to make sure I hadn’t made my life easier w/ MacPorts or something, but this is a huge improvement over the problems surrounding installing PIL on 10.5, which was what actually drove me to use the CoreGraphics Python library in the first place. UPDATE: on a clean 10.6 install, it compiles, but doesn’t have JPEG or FreeType support. waah wahhh
- ImageMagick defaults to Lanczos filtering by default, which is quite slow. Testing out various filters, Box filtering was about twice as fast and for my test images had neglible-to-nonexistent image quality differences even under the loupe. Definitely worth poking around a bit if you’re trying to get better performance.
- The 64-bit shared lib version of ImageMagick is fair bit faster than the 32-bit static version. Until I’m all on 64-bit hardware, is a bit of a moot point to do further testing though. I’m assuming the extra sys time is due to the staticness and the remainder is due to 64-bitness.
- Given roughly equivalent performance between PIL and ImageMagick, I’ll be going with ImageMagick for the additional flexibility/features it provides.
- Although it doesn’t work for this particular set of operations, I wanted to mention that Marc Lyniage’s CoreImageTool is just a wicked, wicked piece of software. It of course has all the CoreImage caveats though, especially if you have to deal with Intel’s crappy GPUs (*fist shaking*)