https://github.com/starainDou 歡迎點(diǎn)星
拍照方式
拍照大體上有兩種方式:UIImagePickerController方式和AVFoundation方式歼跟,前者簡單易用但是不利于定制和一些復(fù)雜操作,后者反之。
* UIImagePickerController 拍照
屬性、枚舉台夺、代理
@property (nonatomic) UIImagePickerControllerSourceType sourceType;
typedef NS_ENUM(NSInteger, UIImagePickerControllerSourceType) {
UIImagePickerControllerSourceTypePhotoLibrary,//照片庫
UIImagePickerControllerSourceTypeCamera,//攝像頭
UIImagePickerControllerSourceTypeSavedPhotosAlbum//相簿
};
/*
媒體類型策幼,默認(rèn)情況下此數(shù)組包含kUTTypeImage,表示拍照
如果要錄像稻艰,必須設(shè)置為kUTTypeVideo(視頻不帶聲音)或kUTTypeMovie(視頻帶聲音)
*/
@property (nonatomic,copy) NSArray<NSString *> *mediaTypes;
@property (nonatomic) NSTimeInterval videoMaximumDuration;//視頻最大錄制時長扛禽,默認(rèn)10s
@property (nonatomic) UIImagePickerControllerQualityType videoQuality;//視頻質(zhì)量
typedef NS_ENUM(NSInteger, UIImagePickerControllerQualityType) {
UIImagePickerControllerQualityTypeHigh = 0, //高清 1920x1080
UIImagePickerControllerQualityTypeMedium, //中等锋边,適合WiFi傳輸 568x320
UIImagePickerControllerQualityTypeLow, //低質(zhì)量,適合蜂窩網(wǎng)傳輸 224x128
UIImagePickerControllerQualityType640x480, //640*480
UIImagePickerControllerQualityTypeIFrame1280x720, //1280*720
UIImagePickerControllerQualityTypeIFrame960x540, //960*540
};
@property (nonatomic) BOOL showsCameraControls;/* 是否顯示攝像頭控制面板编曼,默認(rèn)為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;/* 攝像頭設(shè)備 */
typedef NS_ENUM(NSInteger, UIImagePickerControllerCameraDevice) {
UIImagePickerControllerCameraDeviceRear,//前置攝像頭
UIImagePickerControllerCameraDeviceFront//后置攝像頭
};
@property (nonatomic) UIImagePickerControllerCameraFlashMode cameraFlashMode;/* 閃光燈模式 */
typedef NS_ENUM(NSInteger, UIImagePickerControllerCameraFlashMode) {
UIImagePickerControllerCameraFlashModeOff = -1,//關(guān)閉閃光燈
UIImagePickerControllerCameraFlashModeAuto = 0,//閃光燈自動豆巨,默認(rèn)
UIImagePickerControllerCameraFlashModeOn = 1//打開閃光燈
};
/** 對象方法 */
- (void)takePicture; //拍照
- (BOOL)startVideoCapture;//開始錄制視頻
- (void)stopVideoCapture;//停止錄制視頻
/** 代理方法 */
- (void)imagePickerController:(UIImagePickerController *)picker
didFinishPickingMediaWithInfo:(NSDictionary<NSString *,id> *)info;
- (void)imagePickerControllerDidCancel:(UIImagePickerController *)picker;
/** 相冊操作擴(kuò)展 */
/* 保存圖片到相簿 */
void UIImageWriteToSavedPhotosAlbum(
UIImage *image,//保存的圖片UIImage
id completionTarget,//回調(diào)的執(zhí)行者
SEL completionSelector, //回調(diào)方法
void *contextInfo//回調(diào)參數(shù)信息
);
//上面一般保存圖片的回調(diào)方法為:
- (void)image:(UIImage *)image
didFinishSavingWithError:(NSError *)error
contextInfo:(void *)contextInfo;
/* 判斷是否能保存視頻到相簿 */
BOOL UIVideoAtPathIsCompatibleWithSavedPhotosAlbum(NSString *videoPath);
/* 保存視頻到相簿 */
void UISaveVideoAtPathToSavedPhotosAlbum(
NSString *videoPath, //保存的視頻文件路徑
id completionTarget, //回調(diào)的執(zhí)行者
SEL completionSelector,//回調(diào)方法
void *contextInfo//回調(diào)參數(shù)信息
);
//上面一般保存視頻的回調(diào)方法為:
- (void)video:(NSString *)videoPath
didFinishSavingWithError:(NSError *)error
contextInfo:(void *)contextInfo;
具體使用
#import "ViewController.h"
#import <MobileCoreServices/MobileCoreServices.h>
@interface ViewController () <UIImagePickerControllerDelegate,UINavigationControllerDelegate>
@property (strong, nonatomic) UIImagePickerController *pickerController;//拾取控制器
@property (strong, nonatomic) IBOutlet UIImageView *showImageView;//顯示圖片
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
//初始化拾取控制器
[self initPickerController];
}
/* 初始化拾取控制器 */
- (void)initPickerController{
//創(chuàng)建拾取控制器
UIImagePickerController *pickerController = [[UIImagePickerController alloc] init];
//設(shè)置拾取源為攝像頭
pickerController.sourceType = UIImagePickerControllerSourceTypeCamera;
//設(shè)置攝像頭為后置
pickerController.cameraDevice = UIImagePickerControllerCameraDeviceRear;
pickerController.editing = YES;//設(shè)置運(yùn)行編輯,即可以點(diǎn)擊一些拾取控制器的控件
pickerController.delegate = self;//設(shè)置代理
self.pickerController = pickerController;
}
#pragma mark - UI點(diǎn)擊
/* 點(diǎn)擊拍照 */
- (IBAction)imagePicker:(id)sender {
//設(shè)定拍照的媒體類型
self.pickerController.mediaTypes = @[(NSString *)kUTTypeImage];
//設(shè)置攝像頭捕捉模式為捕捉圖片
self.pickerController.cameraCaptureMode = UIImagePickerControllerCameraCaptureModePhoto;
//模式彈出拾取控制器
[self presentViewController:self.pickerController animated:YES completion:nil];
}
/* 點(diǎn)擊錄像 */
- (IBAction)videoPicker:(id)sender {
//設(shè)定錄像的媒體類型
self.pickerController.mediaTypes = @[(NSString *)kUTTypeMovie];
//設(shè)置攝像頭捕捉模式為捕捉視頻
self.pickerController.cameraCaptureMode = UIImagePickerControllerCameraCaptureModeVideo;
//設(shè)置視頻質(zhì)量為高清
self.pickerController.videoQuality = UIImagePickerControllerQualityTypeHigh;
//模式彈出拾取控制器
[self presentViewController:self.pickerController animated:YES completion:nil];
}
#pragma mark - 代理方法
/* 拍照或錄像成功掐场,都會調(diào)用 */
- (void)imagePickerController:(UIImagePickerController *)picker
didFinishPickingMediaWithInfo:(NSDictionary<NSString *,id> *)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];
}
/* 取消拍照或錄像會調(diào)用 */
- (void)imagePickerControllerDidCancel:(UIImagePickerController *)picker
{
NSLog(@"取消");
//拾取控制器彈回
[self dismissViewControllerAnimated:YES completion:nil];
}
#pragma mark - 保存圖片或視頻完成的回調(diào)
- (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 拍照
Camera.jpg
CameraVC.h
// Created by Rain Dou on 15/10/1.
// Copyright ? 2015年 shiwo@ShangHai. All rights reserved.
#import <UIKit/UIKit.h>
@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 <AssetsLibrary/AssetsLibrary.h>
#import <AVFoundation/AVFoundation.h>
#import <MobileCoreServices/MobileCoreServices.h>
#import <ImageIO/ImageIO.h>
#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 創(chuàng)建按鈕
- (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(@"取得后置攝像頭時出現(xiàn)問題.");
return;
}
NSError *error = nil;
_captureDeviceInput = [[AVCaptureDeviceInput alloc] initWithDevice:captureDevice error:&error];
if (error) {
NSLog(@"取得設(shè)備輸入對象時出錯往扔,錯誤原因:%@",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 給輸入設(shè)備添加通知
- (void)addNotificationToCaptureDevice:(AVCaptureDevice *)captureDevice
{
// 添加區(qū)域改變捕獲通知首先設(shè)置設(shè)備允許捕獲
[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 移除設(shè)備通知
- (void)removeNotificationFromCaptureDevice:(AVCaptureDevice *)captureDevice
{
[SWNotification removeObserver:self name:AVCaptureDeviceSubjectAreaDidChangeNotification object:captureDevice];
}
- (void)changeDeviceProperty:(PropertyChangeBlock)propertyChange
{
AVCaptureDevice *captureDevice = [_captureDeviceInput device];
NSError *error = nil;
// 注意改變設(shè)備屬性前先加鎖,調(diào)用完解鎖
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 點(diǎn)擊屏幕聚焦
- (void)tapScreen:(UITapGestureRecognizer *)gesture
{
CGPoint point= [gesture locationInView:self.viewContainer];
// 將UI坐標(biāo)轉(zhuǎn)化為攝像頭坐標(biāo)
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 設(shè)置聚焦點(diǎn)
- (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 設(shè)置聚焦模式
- (void)setFocusMode:(AVCaptureFocusMode)focusMode
{
[self changeDeviceProperty:^(AVCaptureDevice *captureDevice) {
if ([captureDevice isFocusModeSupported:focusMode])
{
[captureDevice setFocusMode:focusMode];
}
}];
}
#pragma mark 設(shè)置曝光模式
- (void)setExposureMode:(AVCaptureExposureMode)exposureMode
{
[self changeDeviceProperty:^(AVCaptureDevice *captureDevice) {
if ([captureDevice isExposureModeSupported:exposureMode])
{
[captureDevice setExposureMode:exposureMode];
}
}];
}
#pragma mark 設(shè)置閃光燈模式
- (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 - 事件響應(yīng)
#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];
// 獲得要調(diào)整的設(shè)備輸入對象
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 關(guān)閉閃光燈
- (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);
// 根據(jù)設(shè)備輸出獲得連接
AVCaptureConnection *captureConnection = [_captureStillImageOutput connectionWithMediaType:AVMediaTypeVideo];
// 根據(jù)連接取得設(shè)備輸出的數(shù)據(jù)
[_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(@"捕獲區(qū)域改變");
}
- (void)sessionRuntimeError:(NSNotification *)notification
{
SWLog(@"會話發(fā)生錯誤");
}
- (void)dealloc {
[_captureSession stopRunning];
[SWNotification removeObserver:self];
}
- (BOOL)prefersStatusBarHidden {
return YES;
}
@end
附加
解決拍照后圖片旋轉(zhuǎn)甚至顛倒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調(diào)用相機(jī)和相冊-細(xì)節(jié)化
封裝相機(jī)功能->>>>>block返回image
仿微信小視頻拍照播放
swift視頻錄制
iOS視頻壓縮存儲至本地并上傳至服務(wù)器
swift avf拍照,錄制
RSKImageCropViewController與TZImagePickerController