相机

https://github.com/starainDou 欢迎点星

拍照方式

拍照大体上有两种方式:UIImagePickerController方式和AVFoundation方式,前者简单易用但是不利于定制和一些复杂操作,后者反之。

* UIImagePickerController 拍照

属性、枚举、代理

@property (nonatomic) UIImagePickerControllerSourceType sourceType;
typedef NS_ENUM(NSInteger, UIImagePickerControllerSourceType) {
    UIImagePickerControllerSourceTypePhotoLibrary,//照片库
    UIImagePickerControllerSourceTypeCamera,//摄像头
    UIImagePickerControllerSourceTypeSavedPhotosAlbum//相簿
};
/* 
  媒体类型,默认情况下此数组包含kUTTypeImage,表示拍照
  如果要录像,必须设置为kUTTypeVideo(视频不带声音)或kUTTypeMovie(视频带声音)
*/
@property (nonatomic,copy) NSArray *mediaTypes;
@property (nonatomic) NSTimeInterval videoMaximumDuration;//视频最大录制时长,默认10s
@property (nonatomic) UIImagePickerControllerQualityType videoQuality;//视频质量
typedef NS_ENUM(NSInteger, UIImagePickerControllerQualityType) {
    UIImagePickerControllerQualityTypeHigh = 0,  //高清 1920x1080
    UIImagePickerControllerQualityTypeMedium,    //中等,适合WiFi传输 568x320
    UIImagePickerControllerQualityTypeLow,      //低质量,适合蜂窝网传输 224x128
    UIImagePickerControllerQualityType640x480, //640*480
    UIImagePickerControllerQualityTypeIFrame1280x720, //1280*720
    UIImagePickerControllerQualityTypeIFrame960x540, //960*540
};

@property (nonatomic)  BOOL showsCameraControls;/* 是否显示摄像头控制面板,默认为YES */
@property (nonatomic,strong) UIView *cameraOverlayView;/* 摄像头上覆盖的视图 */
@property (nonatomic) CGAffineTransform cameraViewTransform;/* 摄像头形变 */

@property (nonatomic) UIImagePickerControllerCameraCaptureMode cameraCaptureMode;/* 摄像头捕捉模式 */
typedef NS_ENUM(NSInteger, UIImagePickerControllerCameraCaptureMode) {
    UIImagePickerControllerCameraCaptureModePhoto,//拍照模式
    UIImagePickerControllerCameraCaptureModeVideo//视频录制模式
};
@property (nonatomic) UIImagePickerControllerCameraDevice cameraDevice;/* 摄像头设备 */
typedef NS_ENUM(NSInteger, UIImagePickerControllerCameraDevice) {
    UIImagePickerControllerCameraDeviceRear,//前置摄像头
    UIImagePickerControllerCameraDeviceFront//后置摄像头
};
@property (nonatomic) UIImagePickerControllerCameraFlashMode cameraFlashMode;/* 闪光灯模式 */
typedef NS_ENUM(NSInteger, UIImagePickerControllerCameraFlashMode) {
    UIImagePickerControllerCameraFlashModeOff  = -1,//关闭闪光灯
    UIImagePickerControllerCameraFlashModeAuto = 0,//闪光灯自动,默认
    UIImagePickerControllerCameraFlashModeOn   = 1//打开闪光灯
};

/** 对象方法 */
- (void)takePicture; //拍照                     
- (BOOL)startVideoCapture;//开始录制视频
- (void)stopVideoCapture;//停止录制视频

/** 代理方法 */
- (void)imagePickerController:(UIImagePickerController *)picker 
didFinishPickingMediaWithInfo:(NSDictionary *)info;
- (void)imagePickerControllerDidCancel:(UIImagePickerController *)picker;

/** 相册操作扩展 */

/* 保存图片到相簿 */
void UIImageWriteToSavedPhotosAlbum(
    UIImage *image,//保存的图片UIImage
    id completionTarget,//回调的执行者
    SEL completionSelector, //回调方法
    void *contextInfo//回调参数信息
);
//上面一般保存图片的回调方法为:
- (void)image:(UIImage *)image 
        didFinishSavingWithError:(NSError *)error 
        contextInfo:(void *)contextInfo;

/* 判断是否能保存视频到相簿 */
BOOL UIVideoAtPathIsCompatibleWithSavedPhotosAlbum(NSString *videoPath);
/* 保存视频到相簿 */
void UISaveVideoAtPathToSavedPhotosAlbum(
    NSString *videoPath, //保存的视频文件路径
    id completionTarget, //回调的执行者
    SEL completionSelector,//回调方法
    void *contextInfo//回调参数信息
);
//上面一般保存视频的回调方法为:
- (void)video:(NSString *)videoPath 
        didFinishSavingWithError:(NSError *)error 
        contextInfo:(void *)contextInfo;

具体使用

#import "ViewController.h"
#import 

@interface ViewController () 
@property (strong, nonatomic) UIImagePickerController *pickerController;//拾取控制器
@property (strong, nonatomic) IBOutlet UIImageView *showImageView;//显示图片
@end

@implementation ViewController
- (void)viewDidLoad {
    [super viewDidLoad];
    //初始化拾取控制器
    [self initPickerController];
}
/* 初始化拾取控制器 */
- (void)initPickerController{
    //创建拾取控制器
    UIImagePickerController *pickerController = [[UIImagePickerController alloc] init];
    //设置拾取源为摄像头
    pickerController.sourceType = UIImagePickerControllerSourceTypeCamera;
    //设置摄像头为后置
    pickerController.cameraDevice = UIImagePickerControllerCameraDeviceRear;
    pickerController.editing = YES;//设置运行编辑,即可以点击一些拾取控制器的控件
    pickerController.delegate = self;//设置代理
    self.pickerController = pickerController;
}
#pragma mark - UI点击
/* 点击拍照 */
- (IBAction)imagePicker:(id)sender {
    //设定拍照的媒体类型
    self.pickerController.mediaTypes = @[(NSString *)kUTTypeImage];
    //设置摄像头捕捉模式为捕捉图片
    self.pickerController.cameraCaptureMode = UIImagePickerControllerCameraCaptureModePhoto;
    //模式弹出拾取控制器
    [self presentViewController:self.pickerController animated:YES completion:nil];
}
/* 点击录像 */
- (IBAction)videoPicker:(id)sender {
    //设定录像的媒体类型
    self.pickerController.mediaTypes = @[(NSString *)kUTTypeMovie];
    //设置摄像头捕捉模式为捕捉视频
    self.pickerController.cameraCaptureMode = UIImagePickerControllerCameraCaptureModeVideo;
    //设置视频质量为高清
    self.pickerController.videoQuality = UIImagePickerControllerQualityTypeHigh;
    //模式弹出拾取控制器
    [self presentViewController:self.pickerController animated:YES completion:nil];
}

#pragma mark - 代理方法
/* 拍照或录像成功,都会调用 */
- (void)imagePickerController:(UIImagePickerController *)picker
didFinishPickingMediaWithInfo:(NSDictionary *)info
{
    //从info取出此时摄像头的媒体类型
    NSString *mediaType = [info objectForKey:UIImagePickerControllerMediaType];

    if ([mediaType isEqualToString:(NSString *)kUTTypeImage]) {//如果是拍照
        //获取拍照的图像
        UIImage *image = [info objectForKey:UIImagePickerControllerOriginalImage];
        //保存图像到相簿
        UIImageWriteToSavedPhotosAlbum(image, self, 
                  @selector(image:didFinishSavingWithError:contextInfo:), nil);

    } else if ([mediaType isEqualToString:(NSString *)kUTTypeMovie]) {//如果是录像
        //获取录像文件路径URL
        NSURL *url = [info objectForKey:UIImagePickerControllerMediaURL];
        NSString *path = url.path;
        //判断能不能保存到相簿
        if (UIVideoAtPathIsCompatibleWithSavedPhotosAlbum(path)) {
            //保存视频到相簿
            UISaveVideoAtPathToSavedPhotosAlbum(path, self, 
                   @selector(video:didFinishSavingWithError:contextInfo:), nil);
        }

    }
    //拾取控制器弹回
    [self dismissViewControllerAnimated:YES completion:nil];
}
/* 取消拍照或录像会调用 */
- (void)imagePickerControllerDidCancel:(UIImagePickerController *)picker
{
    NSLog(@"取消");
    //拾取控制器弹回
    [self dismissViewControllerAnimated:YES completion:nil];
}

#pragma mark - 保存图片或视频完成的回调
- (void)image:(UIImage *)image didFinishSavingWithError:(NSError *)error
                                            contextInfo:(void *)contextInfo {
    NSLog(@"保存图片完成");
    self.showImageView.image = image;
    self.showImageView.contentMode = UIViewContentModeScaleToFill;
}

- (void)video:(NSString *)videoPath didFinishSavingWithError:(NSError *)error
                                                 contextInfo:(void *)contextInfo {
    NSLog(@"保存视频完成");
}
@end
* AVFoundation 拍照
相机_第1张图片
Camera.jpg

CameraVC.h

//  Created by Rain Dou on 15/10/1.
//  Copyright © 2015年 shiwo@ShangHai. All rights reserved.

#import 

@interface CameraVC : UIViewController

@property (nonatomic, copy) void(^CameraBlock)(NSURL *fileURL);

@end

CameraVC.m

//  Created by Rain Dou on 15/10/1.
//  Copyright © 2015年 shiwo@ShangHai. All rights reserved.

#import "CameraVC.h"
#import 
#import 
#import 
#import 
#import "HollowView.h"

#define SOUNDID   1108
#define TextColor SWColor(255, 204, 26, 1.0)
#define ResetText NSLocalizedString(@"Retake", nil)
#define UseText   NSLocalizedString(@"使用gif", nil)
#define AutoText  NSLocalizedString(@"Auto", nil)
#define OffText   NSLocalizedString(@"Off", nil)
#define OnText    NSLocalizedString(@"On", nil)

/** 视频文件输出代理 */
typedef void(^PropertyChangeBlock)(AVCaptureDevice *captureDevice);

@interface CameraVC ()

// AVFoundation
@property (nonatomic, strong) AVCaptureSession *captureSession;
@property (nonatomic, strong) AVCaptureDeviceInput *captureDeviceInput;
@property (nonatomic, strong) AVCaptureStillImageOutput *captureStillImageOutput;
@property (nonatomic, strong) AVCaptureMovieFileOutput *captureMovieFileOutput;
@property (nonatomic, strong) AVCaptureVideoPreviewLayer *captureVideoPreviewLayer;

// view
@property (nonatomic, strong) UIButton *backBtn;
@property (nonatomic, strong) UIButton *toggleBtn;
@property (nonatomic, strong) UIView   *viewContainer;
@property (nonatomic, strong) UIView   *holeView;
@property (nonatomic, strong) UIButton *flashBtn;
@property (nonatomic, strong) UIView   *flashView;
@property (nonatomic, strong) UIButton *takeBtn;
@property (nonatomic, strong) UIButton *resetBtn;
@property (nonatomic, strong) UIButton *useBtn;
@property (nonatomic, strong) UIImageView *focusCursor;

// Data
@property (nonatomic, strong) NSMutableArray *imgArray;
@property (nonatomic, strong) NSURL *gifURL;

@end

@implementation CameraVC

- (void)viewDidLoad {
    [super viewDidLoad];
    self.view.backgroundColor = [UIColor blackColor];
    _imgArray = [NSMutableArray array];
    [self setupNavBar];
    [self setContainerView];
    [self setupToolBar];
    [self initAVCaptureSession];
}

- (void)viewWillAppear:(BOOL)animated {
    [super viewWillAppear:animated];
    self.navigationController.navigationBarHidden = YES;
}
- (void)viewWillDisappear:(BOOL)animated {
    [super viewWillDisappear:animated];
    self.navigationController.navigationBarHidden = NO;
}
#pragma mark - init view
- (void)setupNavBar
{
    _backBtn   = [self btnFrame:CGRectMake(12, 12, 40, 40)               title:nil img:@"Back"          superView:self.view action:@selector(backBtnClick)];
    _toggleBtn = [self btnFrame:CGRectMake(SWScreenW/2.0-20, 14, 40, 40) title:nil img:@"CameraToggle"  superView:self.view action:@selector(toggleBtnClick:)];
    _flashBtn  = [self btnFrame:CGRectMake(SWScreenW-52, 12, 40, 40)     title:nil img:@"CameraFlashOn" superView:self.view action:@selector(flashClick:)];
    _flashView = [[UIView alloc] initWithFrame:CGRectMake(0, 12, SWScreenW-52, 40)];
    [self.view addSubview:_flashView];
    CGFloat tmpWidth = (SWScreenW-104)/3.0;
    [self btnFrame:CGRectMake(52+0*tmpWidth, 0, tmpWidth, 40) title:OffText  img:nil superView:_flashView action:@selector(flashOffClick:)];
    [self btnFrame:CGRectMake(52+1*tmpWidth, 0, tmpWidth, 40) title:OnText   img:nil superView:_flashView action:@selector(flashOnClick:)];
    [self btnFrame:CGRectMake(52+2*tmpWidth, 0, tmpWidth, 40) title:AutoText img:nil superView:_flashView action:@selector(flashAutoClick:)];
    _flashView.backgroundColor = [UIColor blackColor];
    _flashView.hidden = YES;
}
- (void)setContainerView
{
    _viewContainer = [[UIView alloc] initWithFrame:CGRectMake(0, 64, SWScreenW, SWScreenH - 174)];
    [self.view addSubview:_viewContainer];

    _holeView = [[HollowView alloc] initWithFrame:_viewContainer.frame];
    [self.view insertSubview:_holeView aboveSubview:_viewContainer];
}
- (void)setupToolBar
{
    _takeBtn = [self btnFrame:CGRectMake(SWScreenW/2.0-30, SWScreenH-110, 60, 110) title:nil img:@"CameraTake" superView:self.view action:@selector(takeBtnClick:)];
    _resetBtn = [self btnFrame:CGRectMake(26, SWScreenH-45, 50, 25) title:ResetText img:nil superView:self.view action:@selector(resetBtnClick:)];
    _resetBtn.contentHorizontalAlignment = UIControlContentHorizontalAlignmentLeft;
    _useBtn = [self btnFrame:CGRectMake(SWScreenW-86, SWScreenH-45, 60, 25) title:UseText img:nil superView:self.view action:@selector(useBtnClick:)];
    _resetBtn.hidden = YES;
    _useBtn.hidden = YES;
}
#pragma mark 创建按钮
- (UIButton *)btnFrame:(CGRect)frame title:(NSString *)title img:(NSString *)img superView:(UIView *)superView action:(SEL)action
{
    UIButton *button = [UIButton buttonWithType:UIButtonTypeCustom];
    button.frame = frame;
    if (img) [button setImage:[UIImage imageNamed:img] forState:UIControlStateNormal];
    if (title)
    {
        [button setTitle:title forState:UIControlStateNormal];
        [button setTitleColor:TextColor forState:UIControlStateNormal];
        button.titleLabel.font = Font16;
    }
    [button addTarget:self action:action forControlEvents:UIControlEventTouchUpInside];
    [superView addSubview:button];
    return button;
}
#pragma mark - private method
- (void)initAVCaptureSession
{
    _captureSession = [[AVCaptureSession alloc] init];
    if ([_captureSession canSetSessionPreset:AVCaptureSessionPresetHigh])
    {
        [_captureSession setSessionPreset:AVCaptureSessionPreset640x480];
    }
    
    AVCaptureDevice *captureDevice = [self getCameraDeviceWithPosition:AVCaptureDevicePositionBack];
    if (!captureDevice) {
        NSLog(@"取得后置摄像头时出现问题.");
        return;
    }
    
    NSError *error = nil;
    _captureDeviceInput = [[AVCaptureDeviceInput alloc] initWithDevice:captureDevice error:&error];
    if (error) {
        NSLog(@"取得设备输入对象时出错,错误原因:%@",error.localizedDescription);
        return;
    }
    
    _captureStillImageOutput = [[AVCaptureStillImageOutput alloc] init];
    NSDictionary *outputSetting = @{AVVideoCodecKey : AVVideoCodecJPEG};
    [_captureStillImageOutput setOutputSettings:outputSetting];
    
    if ([_captureSession canAddInput:_captureDeviceInput])
    {
        [_captureSession addInput:_captureDeviceInput];
    }
    if ([_captureSession canAddOutput:_captureStillImageOutput])
    {
        [_captureSession addOutput:_captureStillImageOutput];
    }
    
    _captureVideoPreviewLayer = [[AVCaptureVideoPreviewLayer alloc] initWithSession:_captureSession];
    CALayer *containerLayer = self.viewContainer.layer;
    containerLayer.masksToBounds = YES;
    _captureVideoPreviewLayer.frame = containerLayer.bounds;
    _captureVideoPreviewLayer.videoGravity = AVLayerVideoGravityResizeAspectFill;
    [containerLayer insertSublayer:_captureVideoPreviewLayer below:_focusCursor.layer];
    
    [self addNotificationToCaptureDevice:captureDevice];
    [self addGestureRecognizer];
    [self setFlashMode:AVCaptureFlashModeAuto];
    [_captureSession startRunning];
}

- (AVCaptureDevice *)getCameraDeviceWithPosition:(AVCaptureDevicePosition)position
{
    NSArray *devices = [AVCaptureDevice devicesWithMediaType:AVMediaTypeVideo];
    for (AVCaptureDevice *camera in devices)
    {
        if ([camera position] == position)
        {
            return camera;
        }
    }
    return nil;
}
#pragma mark 生成gif
- (void)makeGif
{
    NSDictionary *fileProperties = @{(__bridge id)kCGImagePropertyGIFDictionary:@{(__bridge id)kCGImagePropertyGIFLoopCount:@0,}};
    NSDictionary *frameProperties = @{(__bridge id)kCGImagePropertyGIFDictionary:@{(__bridge id)kCGImagePropertyGIFDelayTime:@0.5f,}};
    NSURL *documentsDirectoryURL = [[NSFileManager defaultManager] URLForDirectory:NSDocumentDirectory inDomain:NSUserDomainMask appropriateForURL:nil create:YES error:nil];
    NSURL *fileURL = [documentsDirectoryURL URLByAppendingPathComponent:@"animated.gif"];
    CGImageDestinationRef destination = CGImageDestinationCreateWithURL((__bridge CFURLRef)fileURL, kUTTypeGIF, self.imgArray.count, NULL);
    CGImageDestinationSetProperties(destination, (__bridge CFDictionaryRef)fileProperties);
    
    for (NSUInteger i = 0; i < self.imgArray.count; i++)
    {
        @autoreleasepool
        {
            CGImageDestinationAddImage(destination, ((UIImage *)self.imgArray[i]).CGImage, (__bridge CFDictionaryRef)frameProperties);
        }
    }
    
    if (!CGImageDestinationFinalize(destination))
    {
        NSLog(@"failed to finalize image destination");
    }
    CFRelease(destination);
    self.gifURL = fileURL;
    NSString *path = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES)[0] stringByAppendingPathComponent:@"animated.gif"];
    SWInfoLog(@"");
    SWLog(@"%@",NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES));
    // 保存到本地相册
    NSData *data = [NSData dataWithContentsOfFile:path];
    ALAssetsLibrary *library = [[ALAssetsLibrary alloc] init];
    [library writeImageDataToSavedPhotosAlbum:data metadata:nil completionBlock:^(NSURL *assetURL, NSError *error) {
        SWInfoLog(@"");
        NSLog(@"Success at %@", [assetURL path] );
    }];
![Camera.jpg](http://upload-images.jianshu.io/upload_images/1465510-f8d27817f1ffd72c.jpg?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)

}
#pragma mark - Notification
#pragma mark 给输入设备添加通知
- (void)addNotificationToCaptureDevice:(AVCaptureDevice *)captureDevice
{
    // 添加区域改变捕获通知首先设置设备允许捕获
    [self changeDeviceProperty:^(AVCaptureDevice *captureDevice) {
        captureDevice.subjectAreaChangeMonitoringEnabled = YES;
    }];
    [SWNotification addObserver:self selector:@selector(areaChange:) name:AVCaptureDeviceSubjectAreaDidChangeNotification object:captureDevice];
}
#pragma mark 给会话添加通知
- (void)addNotificationToCaptureSession:(AVCaptureSession *)captureSession
{
    [SWNotification addObserver:self selector:@selector(sessionRuntimeError:) name:AVCaptureSessionRuntimeErrorNotification object:captureSession];
}
#pragma mark 移除设备通知
- (void)removeNotificationFromCaptureDevice:(AVCaptureDevice *)captureDevice
{
    [SWNotification removeObserver:self name:AVCaptureDeviceSubjectAreaDidChangeNotification object:captureDevice];
}
- (void)changeDeviceProperty:(PropertyChangeBlock)propertyChange
{
    AVCaptureDevice *captureDevice = [_captureDeviceInput device];
    NSError *error = nil;
    // 注意改变设备属性前先加锁,调用完解锁
    if ([captureDevice lockForConfiguration:&error])
    {
        propertyChange(captureDevice);
        [captureDevice unlockForConfiguration];
    }
    else SWLog(@"changeDevicePropertyError:%@",error.localizedDescription);
}

#pragma mark 添加手势
- (void)addGestureRecognizer
{
    UITapGestureRecognizer *tapGesture = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(tapScreen:)];
    [_viewContainer addGestureRecognizer:tapGesture];
}
#pragma mark 点击屏幕聚焦
- (void)tapScreen:(UITapGestureRecognizer *)gesture
{
    CGPoint point= [gesture locationInView:self.viewContainer];
    // 将UI坐标转化为摄像头坐标
    CGPoint cameraPoint= [self.captureVideoPreviewLayer captureDevicePointOfInterestForPoint:point];
    [self setFocusCursorWithPoint:point];
    [self focusWithMode:AVCaptureFocusModeAutoFocus exposureMode:AVCaptureExposureModeAutoExpose atPoint:cameraPoint];
}
#pragma mark 聚焦框
- (void)setFocusCursorWithPoint:(CGPoint)point
{
    _focusCursor.transform = CGAffineTransformMakeScale(1.5, 1.5);
    _focusCursor.alpha = 1.0;
    [UIView animateWithDuration:1.0 animations:^{
        self.focusCursor.transform = CGAffineTransformIdentity;
    } completion:^(BOOL finished) {
        self.focusCursor.alpha = 0;
        
    }];
}
#pragma mark 设置聚焦点
- (void)focusWithMode:(AVCaptureFocusMode)focusMode exposureMode:(AVCaptureExposureMode)exposureMode atPoint:(CGPoint)point
{
    [self changeDeviceProperty:^(AVCaptureDevice *captureDevice) {
        if ([captureDevice isFocusModeSupported:focusMode])
        {
            [captureDevice setFocusMode:AVCaptureFocusModeAutoFocus];
        }
        if ([captureDevice isFocusPointOfInterestSupported])
        {
            [captureDevice setFocusPointOfInterest:point];
        }
        if ([captureDevice isExposureModeSupported:exposureMode])
        {
            [captureDevice setExposureMode:AVCaptureExposureModeAutoExpose];
        }
        if ([captureDevice isExposurePointOfInterestSupported])
        {
            [captureDevice setExposurePointOfInterest:point];
        }
    }];
}

#pragma mark 设置聚焦模式
- (void)setFocusMode:(AVCaptureFocusMode)focusMode
{
    [self changeDeviceProperty:^(AVCaptureDevice *captureDevice) {
        if ([captureDevice isFocusModeSupported:focusMode])
        {
            [captureDevice setFocusMode:focusMode];
        }
    }];
}
#pragma mark 设置曝光模式
- (void)setExposureMode:(AVCaptureExposureMode)exposureMode
{
    [self changeDeviceProperty:^(AVCaptureDevice *captureDevice) {
        if ([captureDevice isExposureModeSupported:exposureMode])
        {
            [captureDevice setExposureMode:exposureMode];
        }
    }];
}
#pragma mark 设置闪光灯模式
- (void)setFlashMode:(AVCaptureFlashMode)flashMode
{
    switch (flashMode) {
        case AVCaptureFlashModeOff:
            [_flashBtn setImage:[UIImage imageNamed:@"CameraFlashOff"] forState:UIControlStateNormal];
            break;
        case AVCaptureFlashModeOn:
            [_flashBtn setImage:[UIImage imageNamed:@"CameraFlashOn"] forState:UIControlStateNormal];
            break;
        case AVCaptureFlashModeAuto:
            [_flashBtn setImage:[UIImage imageNamed:@"CameraFlashAuto"] forState:UIControlStateNormal];
            break;
        default:
            break;
    }
    [self changeDeviceProperty:^(AVCaptureDevice *captureDevice) {
        if ([captureDevice isFlashModeSupported:flashMode])
        {
            [captureDevice setFlashMode:flashMode];
        }
    }];
}
#pragma mark - 事件响应
#pragma mark 返回
- (void)backBtnClick
{
    CATransition* transition = [CATransition animation];
    transition.type = kCATransitionReveal;
    transition.subtype = kCATransitionFromBottom;
    [self.navigationController.view.layer addAnimation:transition forKey:kCATransition];
    [self.navigationController popViewControllerAnimated:NO];
}
#pragma mark 切换摄像头
- (void)toggleBtnClick:(UIButton *)sender
{
    AVCaptureDevice *currentDevice = [_captureDeviceInput device];
    AVCaptureDevicePosition currentPosition = [currentDevice position];
    [self removeNotificationFromCaptureDevice:currentDevice];
    AVCaptureDevice *toChangeDevice;
    AVCaptureDevicePosition toChangePosition = AVCaptureDevicePositionFront;
    if (currentPosition == AVCaptureDevicePositionUnspecified || currentPosition == AVCaptureDevicePositionFront)
    {
        toChangePosition = AVCaptureDevicePositionBack;
    }
    toChangeDevice = [self getCameraDeviceWithPosition:toChangePosition];
    [self addNotificationToCaptureDevice:toChangeDevice];
    // 获得要调整的设备输入对象
    AVCaptureDeviceInput *toChangeDeviceInput = [[AVCaptureDeviceInput alloc]initWithDevice:toChangeDevice error:nil];
    
    // 改变会话的配置前一定要先开启配置,配置完成后提交配置改变
    [self.captureSession beginConfiguration];
    // 移除原有输入对象
    [self.captureSession removeInput:self.captureDeviceInput];
    // 添加新的输入对象
    if ([self.captureSession canAddInput:toChangeDeviceInput])
    {
        [self.captureSession addInput:toChangeDeviceInput];
        self.captureDeviceInput = toChangeDeviceInput;
    }
    // 提交会话配置
    [self.captureSession commitConfiguration];
    [self setFlashMode:AVCaptureFlashModeAuto];

}
#pragma mark 自动闪光灯开启
- (void)flashClick:(UIButton *)sender
{
    _flashView.hidden = NO;
}
- (void)flashAutoClick:(UIButton *)sender
{
    [self setFlashMode:AVCaptureFlashModeAuto];
    _flashView.hidden = YES;
}
#pragma mark 打开闪光灯
- (void)flashOnClick:(UIButton *)sender
{
    [self setFlashMode:AVCaptureFlashModeOn];
    _flashView.hidden = YES;
}
#pragma mark 关闭闪光灯
- (void)flashOffClick:(UIButton *)sender
{
    [self setFlashMode:AVCaptureFlashModeOff];
    _flashView.hidden = YES;
}

#pragma mark 拍照
- (void)takeBtnClick:(UIButton *)sender
{
    [[self class] cancelPreviousPerformRequestsWithTarget:self selector:@selector(takePhotos) object:sender];
    [self performSelector:@selector(takePhotos) withObject:sender afterDelay:0.2f];
}
- (void)takePhotos
{
    AudioServicesPlaySystemSound(SOUNDID);
    // 根据设备输出获得连接
    AVCaptureConnection *captureConnection = [_captureStillImageOutput connectionWithMediaType:AVMediaTypeVideo];
    // 根据连接取得设备输出的数据
    [_captureStillImageOutput captureStillImageAsynchronouslyFromConnection:captureConnection completionHandler:^(CMSampleBufferRef imageDataSampleBuffer, NSError *error)
     {
         if (imageDataSampleBuffer)
         {
             NSData *imageData = [AVCaptureStillImageOutput jpegStillImageNSDataRepresentation:imageDataSampleBuffer];
             UIImage *image = [UIImage imageWithData:imageData];
             UIImageWriteToSavedPhotosAlbum(image, nil, nil, nil);
             UIImage *lastImg = [UIImage squareImage:image scaledToSize:SWScreenW];
             [_imgArray addObject:lastImg];
             if (_imgArray.count >=5)
             {
                 [self takePhotoFinished];
             }
         }
     }];
}
#pragma mark 完成拍摄条件
- (void)takePhotoFinished
{
    _backBtn.hidden = YES;
    _toggleBtn.hidden = YES;
    _takeBtn.hidden = YES;
    _resetBtn.hidden = NO;
    _useBtn.hidden = NO;
    [self makeGif];
}
#pragma mark 重新拍摄
- (void)resetBtnClick:(UIButton *)sender
{
    if (_imgArray)
    {
        [_imgArray removeAllObjects];
    }
    _backBtn.hidden = NO;
    _toggleBtn.hidden = NO;
    _takeBtn.hidden = NO;
    _resetBtn.hidden = YES;
    _useBtn.hidden = YES;
    _flashView.hidden = YES;
    [self setFlashMode:AVCaptureFlashModeAuto];
}
#pragma mark 使用gif
- (void)useBtnClick:(UIButton *)sender
{
    if(self.CameraBlock)
    {
        self.CameraBlock(self.gifURL);
    }
    [self backBtnClick];
}

#pragma mark - 通知对象
- (void)areaChange:(NSNotification *)notification
{
    SWLog(@"捕获区域改变");
}
- (void)sessionRuntimeError:(NSNotification *)notification
{
    SWLog(@"会话发生错误");
}
- (void)dealloc {
    [_captureSession stopRunning];
    [SWNotification removeObserver:self];
}
- (BOOL)prefersStatusBarHidden {
    return YES;
}
@end

附加

解决拍照后图片旋转甚至颠倒bug

// [self fixOrientation:image]
- (UIImage *)fixOrientation:(UIImage *)aImage {
    
    // No-op if the orientation is already correct
    if (aImage.imageOrientation == UIImageOrientationUp)
        return aImage;
    
    // We need to calculate the proper transformation to make the image upright.
    // We do it in 2 steps: Rotate if Left/Right/Down, and then flip if Mirrored.
    CGAffineTransform transform = CGAffineTransformIdentity;
    
    switch (aImage.imageOrientation) {
        case UIImageOrientationDown:
        case UIImageOrientationDownMirrored:
            transform = CGAffineTransformTranslate(transform, aImage.size.width, aImage.size.height);
            transform = CGAffineTransformRotate(transform, M_PI);
            break;
            
        case UIImageOrientationLeft:
        case UIImageOrientationLeftMirrored:
            transform = CGAffineTransformTranslate(transform, aImage.size.width, 0);
            transform = CGAffineTransformRotate(transform, M_PI_2);
            break;
            
        case UIImageOrientationRight:
        case UIImageOrientationRightMirrored:
            transform = CGAffineTransformTranslate(transform, 0, aImage.size.height);
            transform = CGAffineTransformRotate(transform, -M_PI_2);
            break;
        default:
            break;
    }
    
    switch (aImage.imageOrientation) {
        case UIImageOrientationUpMirrored:
        case UIImageOrientationDownMirrored:
            transform = CGAffineTransformTranslate(transform, aImage.size.width, 0);
            transform = CGAffineTransformScale(transform, -1, 1);
            break;
            
        case UIImageOrientationLeftMirrored:
        case UIImageOrientationRightMirrored:
            transform = CGAffineTransformTranslate(transform, aImage.size.height, 0);
            transform = CGAffineTransformScale(transform, -1, 1);
            break;
        default:
            break;
    }
    
    // Now we draw the underlying CGImage into a new context, applying the transform
    // calculated above.
    CGContextRef ctx = CGBitmapContextCreate(NULL, aImage.size.width, aImage.size.height,
                                             CGImageGetBitsPerComponent(aImage.CGImage), 0,
                                             CGImageGetColorSpace(aImage.CGImage),
                                             CGImageGetBitmapInfo(aImage.CGImage));
    CGContextConcatCTM(ctx, transform);
    switch (aImage.imageOrientation) {
        case UIImageOrientationLeft:
        case UIImageOrientationLeftMirrored:
        case UIImageOrientationRight:
        case UIImageOrientationRightMirrored:
            // Grr...
            CGContextDrawImage(ctx, CGRectMake(0,0,aImage.size.height,aImage.size.width), aImage.CGImage);
            break;
            
        default:
            CGContextDrawImage(ctx, CGRectMake(0,0,aImage.size.width,aImage.size.height), aImage.CGImage);
            break;
    }
    
    // And now we just create a new UIImage from the drawing context
    CGImageRef cgimg = CGBitmapContextCreateImage(ctx);
    UIImage *img = [UIImage imageWithCGImage:cgimg];
    CGContextRelease(ctx);
    CGImageRelease(cgimg);
    return img;
}
* 附

iOS调用相机和相册-细节化
封装相机功能->>>>>block返回image
仿微信小视频拍照播放
swift视频录制
iOS视频压缩存储至本地并上传至服务器
swift avf拍照,录制
RSKImageCropViewController与TZImagePickerController

你可能感兴趣的:(相机)