Reduce memory usage with UIImagePickerController

In my application, the user can take multiple images using the UIImagePickerController, and these images are then displayed one after the other in the view.

I had problems with memory management. With cameras today, phones are growing fast in megapixels, UIImages returned from UIImagePickerController are pig memory. On my iPhone 4S, UIImages are about 5 MB; I can’t imagine how they look on new and future models.

One of my friends said that the best way to deal with UIImages is to immediately save them as a JPEG file in my application document directory and release the original UIImage as soon as possible. So this is what I was trying to do. Unfortunately, even after saving the UIImage to JPEG and having no links to it in my code, this is not garbage collection.

Here are the relevant sections of my code. I am using ARC.

// Entry point: UIImagePickerController delegate method
-(void) imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info {

    // Process the image.  The method returns a pathname.
    NSString* path = [self processImage:[info objectForKey:UIImagePickerControllerOriginalImage]];

    // Add the image to the view
    [self addImage:path];
}

-(NSString*) processImage:(UIImage*)image {

    // Get a file path
    NSArray* paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
    NSString* documentsDirectory = [paths objectAtIndex:0];
    NSString* filename = [self makeImageFilename]; // implementation omitted
    NSString* imagePath = [documentsDirectory stringByAppendingPathComponent:filename];

    // Get the image data (blocking; around 1 second)
    NSData* imageData = UIImageJPEGRepresentation(image, 0.1);

    // Write the data to a file
    [imageData writeToFile:imagePath atomically:YES];

    // Upload the image (non-blocking)
    [self uploadImage:imageData withFilename:filename];

    return imagePath;
}

-(void) uploadImage:(NSData*)imageData withFilename:(NSString*)filename {
    // this sends the upload job (implementation omitted) to a thread
    // pool, which in this case is managed by PhoneGap
    [self.commandDelegate runInBackground:^{
        [self doUploadImage:imageData withFilename:filename];
    }];
}

-(void) addImage:(NSString*)path {
    // implementation omitted: make a UIImageView (set bounds, etc).  Save it
    // in the variable iv.

    iv.image = [UIImage imageWithContentsOfFile:path];
    [iv setNeedsDisplay];
    NSLog(@"Displaying image named %@", path);
    self.imageCount++;
}

Notice how the method processImagerefers to UIImage, but only uses it for one thing: creating the NSData * view of this image. So, after the processImage method is complete, the UIImage should be freed from memory, right?

What can I do to reduce memory usage in my application?

Update

Now I understand that a screenshot of the distribution profiler will be useful to explain this issue.

Allocations of app

+4
1

processImage .

, Apple PhotoPicker

, Apple , . , . :

/* Start the timer to take a photo every 1.5 seconds.
CAUTION: for the purpose of this sample, we will continue to take pictures indefinitely.
Be aware we will run out of memory quickly. You must decide the proper threshold number of photos allowed to take from the camera.
One solution to avoid memory constraints is to save each taken photo to disk rather than keeping all of them in memory.
In low memory situations sometimes our "didReceiveMemoryWarning" method will be called in which case we can recover some memory and keep the app running.
*/

, Apple, .

imagePicker :

- (void)imagePickerController:(UIImagePickerController *)picker 
didFinishPickingMediaWithInfo:(NSDictionary *)info
{
    UIImage *image = [info valueForKey:UIImagePickerControllerOriginalImage];

    [self.capturedImages removeAllObjects];   // (1)
    [self.imagePaths addObject:[self processImage:image]]; //(2)

    [self.capturedImages addObject:image];

    if ([self.cameraTimer isValid])
    {
        return;
    }
    [self finishAndUpdate]; //(3)
}

(1) - ,
(2) - , .
(3) - cameraTimer , finishAndUpdate .

processImage: , :
[self uploadImage:imageData withFilename:filename];
.

makeImageFileName:

static int imageName = 0;

-(NSString*)makeImageFilename {
    imageName++;
    return [NSString stringWithFormat:@"%d.jpg",imageName];
}

, Apple.

Apple (Timer (1) (2))

enter image description here

~ 140 ~ 40

(Timer (1) (2))

enter image description here

: ~ 30 .

iPhone5S. - 3264 x 2448 px, 24 (24- RGB). ( ) Jpeg 250 ( 0,1 ) 1-2 ( 0,7) ~ 6 ( 1,0).

, . : , . x x - - . jrturton, , , , , . , () imageView 832 x 640, , , , , . ~ 1,6 , 24 ( ).

processImage, -, , :

1/ . ?
2/ addImage uploadImage . , , .
3/ (- PhoneGap?)

, JPEG-:
NSData* imageData = UIImageJPEGRepresentation(image, 0.1);

, ImageIO, , , ImagePickerController. . : iPhone? AVFoundation, NSData, ,

+7

All Articles