iOS-拍照和调用本地图片

作者: 亦晴工作室 | 来源:发表于2016-08-26 10:07 被阅读725次
    #import <AVFoundation/AVFoundation.h>
    #import "YXKPhotoController.h"
    #import "AVPlayerDemoPlaybackView.h"
    #import "VideoCore.h"
    #import "YXKPublishController.h"
    
    @interface YXKPhotoController () <UIImagePickerControllerDelegate, UINavigationControllerDelegate>
    {
        __weak IBOutlet UIView *photoView;
        __weak IBOutlet UIButton *turnCameraButton;
        __weak IBOutlet UIButton *lightningButton;
        __weak IBOutlet UIButton *cancleButton;
        __weak IBOutlet UIButton *photoButton;
        __weak IBOutlet UIButton *addPhotoButton;
        AVCaptureSession *AVSession;
    }
    
    @property (nonatomic, strong) AVCaptureSession *session;
    @property (nonatomic) BOOL isFlashLight;
    @property (nonatomic, strong) AVCaptureDeviceInput *videoInput;
    @property (nonatomic, strong) AVCaptureStillImageOutput *stillImageOutput;
    @property (nonatomic, strong) AVCaptureVideoPreviewLayer *previewLayer;
    
    @end
    
    @implementation YXKPhotoController
    
    - (void) viewWillDisappear:(BOOL)animated
    {
        [super viewWillDisappear:animated];
        self.tabBarController.tabBar.hidden = NO;
    }
    
    - (void) viewWillAppear:(BOOL)animated
    {
        [super viewWillAppear:animated];
        self.tabBarController.tabBar.hidden = YES;
    }
    
    #pragma mark -- 加载预览图层
    - (void) setUpCameraLayer
    {
        if (self.previewLayer == nil) {
            self.previewLayer = [[AVCaptureVideoPreviewLayer alloc] initWithSession:self.session];
            UIView * view = photoView;
            CALayer * viewLayer = [view layer];
            [viewLayer setMasksToBounds:YES];
           
            CGRect bounds = [view bounds];
            [self.previewLayer setFrame:bounds];
            [self.previewLayer setVideoGravity:AVLayerVideoGravityResizeAspectFill];
           
            [viewLayer insertSublayer:self.previewLayer below:[[viewLayer sublayers] objectAtIndex:0]];
           
        }
    }
    
    - (void) viewDidAppear:(BOOL)animated
    {
        [super viewDidAppear:animated];
        if(self.session)
        {
            [self.session startRunning];
        }
    }
    
    - (void)viewDidLoad {
        [super viewDidLoad];
        [self checkDeviceAuthorizationStatus];
        self.isFlashLight = NO;
        //这个方法的执行我放在init方法里了
        self.session = [[AVCaptureSession alloc] init];
        self.videoInput = [[AVCaptureDeviceInput alloc] initWithDevice:[self backCamera] error:nil];
        //[self fronCamera]方法会返回一个AVCaptureDevice对象,因为我初始化时是采用前摄像头,所以这么写,具体的实现方法后面会介绍
        self.stillImageOutput = [[AVCaptureStillImageOutput alloc] init];
        NSDictionary * outputSettings = [[NSDictionary alloc] initWithObjectsAndKeys:AVVideoCodecJPEG,AVVideoCodecKey, nil];
        //这是输出流的设置参数AVVideoCodecJPEG参数表示以JPEG的图片格式输出图片
        [self.stillImageOutput setOutputSettings:outputSettings];
       
        if ([self.session canAddInput:self.videoInput]) {
            [self.session addInput:self.videoInput];
        }
        if ([self.session canAddOutput:self.stillImageOutput]) {
            [self.session addOutput:self.stillImageOutput];
        }
       
    }
    
    #pragma mark -- 打开闪光灯
    - (IBAction)turnButtonClick:(id)sender
    {
        self.isFlashLight = !self.isFlashLight;
        if(self.isFlashLight)
        {
            [lightningButton setImage:[UIImage imageNamed:@"picker_flash_sel.png"] forState:UIControlStateNormal];
        }
        else
        {
            [lightningButton setImage:[UIImage imageNamed:@"picker_flash.png"] forState:UIControlStateNormal];
            [self closeFlashLight];
        }
    }
    
    -(void)openFlashLight
    {
        AVCaptureDevice * device = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo];
        if (device.torchMode == AVCaptureTorchModeOff) {
            //Create an AV session
            AVCaptureSession * session = [[AVCaptureSession alloc]init];
           
            // Create device input and add to current session
            AVCaptureDeviceInput * input = [AVCaptureDeviceInput deviceInputWithDevice:device error:nil];
            [session addInput:input];
           
            // Create video output and add to current session
            AVCaptureVideoDataOutput * output = [[AVCaptureVideoDataOutput alloc]init];
            [session addOutput:output];
           
            // Start session configuration
            [session beginConfiguration];
            [device lockForConfiguration:nil];
           
            // Set torch to on
            [device setTorchMode:AVCaptureTorchModeOn];
           
            [device unlockForConfiguration];
            [session commitConfiguration];
           
            // Start the session
            [session startRunning];
           
            // Keep the session around
            [self setSession:self.session];
        }
    }
    
    - (void) closeFlashLight
    {
       
    }
    
    #pragma mark -- 反转摄像头
    - (IBAction)turnCameraButtonClick:(id)sender
    {
        [self toggleCamera];
    }
    
    #pragma mark --  翻转摄像头
    - (void)toggleCamera {
        // p判断设备上有几个摄像头
        NSUInteger cameraCount = [[AVCaptureDevice devicesWithMediaType:AVMediaTypeVideo] count];
       
        if (cameraCount > 1) {
            NSError *error;
            AVCaptureDeviceInput *newVideoInput;
            // 获取当前的摄像头是前置还是后置
            AVCaptureDevicePosition position = [[_videoInput device] position];
           
            if (position == AVCaptureDevicePositionBack)
                newVideoInput = [[AVCaptureDeviceInput alloc] initWithDevice:[self frontCamera] error:&error];
            else if (position == AVCaptureDevicePositionFront)
                newVideoInput = [[AVCaptureDeviceInput alloc] initWithDevice:[self backCamera] error:&error];
            else
                return;
           
            if (newVideoInput != nil) {
                // 改变回话的配置前,一定要开启配置,配置完成后提交配置改变
                [self.session beginConfiguration];
                [self.session removeInput:self.videoInput];
                if ([self.session canAddInput:newVideoInput]) {
                    [self.session addInput:newVideoInput];
                    [self setVideoInput:newVideoInput];
                } else {
                    [self.session addInput:self.videoInput];
                }
                // 提交新的配置信息
                [self.session commitConfiguration];
            } else if (error) {
                NSLog(@"toggle carema failed, error = %@", error);
            }
        }
    }
    
    - (IBAction)cancleButtonClick:(id)sender
    {
        self.tabBarController.selectedIndex =  0;
    }
    
    #pragma mark -- 调用摄像头拍照,并且跳转到发布界面
    - (IBAction)photoButtonClick:(id)sender
    {
        [self readImageFromCamera];
    }
    
    #pragma mark -- 从摄像头获取照片
    - (void) readImageFromCamera
    {
        AVCaptureConnection * videoConnection = [self.stillImageOutput connectionWithMediaType:AVMediaTypeVideo];
        if (!videoConnection) {
            NSLog(@"take photo failed!");
            return;
        }
       
        [self.stillImageOutput captureStillImageAsynchronouslyFromConnection:videoConnection completionHandler:^(CMSampleBufferRef imageDataSampleBuffer, NSError *error) {
            if (imageDataSampleBuffer == NULL) {
                return;
            }
          
           
            NSData * imageData = [AVCaptureStillImageOutput jpegStillImageNSDataRepresentation:imageDataSampleBuffer];
            UIImage * image = [UIImage imageWithData:imageData];
            NSLog(@"image size = %@",NSStringFromCGSize(image.size));
            dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.03 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
                    if(self.session)
                    {
                        if(self.isFlashLight)
                        {
                            [self openFlashLight];
                        }
                        [self.session stopRunning];
                    }
                YXKPublishController *publish = [[YXKPublishController alloc] init];
                publish.image = image;
                [self.navigationController pushViewController:publish animated:YES];
            });
        }];
    }
    
    #pragma mark -- 访问本地照片库
    - (IBAction)addPhotoButtonClick:(id)sender
    {
        [self readImageFromAlbum];
    }
    
    #pragma mark -- 从本地读取相册
    - (void) readImageFromAlbum
    {
        UIImagePickerController *imagePicker = [[UIImagePickerController alloc] init];
        // 设置类型, 表示仅仅从相册中获取照片
        imagePicker.sourceType = UIImagePickerControllerSourceTypePhotoLibrary;
        imagePicker.delegate = self;
        // 设置照片是否允许用户编辑
        imagePicker.allowsEditing = NO;
       
        [self presentViewController:imagePicker animated:YES completion:nil];
    }
    
    #pragma mark -- 图片完成处理后提交,代理方法UIPickerControllerDelegate
    - (void) imagePickerController:(UIImagePickerController *)picker didFinishPickingImage:(UIImage *)image editingInfo:(NSDictionary<NSString *,id> *)editingInfo
    {
        YXKPublishController *publish = [[YXKPublishController alloc] init];
        publish.image = image;
        [self.navigationController pushViewController:publish animated:YES];
    }
    
    #pragma mark -- 这是获取前后摄像头对象的方法
    - (AVCaptureDevice *)cameraWithPosition:(AVCaptureDevicePosition) position {
        NSArray *devices = [AVCaptureDevice devicesWithMediaType:AVMediaTypeVideo];
        for (AVCaptureDevice *device in devices) {
            if ([device position] == position) {
                return device;
            }
        }
        return nil;
    }
    
    - (AVCaptureDevice *)frontCamera {
        return [self cameraWithPosition:AVCaptureDevicePositionFront];
    }
    
    - (AVCaptureDevice *)backCamera {
        return [self cameraWithPosition:AVCaptureDevicePositionBack];
    }
    
    #pragma mark -- 是否拥有使用摄像头的权限
    - (void)checkDeviceAuthorizationStatus
    {
        [AVCaptureDevice requestAccessForMediaType:AVMediaTypeVideo completionHandler:^(BOOL granted) {
            if (granted) {
                dispatch_async(dispatch_get_main_queue(), ^{
                    [self setUpCameraLayer];
                });
            }
            else {
                dispatch_async(dispatch_get_main_queue(), ^{
                    UIAlertController * alert = [UIAlertController alertControllerWithTitle:nil
                                                                                    message:@"No permission to use Camera, please change privacy settings" preferredStyle:UIAlertControllerStyleAlert];
                    [alert addAction:[UIAlertAction actionWithTitle:@"Cancel"
                                                              style:UIAlertActionStyleCancel
                                                            handler:^(UIAlertAction * _Nonnull action) {
                                                                [self cancleButtonClick:nil];
                                                            }]];
                   
                    [self presentViewController:alert animated:YES completion:nil];
                });
            }
        }];
    }
    
    - (void)didReceiveMemoryWarning {
        [super didReceiveMemoryWarning];
        // Dispose of any resources that can be recreated.
    }
    
    @end
    

    相关文章

      网友评论

        本文标题:iOS-拍照和调用本地图片

        本文链接:https://www.haomeiwen.com/subject/bxdosttx.html