iOS自定义相机功能

大多数app都会涉及到上传照片这个功能,图片来源无非是从相册获取或者相机拍摄。如果不是特别要求,调用系统已经满足需求。但对于特殊需求,就需要自定义相机拍摄界面了。

对于无需定制的相机,使用系统的UIKit库里的UIImagePickerController类,几行代码,几个代理方法就可满足所需。但如果要深度定制,就要系统库AVFoundation内部的相关类。

创建自己的相机管理类CameraManager(继承于NSObject)

.h文件

#import <Foundation/Foundation.h>
#import <AVFoundation/AVFoundation.h>
//拍照后的回调,传递拍摄的照片
typedef void(^DidCapturePhotoBlock)(UIImage *stillImage);

@interface PXCameraManager : NSObject

@property (nonatomic, strong) AVCaptureSession *session;//AVCaptureSession对象来执行输入设备和输出设备之间的数据传递

@property (nonatomic, strong) AVCaptureVideoPreviewLayer *previewLayer;//预览图层,来显示照相机拍摄到的画面

@property (nonatomic, strong) AVCaptureDeviceInput *deviceInput;//AVCaptureDeviceInput对象是输入流

@property (nonatomic, strong) AVCaptureStillImageOutput *stillImageOutput;//照片输出流对象

@property (nonatomic, assign) CGRect previewLayerFrame;//拍照区域

/* 为其他类提供的自定义接口 */

//设置拍照区域 (其中targetView为要展示拍照界面的view)
- (void)configureWithtargetViewLayer:(UIView *)targetView previewRect:(CGRect)preivewRect;

//拍照成功回调
- (void)takePicture:(DidCapturePhotoBlock)block;

//添加/移除相机浮层(如果有需求要在相机拍照区域添加浮层的时候使用)
- (void)addCoverImageWithImage:(UIImage *)image;
- (void)removeCoverImageWithImage:(UIImage *)image;

//前后摄像头切换
- (void)switchCameras;

//闪光灯切换
- (void)configCameraFlashlight;

@end

.m文件

@property (nonatomic, strong) UIView *preview;//展现拍照区域的view
@property (nonatomic, strong) UIImageView *coverImageView;//拍照区域浮层

@property (nonatomic, assign) BOOL isCaremaBack;
@property (nonatomic, assign) AVCaptureFlashMode flashMode;

//初始化的时候设置自己想要的默认属性
- (instancetype)init{

    self = [super init];
    if (self) {

        self.isCaremaBack = YES;//默认后置摄像头
        self.flashMode = AVCaptureFlashModeAuto;//默认自动闪光灯
    }
    return  self;
}

实现接口的方法

1、准备相关硬件

- (void)configureWithTargetViewLayer:(UIView *)targetView previewRect:(CGRect)preivewRect{

    self.preview = targetView;

    //开始一些相机相关硬件配置    
    [self addSession];//创建session

    [self addVideoPreviewLayerWithRect:preivewRect];//用session 创建 创建layer

    [self addvideoInputBackCamera:self.isCaremaBack];//给session 配置摄像头

    [self addVideoFlashlightWithFlashModel:self.flashMode];//配置闪光灯

    [self addStillImageOutput];//给session 配置输出
}

2、拍照

#pragma mark - 
- (void)takePicture:(DidCapturePhotoBlock)block{

    AVCaptureConnection *captureConnection = [self findCaptureConnection];

    [captureConnection setVideoScaleAndCropFactor:1.0f];

    [_stillImageOutput captureStillImageAsynchronouslyFromConnection:captureConnection completionHandler:^(CMSampleBufferRef imageDataSampleBuffer, NSError *error) {

        NSData *imageData = [AVCaptureStillImageOutput jpegStillImageNSDataRepresentation:imageDataSampleBuffer];

        UIImage *image = [UIImage imageWithData:imageData];
        //这里可以根据不同需求对拍摄到的照片做一些压缩或者裁剪的处理,这里我就偷懒不弄了。
        if (block) {
            block(image);
        }
    }];

}

3、切换摄像头

- (void)switchCameras{
    if (!_deviceInput) {
        return;
    }
    [_session beginConfiguration];

    [_session removeInput:_deviceInput];
    self.isCaremaBack = !self.isCaremaBack;
    [self addvideoInputBackCamera:self.isCaremaBack];

    [_session commitConfiguration];
}

4、切换闪光灯

- (void)configCameraFlashlight{

    switch (self.flashMode) {
        case AVCaptureFlashModeAuto:
        {
            self.flashMode = AVCaptureFlashModeOff;
        }
            break;
        case AVCaptureFlashModeOff:
        {
            self.flashMode = AVCaptureFlashModeOn;
        }
            break;
        case AVCaptureFlashModeOn:
        {
            self.flashMode = AVCaptureFlashModeAuto;
        }
            break;
        default:
            break;
    }

    [self addVideoFlashlightWithFlashModel:self.flashMode];

 }

添加/移除 浮层

- (void)addCoverImageWithImage:(UIImage *)image{

    _coverImageView.image = image;
}
- (void)removeCoverImageWithImage:(UIImage *)image{

    _coverImageView.image = nil;

}

下面是配置硬件里的几个方法实现

- (void)addSession{

    if (!self.session) {
        AVCaptureSession *session = [[AVCaptureSession alloc]init];
        self.session = session;
    }
}
- (void)addVideoPreviewLayerWithRect:(CGRect)previewRect{

    if (!self.previewLayer) {
        AVCaptureVideoPreviewLayer *previewLayer = [[AVCaptureVideoPreviewLayer alloc]initWithSession:_session];
        previewLayer.videoGravity = AVLayerVideoGravityResizeAspectFill;

        self.previewLayer = previewLayer;

        [self.preview.layer addSublayer:self.previewLayer];

    }

    self.previewLayer.frame = previewRect;
}
- (void)addvideoInputBackCamera:(BOOL)back{

    NSArray *devices = [AVCaptureDevice devices];

    AVCaptureDevice *frontCamera;
    AVCaptureDevice *backCamera;
    //获取 前、后 摄像头
    for (AVCaptureDevice *device in devices) {

        if ([device hasMediaType:AVMediaTypeVideo]) {

            if ([device position] == AVCaptureDevicePositionBack) {

                backCamera = device;

            }else if([device position] == AVCaptureDevicePositionFront){

                frontCamera = device;

            }
        }
    }

    NSError *error = nil;

    if(back){
        AVCaptureDeviceInput *backCameraDeviceInput = [AVCaptureDeviceInput deviceInputWithDevice:backCamera error:&error];
        if (!error) {

            if ([_session canAddInput:backCameraDeviceInput]) {

                [_session addInput:backCameraDeviceInput];
                 self.deviceInput = backCameraDeviceInput;

            }else{
                NSLog(@"出错啦");
            }
        }

    }else{

        AVCaptureDeviceInput *frontCameraDeviceInput = [AVCaptureDeviceInput deviceInputWithDevice:frontCamera error:&error];
        if (!error) {

            if ([_session canAddInput:frontCameraDeviceInput]) {

                [_session addInput:frontCameraDeviceInput];
                 self.deviceInput = frontCameraDeviceInput;

            }else{
                NSLog(@"出错啦");
            }
        }
    }

}
- (void)addVideoFlashlightWithFlashModel:(AVCaptureFlashMode )flashModel{

    AVCaptureDevice *device = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo];
    [device lockForConfiguration:nil];

    if ([device hasFlash]) {
        device.flashMode = self.flashMode;
    }

    [device unlockForConfiguration];
}
- (void)addStillImageOutput{

    if (!self.stillImageOutput) {

        AVCaptureStillImageOutput *stillImageOutput = [[AVCaptureStillImageOutput alloc]init];
        NSDictionary *outPutSettingDict = [[NSDictionary alloc]initWithObjectsAndKeys:AVVideoCodecJPEG,AVVideoCodecKey, nil];
        stillImageOutput.outputSettings = outPutSettingDict;

        [_session addOutput:stillImageOutput];

        self.stillImageOutput = stillImageOutput;
    }

}
- (AVCaptureConnection *)findCaptureConnection{

    AVCaptureConnection *videoConnection;

    for (AVCaptureConnection *connection in _stillImageOutput.connections ) {
        for (AVCaptureInputPort *port in connection.inputPorts) {

            if ([[port mediaType] isEqual:AVMediaTypeVideo]) {

                videoConnection = connection;

                return videoConnection;
            }
        }
    }

    return nil;

}

到此,一个自定义相机的类就有了,要使用的时候,尽管调用吧。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持我们。

(0)

相关推荐

  • iOS开发-调用系统相机和相册获取照片示例

    前言:相信大家都知道大部分的app都是有我的模块的,而在我的模块基本都有用户的头像等信息,并且是可以更改头像的.那么今天小编给大家简单介绍一下iOS开发中如何调用系统相机拍照或者相册获取照片.要获取系统相机或者相册,我们需要使用到 UIImagePickerController 这个类.下面我们来看一下如何实现: 首先,需要遵循 UIImagePickerController 代理的两个协议: <UIImagePickerControllerDelegate, UINavigationContr

  • IOS打开系统相机的闪光灯

    IOS有两种的拍照和视频的方式: 1.直接使用UIImagePickerController,这个类提供了一个简单便捷的拍照与选择图片库里图片的功能. 2.另一种是通过AVFoundation.framework框架完全自定义拍照的界面和选择图片库界面.我只做了第一种,就先给大家介绍第一种做法: 一.首先调用接口前,我们需要先判断当前设备是否支持UIImagePickerController,用isSourceTypeAvailable:来判断是否可用 二.查看符合的媒体类型,这个时候我们调用a

  • iOS 10自定义相机功能

    本文实例为大家分享了iOS 10自定义相机功能的具体代码,供大家参考,具体内容如下 直接上代码 // // TGCameraVC.swift // TGPhotoPicker // // Created by targetcloud on 2017/7/25. // Copyright © 2017年 targetcloud. All rights reserved. // import UIKit import AVFoundation import Photos @available(iOS

  • IOS打开照相机与本地相册选择图片实例详解

    IOS打开照相机与本地相册选择图片 最近正好项目里面要集成"打开照相机与本地相册选择图片"的功能,今天就在这边给大家写一个演示程序:打开相机拍摄后或者在相册中选择一张照片,然后将它显示在界面上.好了废话不多说,因为比较简单直接上源码. 首先,我们在头文件中添加需要用到的actionSheet控件,显示图片的UIImageView控件,并且加上所需要的协议 #import <UIKit/UIKit.h> @interface ImagePickerViewController

  • iOS开发-自定义相机实例(仿微信)

    网上有很多自定义相机的例子,这里只是我临时写的一个小demo,仅供参考: 用到了下面几个库: #import <AVFoundation/AVFoundation.h> #import <AssetsLibrary/AssetsLibrary.h> 在使用的时候需要在Info.plist中把相关权限写进去: Privacy - Microphone Usage Description Privacy - Photo Library Usage Description Privacy

  • iOS仿微信相机拍照、视频录制功能

    网上有很多自定义相机的例子,这里只是我临时写的一个iOS自定义相机(仿微信)拍照.视频录制demo,仅供参考: 用到了下面几个库: #import <AVFoundation/AVFoundation.h> #import <AssetsLibrary/AssetsLibrary.h> 在使用的时候需要在Info.plist中把相关权限写进去: Privacy - Microphone Usage Description Privacy - Photo Library Usage

  • iOS框架AVFoundation实现相机拍照、录制视频

    本文实例为大家分享了使用AVFoundation框架实现相机拍照.录制视频的具体代码,供大家参考,具体内容如下 这里是Demo 首先声明以下对象: #import "CustomeCameraViewController.h" #import <AVFoundation/AVFoundation.h> #import <AssetsLibrary/AssetsLibrary.h> @interface CustomeCameraViewController ()

  • iOS自定义相机实现拍照、录制视频

    本文实例为大家分享了iOS自定义相机实现拍照.录制视频的具体代码,供大家参考,具体内容如下 使用AVFoundation框架. 这里是Demo 首先声明以下对象: #import "CustomeCameraViewController.h" #import <AVFoundation/AVFoundation.h> #import <AssetsLibrary/AssetsLibrary.h> @interface CustomeCameraViewContr

  • iOS开发技巧之自定义相机

    最近公司的项目中用到了相机,由于不用系统的相机,UI给的相机切图,必须自定义才可以.就花时间简单研究了一下相机的自定义. 相机属于系统硬件,这就需要我们来手动调用iPhone的相机硬件,分为以下步骤: 1.首先声明以下对象 #import <AVFoundation/AVFoundation.h> //捕获设备,通常是前置摄像头,后置摄像头,麦克风(音频输入) @property (nonatomic, strong) AVCaptureDevice *device; //AVCaptureD

  • IOS10 相册相机闪退bug解决办法

    iOS10系统下调用系统相册.相机功能,遇到闪退的情况,描述如下: This app has crashed because it attempted to access privacy-sensitive data without a usage description.The app's Info.plist must contain an NSPhotoLibraryUsageDescription key with a string value explaining to the use

随机推荐

其他