iPhone Developer Tips Visitor Stats: 126,691 Pageviews and 94,296 visitors in the past 30 days.
|
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)];
Share with iOS Developers:
Comments
8 Responses to “Resize/Scale of an Image – Take 1 – Using an Objective-C Category”
Leave Comment
That’s awesome, I was in the middle of building an iPhone application that required just that. Thanks so much for the tip!
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.
Good catch Martin, I’ve added the import to the code example above.
Thanks
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
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.
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;
}
Brian, have you tried to retain the image before returning it ?
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!