初始化相关信息
/// 本地实现捕捉镜头功能
- (void)initialSession {
if (self.session) {
[self.session startRunning];
return;
}
self.session = [[AVCaptureSession alloc] init];
self.session.sessionPreset = AVCaptureSessionPresetPhoto;
AVCaptureDevice *device = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo];
self.videoInput = [AVCaptureDeviceInput deviceInputWithDevice:device error:nil];
if ([self.session canAddInput:self.videoInput]) {
[self.session addInput:self.videoInput];
}
self.photoOutput = [[AVCapturePhotoOutput alloc] init];
if ([self.session canAddOutput:self.photoOutput]) {
[self.session addOutput:self.photoOutput];
}
[self.photoOutput.connections.lastObject setVideoOrientation:AVCaptureVideoOrientationLandscapeRight];
self.previewLayer = [AVCaptureVideoPreviewLayer layerWithSession:self.session];
self.previewLayer.videoGravity = AVLayerVideoGravityResizeAspectFill;
self.previewLayer.frame = self.view.layer.bounds;
[self.view.layer insertSublayer:self.previewLayer atIndex:0];
[self.session startRunning];
}
切换摄像头
#pragma mark -------begin:摄像头切换功能代码区----------------------
/*操作步骤:
*1.根据媒体类型获取当前捕捉输入物理设备的总数(是否包含前置摄像头);
*2.根据当前处于活跃状态的输入设备,获取未使用的输入设备,(比如当前采集画面的是后置摄像头,这一步需要获取前置摄像头)
*3.获取未使用的输入设备后,需要将其装载到会话Session中,注意 beginConfiguration/commitConfiguration 这两个方法,成对出现,缺一不可。
*/
#pragma mark 摄像头转换
- (void)changeDevices{
if (![self canSwitchCameras]) {
NSLog(@"不支持切换摄像头");
}
NSError * error;
AVCaptureDevice * inActivityDevice = [self inActivityCamera];
AVCaptureDeviceInput * deviceInput = [AVCaptureDeviceInput deviceInputWithDevice:inActivityDevice error:&error];
if (deviceInput) {
//开始装置设备。
[self.session beginConfiguration];
[self.session removeInput:self.videoInput];
if ([self.session canAddInput:deviceInput]) {
[self.session addInput:deviceInput];
self.videoInput = deviceInput;
}else {
//切换失败时,重现将之前的设备添加到会话Session中。
[self.session addInput:self.videoInput];
}
//装置完毕后,需要提交此次的修改。
[self.session commitConfiguration];
}else {
NSLog(@"切换摄像头出错");
}
}
//是否可以切换摄像头
- (BOOL)canSwitchCameras {
//1.获取当前媒体类型的设备数组
NSArray *deviceType = @[AVCaptureDeviceTypeBuiltInWideAngleCamera, AVCaptureDeviceTypeBuiltInDualCamera];
AVCaptureDeviceDiscoverySession *videoDeviceDiscoverySession = [AVCaptureDeviceDiscoverySession discoverySessionWithDeviceTypes:deviceType mediaType:AVMediaTypeVideo position:AVCaptureDevicePositionUnspecified];
//获取 devices
NSArray *devices = videoDeviceDiscoverySession.devices;
NSUInteger count = [devices count];
return count > 1;
}
//根据指定的物理方位返回系统输入设备
- (AVCaptureDevice *)cameraWithPosition:(AVCaptureDevicePosition)position {
NSArray *deviceType = @[AVCaptureDeviceTypeBuiltInWideAngleCamera, AVCaptureDeviceTypeBuiltInDualCamera];
AVCaptureDeviceDiscoverySession *videoDeviceDiscoverySession = [AVCaptureDeviceDiscoverySession discoverySessionWithDeviceTypes:deviceType mediaType:AVMediaTypeVideo position:AVCaptureDevicePositionUnspecified];
//获取 devices
NSArray *devices = videoDeviceDiscoverySession.devices;
for (AVCaptureDevice * device in devices) {
if (device.position == position) {
return device;
}
}
return nil;
}
//获取当前未使用的输入设备(未激活的摄像头)
- (AVCaptureDevice *)inActivityCamera {
AVCaptureDevice * device = nil;
if ([self canSwitchCameras]) {
if (self.videoInput.device.position == AVCaptureDevicePositionBack) {
//注意,这里正好时相反的AVCaptureDevicePosition。
device = [self cameraWithPosition:AVCaptureDevicePositionFront];
}else {
device = [self cameraWithPosition:AVCaptureDevicePositionBack];
}
}
return device;
}
#pragma mark -------end:摄像头切换功能代码区----------------------
保存照片到本地
- 代理的形式(AVCapturePhotoCaptureDelegate)
- (void)savePhoto {
AVCapturePhotoSettings *set = [AVCapturePhotoSettings photoSettings];
[self.photoOutput capturePhotoWithSettings:set delegate:self];
}
#pragma mark - AVCapturePhotoCaptureDelegate
- (void)captureOutput:(AVCapturePhotoOutput *)output didFinishProcessingPhoto:(AVCapturePhoto *)photo error:(NSError *)error API_AVAILABLE(ios(11.0)){
if (!error) {
// 使用该方式获取图片,可能图片会存在旋转问题,在使用的时候调整图片即可
NSData *data = [photo fileDataRepresentation];
UIImage *image = [UIImage imageWithData:data];
// 图片旋转90度
image = [UIImage imageWithCGImage:image.CGImage scale:1 orientation:UIImageOrientationRight];
NSLog(@"image ==== %@", image);
[self.webView evaluateJavaScript:@"capture()" completionHandler:^(id _Nullable script, NSError * _Nullable error) {
NSLog(@"script === %@",script);
UIImage *arImage = [UIImage base64Toimage:script];
dispatch_async(dispatch_get_main_queue(), ^{
[self shotPhoto:image arImage:arImage];
});
}];
}
}
- (void)image:(UIImage *)image didFinishSavingWithError:(NSError *)error contextInfo:(void *)contextInfo{
NSLog(@"%@",contextInfo);
if (error) {
[MBProgressHUD promptMessage:@"保存截图失败" inView:self.view];
}else{
// [UIView animateWithDuration:0.8 animations:^{
// self.backImgView.frame = self.photoBtn.frame;
// } completion:^(BOOL finished) {
// self.photoBtn.hidden = NO;
// [self.photoBtn setImage:image forState:UIControlStateNormal];
// /// 移除图片
// [self.backImgView removeFromSuperview];
// self.backImgView = nil;
// [MBProgressHUD promptMessage:@"截图已保存到本地相册" inView:self.view];
//
// }];
/// 移除图片
[self.backImgView removeFromSuperview];
self.backImgView = nil;
[MBProgressHUD promptMessage:@"截图已保存到本地相册" inView:self.view];
}
}
- block方式(老版本AVCaptureStillImageOutput)
{
self.connection = [self.capVideoOutput connectionWithMediaType:AVMediaTypeVideo];
id handle = ^(CMSampleBufferRef imageDataSampleBuffer,NSError * error){
if (error) {
NSLog(@"%@",error.description);
return ;
}
NSData * imageData = [AVCaptureStillImageOutput jpegStillImageNSDataRepresentation:imageDataSampleBuffer];
UIImage *image = [UIImage imageWithData:imageData];
ALAssetsLibrary * library = [[ALAssetsLibrary alloc]init];
[library writeImageToSavedPhotosAlbum:image.CGImage orientation:(NSInteger)image.imageOrientation completionBlock:^(NSURL *assetURL, NSError *error) {
NSLog(@"%@",assetURL);
}];
};
[self.capVideoOutput captureStillImageAsynchronouslyFromConnection:self.connection completionHandler:handle];
}
+(void)loadImageFinished:(NSString *)imageUrl result:(void (^)(BOOL isSuccess))block
{
[[GYAccess manager] getPhotopermissions:^(bool isPermis) {
if(isPermis) {
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
NSURL *url = [NSURL URLWithString:imageUrl];
NSData *data = [NSData dataWithContentsOfURL:url];
UIImage *image = [UIImage imageWithData:data];
dispatch_async(dispatch_get_main_queue(), ^{
[[PHPhotoLibrary sharedPhotoLibrary] performChanges:^{
//写入图片到相册
PHAssetChangeRequest *req = [PHAssetChangeRequest creationRequestForAssetFromImage:image];
} completionHandler:^(BOOL success, NSError * _Nullable error) {
NSLog(@"success = %d, error = %@", success, error);
block(success);
}];
});
});
}
}];
}
- 获取相册权限
-(void)getPhotopermissions:(void (^)(bool isPermis))success
{
dispatch_async(dispatch_get_main_queue(), ^{
__block bool sranted=NO;
if (@available(iOS 14, *)) {
PHAccessLevel level = PHAccessLevelReadWrite;
[PHPhotoLibrary requestAuthorizationForAccessLevel:level handler:^(PHAuthorizationStatus status) {
switch (status) {
case PHAuthorizationStatusLimited:
NSLog(@"limited");
sranted=YES;
self->isPhoto=sranted;
// [self jumptoVC:@"访问权限受限,无法访问相册中的所有照片"];
success(sranted);
break;
case PHAuthorizationStatusNotDetermined:
NSLog(@"NotDetermined");
sranted=NO;
self->isPhoto=sranted;
[self jumptoVC:@"您还没有允许相册权限"];
success(sranted);
break;
case PHAuthorizationStatusDenied:
NSLog(@"denied");
sranted=NO;
self->isPhoto=sranted;
[self jumptoVC:@"您还没有允许相册权限"];
success(sranted);
break;
case PHAuthorizationStatusAuthorized:
NSLog(@"authorized");
sranted=YES;
self->isPhoto=sranted;
success(sranted);
break;
default:
break;
}
}];
} else {
[PHPhotoLibrary requestAuthorization:^(PHAuthorizationStatus status) {
if (status==PHAuthorizationStatusAuthorized) {
sranted=YES;
}else if (status==PHAuthorizationStatusDenied){
sranted=NO;
[self jumptoVC:@"您还没有允许相册权限"];
NSLog(@"1111sranted==%d",sranted);
}else if (status==PHAuthorizationStatusRestricted){
sranted=YES;
}else
{
sranted=YES;
}
self->isPhoto=sranted;
success(sranted);
NSLog(@"sranted==%d",sranted);
}];
}
});
}