4

I want to know the use of GLReadPixels function./ How it is reading the pixels? Is it reading GLKView pixels or UIView pixels or anything on the mainscreen which is in bounds provided in the glreadFunction. Or it can only be used if we are using GLKView??

Please clarify my doubt.

Atulkumar V. Jain
  • 5,102
  • 9
  • 44
  • 61
Karan Sehgal
  • 91
  • 1
  • 5

2 Answers2

0

It reads pixels from the current OpenGL (ES) framebuffer. It can't be used to read pixels from UIView, but it can be used for reading from a GLKView because its backed by a framebuffer (however, you can only read its data when its the active framebuffer, which it most likely is at the time of drawing). However, if everything you want is a screenshot of your GLKView, you can use its built-in snapshot method to get an UIImage with its content.

JustSid
  • 25,168
  • 7
  • 79
  • 97
  • Thanks for explaining. And one more thing, how can glreadpixel used to take snapshot of the glkview which contains many subview( uiviews of glkviews)?? – Karan Sehgal Jul 10 '12 at 12:19
  • @KaranSehgal It can't. Also, there is no such thing as a UIView of GLKViews. – JustSid Jul 10 '12 at 12:26
  • Hey man thanks for the info.really appreciate it. I dont know opengl, Ijust wanted screenshot of a view with subviews. But renderInContext method is taking much time as i am taking screenshots frequently for making video.So i read somewhere that using opengl could solve my problem.So do you have any idead about this?? – Karan Sehgal Jul 10 '12 at 12:30
  • @KaranSehgal If you `GLKView` contains subviews, you simply can't capture them via OpenGL. In this case you have to use another method like `renderInContext:`, which btw is the fastest one available. – JustSid Jul 10 '12 at 12:39
0

You can use glreadPixels to read background screen. Here is code to do.

- (UIImage*) getGLScreenshot {
    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;
}

- (void)saveGLScreenshotToPhotosAlbum {
    UIImageWriteToSavedPhotosAlbum([self getGLScreenshot], nil, nil, nil);
}
Guru
  • 21,652
  • 10
  • 63
  • 102