I am using following code in iPhone to get smaller cropped image as follows:
- (UIImage*) getSmallImage:(UIImage*) img
{
CGSize size = img.size;
CGFloat ratio = 0;
if (size.width < size.height) {
ratio = 36 / size.width;
} else {
ratio = 36 / size.height;
}
CGRect rect = CGRectMake(0.0, 0.0, ratio * size.width, ratio * size.height);
UIGraphicsBeginImageContext(rect.size);
[img drawInRect:rect];
UIImage *tempImg = [UIGraphicsGetImageFromCurrentImageContext() retain];
UIGraphicsEndImageContext();
return [tempImg autorelease];
}
- (UIImage*)imageByCropping:(UIImage *)imageToCrop toRect:(CGRect)rect
{
//create a context to do our clipping in
UIGraphicsBeginImageContext(rect.size);
CGContextRef currentContext = UIGraphicsGetCurrentContext();
//create a rect with the size we want to crop the image to
//the X and Y here are zero so we start at the beginning of our
//newly created context
CGFloat X = (imageToCrop.size.width - rect.size.width)/2;
CGFloat Y = (imageToCrop.size.height - rect.size.height)/2;
CGRect clippedRect = CGRectMake(X, Y, rect.size.width, rect.size.height);
//CGContextClipToRect( currentContext, clippedRect);
//create a rect equivalent to the full size of the image
//offset the rect by the X and Y we want to start the crop
//from in order to cut off anything before them
CGRect drawRect = CGRectMake(0,
0,
imageToCrop.size.width,
imageToCrop.size.height);
CGContextTranslateCTM(currentContext, 0.0, drawRect.size.height);
CGContextScaleCTM(currentContext, 1.0, -1.0);
//draw the image to our clipped context using our offset rect
//CGContextDrawImage(currentContext, drawRect, imageToCrop.CGImage);
CGImageRef tmp = CGImageCreateWithImageInRect(imageToCrop.CGImage, clippedRect);
//pull the image from our cropped context
UIImage *cropped = [UIImage imageWithCGImage:tmp];//UIGraphicsGetImageFromCurrentImageContext();
CGImageRelease(tmp);
//pop the context to get back to the default
UIGraphicsEndImageContext();
//Note: this is autoreleased*/
return cropped;
}
I am using following line of code in cellForRowAtIndexPath to update the image of the cell:
cell.img.image = [self imageByCropping:[self getSmallImage:[UIImage imageNamed:@"goal_image.png"]] toRect:CGRectMake(0, 0, 36, 36)];
Now when I add this table view and pop it from navigation controller, I see a memory hike.I see no leaks but memory keeps climbing.
Please note that the images changes for each row and I am creating the controller using lazy initialization that is I create or alloc it whenever I need it.
I saw on internet many people facing the same issue, but very rare good solutions. I have multiple views using the same way and I see almost memory raised to 4MB within 20-25 view transitions.
What is the good solution to resolve this issue.
tnx.
You can't return from the routine before you EndImageContext:
return UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
Try this:
UIImage* newImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return newImage;
You don't need the retains or autoreleases that are commented out.
Depending on the size of the images, your use of imageNamed:
may be responsible for the memory growth. This isn't necessarily a problem. imageNamed:
is meant for use by code that frequently loads the same images and is backed by a cache. There were leaks in it prior to iOS 3.0, but they were fixed and I am not aware of any reasons not to use this API if you want to take advantage of the caching.
You should run your code through Instruments, in particular the Leaks template. Using heapshot analysis, you can pinpoint places in your code that increase the memory footprint when you don't expect them to, even if they are missed by traditional leak analysis. Bill Bumgarner wrote a post discussing the use of heapshot analysis. He uses a Mac OS X application for his example, but the techniques apply equally well to iOS apps.
[UIImage imageNamed:]
cause memory leaks because it used internal caching of images.
Simple method is to cache the image externally by programmer.
For that, use
-(UIImage*)thumbnailImage:(NSString*)fileName {
UIImage *thumbnail = [thumbnailCache objectForKey:fileName];
if (nil == thumbnail) {
NSString *thumbnailFile = [NSString stringWithFormat:@"%/%@", [[NSBundle mainBundle]
pathForResource:fileName
ofType:@"png"]]; //dont forget to set correct image type
thumbnail = [UIImage imageWithContentsOfFile:thumbnailFile];
[thumbnailCache setObject:thumbnail forKey:fileName];
}
return thumbnail;
}
Declare NSMutableDictionary *thumbnailCache;
in .h file
And use can use this function like
cell.img.image = [self imageByCropping:[self getSmallImage:[self thumbnailImage:@"goal_image"]] toRect:CGRectMake(0, 0, 36, 36)];
Clear the application shared cache ie set to nil
I think this will solve ur issue.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With