ifish/Ifish/views/CustomcamerFile/CusomeCameraViewController.m

575 lines
22 KiB
Objective-C
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

//
// CusomeCameraViewController.m
// CollectionViewTest
//
// Created by imac on 17/2/17.
// Copyright © 2017年 xiang. All rights reserved.
//
#import "CusomeCameraViewController.h"
#define kScreenBounds [UIScreen mainScreen].bounds
#define kScreenWidth kScreenBounds.size.width*1.0
#define kScreenHeight kScreenBounds.size.height*1.0
#import "ViewController.h"
#import <AVFoundation/AVFoundation.h>
@interface CusomeCameraViewController ()<AVCaptureMetadataOutputObjectsDelegate,UIAlertViewDelegate>
//捕获设备,通常是前置摄像头,后置摄像头,麦克风(音频输入)
@property(nonatomic)AVCaptureDevice *device;
//AVCaptureDeviceInput 代表输入设备他使用AVCaptureDevice 来初始化
@property(nonatomic)AVCaptureDeviceInput *input;
//当启动摄像头开始捕获输入
@property(nonatomic)AVCaptureMetadataOutput *output;
@property (nonatomic)AVCaptureStillImageOutput *ImageOutPut;
//session由他把输入输出结合在一起并开始启动捕获设备摄像头
@property(nonatomic)AVCaptureSession *session;
//图像预览层,实时显示捕获的图像
@property(nonatomic)AVCaptureVideoPreviewLayer *previewLayer;
@property (nonatomic)UIButton *PhotoButton;
@property (nonatomic)UIButton *flashButton;
@property (nonatomic)UIImageView *imageView;
@property (nonatomic)UIView *focusView;
@property (nonatomic)BOOL isflashOn;
@property (nonatomic)UIImage *image;
@property (nonatomic)UIImage *cutedImage;
@property (nonatomic)BOOL canCa;
@property(nonatomic,strong) UIButton *leftButton;
@property(nonatomic,strong) UIButton *rightButton;
@property(nonatomic,strong) UIButton *reMakeButton;
@property(nonatomic,strong) UIButton *userButton;
@end
@implementation CusomeCameraViewController
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view.
_canCa = [self canUserCamear];
if (_canCa) {
[self customCamera];
[self customUI];
}else{
return;
}
}
- (void)customUI{
_PhotoButton = [UIButton buttonWithType:UIButtonTypeCustom];
_PhotoButton.frame = CGRectMake(kScreenWidth*1/2.0-30, kScreenHeight-100, 60, 60);
[_PhotoButton setImage:[UIImage imageNamed:@"photograph"] forState: UIControlStateNormal];
[_PhotoButton setImage:[UIImage imageNamed:@"photograph_Select"] forState:UIControlStateNormal];
[_PhotoButton addTarget:self action:@selector(shutterCamera) forControlEvents:UIControlEventTouchUpInside];
[self.view addSubview:_PhotoButton];
_focusView = [[UIView alloc]initWithFrame:CGRectMake(0, 0, 80, 80)];
_focusView.layer.borderWidth = 1.0;
_focusView.layer.borderColor =[UIColor greenColor].CGColor;
_focusView.backgroundColor = [UIColor clearColor];
[self.view addSubview:_focusView];
_focusView.hidden = YES;
self.leftButton = [UIButton buttonWithType:UIButtonTypeCustom];
_leftButton.frame = CGRectMake(kScreenWidth*1/2.0-30 - 20 - 60, kScreenHeight-100, 60, 60);
[_leftButton setTitle:@"取消" forState:UIControlStateNormal];
_leftButton.titleLabel.textAlignment = NSTextAlignmentCenter;
[_leftButton addTarget:self action:@selector(cancle:) forControlEvents:UIControlEventTouchUpInside];
[self.view addSubview:_leftButton];
self.rightButton = [UIButton buttonWithType:UIButtonTypeCustom];
_rightButton.frame = CGRectMake(CGRectGetMaxX(_PhotoButton.frame)+20, kScreenHeight-100, 60, 60);
[_rightButton setTitle:@"切换" forState:UIControlStateNormal];
_rightButton.titleLabel.textAlignment = NSTextAlignmentCenter;
[_rightButton addTarget:self action:@selector(changeCamera) forControlEvents:UIControlEventTouchUpInside];
[self.view addSubview:_rightButton];
_flashButton = [UIButton buttonWithType:UIButtonTypeCustom];
_flashButton.frame = CGRectMake(kScreenWidth-80,100, 80, 60);
[_flashButton setTitle:@"闪光灯关" forState:UIControlStateNormal];
[_flashButton addTarget:self action:@selector(FlashOn) forControlEvents:UIControlEventTouchUpInside];
//[self.view addSubview:_flashButton];
UITapGestureRecognizer *tapGesture = [[UITapGestureRecognizer alloc]initWithTarget:self action:@selector(focusGesture:)];
[self.view addGestureRecognizer:tapGesture];
}
- (void)customCamera{
self.view.backgroundColor = [UIColor blackColor];
//使用AVMediaTypeVideo 指明self.device代表视频默认使用后置摄像头进行初始化
self.device = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo];
//使用设备初始化输入
self.input = [[AVCaptureDeviceInput alloc]initWithDevice:self.device error:nil];
//生成输出对象
self.output = [[AVCaptureMetadataOutput alloc]init];
self.ImageOutPut = [[AVCaptureStillImageOutput alloc] init];
//生成会话,用来结合输入输出
self.session = [[AVCaptureSession alloc]init];
if ([self.session canSetSessionPreset:AVCaptureSessionPreset1280x720]) {
self.session.sessionPreset = AVCaptureSessionPreset1280x720;
}
if ([self.session canAddInput:self.input]) {
[self.session addInput:self.input];
}
if ([self.session canAddOutput:self.ImageOutPut]) {
[self.session addOutput:self.ImageOutPut];
}
//使用self.session初始化预览层self.session负责驱动input进行信息的采集layer负责把图像渲染显示
self.previewLayer = [[AVCaptureVideoPreviewLayer alloc]initWithSession:self.session];
CGFloat previewH = kScreenWidth * 0.56;
self.previewLayer.frame = CGRectMake(0,kScreenHeight/2 - previewH/2, kScreenWidth, previewH);
self.previewLayer.videoGravity = AVLayerVideoGravityResizeAspectFill;
//self.previewLayer.videoGravity = AVLayerVideoGravityResizeAspect;
[self.view.layer addSublayer:self.previewLayer];
//开始启动
[self.session startRunning];
if ([_device lockForConfiguration:nil]) {
if ([_device isFlashModeSupported:AVCaptureFlashModeAuto]) {
[_device setFlashMode:AVCaptureFlashModeAuto];
}
//自动白平衡
if ([_device isWhiteBalanceModeSupported:AVCaptureWhiteBalanceModeAutoWhiteBalance]) {
[_device setWhiteBalanceMode:AVCaptureWhiteBalanceModeAutoWhiteBalance];
}
[_device unlockForConfiguration];
}
}
- (void)FlashOn{
if ([_device lockForConfiguration:nil]) {
if (_isflashOn) {
if ([_device isFlashModeSupported:AVCaptureFlashModeOff]) {
[_device setFlashMode:AVCaptureFlashModeOff];
_isflashOn = NO;
[_flashButton setTitle:@"闪光灯关" forState:UIControlStateNormal];
}
}else{
if ([_device isFlashModeSupported:AVCaptureFlashModeOn]) {
[_device setFlashMode:AVCaptureFlashModeOn];
_isflashOn = YES;
[_flashButton setTitle:@"闪光灯开" forState:UIControlStateNormal];
}
}
[_device unlockForConfiguration];
}
}
- (void)changeCamera{
NSUInteger cameraCount = [[AVCaptureDevice devicesWithMediaType:AVMediaTypeVideo] count];
if (cameraCount > 1) {
NSError *error;
CATransition *animation = [CATransition animation];
animation.duration = .5f;
animation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];
animation.type = @"oglFlip";
AVCaptureDevice *newCamera = nil;
AVCaptureDeviceInput *newInput = nil;
AVCaptureDevicePosition position = [[_input device] position];
if (position == AVCaptureDevicePositionFront){
newCamera = [self cameraWithPosition:AVCaptureDevicePositionBack];
animation.subtype = kCATransitionFromLeft;
}
else {
newCamera = [self cameraWithPosition:AVCaptureDevicePositionFront];
animation.subtype = kCATransitionFromRight;
}
newInput = [AVCaptureDeviceInput deviceInputWithDevice:newCamera error:nil];
[self.previewLayer addAnimation:animation forKey:nil];
if (newInput != nil) {
[self.session beginConfiguration];
[self.session removeInput:_input];
if ([self.session canAddInput:newInput]) {
[self.session addInput:newInput];
self.input = newInput;
} else {
[self.session addInput:self.input];
}
[self.session commitConfiguration];
} else if (error) {
NSLog(@"toggle carema failed, error = %@", error);
}
}
}
- (AVCaptureDevice *)cameraWithPosition:(AVCaptureDevicePosition)position{
NSArray *devices = [AVCaptureDevice devicesWithMediaType:AVMediaTypeVideo];
for ( AVCaptureDevice *device in devices )
if ( device.position == position ) return device;
return nil;
}
- (void)focusGesture:(UITapGestureRecognizer*)gesture{
CGPoint point = [gesture locationInView:gesture.view];
[self focusAtPoint:point];
}
- (void)focusAtPoint:(CGPoint)point{
CGSize size = self.view.bounds.size;
CGPoint focusPoint = CGPointMake( point.y /size.height ,1-point.x/size.width );
NSError *error;
if ([self.device lockForConfiguration:&error]) {
if ([self.device isFocusModeSupported:AVCaptureFocusModeAutoFocus]) {
[self.device setFocusPointOfInterest:focusPoint];
[self.device setFocusMode:AVCaptureFocusModeAutoFocus];
}
if ([self.device isExposureModeSupported:AVCaptureExposureModeAutoExpose ]) {
[self.device setExposurePointOfInterest:focusPoint];
[self.device setExposureMode:AVCaptureExposureModeAutoExpose];
}
[self.device unlockForConfiguration];
_focusView.center = point;
_focusView.hidden = NO;
[UIView animateWithDuration:0.3 animations:^{
_focusView.transform = CGAffineTransformMakeScale(1.25, 1.25);
}completion:^(BOOL finished) {
[UIView animateWithDuration:0.5 animations:^{
_focusView.transform = CGAffineTransformIdentity;
} completion:^(BOOL finished) {
_focusView.hidden = YES;
}];
}];
}
}
#pragma mark - 拍照
- (void) shutterCamera
{
AVCaptureConnection * videoConnection = [self.ImageOutPut connectionWithMediaType:AVMediaTypeVideo];
if (!videoConnection) {
NSLog(@"take photo failed!");
return;
}
[self.ImageOutPut captureStillImageAsynchronouslyFromConnection:videoConnection completionHandler:^(CMSampleBufferRef imageDataSampleBuffer, NSError *error) {
if (imageDataSampleBuffer == NULL) {
return;
}
NSData * imageData = [AVCaptureStillImageOutput jpegStillImageNSDataRepresentation:imageDataSampleBuffer];
self.image = [UIImage imageWithData:imageData];
[self.session stopRunning];
CGFloat ImgH = kScreenWidth*0.56;
self.imageView = [[UIImageView alloc]initWithFrame:CGRectMake(0,0,kScreenWidth,ImgH)];
self.imageView.center = self.view.center;
self.imageView.contentMode = UIViewContentModeScaleAspectFill;
[self.view insertSubview:_imageView belowSubview:_PhotoButton];
self.cutedImage = [self fixOrientation:self.image];
self.cutedImage = [self wf_thumbnailsCutfullPhoto:self.cutedImage];
self.imageView.layer.masksToBounds = YES;
self.imageView.image = self.cutedImage;
self.leftButton.selected = YES;
self.rightButton.selected = YES;
[self setcameraSelectBtns];
//拍照获取到的图片真实大小
NSLog(@"image size = %@",NSStringFromCGSize(self.image.size));
//和显示镜头尺寸相同比例的裁剪后的图片 大小
NSLog(@"cutedImage size = %@",NSStringFromCGSize(self.cutedImage.size));
}];
}
-(void)setcameraSelectBtns{
[_leftButton removeFromSuperview];
[_rightButton removeFromSuperview];
self.reMakeButton= [UIButton buttonWithType:UIButtonTypeCustom];
_reMakeButton.frame = CGRectMake(kScreenWidth*1/2.0-30 - 20 - 60, kScreenHeight-100, 60, 60);
[_reMakeButton setTitle:@"重拍" forState:UIControlStateNormal];
_reMakeButton.titleLabel.textAlignment = NSTextAlignmentCenter;
[_reMakeButton addTarget:self action:@selector(reMakeButton:) forControlEvents:UIControlEventTouchUpInside];
[self.view addSubview:self.reMakeButton];
self.userButton= [UIButton buttonWithType:UIButtonTypeCustom];
_userButton.frame = CGRectMake(CGRectGetMaxX(_PhotoButton.frame)+20, kScreenHeight-100, 60, 60);
[_userButton setTitle:@"使用" forState:UIControlStateNormal];
_userButton.titleLabel.textAlignment = NSTextAlignmentCenter;
[_userButton addTarget:self action:@selector(userButton:) forControlEvents:UIControlEventTouchUpInside];
[self.view addSubview:_userButton];
}
-(void)setNormalBtns{
[_reMakeButton removeFromSuperview];
[_userButton removeFromSuperview];
self.leftButton= [UIButton buttonWithType:UIButtonTypeCustom];
_leftButton.frame =CGRectMake(kScreenWidth*1/2.0-30 - 20 - 60, kScreenHeight-100, 60, 60);
[_leftButton setTitle:@"取消" forState:UIControlStateNormal];
_leftButton.titleLabel.textAlignment = NSTextAlignmentCenter;
[_leftButton addTarget:self action:@selector(cancle:) forControlEvents:UIControlEventTouchUpInside];
[self.view addSubview:_leftButton];
self.rightButton = [UIButton buttonWithType:UIButtonTypeCustom];
_rightButton.frame = CGRectMake(CGRectGetMaxX(_PhotoButton.frame)+20, kScreenHeight-100, 60, 60);
[_rightButton setTitle:@"切换" forState:UIControlStateNormal];
_rightButton.titleLabel.textAlignment = NSTextAlignmentCenter;
[_rightButton addTarget:self action:@selector(changeCamera) forControlEvents:UIControlEventTouchUpInside];
[self.view addSubview:_rightButton];
}
//裁剪图片,
- (UIImage *)wf_thumbnailsCutfullPhoto:(UIImage*)image
{
CGSize newSize;
CGImageRef imageRef = nil;
newSize.width = image.size.width;
newSize.height = image.size.width * 0.56;
CGFloat capImgW = kScreenWidth;
CGFloat CapImgH = kScreenWidth *0.56;
imageRef = CGImageCreateWithImageInRect(self.image.CGImage, CGRectMake(0, fabs(image.size.height - newSize.height) / 2, newSize.width, newSize.height));
if ((image.size.width / image.size.height) < (capImgW / CapImgH)) {
newSize.width = image.size.width;
newSize.height = image.size.width * CapImgH / capImgW;
imageRef = CGImageCreateWithImageInRect([image CGImage], CGRectMake(0, fabs(image.size.height - newSize.height) / 2, newSize.width, newSize.height));
} else {
newSize.height = image.size.height;
newSize.width = image.size.height * capImgW / CapImgH;
imageRef = CGImageCreateWithImageInRect([image CGImage], CGRectMake(fabs(image.size.width - newSize.width) / 2, 0, newSize.width, newSize.height));
}
UIImage *img = [UIImage imageWithCGImage:imageRef];
CGImageRelease(imageRef);
return img;
}
- (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;
}
- (UIImage *) scaleFromImage: (UIImage *) image toSize: (CGSize) size
{
UIGraphicsBeginImageContext(size);
[image drawInRect:CGRectMake(0, 0, size.width, size.height)];
UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return newImage;
}
//截取部分图像
-(UIImage*)getSubImage:(CGRect)rect
{
CGImageRef subImageRef = CGImageCreateWithImageInRect(self.image.CGImage, CGRectMake(0, fabs(kScreenHeight - kScreenWidth *0.56) / 2, kScreenWidth, kScreenWidth *0.56));
CGRect smallBounds = CGRectMake(0, 0, CGImageGetWidth(subImageRef), CGImageGetHeight(subImageRef));
UIGraphicsBeginImageContext(smallBounds.size);
CGContextRef context = UIGraphicsGetCurrentContext();
CGContextDrawImage(context, smallBounds, subImageRef);
UIImage* smallImage = [UIImage imageWithCGImage:subImageRef];
UIGraphicsEndImageContext();
return smallImage;
}
#pragma - 保存至相册
- (void)saveImageToPhotoAlbum:(UIImage*)savedImage
{
UIImageWriteToSavedPhotosAlbum(savedImage, self, @selector(image:didFinishSavingWithError:contextInfo:), NULL);
}
// 指定回调方法
- (void)image: (UIImage *) image didFinishSavingWithError: (NSError *) error contextInfo: (void *) contextInfo
{
// NSString *msg = nil ;
// if(error != NULL){
// msg = @"保存图片失败" ;
// }else{
// msg = @"保存图片成功" ;
// }
// UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"保存图片结果提示"
// message:msg
// delegate:self
// cancelButtonTitle:@"确定"
// otherButtonTitles:nil];
//[alert show];
}
-(void)cancle:(UIButton*)btn{
[self dismissViewControllerAnimated:YES completion:^{
}];
}
#pragma mark - 检查相机权限
- (BOOL)canUserCamear{
AVAuthorizationStatus authStatus = [AVCaptureDevice authorizationStatusForMediaType:AVMediaTypeVideo];
if (authStatus == AVAuthorizationStatusDenied) {
UIAlertView *alertView = [[UIAlertView alloc]initWithTitle:@"请打开相机权限" message:@"设置-隐私-相机" delegate:self cancelButtonTitle:@"确定" otherButtonTitles:@"取消", nil];
alertView.tag = 100;
[alertView show];
return NO;
}
else{
return YES;
}
return YES;
}
- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex{
if (buttonIndex == 0 && alertView.tag == 100) {
NSURL * url = [NSURL URLWithString:UIApplicationOpenSettingsURLString];
if([[UIApplication sharedApplication] canOpenURL:url]) {
[[UIApplication sharedApplication] openURL:url];
}
}
}
#pragma mark - 重拍
-(void)reMakeButton:(UIButton*)btn{
[self setNormalBtns];
[self.imageView removeFromSuperview];
[self.session startRunning];
}
#pragma mark - 使用
-(void)userButton:(UIButton *)btn{
[self saveImageToPhotoAlbum:self.cutedImage];
_tailoredImage ? _tailoredImage(self.cutedImage) : nil;
[self dismissViewControllerAnimated:YES completion:^{
}];
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
/*
#pragma mark - Navigation
// In a storyboard-based application, you will often want to do a little preparation before navigation
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
// Get the new view controller using [segue destinationViewController].
// Pass the selected object to the new view controller.
}
*/
@end