views:

251

answers:

3

I've seen this question asked dozens of times but never answered.

How do you resize a UIImage (specifically one returned from the UIImagePickerController camera). When I try any of the methods that are out there I get a memory spike between 20 and 40MB. It does go away but I know that on some hardware this is completely unacceptable.

I've tried the methods that use the following operations: drawInRect:, CGContextDrawImage(), imageWithCGImage:scale:orientation:

I understand that uncompressed images living in memory take up more space than on disk, but it seems like the most common UIImage resize operations involve creating copies of the image data.

Even Apple recommends immediately resizing a picture taken with the camera. However (b/c I believe they know this topic is intensely complex) they offer no words of guidance on how to manage that. Especially how to do it the moment the image data is returned.

Does anyone have a smooth method to resize a large UIImage while conserving memory? I know that's a tall order.

A: 

I dont have a 100% great answer here but you have a couple options. The iphone will let you enter the edit/crop etc mode. I think that's what Apple wants you to use. For us that wasn't quite acceptable. We grab the image data, get the pixel data, release the original image. Then resize the top half, then second ourselves. I'd post some code but am not at work. I can in a few days after vacation...

David Nelson
Depending on how you "get" the pixel data, that might incur an unnecessary copy (once inside `UIImage` and again into your buffer)
rpetrich
A: 

A method that uses little memory is to create a bitmap context with CGBitmapContextCreate and draw the UIImage into it. The only additional memory this will use is what you've malloced and some small CGContext overhead.

If you want to get fancy, you could instead mmap with the PROT_WRITE flag set and be limited only by the virtual address space

rpetrich
I tried that method but could not manage to conserve memory. Is there a specific retain/release pattern that begins and ends with a UIImage that you can share?
Samma Lamma
I don't have any code samples because I just use the much simpler private API in my jailbreak applications. The code above will get you an image resized into a buffer of your choosing. To create an `UIImage` out of that, chain the following APIs: `CGDataProviderCreateWithData`, `CGImageCreate` and `-[UIImage initWithCGImage:]`. Be sure to follow proper memory management patterns and to specify a proper custom release callback for your `CGDataProvider`.
rpetrich
+1  A: 

Have you tried benchmarking the memory footprint used by resizing UIImage with the category methods described in the following blog post.

I've used similar resizing to make thumbnails for larger pictures download by the app. My pictures aren't probably as large as those that you're picking from your image picker controller, but I have found pretty good performance resulted.

Hope it helps in some way.

petert