Advertise here




Advertise here

Howdy, Stranger!

It looks like you're new here. If you want to get involved, click one of these buttons!

UIImagePickerController memory issues!

simsimmasimsimma Posts: 9New Users
edited January 2011 in iPhone SDK Development
Hi,

So in my application I want the user to be able to take as many photos as they like and store them for future lookup.

I use the sample code online for instantiating the camera.

Once the image is grabbed I use UIImageView to show the image to the user.

The problem is that after taking five pictures or so the application crashes!

Has anyone else had any issues with the camera and what did people have to do to fix it?!
Post edited by simsimma on

Replies

  • hack4hack4 Posts: 7New Users
    edited September 2008
    Are you sure you're releasing the image picker once you've used it?

    A lot of the sample code you see online doesn't seem to do that.
  • simsimmasimsimma Posts: 9New Users
    edited September 2008
    I think so, here is the code:
    -(BOOL)startCameraPickerFromViewController:(UIViewController*)controller usingDelegate:(id<UIImagePickerControllerDelegate>)delegateObject
    
    {
    	
        if ( (![UIImagePickerController isSourceTypeAvailable:UIImagePickerControllerSourceTypeCamera])
    		
    		|| (delegateObject == nil) || (controller == nil))
    		
            return NO;
    	
    	
    	
        if(imagepicker == nil){
    		imagepicker = [[UIImagePickerController alloc] init];
    	
        imagepicker.sourceType = UIImagePickerControllerSourceTypeCamera;
    	
        imagepicker.delegate = delegateObject;
    	}
    	
        //picker.allowsImageEditing = YES;
        // Picker is displayed asynchronously.
    	
        [controller presentModalViewController:imagepicker animated:YES];
    	
        return YES;
    	
    }
    
    imagepicker is deallocated in the dealloc function of my parent view controller.

    Now, after a person takes a photo I do the following:
    - (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingImage:(UIImage *)image editingInfo:(NSDictionary *)editingInfo{
    	
    	//we need to save each image and then show it in the interface!
    	int row = (self.numPhotos / 4);
    	int mod = self.numPhotos % 4;
    	
    	UIImageView *imageview = [[UIImageView alloc] initWithImage:image];
        [imageview setFrame:CGRectMake(mod * 80.0, row*120.0 + 120.0, 80.0, 120.0)];
    	[self.view addSubview:imageview];
    	
    	[imageview release];
    	
    	self.numPhotos = self.numPhotos + 1;
    	[self.navigationController dismissModalViewControllerAnimated:YES];
    
    }
    

    From running instruments I see that after I take the image, 8MB or so of space is taken up. But that space never gets released. So each time I take a photo, the memory goes up to hit 40MB which then causes the crash.

    What am I doing wrong here? How do I clear the data taken by the UIImagePickerController class so that I'm not causing a crash after 5 pictures?

    Cheers
  • NewiPhoneDeveloperNewiPhoneDeveloper Posts: 459Registered Users
    edited September 2008
    Having the same issue here. Have you managed to solve that?
    Websites:<br />
    <a href="http://www.friendlydeveloper.com" target="_blank">Friendlydeveloper</a> - Coding Blog<br />
    <a href="http://www.codingsessions.com" target="_blank">Codingsessions</a> - Live iOS Training<br />
    <br />
    iPhone Apps: <br />
    <a hr
  • johnnybluejeansjohnnybluejeans Posts: 52Registered Users
    edited September 2008
    I too have this issue. If you follow Apple's sample code exactly, you will get a crash after about 5-6 photos because of memory use.
  • mkrollmkroll Posts: 15Registered Users
    edited September 2008
    Maybe someone more familiar with iPhone development could give us a hint concerning this issue. I'm having the same memory issue with the image picker here.

    Thanks,
    Michael.
  • NewiPhoneDeveloperNewiPhoneDeveloper Posts: 459Registered Users
    edited September 2008
    Hi there,

    let me share the piece of code with you, that finally solved my memory issues!
    //this is my ViewController.h
    
    @interface myViewController: UIViewController <UIImagePickerControllerDelegate> {
    UIImagePickerController *picker;
    }
    
    @property (nonatomic, retain) UIImagePickerController *picker;
    
    - (IBAction)openPhotolibrary:(id)sender;
    - (void)useImage:(UIImage *)image;
    
    @end
    
    //this is inside my ViewController.m
    - (IBAction)openPhotolibrary:(id)sender {
    
    	if ([UIImagePickerController isSourceTypeAvailable:UIImagePickerControllerSourceTypePhotoLibrary]) {
    
                    //Now this seems to do the trick. The picker only gets allocated once. Therefore no memory issues any longer!
                    //Before I did it this way, my app crashed after picking 25 images. This one still was OK after picking about 50 images.
    		if (picker == nil) {
    			picker = [[UIImagePickerController alloc] init];
    			picker.sourceType = UIImagePickerControllerSourceTypePhotoLibrary;
    			picker.allowsImageEditing = YES;
    			picker.delegate = self;
    		}
    		[self presentModalViewController:picker animated:YES];
    	}
    }
    
    - (void)useImage:(UIImage *)image {
       //add code to use the picked image
    }
    
    - (void)imagePickerControllerDidCancel:(UIImagePickerController *)CurrentPicker {
        //hide the picker if user cancels picking an image.
    	[[CurrentPicker parentViewController] dismissModalViewControllerAnimated:YES];
    }
    
    - (void)dealloc {
        [picker release];
        [super dealloc];
    }
    
    

    Hope this helps.
    Websites:<br />
    <a href="http://www.friendlydeveloper.com" target="_blank">Friendlydeveloper</a> - Coding Blog<br />
    <a href="http://www.codingsessions.com" target="_blank">Codingsessions</a> - Live iOS Training<br />
    <br />
    iPhone Apps: <br />
    <a hr
  • airsourceairsource Posts: 3New Users
    edited November 2008
    I just wrote a blog post analysing the issue in a bit more depth at

    The Airsource - Memory usage in UIImagePickerController

    Airsource - Mobile Software Experts
    The Airsource - A blog on mobile software
  • scottiphonescottiphone Posts: 802Registered Users
    edited November 2008
    So have you filed a bug report with all of this information to Apple?
  • johnqhjohnqh Posts: 812Registered Users @ @ @
    edited November 2008
    simsimma wrote: »
    I think so, here is the code:
    -(BOOL)startCameraPickerFromViewController:(UIViewController*)controller usingDelegate:(id<UIImagePickerControllerDelegate>)delegateObject
    
    {
    	
        if ( (![UIImagePickerController isSourceTypeAvailable:UIImagePickerControllerSourceTypeCamera])
    		
    		|| (delegateObject == nil) || (controller == nil))
    		
            return NO;
    	
    	
    	
        if(imagepicker == nil){
    		imagepicker = [[UIImagePickerController alloc] init];
    	
        imagepicker.sourceType = UIImagePickerControllerSourceTypeCamera;
    	
        imagepicker.delegate = delegateObject;
    	}
    	
        //picker.allowsImageEditing = YES;
        // Picker is displayed asynchronously.
    	
        [controller presentModalViewController:imagepicker animated:YES];
    	
        return YES;
    	
    }
    
    imagepicker is deallocated in the dealloc function of my parent view controller.

    Now, after a person takes a photo I do the following:
    - (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingImage:(UIImage *)image editingInfo:(NSDictionary *)editingInfo{
    	
    	//we need to save each image and then show it in the interface!
    	int row = (self.numPhotos / 4);
    	int mod = self.numPhotos % 4;
    	
    	UIImageView *imageview = [[UIImageView alloc] initWithImage:image];
        [imageview setFrame:CGRectMake(mod * 80.0, row*120.0 + 120.0, 80.0, 120.0)];
    	[self.view addSubview:imageview];
    	
    	[imageview release];
    	
    	self.numPhotos = self.numPhotos + 1;
    	[self.navigationController dismissModalViewControllerAnimated:YES];
    
    }
    

    From running instruments I see that after I take the image, 8MB or so of space is taken up. But that space never gets released. So each time I take a photo, the memory goes up to hit 40MB which then causes the crash.

    What am I doing wrong here? How do I clear the data taken by the UIImagePickerController class so that I'm not causing a crash after 5 pictures?

    Cheers

    I must be missing something.

    For every photo (1600x1200 at RGBA, so 8MB), you create a UIImageView which displays the image, of course the memory usage increases by 8MB. About 4 of those full size images will make iPhone run out of memory and crash.

    The problem (at least in the above code) is not the image picker, it is your code.
  • qjkbanksqjkbanks Posts: 1New Users
    edited November 2008
    Which Apple sample code are you using. Can you provide a link?

    Thank you...
  • vargonianvargonian Posts: 5New Users
    edited January 2009
    I'm seeing this leak too, on the device. I'm pulling my hair out trying to figure out if it's my code or something with the UIImagePickerController.

    Can anyone confirm that this is still an issue?
  • BostonMerlinBostonMerlin Posts: 399Registered Users
    edited January 2009
    This is still an issue. I've had the same problem. Per the recommendation of other users i created a singleton method on my app delegate to retain an instance of the pickercontroller if/when it's ever called and never release the object until the app shutsdown. I don't like this solution as it goes against everything we're supposed to avoid regarding memory management but i've not found any other method that helps. reasing the picturecontroller does nothing to reduce the memory.

    I would love to find out what's going on here.. My app was denied by apple recently because they experienced crashes when picking pictures.. so i added the singleton and resubmitted....

    John

    <br />
    <b>I love being a dad, flying airplanes and writing code.</b><br />
    <br />
    Follow me on Twitter: <a href=
  • tkilmertkilmer Posts: 583Registered Users
    edited January 2009
    I found out with my application, that it was not the picker controller. I learned that it was what I was doing with the images. Storing one UIImage that came from the camera took up a huge amount of memory. By the time I took 5, it crashed. I started to store my images as NSData instead. Whenever I needed to use the image, I would initialize it with that data. This way, you could release the picker controller and use it like you are suppose to. I found that it works so much better.
  • BostonMerlinBostonMerlin Posts: 399Registered Users
    edited January 2009
    i agree that sounds like a good place to look. in my case i'm not letting users pick from the camera only the library. once a picture is chosen i'm compressing it down to a manageable size (< 200k) and i only ever show one image at a time. I'm still digging around but instruments is not showing me anything to go on at the moment.

    I do have another screen that displays images.. i like the idea of using nsdata to store them.. will investigate that further.

    Thanks!
    John

    <br />
    <b>I love being a dad, flying airplanes and writing code.</b><br />
    <br />
    Follow me on Twitter: <a href=
  • scotopiascotopia Posts: 2,074Registered Users
    edited January 2009
    I am using an UIImagePickerController to get a picture from the users library but I am having trouble doing exactly what i want to do; which is basically as follows:

    Say I have a bounding box area specified on the screen (say 128 x 128 pixels). After the user has picked his photo and finalized zoom/scale etc and is done; I want only the area that is inside that bounding box to be retained: saved as it's own image inside the documents folder of the app for later user in the app. It is imperative that only the 128 x 128 final result is saved (for obvious memory reasons).

    It's worth noting that the project I am working on is 2D OpenGL based (like GLSprite). Can anyone help me accomplish this?
    <div align="center"><br />
    <br />
    <a href="http://bit.ly/c4r7uo" target="_blank">omegasoftIconBanner.png</a><br />
    <br />
    <a href="http://bit.ly/9EGiHD" target="_blank">Aura Trainer</a> | <a href="http://bi
  • scotopiascotopia Posts: 2,074Registered Users
    edited January 2009
    ::Bump::
    <div align="center"><br />
    <br />
    <a href="http://bit.ly/c4r7uo" target="_blank">omegasoftIconBanner.png</a><br />
    <br />
    <a href="http://bit.ly/9EGiHD" target="_blank">Aura Trainer</a> | <a href="http://bi
  • BostonMerlinBostonMerlin Posts: 399Registered Users
    edited January 2009
    scotopia i cant help with your question but you should throw it in a new thread as it's off-topic... we're dealing with memory issues at the moment!


    John

    <br />
    <b>I love being a dad, flying airplanes and writing code.</b><br />
    <br />
    Follow me on Twitter: <a href=
  • scotopiascotopia Posts: 2,074Registered Users
    edited January 2009
    It was in a new thread that got avoided like the plague; so I figured I'd pester you guys here cause I'm desperate. ;) I didn't think it was really off topic though; because this does have to do with memory management of the UIImagePickerController resulting images...so its close. I thought it was determined that there was no "bug" and its just that the resulting images you end up are mammoth in memory size (8 megs) leading to a crash; so at it's heart, our issues are very related I think.
    <div align="center"><br />
    <br />
    <a href="http://bit.ly/c4r7uo" target="_blank">omegasoftIconBanner.png</a><br />
    <br />
    <a href="http://bit.ly/9EGiHD" target="_blank">Aura Trainer</a> | <a href="http://bi
  • adeemadeem Posts: 34Tutorial Authors
    edited April 2009
    Hi there,

    let me share the piece of code with you, that finally solved my memory issues!
    //this is my ViewController.h
    
    @interface myViewController: UIViewController <UIImagePickerControllerDelegate> {
    UIImagePickerController *picker;
    }
    
    @property (nonatomic, retain) UIImagePickerController *picker;
    
    - (IBAction)openPhotolibrary:(id)sender;
    - (void)useImage:(UIImage *)image;
    
    @end
    
    //this is inside my ViewController.m
    - (IBAction)openPhotolibrary:(id)sender {
    
    	if ([UIImagePickerController isSourceTypeAvailable:UIImagePickerControllerSourceTypePhotoLibrary]) {
    
                    //Now this seems to do the trick. The picker only gets allocated once. Therefore no memory issues any longer!
                    //Before I did it this way, my app crashed after picking 25 images. This one still was OK after picking about 50 images.
    		if (picker == nil) {
    			picker = [[UIImagePickerController alloc] init];
    			picker.sourceType = UIImagePickerControllerSourceTypePhotoLibrary;
    			picker.allowsImageEditing = YES;
    			picker.delegate = self;
    		}
    		[self presentModalViewController:picker animated:YES];
    	}
    }
    
    - (void)useImage:(UIImage *)image {
       //add code to use the picked image
    }
    
    - (void)imagePickerControllerDidCancel:(UIImagePickerController *)CurrentPicker {
        //hide the picker if user cancels picking an image.
    	[[CurrentPicker parentViewController] dismissModalViewControllerAnimated:YES];
    }
    
    - (void)dealloc {
        [picker release];
        [super dealloc];
    }
    
    

    Hope this helps.

    Thanks :) it work for me!
    Adeem<br />
    For Tutorials on iPhone check out <a href="http://adeem.me/blog" target="_blank">http://adeem.me/blog</a><br />
    iPhone Tutorial on Demand!
  • lokidillokidil Posts: 112Registered Users
    edited June 2009
    i agree that sounds like a good place to look. in my case i'm not letting users pick from the camera only the library. once a picture is chosen i'm compressing it down to a manageable size (< 200k) and i only ever show one image at a time. I'm still digging around but instruments is not showing me anything to go on at the moment.

    I do have another screen that displays images.. i like the idea of using nsdata to store them.. will investigate that further.

    Thanks!
    John

    I am also having the same problem. Have u rectified it. Then how to compress the captured image plz help me!!
  • lokidillokidil Posts: 112Registered Users
    edited June 2009
    simsimma wrote: »
    Hi,

    So in my application I want the user to be able to take as many photos as they like and store them for future lookup.

    I use the sample code online for instantiating the camera.

    Once the image is grabbed I use UIImageView to show the image to the user.

    The problem is that after taking five pictures or so the application crashes!

    Has anyone else had any issues with the camera and what did people have to do to fix it?!

    Hey i m with solution now check out this code this will allow us to take infinite photos
    - (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingImage:(UIImage *)image editingInfo:(NSDictionary *)editingInfo {
    	
    	CGImageRef			imageRef = [image CGImage];
    	CGImageAlphaInfo	alphaInfo = CGImageGetAlphaInfo(imageRef);
    	unsigned char* rawData;
    	CGRect thumbRect = CGRectMake(0,0,480,480);
    
    	if (alphaInfo == kCGImageAlphaNone)
    		alphaInfo = kCGImageAlphaNoneSkipLast;
    	
    	CGContextRef bitmap = CGBitmapContextCreate(
    												NULL,
    												thumbRect.size.width,		// width
    												thumbRect.size.height,		// height
    												CGImageGetBitsPerComponent(imageRef),	// really needs to always be 8
    												//4 * thumbRect.size.width,	// rowbytes
    												CGImageGetBytesPerRow(imageRef),
    												CGImageGetColorSpace(imageRef),
    												alphaInfo
    												);
    	
    	CGContextRotateCTM (bitmap, radians(-90));
    	CGContextTranslateCTM (bitmap, -thumbRect.size.width, 0);
    	CGContextDrawImage(bitmap, thumbRect, imageRef);
    	CGImageRef	ref = CGBitmapContextCreateImage(bitmap);
    	image = [UIImage imageWithCGImage:ref];
    	CGContextRelease(bitmap);	// ok if NULL
    	thumbRect = CGRectMake(0,0,320,430);
    	bitmap = CGBitmapContextCreate(
    								   NULL,
    								   thumbRect.size.width,		// width
    								   thumbRect.size.height,		// height
    								   CGImageGetBitsPerComponent(imageRef),	// really needs to always be 8
    								   //4 * thumbRect.size.width,	// rowbytes
    								   CGImageGetBytesPerRow(imageRef),
    								   CGImageGetColorSpace(imageRef),
    								   alphaInfo
    								   );
    
    	CGContextDrawImage(bitmap, thumbRect, ref);
    	CGImageRelease (ref);///////////new
    
    	ref = CGBitmapContextCreateImage(bitmap);
    	
    	image = [UIImage imageWithCGImage:ref];
    	
    	
    	CGContextRelease(bitmap);	// ok if NULL
    	CGImageRelease(ref);
    	
    	NSUInteger width = CGImageGetWidth(imageRef);
    	NSUInteger height = CGImageGetHeight(imageRef);
    	CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
    	if(rawData)free(rawData);////////////////new
    	rawData = malloc(height * width * 4);
    	NSUInteger bytesPerPixel = 4;
    	NSUInteger bytesPerRow = bytesPerPixel * width;
    	NSUInteger bitsPerComponent = 8;
    	CGContextRef contextC = CGBitmapContextCreate(rawData, width, height, bitsPerComponent, bytesPerRow, colorSpace, kCGImageAlphaPremultipliedLast | kCGBitmapByteOrder32Big);
    	CGColorSpaceRelease(colorSpace);
    	
    	CGContextDrawImage(contextC, CGRectMake(0, 0, width, height), imageRef);
    	CGContextRelease(contextC);
    
    	imgView.image =[[[UIImage alloc] initWithData:UIImageJPEGRepresentation(image, 1.0)] autorelease];//Where imgView is the UIImageView
    
    	[picker dismissModalViewControllerAnimated: YES];
    	[picker release];
    }
    
  • BinduBindu Posts: 2New Users
    edited May 2010
    Hello Can anyone help me ?

    I am picking an image with a UIImagePickerControl with the code

    UIImagePickerController *picker = [[UIImagePickerController alloc] init];
    picker.delegate = self;

    if((UIButton *) sender == choosePhoto) {
    picker.sourceType = UIImagePickerControllerSourceTypeSavedPhotosAlbum;


    }
    else {
    picker.sourceType = UIImagePickerControllerSourceTypeCamera;

    }


    I need to pas this image data to next view

    i got the code for taking image data representation

    UIImage *img = [UIImage imageNamed:@"some.png"];

    NSData *dataObj = UIImageJPEGRepresentation(img, 1.0);


    how can I get the image representation of same image that i am taking with UIImagePickerControl

    Can u pls send me the code to use that image ?
  • JuanMazueraJuanMazuera Posts: 24Registered Users
    edited May 2010
    tkilmer wrote: »
    I found out with my application, that it was not the picker controller. I learned that it was what I was doing with the images. Storing one UIImage that came from the camera took up a huge amount of memory. By the time I took 5, it crashed. I started to store my images as NSData instead. Whenever I needed to use the image, I would initialize it with that data. This way, you could release the picker controller and use it like you are suppose to. I found that it works so much better.

    Hi, this is my first post in this page, its a great site and i've learned a lot. I have a question for you, i'm building an app where the user can select images i have uiimagepickercontroller and its all ok but how do you do to save those selected images to an image array to show on an imageview inside your app and that keeps that info even when you close and relaunch your app? Thanks in advance, happy coding

    Edit: user picks images from photolibrary, not from camera
  • spymasterspymaster Posts: 1New Users
    edited January 2011
    If you're displaying this view once for each image selection, then you will be creating a memory leak by allocating the image picker, but not releasing it.

    The Apple sample releases the UIImagePickerController after an image has been selected. Your code doesn't do this.

    This is the way to do it:
    [picker release];

    or

    [picker autorelease];

    From the code you posted, you're not doing this, so the previous allocs are sitting around in memory.

    The reason your solution below alleviates the problem is that because you're conditionally allocating the picker, you only do it once.

    Just thought I'd point this out to solve the mystery :)
Sign In or Register to comment.