When I try to use this method to convert a OpenGL view to UIImage, only the view's background is returned, but not the GLView content. How can I convert OpenGL's context into a UIImage?
Asked
Active
Viewed 4,464 times
5
-
I had the same problem and with the answers provided here I got a black screen. See my answer to this question to see how I finally got it to work. http://stackoverflow.com/questions/11036288/xcode-screenshot-eaglcontext/11868013#11868013 – Nate_Hirsch Aug 08 '12 at 15:39
3 Answers
9
It depends on what OpenGL view you are using. Since iOS 5 you can make use of GLKit and the corresponding GLKView that greatly simplifies the process of rendering an UIImage.
GLKView* v = (GLKView*) _previewViewController.view;
UIImage* thumbnail = [v snapshot];

Christoph
- 1,965
- 16
- 35
6
Use the below code to convert your opengl
view in UIImage
.
GLubyte *buffer = (GLubyte *) malloc(backingWidth * backingHeight * 4);
GLubyte *buffer2 = (GLubyte *) malloc(backingWidth * backingHeight * 4);
GLvoid *pixel_data = nil;
glReadPixels(0, 0, backingWidth, backingHeight, GL_RGBA, GL_UNSIGNED_BYTE,
(GLvoid *)buffer);
for (int y=0; y<backingHeight; y++) {
for (int x=0; x<backingWidth*4; x++) {
buffer2[y * 4 * backingWidth + x] =
buffer[(backingHeight - y - 1) * backingWidth * 4 + x];
}
}
CGDataProviderRef provider;
provider = CGDataProviderCreateWithData(NULL, buffer2,
backingWidth * backingHeight * 4,
freeImageData);
// set up for CGImage creation
int bitsPerComponent = 8;
int bitsPerPixel = 32;
int bytesPerRow = 4 * backingWidth;
CGColorSpaceRef colorSpaceRef = CGColorSpaceCreateDeviceRGB();
CGBitmapInfo bitmapInfo = kCGBitmapByteOrderDefault;
// Use this to retain alpha
//CGBitmapInfo bitmapInfo = kCGImageAlphaPremultipliedLast;
CGColorRenderingIntent renderingIntent = kCGRenderingIntentDefault;
CGImageRef imageRef = CGImageCreate(backingWidth, backingHeight,
bitsPerComponent, bitsPerPixel,
bytesPerRow, colorSpaceRef,
bitmapInfo, provider,
NULL, NO,
renderingIntent);
// this contains our final image.
UIImage *newUIImage = [UIImage imageWithCGImage:imageRef];

Jhaliya - Praveen Sharma
- 31,697
- 9
- 72
- 76
4
Thanks for the code. I find it usefull but I had to put some extra code in order to properly release allocated memory with buffer, buffer2, imageRef, colorSpaceRef and provider pointer. Note that buffer2 is released with provider release function.
static void myProviderReleaseData (void *info,const void *data,size_t size)
{
free((void*)data);
}
- (UIImage*)renderToImage
{
// The image size should be grabbed from your ESRenderer class.
// That parameter is get in renderer function:
// - (BOOL) resizeFromLayer:(CAEAGLLayer *)layer {
// glGetRenderbufferParameterivOES(GL_RENDERBUFFER_OES, GL_RENDERBUFFER_WIDTH_OES, &backingWidth);
GLint backingWidth = renderer.backingWidth;
GLint backingHeight = renderer.backingHeight;
GLubyte *buffer = (GLubyte *) malloc(backingWidth * backingHeight * 4);
GLubyte *buffer2 = (GLubyte *) malloc(backingWidth * backingHeight * 4);
glReadPixels(0, 0, backingWidth, backingHeight, GL_RGBA, GL_UNSIGNED_BYTE,
(GLvoid *)buffer);
for (int y=0; y<backingHeight; y++) {
for (int x=0; x<backingWidth*4; x++) {
buffer2[y * 4 * backingWidth + x] =
buffer[(backingHeight - y - 1) * backingWidth * 4 + x];
}
}
free(buffer);
CGDataProviderRef provider = CGDataProviderCreateWithData(NULL, buffer2,
backingWidth * backingHeight * 4,
myProviderReleaseData);
// set up for CGImage creation
int bitsPerComponent = 8;
int bitsPerPixel = 32;
int bytesPerRow = 4 * backingWidth;
CGColorSpaceRef colorSpaceRef = CGColorSpaceCreateDeviceRGB();
// Use this to retain alpha
CGBitmapInfo bitmapInfo = kCGImageAlphaPremultipliedLast;
CGColorRenderingIntent renderingIntent = kCGRenderingIntentDefault;
CGImageRef imageRef = CGImageCreate(backingWidth, backingHeight,
bitsPerComponent, bitsPerPixel,
bytesPerRow, colorSpaceRef,
bitmapInfo, provider,
NULL, NO,
renderingIntent);
// this contains our final image.
UIImage *newUIImage = [UIImage imageWithCGImage:imageRef];
CGImageRelease(imageRef);
CGColorSpaceRelease(colorSpaceRef);
CGDataProviderRelease(provider);
return newUIImage;
}

Krešimir Prcela
- 4,257
- 33
- 46
-
This renders black background on the layer whereas i have already set my layer background to clear color in initwithcoder ????? – manishnath Sep 19 '11 at 07:47