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 拍照
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