1

我有一个类似于 GLPaint 示例的应用程序(但在 OpenGL ES 2.0 上)。我想在某些时候获取绘图视图的屏幕截图。我已经读过这个话题

但我不明白我应该在什么时候调用 CVOpenGLESTextureCacheCreate 并做其他事情。请问谁能帮帮我?

4

3 回答 3

2

我在您链接到的答案中描述的代码描述了像素缓冲区的创建、其匹配纹理的提取以及将该纹理绑定为帧缓冲区的输出。您使用该代码一次来设置您将渲染场景的帧缓冲区。

每当您想从该纹理中捕获时,您可能希望使用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。

于 2012-09-12T15:09:53.223 回答
0

另一种选择是:

  1. 创建一个新的 CGBitmapContext
  2. 调用 [layer renderInContext:yourNewContext]
  3. 从位图上下文中获取 CGImage
  4. 获取一个像素缓冲区,将 CGImage 放入其中,然后使用 AVAdaptor 将其附加到 AssetWriter。

祝你好运!

编辑

这可能行不通:我现在正在对其进行测试,并将尽快重新发布。

于 2013-08-18T16:41:58.333 回答
0

试试VTCreateCGImageFromCVPixelBufferVideoToolbox适用于 iOS 9.x+):

OSStatus VTCreateCGImageFromCVPixelBuffer(CVPixelBufferRef pixelBuffer, CFDictionaryRef options, CGImageRef  _Nullable *imageOut);
Parameters

指定将成为 CGImage 图像数据源的像素缓冲区(设置options为 NULL)。

于 2017-05-10T01:20:38.843 回答