iPad定制相机界面

  我的应用是iPad上的,工作在Landscape模式,也就是所谓的横屏模式,并且相机界面要定制。首先考虑的当然是UIImagePickerController的cameraOverlayView属性。但是遇到了问题,当iPad旋转后,自定义的视图也会跟着旋转,但是iPhone上就没有问题。尝试子类化UIImagePickerController的- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation方法却没有被调用,很是奇怪,原来官方文档说:“

Important The UIImagePickerController class supports portrait mode only. This class is intended to be used as-is and does not support subclassing. ”

  我就无语了。既然让自定义视图,为啥旋转得不到响应。

  最终得知定制视图还可以通过另一种方式AVFoundation。这个框架比较底层,更加灵活。所以对此进行了学习,通过不懈努力,终于实现了自己的需求。

现在把使用AVFoundation捕捉静态图片做个简单的的介绍:

先来看下AVCaptureSession的工作原理: AVCaptureSession是用来协调控制捕捉设备和输出数据的一个类。

AVCaptureSession

  捕捉图像至少需要一下几个对象:

1 AVCaptureDevice:是输入设备的抽象,比如摄像机、麦克风

AVCaptureInput:用来配置输入设备

AVCaptureOutput:用来管理输出视频文件或者静态图像

AVCaptureSession:协调数据从输入设备到输出对象

 

  如果想从摄像头捕捉一张静态图像,那么需要完成一下几个步骤:

    • Create an AVCaptureSession object to coordinate the flow of data from an AV input device to an output

      (创建AVCaptureSession)对象

    • Find the AVCaptureDevice object for the input type you want

      (获取输入设备)

    • Create an AVCaptureDeviceInput object for the device

      (为输入设备创建 AVCaptureDeviceInput对象)

    • Create an AVCaptureVideoDataOutput object to produce video frames

      (创建输出对象用来产生视频帧)

    • Implement a delegate for the AVCaptureVideoDataOutput object to process video frames

      (完成输出协议,处理视频帧)

    • Implement a function to convert the CMSampleBuffer received by the delegate into a UIImage object                                                                              (完成方法实现CMSampleBuffer到UIImage的转换)

下面是对应具体实现:

/*创建并配置 Session*/
AVCaptureSession *session = [[AVCaptureSession alloc] init];
session.sessionPreset = AVCaptureSessionPresetMedium;
/*创建并配置输入设备*/
AVCaptureDevice *device =
        [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo];
 
NSError *error = nil;
AVCaptureDeviceInput *input =
        [AVCaptureDeviceInput deviceInputWithDevice:device error:&error];
if (!input) {
    // Handle the error appropriately.
}
[session addInput:input];
/*创建输出对象*/
AVCaptureVideoDataOutput *output = [[[AVCaptureVideoDataOutput alloc] init] autorelease]; [session addOutput:output]; output.videoSettings = [NSDictionary dictionaryWithObject:[NSNumber numberWithInt:kCVPixelFormatType_32BGRA] forKey:(id)kCVPixelBufferPixelFormatTypeKey]; output.minFrameDuration = CMTimeMake(1, 15);
dispatch_queue_t queue = dispatch_queue_create("MyQueue", NULL);
[output setSampleBufferDelegate:self queue:queue];
dispatch_release(queue);
/*完成协议*/
- (void)captureOutput:(AVCaptureOutput *)captureOutput
         didOutputSampleBuffer:(CMSampleBufferRef)sampleBuffer
         fromConnection:(AVCaptureConnection *)connection {

  NSAutoreleasePool * pool = [[NSAutoreleasePoolalloc] init];


    UIImage *image = imageFromSampleBuffer(sampleBuffer);
    // Add your code here that uses the image.

  [pool drain];

}
/*开始不抓捕*/
[session startRunning];

需要注意的是:创建输出对象的时候,要设定委托对象,并且要在一个新创建的运行队列里,所以使用了 dispatch_queue_t。协议回调的时候是运行在这个队列中的,所以在协议处理函数中要增加内存池。

以上就是基本的用法,下面贴出我根据书上的一个例子改装的Demo。实现过程中遇到了问题,就是屏幕旋转的时候,实时画面反转错误。所以在旋转的时候,要更改

AVCaptureVideoPreviewLayer的方向。还是看代码吧!

https://github.com/cokecoffe/ios-demo/tree/master/CameraWithAVFoudation

原文地址:https://www.cnblogs.com/cokecoffe/p/2592701.html