如何使用Metal API或Accelerate Framework绘制裁剪的位图?

时间:2015-04-23 02:57:38

标签: ios core-graphics accelerate-framework metal vimage

我正在实施一个自定义视频合成器来裁剪视频帧。目前我使用Core Graphics执行此操作:

-(void)renderImage:(CGImageRef)image inBuffer:(CVPixelBufferRef)destination {
    CGRect cropRect = // some rect ...
    CGImageRef currentRectImage = CGImageCreateWithImageInRect(photoFullImage, cropRect);

    size_t width = CVPixelBufferGetWidth(destination);
    size_t height = CVPixelBufferGetHeight(destination);

    CGContextRef context = CGBitmapContextCreate(CVPixelBufferGetBaseAddress(destination),       // data
                                             width,
                                             height,
                                             8,                                              // bpp
                                             CVPixelBufferGetBytesPerRow(destination),
                                             CGImageGetColorSpace(backImage),
                                             CGImageGetBitmapInfo(backImage));

    CGRect frame = CGRectMake(0, 0, width, height);
    CGContextDrawImage(context, frame, currentRectImage);
    CGContextRelease(context);
}

如何使用Metal API执行此操作?它应该快得多,对吧? 使用Accelerate Framework(特定于vImage)怎么样?那会更简单吗?

2 个答案:

答案 0 :(得分:3)

好的,我不知道这对你有用,但仍然如此。 请查看以下代码:

- (void)captureOutput:(AVCaptureOutput *)captureOutput didOutputSampleBuffer:(CMSampleBufferRef)sampleBuffer fromConnection:(AVCaptureConnection *)connection
{
  CVPixelBufferRef pixelBuffer = CMSampleBufferGetImageBuffer(sampleBuffer);

  id<MTLTexture> textureY = nil;

  {
    size_t width = CVPixelBufferGetWidth(pixelBuffer);
    size_t height = CVPixelBufferGetHeight(pixelBuffer);

    MTLPixelFormat pixelFormat = MTLPixelFormatBGRA8Unorm;

    CVMetalTextureRef texture = NULL;
    CVReturn status = CVMetalTextureCacheCreateTextureFromImage(NULL, _textureCache, pixelBuffer, NULL, pixelFormat, width, height, 0, &texture);
    if(status == kCVReturnSuccess)
    {
      textureY = CVMetalTextureGetTexture(texture);
      if (self.delegate){
        [self.delegate textureUpdated:textureY];
      }
      CFRelease(texture);
    }
  }
}

我使用此代码将CVPixelBufferRef转换为MTLTexture。之后你应该创建blitCommandEncoder并使用它的

func copyFromTexture(sourceTexture: MTLTexture, sourceSlice: Int, sourceLevel: Int, sourceOrigin: MTLOrigin, sourceSize: MTLSize, toTexture destinationTexture: MTLTexture, destinationSlice: Int, destinationLevel: Int, destinationOrigin: MTLOrigin)

在其中,您可以选择裁剪的矩形并将其复制到其他纹理。

下一步是将生成的MTLTextures转换回CVPixelBufferRefs,然后制作视频,遗憾的是我不知道该怎么做。

真的很想听听你的想法。欢呼声。

答案 1 :(得分:2)

因为它使用裸指针和未封装的数据,所以vImage会&#34; crop&#34;通过将指针移动到图像的左上角以指向新的左上角并相应地减小高度和宽度。您现在有一个vImage_Buffer,它指的是图像中间的区域。当然,您仍然需要将内容再次导出为文件或将其复制到预定要绘制到屏幕的内容。参见例如vImageCreateCGImageFromBuffer()。

CG可以通过CGImageCreateWithImageInRect()

自行完成

Metal可以将其作为简单的计算副本内核,MTLBlitCommandEncoder blit或纹理的3D渲染应用程序执行此操作,以获得具有适当坐标偏移的三角形集合。