The connection to the assets was interrupted or the assets died (with memory warnings)
We are trying to allow users to import an image from their albums ( UIImagePickerController
), as well as scale / resize images larger than 8 megapixels (iPhone standard).
But every time the application crashes with warnings Connection to assetsd was interrupted or assetsd died
and Received memory warning
after or before importing the image. Sometimes a message appears Received memory warning
when looking for an image to import into UIImagePickerController
.
Especially on iPhone 4S it is worse, please help us optimize our code to run without warnings or crashes on older devices like iPhone 4S or iPad 2.
Let us know if we are doing something wrong when scaling / resizing an image using CoreGraphics. (Because huge memory is used here).
- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info
{
UIImage *selectedImage=[info objectForKey:UIImagePickerControllerOriginalImage];
if(UI_USER_INTERFACE_IDIOM()==UIUserInterfaceIdiomPhone)
{
[picker dismissViewControllerAnimated:YES completion:nil];
}
else
{
[popoverController dismissPopoverAnimated:YES];
[self popoverControllerDidDismissPopover:popoverController];
}
// COMPRESSING IMAGE
NSData *selectedImageData=UIImageJPEGRepresentation(selectedImage, 0.1);
UIImage *selectedImageFromData=[UIImage imageWithData:selectedImageData];
// IMAGE ASPECT RATIO
CGFloat originalWidth=selectedImageFromData.size.width;
CGFloat originalHeight=selectedImageFromData.size.height;
CGFloat myWidth=2048;
CGFloat myHeight=2048;
CGFloat widthRatio=myWidth/originalWidth;
CGFloat heightRatio=myHeight/originalHeight;
CGFloat dynamicWidth=heightRatio*originalWidth;
CGFloat dynamicHeight=widthRatio*originalHeight;
//SCALING UIIMAGE MORE THAN 8 MEGAPIXELS
if (((selectedImageFromData.size.width>3264) && (selectedImageFromData.size.height>2448)) || ((selectedImageFromData.size.height>3264) && (selectedImageFromData.size.width>2448)))
{
// DATA FROM UIIMAGE TO CORE GRAPHICS
CGImageRef CoreGraphicsImage=selectedImageFromData.CGImage;
CGColorSpaceRef colorSpace = CGImageGetColorSpace(CoreGraphicsImage);
CGBitmapInfo bitmapInfo=CGImageGetBitmapInfo(CoreGraphicsImage);
CGImageGetBitsPerComponent(CoreGraphicsImage);
// RESIZING WIDTH OF THE IMAGE
if (originalWidth>originalHeight)
{
CGContextRef context=CGBitmapContextCreate(NULL, myWidth, dynamicHeight, CGImageGetBitsPerComponent(CoreGraphicsImage), CGImageGetBytesPerRow(CoreGraphicsImage), colorSpace, bitmapInfo);
CGContextSetInterpolationQuality(context, kCGInterpolationHigh);
CGContextDrawImage(context, CGRectMake(0, 0, myWidth, dynamicHeight), CoreGraphicsImage);
CGImageRef CGscaledImage=CGBitmapContextCreateImage(context);
UIImage *CGLastimage = [UIImage imageWithCGImage: CGscaledImage];
NSLog(@"%f",CGLastimage.size.width);
NSLog(@"%f",CGLastimage.size.height);
VisualEffectImageVIew.image=CGLastimage;
BackgroundImageView.image=CGLastimage;
ForegroundImageView.image=CGLastimage;
}
//RESIZING HEIGHT OF THE IMAGE
if (originalHeight>originalWidth)
{
CGContextRef context=CGBitmapContextCreate(NULL, dynamicWidth, myHeight, CGImageGetBitsPerComponent(CoreGraphicsImage), CGImageGetBytesPerRow(CoreGraphicsImage), colorSpace, bitmapInfo);
CGContextSetInterpolationQuality(context, kCGInterpolationHigh);
CGContextDrawImage(context, CGRectMake(0, 0, dynamicWidth, myHeight), CoreGraphicsImage);
CGImageRef CGscaledImage=CGBitmapContextCreateImage(context);
UIImage *CGLastimage = [UIImage imageWithCGImage: CGscaledImage];
NSLog(@"%f",CGLastimage.size.width);
NSLog(@"%f",CGLastimage.size.height);
VisualEffectImageVIew.image=CGLastimage;
BackgroundImageView.image=CGLastimage;
ForegroundImageView.image=CGLastimage;
}
}
else
{
NSLog(@" HEIGHT %f",selectedImageFromData.size.height);
NSLog(@" WIDTH %f",selectedImageFromData.size.width);
VisualEffectImageVIew.image=selectedImageFromData;
BackgroundImageView.image=selectedImageFromData;
ForegroundImageView.image=selectedImageFromData;
}
}
Memory report
when scrolling in UIImagePickerController
http://i.stack.imgur.com/qxx62.png
when scaling / resizing UIImage
source to share
Two points.
First, you are not releasing the objects you create - you are leaking a huge amount of memory. Regardless of whether you are using ARC, you must call CGContextRelease or CGImageRelease as needed for each CGCreate call.
Second, if you just want to resize, using coregraphics would be overkill, use UIKit instead. In the code I'm using below, note the use of @autorelease to make sure objects are cleaned up by ARC as soon as the context ends.
- (UIImage *)fitImage:(UIImage *)image scaledToFillSize:(CGSize)size {
// do not upscale
@autoreleasepool {
if( image.size.width <= size.width && image.size.height <= size.height )
return image;
CGFloat scale = MIN(size.width/image.size.width, size.height/image.size.height);
CGFloat width = image.size.width * scale;
CGFloat height = image.size.height * scale;
CGRect imageRect;
// center image
if( scale != 1.0 ) { // avoid divide by zero?
if( size.width/image.size.width < size.height/image.size.height ) {
// height needs to be centered
imageRect = CGRectMake(0, (size.height-height)/2, width, height);
} else {
// width needs to be centered
imageRect = CGRectMake((size.width-width)/2, 0, width, height);
}
}
UIGraphicsBeginImageContextWithOptions(size, YES, 0);
[[UIColor CollageBorderUIColor] setFill]; // otherwise it ugly black fill
UIRectFill(CGRectMake(0, 0, size.width, size.height));
[image drawInRect:imageRect];
UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return newImage;
}
}
source to share