Files
ifish/Ifish/views/CustomcamerFile/CusomeCameraViewController.m
T

573 lines
22 KiB
Objective-C

//
// CusomeCameraViewController.m
// CollectionViewTest
//
// Created by imac on 17/2/17.
// Copyright © 2017年 xiang. All rights reserved.
//
#import "CusomeCameraViewController.h"
#define kScreenBounds [UIScreen mainScreen].bounds
#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