iOS使用AVCaptureSession自定义相机

转自:http://www.2cto.com/kf/201409/335951.html

关于iOS调用摄像机来获取照片,通常我们都会调用UIImagePickerController来调用系统提供的相机来拍照,这个控件非常好 用。但是有时UIImagePickerController控件无法满足我们的需求,例如我们需要更加复杂的OverlayerView,这时候我们就 要自己构造一个摄像机控件了。

这需要使用AVFoundation.framework这个framework里面的组件了,所以我们先要导入这个头文件,另外还需要的组件官方文档是这么说的:

● An instance of AVCaptureDevice to represent the input device, such as a camera or microphone
● An instance of a concrete subclass of AVCaptureInput to configure the ports from the input device
● An instance of a concrete subclass of AVCaptureOutput to manage the output to a movie file or still image
● An instance of AVCaptureSession to coordinate the data flow from the input to the output

这里我只构造了一个具有拍照功能的照相机,至于录影和录音功能这里就不加说明了。

总结下来,我们需要以下的对象:

?


1

2

3

4

5

6

7

8

9

10

11

12

13

14

@property (nonatomic, strong)       AVCaptureSession            * session;

//AVCaptureSession对象来执行输入设备和输出设备之间的数据传递

@property (nonatomic, strong)       AVCaptureDeviceInput        * videoInput;

//AVCaptureDeviceInput对象是输入流

@property (nonatomic, strong)       AVCaptureStillImageOutput   * stillImageOutput;

//照片输出流对象,当然我的照相机只有拍照功能,所以只需要这个对象就够了

@property (nonatomic, strong)       AVCaptureVideoPreviewLayer  * previewLayer;

//预览图层,来显示照相机拍摄到的画面

@property (nonatomic, strong)       UIBarButtonItem             * toggleButton;

//切换前后镜头的按钮

@property (nonatomic, strong)       UIButton                    * shutterButton;

//拍照按钮

@property (nonatomic, strong)       UIView                      * cameraShowView;

//放置预览图层的View

我的习惯是在init方法执行的时候创建这些对象,然后在viewWillAppear方法里加载预览图层。现在就让我们看一下代码就清楚了。

?


1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

- (void) initialSession

{

    //这个方法的执行我放在init方法里了

    self.session = [[AVCaptureSession alloc] init];

    self.videoInput = [[AVCaptureDeviceInput alloc] initWithDevice:[self frontCamera] error:nil];

    //[self fronCamera]方法会返回一个AVCaptureDevice对象,因为我初始化时是采用前摄像头,所以这么写,具体的实现方法后面会介绍

    self.stillImageOutput = [[AVCaptureStillImageOutput alloc] init];

    NSDictionary * outputSettings = [[NSDictionary alloc] initWithObjectsAndKeys:AVVideoCodecJPEG,AVVideoCodecKey, nil];

    //这是输出流的设置参数AVVideoCodecJPEG参数表示以JPEG的图片格式输出图片

    [self.stillImageOutput setOutputSettings:outputSettings];

    

    if ([self.session canAddInput:self.videoInput]) {

        [self.session addInput:self.videoInput];

    }

    if ([self.session canAddOutput:self.stillImageOutput]) {

        [self.session addOutput:self.stillImageOutput];

    }

    

}

这是获取前后摄像头对象的方法

?


1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

- (AVCaptureDevice *)cameraWithPosition:(AVCaptureDevicePosition) position {

    NSArray *devices = [AVCaptureDevice devicesWithMediaType:AVMediaTypeVideo];

    for (AVCaptureDevice *device in devices) {

        if ([device position] == position) {

            return device;

        }

    }

    return nil;

}

- (AVCaptureDevice *)frontCamera {

    return [self cameraWithPosition:AVCaptureDevicePositionFront];

}

- (AVCaptureDevice *)backCamera {

    return [self cameraWithPosition:AVCaptureDevicePositionBack];

}

接下来在viewWillAppear方法里执行加载预览图层的方法

?


1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

- (void) setUpCameraLayer

{

    if (_cameraAvaible == NO) return;

    

    if (self.previewLayer == nil) {

        self.previewLayer = [[AVCaptureVideoPreviewLayer alloc] initWithSession:self.session];

        UIView * view = self.cameraShowView;

        CALayer * viewLayer = [view layer];

        [viewLayer setMasksToBounds:YES];

        

        CGRect bounds = [view bounds];

        [self.previewLayer setFrame:bounds];

        [self.previewLayer setVideoGravity:AVLayerVideoGravityResizeAspect];

        

        [viewLayer insertSublayer:self.previewLayer below:[[viewLayer sublayers] objectAtIndex:0]];

        

    }

}

注意以下的方法,在viewDidAppear和viewDidDisappear方法中启动和关闭session

?


1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

- (void) viewDidAppear:(BOOL)animated

{

    [super viewDidAppear:animated];

    if (self.session) {

        [self.session startRunning];

    }

}

- (void) viewDidDisappear:(BOOL)animated

{

    [super viewDidDisappear: animated];

    if (self.session) {

        [self.session stopRunning];

    }

}

接着我们就来实现切换前后镜头的按钮,按钮的创建我就不多说了

?


1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

- (void)toggleCamera {

    NSUInteger cameraCount = [[AVCaptureDevice devicesWithMediaType:AVMediaTypeVideo] count];

    if (cameraCount > 1) {

        NSError *error;

        AVCaptureDeviceInput *newVideoInput;

        AVCaptureDevicePosition position = [[_videoInput device] position];

        

        if (position == AVCaptureDevicePositionBack)

            newVideoInput = [[AVCaptureDeviceInput alloc] initWithDevice:[self frontCamera] error:&error];

        else if (position == AVCaptureDevicePositionFront)

            newVideoInput = [[AVCaptureDeviceInput alloc] initWithDevice:[self backCamera] error:&error];

        else

            return;

        

        if (newVideoInput != nil) {

            [self.session beginConfiguration];

            [self.session removeInput:self.videoInput];

            if ([self.session canAddInput:newVideoInput]) {

                [self.session addInput:newVideoInput];

                [self setVideoInput:newVideoInput];

            } else {

                [self.session addInput:self.videoInput];

            }

            [self.session commitConfiguration];

        } else if (error) {

            NSLog(@"toggle carema failed, error = %@", error);

        }

    }

}

这是切换镜头的按钮方法

?


1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

- (void) shutterCamera

{

    AVCaptureConnection * videoConnection = [self.stillImageOutput connectionWithMediaType:AVMediaTypeVideo];

    if (!videoConnection) {

        NSLog(@"take photo failed!");

        return;

    }

    

    [self.stillImageOutput captureStillImageAsynchronouslyFromConnection:videoConnection completionHandler:^(CMSampleBufferRef imageDataSampleBuffer, NSError *error) {

        if (imageDataSampleBuffer == NULL) {

            return;

        }

        NSData * imageData = [AVCaptureStillImageOutput jpegStillImageNSDataRepresentation:imageDataSampleBuffer];

        UIImage * image = [UIImage imageWithData:imageData];

        NSLog(@"image size = %@",NSStringFromCGSize(image.size));

    }];

}

这是拍照按钮的方法

这样自定义照相机的简单功能就完成了,如果你想要再添加其他复杂的功能,可以参考一下下面这篇文章,希望对你们有所帮助。

http://course.gdou.com/blog/Blog.pzs/archive/2011/12/14/10882.html

时间: 2024-12-24 01:41:36

iOS使用AVCaptureSession自定义相机的相关文章

iOS开发笔记17:自定义相机拍照

之前用AVFoundation自定义相机做了拍照与视频相关的东西,为什么要自定义呢?主要是提供更个性化的交互设计,符合app主题,对于视频来说,也便于提供更多丰富有趣的功能.前段时间整理了下拍照部分的功能,主要分为以下五个部分 1.初始化,建立会话,获取摄像头 使用AVCaptureSessionPresetPhoto模式,输出的图片分辨率与系统相机输出的分辨率保持一致 添加后置摄像头与图片输出(默认采用后置摄像头拍摄) 2.嵌入实时预览层 获取实时预览画面,添加手势,初始化时默认在画面中心点对

IOS开发调用系统相机和打开闪光灯

IOS开发调用系统相机和打开闪光灯      今天给大家分享一下如何调用iphone的拍照功能和打开闪光灯,有些代码我也不太理解,很多是在网上借鉴其他人的.IOS有两种的拍照和视频的方 式:1.直接使用UIImagePickerController,这个类提供了一个简单便捷的拍照与选择图片库里图片的功能.2.另一种是通过 AVFoundation.framework框架完全自定义拍照的界面和选择图片库界面.我只做了第一种,就先给大家介绍第一种做法: 一.首先调用接口前,我们需要先判断当前设备是否

AVFoundation的自定义相机

最近由于工作项目的功能需求,需要用到AVFoundation来自定义相机的功能.所以花了点时间去研究了一下. 在网上可以找到很多实用AVFoundation的自定义相机自定义相机的博文,虽然功能的确是完成了,但是距离我的目标还是有不少的差距的. 首先声明,预览的照片是正方形的,拍摄结果最后得到的图片也是正方形的,再好多的博文上我都没有找到该怎么设置才可以得到正方形的图片. 我是首先拍一张照片,然后在使用图片裁剪的方式得到的正方行图片.好了,接下来就让我们开始吧. 首先要了解这几个类的用处 /**

自定义相机(二) -- 拍照

实现功能: 相机拍照,把图像保持到系统相册. 运行环境: 1.  XCODE 5.1.1 2.  真机(IPHONE5  ,  IOS6.1.4) #import <UIKit/UIKit.h> #import <AVFoundation/AVFoundation.h> //导入 - "视频流" @interface MCViewController : UIViewController @property (strong, nonatomic) AVCaptu

自定义相机(一) -- 预览视频流

实现功能: 自定义视频流,实时预览. 运行环境: 1.  XCODE 5.1.1 2.  真机(IPHONE5  ,  IOS6.1.4) #import <UIKit/UIKit.h> #import <AVFoundation/AVFoundation.h> //导入 - "视频流" @interface MCViewController : UIViewController @property (strong, nonatomic) AVCaptureSe

自定义相机(三) -- 视频流数据 AND 预览 拍照 变焦

实现功能: 1. 视频流数据 2. 预览和拍照变焦, 所见即所得. 运行环境: 1.  XCODE 5.1.1 2.  真机(IPHONE5  ,  IOS6.1.4) #import <UIKit/UIKit.h> #import <AVFoundation/AVFoundation.h> //导入 - "视频流" @interface MCViewController : UIViewController<AVCaptureVideoDataOutpu

Android Multimedia框架总结(十四)Camera框架初识及自定义相机案例

转载请把头部出处链接和尾部二维码一起转载,本文出自逆流的鱼yuiop:http://blog.csdn.net/hejjunlin/article/details/52738492 前言:国庆节告一段落,又是新一月,上月主要是围绕MediaPlayer相关展开,从今天开始,开始分析多媒体框架中的Camera模块,看下今天的Agenda: Camera拍照 Camera录像 新API android.hardware.camera2 新旧API特点对比 Camera自定义相机 新API andro

Android调用系统相机、自定义相机、处理大图片

Android调用系统相机和自定义相机实例 本博文主要是介绍了android上使用相机进行拍照并显示的两种方式,并且由于涉及到要把拍到的照片显示出来,该例子也会涉及到Android加载大图片时候的处理(避免OOM),还有简要提一下有些人SurfaceView出现黑屏的原因. Android应用拍照的两种方式,下面为两种形式的Demo展示出来的效果.    知识点: 一.调用系统自带的相机应用 二.自定义我们自己的拍照界面 三.关于计算机解析图片原理(如何正确加载图片到Android应用中) 所需

iOS开发中自定义字体的方法

http://www.cnblogs.com/iyou/archive/2014/05/25/3751669.html 1. 首先下载你想要设置的字体库,例如设置方正启体简体 2. 添加到工程,一定要注意勾选红色框框处,默认是不勾选的  添加以后 3.在plist文件中添加 4.现在已经添加成功了,但是要使用就必须知道FontName,用以下代码可查到 NSArray *familyNames = [[NSArray alloc] initWithArray:[UIFont familyName