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

http://i.stack.imgur.com/ELCA6.png

+3


source to share


1 answer


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;
    }
}

      

+3


source







All Articles