2012-01-26 26 views
18

这似乎是一个简单的任务,但它使我疯狂。 是否可以将包含AVCaptureVideoPreviewLayer的UIView作为子图层转换为要保存的图像?我想创建一个增强现实覆盖,并有一个按钮将图片保存到相机胶卷。拿着电源按钮+主键捕捉屏幕截图到相机胶卷,这意味着我的所有捕获逻辑工作,并且任务是可能的。但我似乎无法使其以编程方式工作。是否可以在图形上下文中呈现AVCaptureVideoPreviewLayer?

我使用AVCaptureVideoPreviewLayer捕获相机图像的实时预览。我所有的尝试渲染图像失败:

previewLayer = [AVCaptureVideoPreviewLayer layerWithSession:captureSession]; 
//start the session, etc... 


//this saves a white screen 
- (IBAction)saveOverlay:(id)sender { 
    NSLog(@"saveOverlay"); 

    UIGraphicsBeginImageContext(appDelegate.window.bounds.size); 
     UIGraphicsBeginImageContext(scrollView.frame.size); 

    [previewLayer.presentationLayer renderInContext:UIGraphicsGetCurrentContext()]; 


// [appDelegate.window.layer renderInContext:UIGraphicsGetCurrentContext()]; 

    UIImage *screenshot = UIGraphicsGetImageFromCurrentImageContext(); 
    UIGraphicsEndImageContext(); 

    UIImageWriteToSavedPhotosAlbum(screenshot, self, 
            @selector(image:didFinishSavingWithError:contextInfo:), nil); 
} 

//这呈现的一切,除了预览图层,这是空白的。

[appDelegate.window.layer renderInContext:UIGraphicsGetCurrentContext()]; 

我读过的地方,这可能是由于iPhone的安全问题。这是真的?

只是要清楚:我不想为相机保存图像。我想将透明预览图层保存在另一个图像上,从而创建透明度。但由于某种原因,我无法完成工作。

回答

4

我可以建议你尝试GPU图像。

https://github.com/BradLarson/GPUImage

它使用OpenGL,所以它是相当快的。它可以处理来自相机的图片并为它们添加滤镜(其中包含很多滤镜),包括边缘检测,运动检测以及更多

这就像OpenCV一样,但基于我自己的体验,GPU图像更易于与项目连接而语言是客观的。如果你决定使用Box2D的物理学

问题可能出现 - 是使用OpenGL太,你将需要花一些时间,直到这2个框架将停止战斗))

+0

我猜的OP和我正在努力,是让使用avcapturevideopreviewlayer实况视频,并尝试添加一个缩放后的图像。我正在尝试在基于人脸检测的实时视频供稿顶部添加缩放图像,并且保存的屏幕截图仅为叠加而不是avcapturevideopreviewlayer。 –

+0

在GPU图像中,往往会在图层上添加滤镜,所以我非常确定只能保存当前图层(GPU图像中有方法可以从图像中制作UIImage)。如果您想要获取显示内容 - 那里是以编程方式制作屏幕截图的方式。现在我不记得了,但是我在堆栈中看到它) – Roma

+0

罗马人,非常感谢你的回答。尽管我没有使用GPUImage,但我一定会尽快使用它。感谢您发布它作为替代选项。 –

15

我喜欢@利用GPU图像罗马的建议- 好想法。 。 。 。但是,如果你想要一个纯CocoaTouch方法,这里是做什么:

实施AVCaptureVideoDataOutputSampleBufferDelegate

- (void)captureOutput:(AVCaptureOutput *)captureOutput didOutputSampleBuffer:(CMSampleBufferRef)sampleBuffer 
fromConnection:(AVCaptureConnection *)connection 
{ 
    // Create a UIImage+Orientation from the sample buffer data 
    if (_captureFrame) 
    { 
     [captureSession stopRunning]; 

     _captureFrame = NO; 
     UIImage *image = [ImageTools imageFromSampleBuffer:sampleBuffer]; 
     image = [image rotate:UIImageOrientationRight]; 

     _frameCaptured = YES; 

     if (delegate != nil) 
     { 
      [delegate cameraPictureTaken:image]; 
     } 
    } 
} 

捕获如下:

+ (UIImage *) imageFromSampleBuffer:(CMSampleBufferRef) sampleBuffer 
{ 
    // Get a CMSampleBuffer's Core Video image buffer for the media data 
    CVImageBufferRef imageBuffer = CMSampleBufferGetImageBuffer(sampleBuffer); 
    // Lock the base address of the pixel buffer 
    CVPixelBufferLockBaseAddress(imageBuffer, 0); 

    // Get the number of bytes per row for the pixel buffer 
    void *baseAddress = CVPixelBufferGetBaseAddress(imageBuffer); 

    // Get the number of bytes per row for the pixel buffer 
    size_t bytesPerRow = CVPixelBufferGetBytesPerRow(imageBuffer); 
    // Get the pixel buffer width and height 
    size_t width = CVPixelBufferGetWidth(imageBuffer); 
    size_t height = CVPixelBufferGetHeight(imageBuffer); 

    // Create a device-dependent RGB color space 
    CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB(); 

    // Create a bitmap graphics context with the sample buffer data 
    CGContextRef context = CGBitmapContextCreate(baseAddress, width, height, 8, 
              bytesPerRow, colorSpace, kCGBitmapByteOrder32Little | kCGImageAlphaPremultipliedFirst); 
    // Create a Quartz image from the pixel data in the bitmap graphics context 
    CGImageRef quartzImage = CGBitmapContextCreateImage(context); 
    // Unlock the pixel buffer 
    CVPixelBufferUnlockBaseAddress(imageBuffer,0); 

    // Free up the context and color space 
    CGContextRelease(context); 
    CGColorSpaceRelease(colorSpace); 

    // Create an image object from the Quartz image 
    UIImage *image = [UIImage imageWithCGImage:quartzImage]; 

    // Release the Quartz image 
    CGImageRelease(quartzImage); 

    return (image); 
} 

交融的UIImage与覆盖

  • 现在你已经有了UIImage,把它添加到一个新的UIView中。
  • 在顶部添加叠加层作为子视图。

捕捉新的UIView

+ (UIImage*)imageWithView:(UIView*)view 
{ 
    UIGraphicsBeginImageContextWithOptions(view.bounds.size, view.opaque, [UIScreen mainScreen].scale); 
    [view.layer renderInContext:UIGraphicsGetCurrentContext()]; 
    UIImage* img = UIGraphicsGetImageFromCurrentImageContext(); 
    UIGraphicsEndImageContext(); 
    return img; 
} 
+0

我认为这是我正在寻找的。将试图让这个运行,让你知道它是如何去。感谢你及时的答复! –

+0

你使用的图像扩展名为图像= [图像旋转:UIImageOrientationRight]; ? –

+0

是的,该步骤是可选的。但是,让我给你的代码。 –

相关问题