For anyone who is interested, I solved my problem. There were two main issues involved:
Firstly the fact that I was applying a transform from a large image to a much smaller image, meaning the scale values screwed up everything. I got around this by first transforming my original image and then cropping the result.
Secondly, transforms were all being applied from the top-left corner of the image, whereas the imageView's transform was applying from the center. So to work around that I just had to translate by (width/2, height/2), apply the transformation and then translate back.
Here's the new code:
Code:
CGRect rect = CGRectMake(0, 0, imageView.image.size.width, imageView.image.size.height);
// Begin the drawing
UIGraphicsBeginImageContext(imageView.image.size);
CGContextRef ctx = UIGraphicsGetCurrentContext();
// Clear whole thing
CGContextClearRect(ctx, rect);
// Transform the image (as the image view has been transformed)
CGContextTranslateCTM(ctx, rect.size.width*0.5, rect.size.height*0.5);
CGContextConcatCTM(ctx, imageView.transform);
CGContextTranslateCTM(ctx, -rect.size.width*0.5, -rect.size.height*0.5);
// Tanslate and scale upside-down to compensate for Quartz's inverted coordinate system
CGContextTranslateCTM(ctx, 0.0, rect.size.height);
CGContextScaleCTM(ctx, 1.0, -1.0);
// Draw view into context
CGContextDrawImage(ctx, rect, imageView.image.CGImage);
// Create the new UIImage from the context
UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext();
// End the drawing
UIGraphicsEndImageContext();
// Begin the drawing (again)
UIGraphicsBeginImageContext(cropRect.size);
ctx = UIGraphicsGetCurrentContext();
// Clear whole thing
CGContextClearRect(ctx, CGRectMake(0, 0, cropRect.size.width, cropRect.size.height));
// Translate to compensate for the different positions of the image
CGContextTranslateCTM(ctx, -((newImage.size.width*0.5)-(cropRect.size.width*0.5)),
(newImage.size.height*0.5)-(cropRect.size.height*0.5));
// Tanslate and scale upside-down to compensate for Quartz's inverted coordinate system
CGContextTranslateCTM(ctx, 0.0, cropRect.size.height);
CGContextScaleCTM(ctx, 1.0, -1.0);
// Draw view into context
CGContextDrawImage(ctx, CGRectMake(0,0,newImage.size.width,newImage.size.height), newImage.CGImage);
// Create the new UIImage from the context
newImage = UIGraphicsGetImageFromCurrentImageContext();
// End the drawing
UIGraphicsEndImageContext();