iOS自定义相机功能

Lida ·
更新时间:2024-11-10
· 1704 次阅读

大多数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; }

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



相机 IOS

需要 登录 后方可回复, 如果你还没有账号请 注册新账号