iOS 切换摄像图,捕捉摄像头画面

初始化相关信息

/// 本地实现捕捉镜头功能
- (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:摄像头切换功能代码区----------------------

保存照片到本地

  1. 代理的形式(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];
    }
}
  1. 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);
                            
                    }];
                });
            });
           
        }
    }];
  
}

  1. 获取相册权限

-(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);
        }];
        
        
        
    }
     
    });
    

    


   

}

你可能感兴趣的:(iOS 切换摄像图,捕捉摄像头画面)