views:

135

answers:

1
+2  Q: 

Memory Map UIImage

Hello,

I have a UIImage and I would like to put its data in a file and and then used a mapped file to save some memory. Apparently, the UIImage data is private and it's not possible to access it. Would you have any suggestions to solve that?

Thanks!

+2  A: 

If you want to memory map the encoded image data, then mmap a file and provide a reference to the data by passing a CGDataProviderRef to CGImageCreate.

mapped = mmap( NULL , length , ... );
provider = CGDataProviderCreateWithData( mapped , mapped , length , munmap_wrapper );
image = CGImageCreate( ... , provider , ... );
uiimage = [UIImage imageWithCGImage:image];
...

Where munmap_wrapper is something like this:

// conform to CGDataProviderReleaseDataCallback
void munmap_wrapper( void *p , const void *cp , size_t l ) { munmap( p , l ); }

If you want to memory map the actual pixels, instead of the encoded source data, you would do something similar with a CGBitmapContext. You would also create the provider and image so the image refers to the same pixels as the context. Whatever is drawn in the context will be the content of the image. The width, height, color space and other parameters should be identical for the context and image.

context = CGBitmapContextCreate( mapped , ... );

In this case, length will be at least bytes_per_row*height bytes so the file must be at least that large.

If you have an existing image and you want to mmap the pixels, then create the bitmap context with the size and color space of your image and use CGContextDrawImage to draw the image in the context.

You did not say the source of your image, but if you are creating it at runtime it would be more efficient to create it directly in the bitmap context. Any image creation requires a bitmap context behind the scenes, so it might as well be the memory mapped one from the start.

drawnonward
Thanks for this great answer! I will look into that. I'm not really familiar with memory mapping but I was looking for ways to keep my memory usage down.Yes, I do have access to the bitmap since I manipulate this bitmap and then convert it to an UIImage using a CGDataProviderRef and CGImageCreate. So I guess I could do the memory mapping at this point by giving a memory mapped data to the CGDataProviderRef.
Kamchatka
You could try `MAP_ANON` if you do not care about the file. With that you can treat mmap almost like malloc.
drawnonward
Can I use the MAP_ANON without specifying a file? If I do a mmap and then try to memcpy the data with the same size as mmap, I get a EXC_BAD_ACCESS.
Kamchatka
According to `man mmap` you can by passing -1 as the file id, but mmap could be different on iPhone.
drawnonward
Did you specify `MAP_SHARED` and `PROT_READ | PROT_WRITE` where expected in mmap?
drawnonward
Ok my mistake was that I had PROT_NONE and MAP_PRIVATE I guess. Do I need MAP_SHARED if only my process access it?
Kamchatka