如何将OpenGL视图捕获为UIImage?

5
当我尝试使用这种方法将OpenGL视图转换为UIImage时,只返回了视图的背景,而不是GLView内容。如何将OpenGL的上下文转换为UIImage?

我曾经遇到过同样的问题,但是在这里提供的答案下,我得到了一个黑屏。请查看我的回答以了解我最终如何使其工作。 http://stackoverflow.com/questions/11036288/xcode-screenshot-eaglcontext/11868013#11868013 - Nate_Hirsch
3个回答

9

6
使用以下代码将您的opengl视图转换为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];

Taken from


这会渲染黑色背景。有人能帮我看看为什么吗? - Narek Safaryan

4

感谢提供代码。我发现它很有用,但是为了正确释放缓冲区、缓冲区2、图像引用、颜色空间引用和提供程序指针所分配的内存,我需要添加一些额外的代码。请注意,使用提供程序释放函数来释放缓冲区2。

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;
}   

这会在图层上呈现黑色背景,而我已经在initWithCoder中将图层背景设置为透明颜色了。 - manishnath

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接