// // 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 @interface CusomeCameraViewController () //捕获设备,通常是前置摄像头,后置摄像头,麦克风(音频输入) @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