USERX2DX
USERX2DX

Reputation: 217

Connection to assetsd was interrupted or assetsd died (with memory warnings)

We are trying to let users import picture from their albums(UIImagePickerController) and also we are scaling/resizing down images that are greater than 8 megapixels(iPhone standard).

But every time the app crashes with Connection to assetsd was interrupted or assetsd died and Received memory warning warnings after or before importing picture.At times Received memory warning warning pops up when still looking for picture to import in UIImagePickerController.

Specially on iPhone 4S this is worse, please help us in optimising our code so that it runs without warnings and crashes on older devices like iPhone 4S or iPad 2.

Let us know if we are doing anything wrong in scaling/resizing down image using CoreGraphics.(Because this is where huge memory is used).

 - (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

https://i.sstatic.net/qxx62.png

when scaling/resizing UIImage

https://i.sstatic.net/ELCA6.png

Upvotes: 4

Views: 7570

Answers (1)

xaphod
xaphod

Reputation: 6804

Two points.

First, you are not releasing the objects you create -- you are leaking huge amounts of memory. Regardless of whether you are using ARC, you must call CGContextRelease or CGImageRelease as appropriate for every CGCreate call.

Second, if you just want to resize, using coregraphics is overkill, use UIKit instead. In the code I use below, note the use of @autorelease to ensure that 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's ugly black fill
        UIRectFill(CGRectMake(0, 0, size.width, size.height));
        [image drawInRect:imageRect];
        UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext();
        UIGraphicsEndImageContext();
        return newImage;
    }
}

Upvotes: 4

Related Questions