【问题标题】:How can I dump OpenGL RenderBuffer to PNG or JPG image?如何将 OpenGL RenderBuffer 转储为 PNG 或 JPG 图像?
【发布时间】:2011-02-21 21:23:10
【问题描述】:

我正在开发一个使用 OpenGL 帧缓冲区/渲染缓冲区来绘制手绘线的项目。此应用程序使用 OpenGL ES 1.x,我不知道如何将当前屏幕转储为 PNG 或 JPG 图像。

感谢您阅读此问题。

来自 OpenGL 新手。

用于创建帧缓冲区和渲染缓冲区的代码。

// Generate IDs for a framebuffer object and a color renderbuffer
glGenFramebuffersOES(1, &viewFramebuffer);
glGenRenderbuffersOES(1, &viewRenderbuffer);

glBindFramebufferOES(GL_FRAMEBUFFER_OES, viewFramebuffer);
glBindRenderbufferOES(GL_RENDERBUFFER_OES, viewRenderbuffer);

// This call associates the storage for the current render buffer with the EAGLDrawable (our CAEAGLLayer)
// allowing us to draw into a buffer that will later be rendered to screen wherever the layer is (which corresponds with our view).
[context renderbufferStorage:GL_RENDERBUFFER_OES fromDrawable:(id<EAGLDrawable>)self.layer];
glFramebufferRenderbufferOES(GL_FRAMEBUFFER_OES, GL_COLOR_ATTACHMENT0_OES, GL_RENDERBUFFER_OES, viewRenderbuffer);

glGetRenderbufferParameterivOES(GL_RENDERBUFFER_OES, GL_RENDERBUFFER_WIDTH_OES, &backingWidth);
glGetRenderbufferParameterivOES(GL_RENDERBUFFER_OES, GL_RENDERBUFFER_HEIGHT_OES, &backingHeight);

// For this sample, we also need a depth buffer, so we'll create and attach one via another renderbuffer.
glGenRenderbuffersOES(1, &depthRenderbuffer);
glBindRenderbufferOES(GL_RENDERBUFFER_OES, depthRenderbuffer);
glRenderbufferStorageOES(GL_RENDERBUFFER_OES, GL_DEPTH_COMPONENT16_OES, backingWidth, backingHeight);
glFramebufferRenderbufferOES(GL_FRAMEBUFFER_OES, GL_DEPTH_ATTACHMENT_OES, GL_RENDERBUFFER_OES, depthRenderbuffer);

【问题讨论】:

标签: iphone opengl-es


【解决方案1】:
-(UIImage *)dumpImage
{
    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);

    /* make upside down */

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

    // make data provider from buffer
    CGDataProviderRef 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);

    // make UIImage from CGImage
    UIImage *newUIImage = [UIImage imageWithCGImage:imageRef];

    return newUIImage;
}

freeImageData() 稍后释放数据。

void freeImageData(void *info, const void *data, size_t size) 
{
    //printf("freeImageData called");
    free((void*)data);
}

【讨论】:

  • 要完成这个想法,您可以使用 UIImagePNGRepresentation 或 UIImageJPEGRepresentation 来获取包含编码为 PNG 或 JPEG 的 UIImage 的 NSData。然后,您可以在磁盘上的任何位置输出 NSData(或传输它或任何您想要的),或使用 UIImageWriteToSavedPhotosAlbum 直接写入相册。
  • 如果您关心速度,您可以在阅读之前在 GPU 上翻转图像。这可以通过在固定功能模式下绘制具有翻转纹理坐标的四边形或使用简单的着色器来完成。
猜你喜欢
  • 1970-01-01
  • 2012-06-01
  • 2013-01-08
  • 1970-01-01
  • 1970-01-01
  • 2019-08-25
  • 2013-05-10
  • 1970-01-01
  • 2015-01-31
相关资源
最近更新 更多