前段時間公司需要做一個身份識別的功能,而系統相機無法滿足要求,so自己自定義了。
上代碼:
.h文件
#import <UIKit/UIKit.h> #import <AVFoundation/AVFoundation.h> @interface ViewController : UIViewController @property (nonatomic, strong) AVCaptureSession* session; /** * 輸入設備 */ @property (nonatomic, strong) AVCaptureDeviceInput* videoInput; /** * 照片輸出流 */ @property (nonatomic, strong) AVCaptureStillImageOutput* stillImageOutput; /** * 預覽圖層 */ @property (nonatomic, strong) AVCaptureVideoPreviewLayer* previewLayer; /** * 最后的縮放比例 */ @property(nonatomic,assign)CGFloat effectiveScale; @property (nonatomic, strong) UIView *backView;
.m文件
在這個文件你需要什么樣的相機都可以在這里面設置,需要放大放小,閃光各種功能都在此處可以設置。
@interface ViewController () @end @implementation ViewController - (void)viewWillAppear:(BOOL)animated{ [super viewWillAppear:YES]; if (self.session) { [self.session startRunning]; } } - (void)viewDidDisappear:(BOOL)animated{ [super viewDidDisappear:YES]; if (self.session) { [self.session stopRunning]; } } - (void)viewDidLoad { self.view.backgroundColor = [UIColor blackColor]; self.backView = [[UIView alloc] initWithFrame:CGRectMake(0, 0,SelfWidth, SelfHeight - 120)]; [self.view addSubview:self.backView]; UIView *view = [[UIView alloc]initWithFrame:CGRectMake(SelfWidth/2 - 30, SelfHeight - 120 + 30, 60, 60)]; view.backgroundColor = [UIColor whiteColor]; view.layer.cornerRadius = 30; [view.layer masksToBounds]; [self.view addSubview:view]; //自己定義一個和原生的相機一樣的按鈕 UIButton *button = [UIButton buttonWithType:UIButtonTypeRoundedRect]; button.frame = CGRectMake(SelfWidth/2 - 25, SelfHeight - 120 + 35, 50, 50); button.backgroundColor = [UIColor whiteColor]; button.layer.cornerRadius = 25; button.layer.borderWidth = 2; button.layer.borderColor = [UIColor blackColor].CGColor; [button.layer masksToBounds]; [button addTarget:self action:@selector(buttondown) forControlEvents:UIControlEventTouchUpInside]; [self.view addSubview:button]; //在相機中加個框 CALayer *Mylayer=[CALayer layer]; Mylayer.bounds=CGRectMake(10, (SelfHeight - (SelfWidth - 20)/1.6)/2, SelfWidth - 20, (SelfWidth - 20)/1.6); Mylayer.position=CGPointMake(SelfWidth/2, (SelfHeight - 120)/2); Mylayer.masksToBounds=YES; Mylayer.borderWidth=1; Mylayer.borderColor=[UIColor whiteColor].CGColor; [self.view.layer addSublayer:Mylayer]; UIButton *Lbtn = [UIButton buttonWithType:UIButtonTypeRoundedRect]; Lbtn.frame = CGRectMake(20, SelfHeight - 80 , 40, 40); [Lbtn setTitle:@"取消" forState:UIControlStateNormal]; Lbtn.titleLabel.font = [UIFont systemFontOfSize:15]; [Lbtn setTintColor:[UIColor whiteColor]]; [Lbtn addTarget:self action:@selector(back) forControlEvents:UIControlEventTouchUpInside]; [self.view addSubview:Lbtn]; [self initAVCaptureSession]; //設置相機屬性 self.effectiveScale = 1.0f; } //設置相機屬性 - (void)initAVCaptureSession{ self.session = [[AVCaptureSession alloc] init]; [self.session setSessionPreset:AVCaptureSessionPresetHigh]; NSError *error; AVCaptureDevice *device = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo]; //更改這個設置的時候必須先鎖定設備,修改完后再解鎖,否則崩潰 [device lockForConfiguration:nil]; //設置閃光燈為自動 [device setFlashMode:AVCaptureFlashModeAuto]; [device unlockForConfiguration]; self.videoInput = [[AVCaptureDeviceInput alloc] initWithDevice:device error:&error]; AVCaptureVideoDataOutput *captureOutput = [[AVCaptureVideoDataOutput alloc] init]; if (error) { NSLog(@"%@",error); } self.stillImageOutput = [[AVCaptureStillImageOutput alloc] init]; //輸出設置。AVVideoCodecJPEG 輸出jpeg格式圖片 NSDictionary * outputSettings = [[NSDictionary alloc] initWithObjectsAndKeys:AVVideoCodecJPEG,AVVideoCodecKey, nil]; [self.stillImageOutput setOutputSettings:outputSettings]; if ([self.session canAddInput:self.videoInput]) { [self.session addInput:self.videoInput]; } if ([self.session canAddOutput:captureOutput]) { [self.session addOutput:captureOutput]; } if ([self.session canAddOutput:self.stillImageOutput]) { [self.session addOutput:self.stillImageOutput]; } //初始化預覽圖層 self.previewLayer = [[AVCaptureVideoPreviewLayer alloc] initWithSession:self.session]; [self.previewLayer setVideoGravity:AVLayerVideoGravityResizeAspectFill]; NSLog(@"%f",SelfWidth); self.previewLayer.frame = CGRectMake(0, 0,SelfWidth, SelfHeight - 120); self.backView.layer.masksToBounds = YES; [self.backView.layer addSublayer:self.previewLayer]; } - (AVCaptureVideoOrientation)avOrientationForDeviceOrientation:(UIDeviceOrientation)deviceOrientation { AVCaptureVideoOrientation result = (AVCaptureVideoOrientation)deviceOrientation; if ( deviceOrientation == UIDeviceOrientationLandscapeLeft ) result = AVCaptureVideoOrientationLandscapeRight; else if ( deviceOrientation == UIDeviceOrientationLandscapeRight ) result = AVCaptureVideoOrientationLandscapeLeft; return result; } //照相按鈕點擊事件 -(void)buttondown{ NSLog(@"takephotoClick..."); AVCaptureConnection *stillImageConnection = [self.stillImageOutput connectionWithMediaType:AVMediaTypeVideo]; UIDeviceOrientation curDeviceOrientation = [[UIDevice currentDevice] orientation]; AVCaptureVideoOrientation avcaptureOrientation = [self avOrientationForDeviceOrientation:curDeviceOrientation]; [stillImageConnection setVideoOrientation:avcaptureOrientation]; [stillImageConnection setVideoScaleAndCropFactor:self.effectiveScale]; [self.stillImageOutput captureStillImageAsynchronouslyFromConnection:stillImageConnection completionHandler:^(CMSampleBufferRef imageDataSampleBuffer, NSError *error) { NSData *jpegData = [AVCaptureStillImageOutput jpegStillImageNSDataRepresentation:imageDataSampleBuffer]; [self makeImageView:jpegData]; NSLog(@"jpegDatajpegData == %ld",(unsigned long)[jpegData length]/1024); }]; } //拍照之后調到相片詳情頁面 -(void)makeImageView:(NSData*)data{ imageDetailViewController*imageView = [[imageDetailViewController alloc] init]; imageView.data = data; [self presentViewController:imageView animated:NO completion:nil]; } //返回 -(void)back{ [self dismissViewControllerAnimated:YES completion:nil]; }
再進入詳情頁面進行照片的裁剪並顯示
#import <UIKit/UIKit.h> @interface imageDetailViewController : UIViewController @property(nonatomic,strong)NSData *data; @end
#import "imageDetailViewController.h" @interface imageDetailViewController () { UIImage *imageIm; } @end @implementation imageDetailViewController - (void)viewDidLoad { [super viewDidLoad]; self.view.backgroundColor = [UIColor blackColor]; UIImageView *imageView =[[UIImageView alloc] initWithFrame:CGRectMake(0, -64, SelfWidth, SelfHeight)]; imageView.image = [UIImage imageWithData:_data]; [self.view addSubview:imageView]; imageIm =[UIImage imageWithData:_data]; CGSize originalsize = [ imageView.image size]; NSLog(@"改變前圖片的寬度為%f,圖片的高度為%f",originalsize.width,originalsize.height); UIButton *button = [UIButton buttonWithType:UIButtonTypeRoundedRect]; button.frame = CGRectMake(15, SelfHeight - 50, 40, 40); [button setTitle:@"重拍" forState:UIControlStateNormal]; [button setTintColor:[UIColor whiteColor]]; [button addTarget:self action:@selector(back) forControlEvents:UIControlEventTouchUpInside]; [self.view addSubview:button]; CALayer *Mylayer=[CALayer layer]; Mylayer.bounds=CGRectMake(10, (SelfHeight - (SelfWidth - 20)/1.6)/2, SelfWidth - 20, (SelfWidth - 20)/1.6); Mylayer.position=CGPointMake(SelfWidth/2, (SelfHeight - 120)/2); Mylayer.masksToBounds=YES; Mylayer.borderWidth=1; Mylayer.borderColor=[UIColor whiteColor].CGColor; [self.view.layer addSublayer:Mylayer]; UIButton *rightButton = [UIButton buttonWithType:UIButtonTypeRoundedRect]; rightButton.frame = CGRectMake(SelfWidth - 90, SelfHeight - 50, 80, 40); [rightButton setTitle:@"使用照片" forState:UIControlStateNormal]; [rightButton setTintColor:[UIColor whiteColor]]; [rightButton addTarget:self action:@selector(rightButton) forControlEvents:UIControlEventTouchUpInside]; [self.view addSubview:rightButton]; // Do any additional setup after loading the view. } -(void)rightButton{ //截取照片,截取到自定義框內的照片 imageIm = [self image:imageIm scaleToSize:CGSizeMake(SelfWidth, SelfHeight)]; //應為在展開相片時放大的兩倍,截取時也要放大兩倍 imageIm = [self imageFromImage:imageIm inRect:CGRectMake(10*2, (SelfHeight - (SelfWidth - 20) /1.6)/2*2, (SelfWidth - 20)*2 , (SelfWidth - 20)/1.6*2)]; //將圖片存儲到相冊 UIImageWriteToSavedPhotosAlbum(imageIm, self, nil, nil); //截取之后將圖片顯示在照相時頁面,和拍攝時的照片進行像素對比 UIImageView *imageView =[[UIImageView alloc] initWithFrame:CGRectMake(10, (SelfHeight - (SelfWidth - 20) /1.6)/2 + 170, SelfWidth - 20 , (SelfWidth - 20)/1.6)]; imageView.image = imageIm; [self.view addSubview:imageView]; } //截取圖片 -(UIImage*)image:(UIImage *)imageI scaleToSize:(CGSize)size{ /* UIGraphicsBeginImageContextWithOptions(CGSize size, BOOL opaque, CGFloat scale) CGSize size:指定將來創建出來的bitmap的大小 BOOL opaque:設置透明YES代表透明,NO代表不透明 CGFloat scale:代表縮放,0代表不縮放 創建出來的bitmap就對應一個UIImage對象 */ UIGraphicsBeginImageContextWithOptions(size, NO, 2.0); //此處將畫布放大兩倍,這樣在retina屏截取時不會影響像素 [imageI drawInRect:CGRectMake(0, 0, size.width, size.height)]; UIImage* scaledImage = UIGraphicsGetImageFromCurrentImageContext(); UIGraphicsEndImageContext(); return scaledImage; } -(UIImage *)imageFromImage:(UIImage *)imageI inRect:(CGRect)rect{ CGImageRef sourceImageRef = [imageI CGImage]; CGImageRef newImageRef = CGImageCreateWithImageInRect(sourceImageRef, rect); UIImage *newImage = [UIImage imageWithCGImage:newImageRef]; return newImage; } -(void)back{ [self dismissViewControllerAnimated:NO completion:nil]; }
完整代碼下載,GitHub:https://github.com/micaimanong/CameraDema