【发布时间】:2012-09-12 09:15:34
【问题描述】:
我有一个类似于 GLPaint 示例的应用程序(但在 OpenGL ES 2.0 上)。我想在某些时候获取绘图视图的屏幕截图。我已经读过这个topic
但我不明白我应该在什么时候调用 CVOpenGLESTextureCacheCreate 并做其他事情。谁能帮帮我?
【问题讨论】:
标签: ios opengl-es opengl-es-2.0
我有一个类似于 GLPaint 示例的应用程序(但在 OpenGL ES 2.0 上)。我想在某些时候获取绘图视图的屏幕截图。我已经读过这个topic
但我不明白我应该在什么时候调用 CVOpenGLESTextureCacheCreate 并做其他事情。谁能帮帮我?
【问题讨论】:
标签: ios opengl-es opengl-es-2.0
我在the answer 中描述的代码描述了像素缓冲区的创建、匹配纹理的提取以及将该纹理绑定为帧缓冲区的输出。您使用该代码一次来设置将渲染场景的帧缓冲区。
每当您想从该纹理中捕获时,您可能需要使用glFinish() 进行阻塞,直到所有 OpenGL ES 渲染完成,然后使用我在此处描述的代码:
CVPixelBufferLockBaseAddress(renderTarget, 0);
_rawBytesForImage = (GLubyte *)CVPixelBufferGetBaseAddress(renderTarget);
// Do something with the bytes
CVPixelBufferUnlockBaseAddress(renderTarget, 0);
提取包含场景图像的纹理的原始字节。
iOS 纹理的内部字节顺序是 BGRA,因此您需要使用类似以下的内容从这些字节创建 CGImageRef:
// It appears that the width of a texture must be padded out to be a multiple of 8 (32 bytes) if reading from it using a texture cache
NSUInteger paddedWidthOfImage = CVPixelBufferGetBytesPerRow(renderTarget) / 4.0;
NSUInteger paddedBytesForImage = paddedWidthOfImage * (int)currentFBOSize.height * 4;
dataProvider = CGDataProviderCreateWithData((__bridge_retained void*)self, _rawBytesForImage, paddedBytesForImage, dataProviderUnlockCallback);
cgImageFromBytes = CGImageCreate((int)currentFBOSize.width, (int)currentFBOSize.height, 8, 32, CVPixelBufferGetBytesPerRow(renderTarget), defaultRGBColorSpace, kCGBitmapByteOrder32Little | kCGImageAlphaPremultipliedFirst, dataProvider, NULL, NO, kCGRenderingIntentDefault);
在上面,我使用dataProviderUnlockCallback() 函数来处理像素缓冲区的解锁和安全恢复渲染,但在您的情况下您可能会忽略它,只需将 NULL 传递给那里的参数。
【讨论】:
另一种选择是:
祝你好运!
编辑
这可能行不通:我现在正在测试,会尽快重新发布。
【讨论】:
-renderInContext: 不捕获 OpenGL ES 内容。
试试VideoToolbox 的VTCreateCGImageFromCVPixelBuffer(适用于iOS 9.x+):
OSStatus VTCreateCGImageFromCVPixelBuffer(CVPixelBufferRef pixelBuffer, CFDictionaryRef options, CGImageRef _Nullable *imageOut);
Parameters
指定将成为 CGImage 图像数据源的像素缓冲区(将 options 设置为 NULL)。
【讨论】: