網(wǎng)站首頁(yè) 編程語(yǔ)言 正文
大多數(shù)app都會(huì)涉及到上傳照片這個(gè)功能,圖片來(lái)源無(wú)非是從相冊(cè)獲取或者相機(jī)拍攝。如果不是特別要求,調(diào)用系統(tǒng)已經(jīng)滿足需求。但對(duì)于特殊需求,就需要自定義相機(jī)拍攝界面了。
對(duì)于無(wú)需定制的相機(jī),使用系統(tǒng)的UIKit庫(kù)里的UIImagePickerController類,幾行代碼,幾個(gè)代理方法就可滿足所需。但如果要深度定制,就要系統(tǒng)庫(kù)AVFoundation內(nèi)部的相關(guān)類。
創(chuàng)建自己的相機(jī)管理類CameraManager(繼承于NSObject)
.h文件
#import <Foundation/Foundation.h>
#import <AVFoundation/AVFoundation.h>
//拍照后的回調(diào),傳遞拍攝的照片
typedef void(^DidCapturePhotoBlock)(UIImage *stillImage);
@interface PXCameraManager : NSObject
@property (nonatomic, strong) AVCaptureSession *session;//AVCaptureSession對(duì)象來(lái)執(zhí)行輸入設(shè)備和輸出設(shè)備之間的數(shù)據(jù)傳遞
@property (nonatomic, strong) AVCaptureVideoPreviewLayer *previewLayer;//預(yù)覽圖層,來(lái)顯示照相機(jī)拍攝到的畫面
@property (nonatomic, strong) AVCaptureDeviceInput *deviceInput;//AVCaptureDeviceInput對(duì)象是輸入流
@property (nonatomic, strong) AVCaptureStillImageOutput *stillImageOutput;//照片輸出流對(duì)象
@property (nonatomic, assign) CGRect previewLayerFrame;//拍照區(qū)域
/* 為其他類提供的自定義接口 */
//設(shè)置拍照區(qū)域 (其中targetView為要展示拍照界面的view)
- (void)configureWithtargetViewLayer:(UIView *)targetView previewRect:(CGRect)preivewRect;
//拍照成功回調(diào)
- (void)takePicture:(DidCapturePhotoBlock)block;
//添加/移除相機(jī)浮層(如果有需求要在相機(jī)拍照區(qū)域添加浮層的時(shí)候使用)
- (void)addCoverImageWithImage:(UIImage *)image;
- (void)removeCoverImageWithImage:(UIImage *)image;
//前后攝像頭切換
- (void)switchCameras;
//閃光燈切換
- (void)configCameraFlashlight;
@end
.m文件
@property (nonatomic, strong) UIView *preview;//展現(xiàn)拍照區(qū)域的view
@property (nonatomic, strong) UIImageView *coverImageView;//拍照區(qū)域浮層
@property (nonatomic, assign) BOOL isCaremaBack;
@property (nonatomic, assign) AVCaptureFlashMode flashMode;
//初始化的時(shí)候設(shè)置自己想要的默認(rèn)屬性
- (instancetype)init{
? ? self = [super init];
? ? if (self) {
? ? ? ? self.isCaremaBack = YES;//默認(rèn)后置攝像頭
? ? ? ? self.flashMode = AVCaptureFlashModeAuto;//默認(rèn)自動(dòng)閃光燈
? ? }
? ? return ?self;
}
實(shí)現(xiàn)接口的方法
1、準(zhǔn)備相關(guān)硬件
- (void)configureWithTargetViewLayer:(UIView *)targetView previewRect:(CGRect)preivewRect{
? ? self.preview = targetView;
? ? //開(kāi)始一些相機(jī)相關(guān)硬件配置 ? ?
? ? [self addSession];//創(chuàng)建session
? ? [self addVideoPreviewLayerWithRect:preivewRect];//用session 創(chuàng)建 創(chuàng)建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];
? ? ? ? //這里可以根據(jù)不同需求對(duì)拍攝到的照片做一些壓縮或者裁剪的處理,這里我就偷懶不弄了。
? ? ? ? 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;
}
下面是配置硬件里的幾個(gè)方法實(shí)現(xiàn)
- (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(@"出錯(cuò)啦");
? ? ? ? ? ? }
? ? ? ? }
? ? }else{
? ? ? ? AVCaptureDeviceInput *frontCameraDeviceInput = [AVCaptureDeviceInput deviceInputWithDevice:frontCamera error:&error];
? ? ? ? if (!error) {
? ? ? ? ? ? if ([_session canAddInput:frontCameraDeviceInput]) {
? ? ? ? ? ? ? ? [_session addInput:frontCameraDeviceInput];
? ? ? ? ? ? ? ? ?self.deviceInput = frontCameraDeviceInput;
? ? ? ? ? ? }else{
? ? ? ? ? ? ? ? NSLog(@"出錯(cuò)啦");
? ? ? ? ? ? }
? ? ? ? }
? ? }
}
- (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;
}
到此,一個(gè)自定義相機(jī)的類就有了,要使用的時(shí)候,盡管調(diào)用吧。
原文鏈接:https://blog.csdn.net/u013749108/article/details/50705512
相關(guān)推薦
- 2022-03-13 C語(yǔ)言基于graphics.h實(shí)現(xiàn)圣誕樹(shù)_C 語(yǔ)言
- 2021-09-25 Flutter實(shí)現(xiàn)底部彈窗效果_Android
- 2022-07-29 python中open函數(shù)對(duì)文件處理的使用教程_python
- 2023-12-09 SpringBoot自定義異常處理機(jī)制
- 2022-07-16 Electron項(xiàng)目中的NSIS配置項(xiàng)
- 2023-04-06 python?numpy.linalg.norm函數(shù)的使用及說(shuō)明_python
- 2024-04-04 mybatis-config.xml的配置
- 2022-06-02 Go語(yǔ)言中定時(shí)任務(wù)庫(kù)Cron使用方法介紹_Golang
- 最近更新
-
- window11 系統(tǒng)安裝 yarn
- 超詳細(xì)win安裝深度學(xué)習(xí)環(huán)境2025年最新版(
- Linux 中運(yùn)行的top命令 怎么退出?
- MySQL 中decimal 的用法? 存儲(chǔ)小
- get 、set 、toString 方法的使
- @Resource和 @Autowired注解
- Java基礎(chǔ)操作-- 運(yùn)算符,流程控制 Flo
- 1. Int 和Integer 的區(qū)別,Jav
- spring @retryable不生效的一種
- Spring Security之認(rèn)證信息的處理
- Spring Security之認(rèn)證過(guò)濾器
- Spring Security概述快速入門
- Spring Security之配置體系
- 【SpringBoot】SpringCache
- Spring Security之基于方法配置權(quán)
- redisson分布式鎖中waittime的設(shè)
- maven:解決release錯(cuò)誤:Artif
- restTemplate使用總結(jié)
- Spring Security之安全異常處理
- MybatisPlus優(yōu)雅實(shí)現(xiàn)加密?
- Spring ioc容器與Bean的生命周期。
- 【探索SpringCloud】服務(wù)發(fā)現(xiàn)-Nac
- Spring Security之基于HttpR
- Redis 底層數(shù)據(jù)結(jié)構(gòu)-簡(jiǎn)單動(dòng)態(tài)字符串(SD
- arthas操作spring被代理目標(biāo)對(duì)象命令
- Spring中的單例模式應(yīng)用詳解
- 聊聊消息隊(duì)列,發(fā)送消息的4種方式
- bootspring第三方資源配置管理
- GIT同步修改后的遠(yuǎn)程分支