As part of a larger project, I was faced with the mini challenge of cropping a UIImage. Seems like a straightforward thing to do (and in fact, it was when I’d finished looking into various ways of doing it).
My requirement was to take an existing UIImage and crop off the top section of the image. To the left, you should see a poor diagram of the crop I wanted to make. The green area (the full size of the image) is my original image, weighing in at 320 pixels by 480 pixels. The red area is the area I wanted to be left with, which was to be 320 pixels by 430 pixels (a cutting of 50 pixels off the top!). Lets do it!
CROPPING THE IMAGE
First I started by pulling the image into a UIImage object. For the purposes of this demo, lets assume you have an image called myimage.png already in your project and this image is 320px wide by 480px tall…
// Grab our original image UIImage *originalImage = [UIImage imageNamed:@"myimage.png"];
Nothing too difficult there. Okay, so now I need to define the bounds which my new image will use. What I wanted to do was chop a chunk off the top of the image – lets say 50px or so. So I go ahead and create a CGRect which holds the offset for the crop of the image (X and Y) and the width / height…
// Make a new bounding rectangle including our crop CGRect newSize = CGRectMake(0.0, 50.0, 320.0, 430.0);
So you see we create our rect, but notice that the offset is 50 pixels down and (not surprisingly) 430 pixels in height (the original image minus the 50 pixels we want to chop). Now that I know what my original image was, and what I want it to be – I use the quartz API to create a new image reference, using the new size and my original image. Of course, when I try to put my original image into this space – it doesn’t fit, so the top gets cropped as per our setting…
// Create a new image in quartz with our new bounds and original image CGImageRef tmp = CGImageCreateWithImageInRect([originalImage CGImage], newSize);
Now that we have the new image, all cropped up – we put it back into a UIImage object so we can use it (and of course, we release the memory we used with the quartz object…
// Pump our cropped image back into a UIImage object UIImage *newImage = [UIImage imageWithCGImage:tmp]; // Be good memory citizens and release the memory CGImageRelease(tmp);
And that’s all there is to it. You’ve now got your new image, cropped and ready. Simple pimple. Just for completeness, here is the full code to crop the image (all five lines of it… whoop).
// Grab our original image UIImage *originalImage = [UIImage imageNamed:@"myimage.png"]; // Make a new bounding rectangle including our crop CGRect newSize = CGRectMake(0.0, 50.0, 320.0, 430.0); // Create a new image in quartz with our new bounds and original image CGImageRef tmp = CGImageCreateWithImageInRect([originalImage CGImage], newSize); // Pump our cropped image back into a UIImage object UIImage *newImage = [UIImage imageWithCGImage:tmp]; // Be good memory citizens and release the memory CGImageRelease(tmp);
SAVING THE IMAGE
(an after-post edit!)
As a thought, I figured it would also be useful to know as part of this tutorial how to save the file to the documents directory. Lets face it, you probably don’t want to be making these crops all the time. Here’s how you can save your image…
// Get the application documents directory NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES); NSString *documentsDirectory = [paths objectAtIndex:0]; // Create a filename string with the documents path and our filename NSString *fileName = [documentsDirectory stringByAppendingPathComponent:@"mynewimage.png"]; // Save image to disk [UIImagePNGRepresentation(newImage) writeToFile:fileName atomically:YES];
The above doesn’t take much explanation really – we pluck out the documents directory path (as if by magic), add our filename to the end of it – then use UIImagePNGRepresentation to sore the image to disk. Job done!