0

i have glview in my uiview ,now i have to take scrren shot of combine view of uiview and glview. i googled lot but i dnt found any thing useful i know how to take scrrenshot of glview

nt width = glView.frame.size.width; int height = glView.frame.size.height;

NSInteger myDataLength = width * height * 4;
// allocate array and read pixels into it.
GLubyte *buffer = (GLubyte *) malloc(myDataLength);
glReadPixels(0, 0, width, height, 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 < height; y++)
{
    for(int x = 0; x < width * 4; x++)
    {
        buffer2[((height - 1) - y) * width * 4 + x] = buffer[y * 4 * width + 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 * width;
CGColorSpaceRef colorSpaceRef = CGColorSpaceCreateDeviceRGB();
CGBitmapInfo bitmapInfo = kCGBitmapByteOrderDefault;
CGColorRenderingIntent renderingIntent = kCGRenderingIntentDefault;
// make the cgimage
CGImageRef imageRef = CGImageCreate(width, height, bitsPerComponent, bitsPerPixel, bytesPerRow, colorSpaceRef, bitmapInfo, provider, NULL, NO, renderingIntent);
// then make the uiimage from that
UIImage *myImage = [UIImage imageWithCGImage:imageRef];
return myImage;
genpfault
  • 51,148
  • 11
  • 85
  • 139
dipak
  • 135
  • 4
  • 13

2 Answers2

5

It seems like it's pretty tricky to get a screenshot nowadays, especially when you're mixing the UIKit and OpenGL ES: there used to be UIGetScreenImage() but Apple made it private again and is rejecting apps that use it.

Instead, there are two "solutions" to replace it: Screen capture in UIKit applications and OpenGL ES View Snapshot. The former does not capture OpenGL ES or video content while the later is only for OpenGL ES.

There is another technical note How do I take a screenshot of my app that contains both UIKit and Camera elements?, and here they essentially say: You need to first capture the camera picture and then when rendering the view hierarchy, draw that image in the context.

The very same would apply for OpenGL ES: You would first need to render a snapshot for your OpenGL ES view, then render the UIKit view hierarchy into an image context and draw the image of your OpenGL ES view on top of it. Very ugly, and depending on your view hierarchy it might actually not be what you're seeing on screen (e. g. if there are views in front of your OpenGL view).

DarkDust
  • 90,870
  • 19
  • 190
  • 224
  • @ DarkDust :- very useful answer.....hey i have an issue regarding capturing the OpenGl es using glReadPixels ....a call to glReadPixels() decreases the FPS from around 30 to 2-3 only....why ? – Tornado Aug 08 '11 at 07:08
  • @Tornado: I have no idea, but generally, Apple says that its OpenGL ES implementation is tuned to write operations and reading any state is slow and should be avoided. It's better to remember the states you care about yourself rather than querying it. That can't be done for `glReadPixels`, of course, but I guess you should try to reduce the calls to it if possible. – DarkDust Aug 08 '11 at 07:31
  • @ DarkDust k hey i m trying the record the gameplay of my game so that i can upload its video to youtube from device itself...m trying to do same thing as Talking tomcat app for iphone..recording the video then playing it ,etc...i think that app is also made with the help of Opengl ES it also has the video recording facility but it doesnot slows down while reading each frame any idea ? – Tornado Aug 08 '11 at 07:49
  • @Tornado: No, please ask a new question about that. – DarkDust Aug 08 '11 at 09:36
1

Inspired by DarkDust, I was successful in implementing a screen capture of a mix of uiview and openglview (cocos2d 2.0 view). I've sanitized the code a bit and pasted below, hopefully it's helpful for others.

To help explain the setup, my app screen has 4 view layers: the back is a background UIView with background images "backgroundLayer", the middle are 2 layers of Cocos2d glview "glLayer1 and glLayer2"; and the front is another UIView layer with a few native UI controls (e.g. UIButtons) "frontView".

Here's the code:

+ (UIImage *) grabScreenshot
{
    // Get the 2 layers in the middle of cocos2d glview and store it as UIImage
    [CCDirector sharedDirector].nextDeltaTimeZero = YES;

    CGSize winSize = [CCDirector sharedDirector].winSize;
    CCRenderTexture* rtx =
        [CCRenderTexture renderTextureWithWidth:winSize.width
                                         height:winSize.height];
    [rtx begin];
    [glLayer1 visit];
    [glLayer2 visit];
    [rtx end];

    UIImage *openglImage = [rtx getUIImage];

    UIGraphicsBeginImageContext(winSize);

    // Capture the bottom layer
    [backgroundView.layer renderInContext:UIGraphicsGetCurrentContext()];
    // Save the captured glLayers image to the image context
    [openglImage drawInRect:CGRectMake(0, 0, openglImage.size.width, openglImage.size.height)];
    [frontView.layer renderInContext:UIGraphicsGetCurrentContext()];

    UIImage *viewImage = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();

    return viewImage;
}
marcwjj
  • 1,705
  • 1
  • 12
  • 11