Search for scaling an image and google will return several useful answers. Most example code involves a category on UIImage that returns the modified (scaled) image. For example the linked code found on stackoverflow.com shows the basic approach most used:
@interface UIImage (ScalingAdditions)
- (UIImage *) imageScaledToSize:(CGSize)targetSize;
@end
@implementation UIImage (ScalingAdditions)
- (UIImage *) imageScaledToSize:(CGSize)targetSize {
UIImage *newImage = nil;
UIGraphicsBeginImageContext(targetSize);
// ... do your image processing here ...
// CGContextRef ctx = UIGraphcisGetCurrentContext();
// CGContextFillRect(ctx, CGRectMake(0, 0, 10, 10));
newImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return newImage;
}
@endI've used code just like this multiple times, without much problems. Resizing an image (or any graphics operation for that matter) is cpu intensive and takes a little time. The crashes started to appear when I moved the call to - [UIImage imageScaledToSize:] to a background thread to prevent locking up the UI when processing multiple images.
You can't use UIGraphicsBeginImageContext and family from threads other than the main thread!
Somehow this never gets mentioned in the examples I find online. No one interested in batch processing large number of images out there? My advice to anyone who is: start using the CGBitmapContextCreate family of functions to create an offscreen buffer to create image contexts that also work on threads other than the main one.
The way I use this is to create a NSOperation subclass that does the heavy duty processing in the background using a NSOperationQueue. When finished the operation delegate gets notified with the new UIImage object.
My version is listed below (shortened for brievity) Notice the usage of the CGBitmapContextCreate to set up the offscreen buffer:
#pragma mark -
#pragma mark Interface
@class JKImageOperation;
@protocol JKImageOperationDelegate <NSObject>
- (void) imageOperation:(JKImageOperation *)op didFinishWithImage:(UIImage *)image;
@end
@interface JKImageOperation : NSOperation {
id<JKImageOperationDelegate> delegate;
}
@property(nonatomic, assign) id<JKImageOperationDelegate> delegate;
@end
#pragma mark -
#pragma mark Implementation
@implementation JKImageOperation
@synthesize delegate;
- (void) main {
CGSize imageSize = CGSizeMake(/* width, height */);
UIImage *newImage = nil;
void *data = malloc(imageSize.width * imageSize.height * 4);
CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
CGContextRef ctx = CGBitmapContextCreate(data,
imageSize.width,
imageSize.height, 8,
imageSize.width*4,
colorSpace,
kCGImageAlphaPremultipliedLast
);
CGColorSpaceRelease(colorSpace);
// ... do your image processing here ...
// CGContextFillRect(ctx, CGRectMake(0, 0, 10, 10));
CGImageRef image = CGBitmapContextCreateImage(ctx);
UIImage *returnImage = [UIImage imageWithCGImage:image];
CGImageRelease(image);
// notify self delegate
if (delegate) {
NSInvocation *invocation = /*invocation to delegate method and target */;
// set parameters on invocation
[invocation performSelectorOnMainThread:@selector(invoke)
withObject:nil
waitUntilDone:YES];
}
CGContextRelease(ctx);
free(data);
}
@end