I am trying to get a UIImage from what is displayed in my EAGLView. Any suggestions on how to do this?
An EAGLView
is just a kind of view, and its underlying CAEAGLLayer
is just a kind of layer. That means, that the standard approach for converting a view/layer into a UIImage will work. (The fact that the linked question is UIWebview doesn't matter; that's just yet another kind of view.)
-(UIImage *) saveImageFromGLView
{
NSInteger myDataLength = 320 * 480 * 4;
// allocate array and read pixels into it.
GLubyte *buffer = (GLubyte *) malloc(myDataLength);
glReadPixels(0, 0, 320, 480, GL_RGBA, GL_UNSIGNED_BYTE, buffer);
// gl renders "upside down" so swap top to bottom into new array.
// there's gotta be a better way, but this works.
GLubyte *buffer2 = (GLubyte *) malloc(myDataLength);
for(int y = 0; y <480; y++)
{
for(int x = 0; x <320 * 4; x++)
{
buffer2[(479 - y) * 320 * 4 + x] = buffer[y * 4 * 320 + x];
}
}
// make data provider with data.
CGDataProviderRef provider = CGDataProviderCreateWithData(NULL, buffer2, myDataLength, NULL);
// prep the ingredients
int bitsPerComponent = 8;
int bitsPerPixel = 32;
int bytesPerRow = 4 * 320;
CGColorSpaceRef colorSpaceRef = CGColorSpaceCreateDeviceRGB();
CGBitmapInfo bitmapInfo = kCGBitmapByteOrderDefault;
CGColorRenderingIntent renderingIntent = kCGRenderingIntentDefault;
// make the cgimage
CGImageRef imageRef = CGImageCreate(320, 480, bitsPerComponent, bitsPerPixel, bytesPerRow, colorSpaceRef, bitmapInfo, provider, NULL, NO, renderingIntent);
// then make the uiimage from that
UIImage *myImage = [UIImage imageWithCGImage:imageRef];
return myImage;
}
Although the code above works perfectly, it is a bit leaky.
In the saveImageFromGLView method, buffer, which was allocated using malloc(), must be free()'d eventually! Don't free buffer2 though - apparently it is used by the UIImage which is created and will be released whenever the UIImage gets released.
Furthermore provider, colorSpaceRef, and imageRef must get released. That is the lines
CGDataProviderRelease(provider);
must be added. The rule of thumb here is that any method that contains "Create" in its name returns an object with a retain count of 1, meaning that the object must be released at some point in time so that it can be freed from memory.
CGColorSpaceRelease(colorSpaceRef);
CGImageRelease(imageRef);
Hope this helps!
Yes, need to clean up memory.
How about the return myImage, still need to release it ? autorelease can be used here ?