Resize/Scale of an Image – Take 1 – Using an Objective-C Category

November 11, 2009

Editor’s Note: Part 2 of this post Resize/Scale of an Image – Take 2 – Thread Safe Approach takes this idea to the next level, showing how to dynamically resize images using thread safe code.

Given how common it is to scale an image within an application, it’s surprising (at least to me) that such a method is not included in the UIImage class. Let’s go ahead and take care of this omission by adding a simple method which will provide a means to scale an image.

We’ll use an Objective-C category to add a method to the UIImage class. I covered categories in this post. No question, categories are your friend, as they are very handy in cases such as this, where you would like to add functionality to an existing class.

Defining the UIImage Scale Category

To add a method to the UIImage class, there are two steps we need to take care in the interface defintion. First, create an interface definition for UIImage and add a category name inside a set of parenthesis after the interface declaration. Second, create the method declaration. An example follows:

//  UIImage+Scale.h
 
@interface UIImage (scale)
 
-(UIImage*)scaleToSize:(CGSize)size;
 
@end
Implementation UIImage Scale Category

With the interface in place, let’s write the code for the method that will be added to the UIImage class.

//  UIImage+Scale.h
 
#import "UIImage+Scale.h"
 
@implementation UIImage (scale)
 
-(UIImage*)scaleToSize:(CGSize)size
{
  // Create a bitmap graphics context
  // This will also set it as the current context
  UIGraphicsBeginImageContext(size);
 
  // Draw the scaled image in the current context
  [self drawInRect:CGRectMake(0, 0, size.width, size.height)];
 
  // Create a new image from current context
  UIImage* scaledImage = UIGraphicsGetImageFromCurrentImageContext();
 
  // Pop the current context from the stack
  UIGraphicsEndImageContext();
 
  // Return our new scaled image
  return scaledImage;
}
 
@end
Using the UIImage Scale Method

Calling the new scale method we added to UIImage is as simple as this:

#import "UIImage+Scale.h"
 
...
 
// Create an image
UIImage *image = [UIImage imageNamed:@"myImage.png"];
 
// Scale the image
UIImage *scaledImage = [image scaleToSize:CGSizeMake(25.0f, 35.0f)];

13 comments

That’s awesome, I was in the middle of building an iPhone application that required just that. Thanks so much for the tip!

by Poseidon on Nov 11, 2009. Reply #

This is awesome! thanks. I did get a warning that uiimage might not responde to scaleToSize (everything worked despite the warning). I was able to get rid of the warning by importing the uiimage+scale.h file to the .m file where I was using the function.

by Martin on Nov 15, 2009. Reply #

Good catch Martin, I’ve added the import to the code example above.

Thanks

by John Muchow on Nov 15, 2009. Reply #

Just be aware that this code is not thread safe, since it depends on the global current context… If you would like code that is thread safe (and unfortunately a bit more complex ;) I could post that

Coop

by Coop on Jan 21, 2010. Reply #

Hey Coop,

Thanks for the heads up and code example…

Readers: if you would like to read/download the thread safe example, check out part 2 of this post here: How to Resize/Scale and Image using Thread Safe Code.

by John Muchow on Jan 21, 2010. Reply #

This is works great but I have showing memory leaks in Instruments when I call this code. But maybe it is the way I call it:

- (UIImage *) getImageForIndex:(NSIndexPath *)indexPath {

NSInteger row = [indexPath row];
NSInteger section = [indexPath section];

CSLewisTriviaAppDelegate *appDelegate = (CSLewisTriviaAppDelegate *)[[UIApplication sharedApplication] delegate];
NSDictionary *itemAtIndex = (NSDictionary *)[[appDelegate dataController] objectInCategoryArrayAtIndex:section];
NSString *categoryName = [itemAtIndex objectForKey:@"name"];
Resources *tempResourcesObject = [[appDelegate dataController] returnResourcesObject];

NSDictionary *bonusInfoLinksResourceDict = [tempResourcesObject getResourceImageAndTitle:categoryName row:row];

NSDictionary *resourceDictionary = [self returnResourceDictionary:bonusInfoLinksResourceDict indexPath:indexPath];

// nothing found
if (resourceDictionary == nil) {
return nil;
}

UIImage *image = [UIImage imageNamed:[resourceDictionary objectForKey:@"image"]];
image = [image scaleToSize:CGSizeMake(80.0f, 100.0f)];

return image;
}

by Brian on Mar 16, 2010. Reply #

Brian, have you tried to retain the image before returning it ?

by John Muchow on Mar 17, 2010. Reply #

Of course! I did go back and review memory management to see where my misunderstanding was. I ended up adding the retain and then an autorelease so that the caller doesn’t have to worry about releasing it:

- (UIImage *) getImageForIndex:(NSIndexPath *)indexPath {

image = [image scaleToSize:CGSizeMake(80.0f, 100.0f)];
[image retain];
return [image autorelease];
}

This clears up the problem in Instruments. Thanks!

by Brian on Mar 17, 2010. Reply #

Really laconic and nice code. Thank you very much.

by Slava on Jan 25, 2011. Reply #

Does this method will use the same amount of memory if I load a ‘thumbnail’ from the image that I want to resize?

by Bruno on May 27, 2011. Reply #

Thanks for sharing this useful post!

by BlackBook on Aug 10, 2011. Reply #

Thanks a lot! I was looking just for this and I’m still a nooby in CoreGraphics.

by ricard.perez on Sep 5, 2011. Reply #

Wow, that is really cool. Very clever and handy way to scale images! I adopt it :)

by Nicolas Embleton on Feb 24, 2012. Reply #

Leave a Comment