/*? 自定義相機:四個核心對象;前后攝像頭的對調(diào);拍照和保存;裁剪圖片;水印圖片;? */
#import "TwoViewController.h"
#import<AVFoundation/AVFoundation.h>
@interface TwoViewController ()
@property (nonatomic,strong) AVCaptureDeviceInput *deviceInput;
@property (weak, nonatomic) IBOutlet UIImageView *waterPrintImageView;
@property (weak, nonatomic) IBOutlet UILabel *sportDistanceLabel;
@property (weak, nonatomic) IBOutlet UILabel *tipLabel;
@property (weak, nonatomic) IBOutlet UIButton *captureBtn;
//都是輸出設(shè)備
//@property (nonatomic,strong) AVCapturePhotoOutput *output;
@property (nonatomic,strong) AVCaptureStillImageOutput *output;
@property (nonatomic,strong) AVCaptureSession *session;
//預(yù)覽圖層,取景框? 添加到layer上
@property (nonatomic,weak) AVCaptureVideoPreviewLayer *pre_Layer;
@end
@implementation TwoViewController
//旋轉(zhuǎn)按鈕
- (IBAction)rotateCamera:(id)sender {
//獲取翻轉(zhuǎn)后的攝像頭,給會話
AVCaptureDevice *device = [self captureDevice];
AVCaptureDeviceInput *deviceInput = [AVCaptureDeviceInput deviceInputWithDevice:device error:nil];
//從會話中刪除攝像頭
[self.session removeInput:self.deviceInput];
//停止會話
[self.session stopRunning];
//將輸入設(shè)備添加到會話中,如果會話中有輸入設(shè)備,不能再進入新的涉嫌頭設(shè)備 需要刪除之前的攝像頭
if ([self.session canAddInput:deviceInput]) {
[self.session addInput:deviceInput];
//開始會話
[self.session startRunning];
self.deviceInput = deviceInput;
}
}
//抽取方法
- (AVCaptureDevice *)captureDevice {
//獲取相機位置
AVCaptureDevicePosition position = (self.deviceInput.device.position != AVCaptureDevicePositionBack) ? AVCaptureDevicePositionBack : AVCaptureDevicePositionFront;
//獲取輸入設(shè)備
NSArray *array = [AVCaptureDevice devicesWithMediaType:AVMediaTypeVideo];
AVCaptureDevice *device;
for (AVCaptureDevice *obj in array) {
if (position == obj.position) {
device = obj;
break;
}
}
return? device;
}
- (void)setupSession {
//輸入設(shè)備
//獲取設(shè)備 攝像頭有兩個
//? ? NSArray *devices = [AVCaptureDevice devicesWithMediaType:AVMediaTypeVideo];
//? ? 獲取后置攝像頭
//? ? AVCaptureDevice *backDevice;
//
//? ? for (AVCaptureDevice *device in devices) {
//
//? ? ? ? if (device.position == AVCaptureDevicePositionBack) {
//
//? ? ? ? ? ? backDevice = device;
//? ? ? ? ? ? break;
//? ? ? ? }
//
//
//? ? }
//獲取后置攝像頭
//? ? AVCaptureDevice *device = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo];
AVCaptureDevice *device = [self captureDevice];
self.deviceInput = [AVCaptureDeviceInput deviceInputWithDevice:device error:nil];
//? ? self.output = [[AVCapturePhotoOutput alloc]init];
self.output = [[AVCaptureStillImageOutput alloc]init];
//會話
self.session = [[AVCaptureSession alloc]init];
if ([self.session canAddInput:self.deviceInput]) {
[self.session addInput:self.deviceInput];
}
if ([self.session canAddOutput:self.output]) {
[self.session addOutput:self.output];
}
//創(chuàng)建取景框? 預(yù)覽圖層
AVCaptureVideoPreviewLayer *preViewLayer = [[AVCaptureVideoPreviewLayer alloc]initWithSession:self.session];
self.pre_Layer = preViewLayer;
//設(shè)置大小
CGRect rect = [UIScreen mainScreen].bounds;
rect.size.height -= 126;
self.pre_Layer.frame = rect;
//最好在viewWillLayoutSubviews設(shè)置? viewDidLoad里設(shè)置顯示不出來
//取景框添加到layer上
[self.view.layer addSublayer:preViewLayer];
//開啟會話? 取景框大小跟不上? 取景框不能被壓縮,高度變矮,寬度不變,圖片變形
self.pre_Layer.videoGravity = AVLayerVideoGravityResizeAspectFill;
[self startSession];
}
- (void)startSession {
[self.session startRunning];
}
- (void)stopSession {
[self.session stopRunning];
}
- (IBAction)cancelBtn:(id)sender {
[self dismissViewControllerAnimated:YES completion:nil];
}
- (IBAction)startCapture:(id)sender {
[self saveImage];
}
//保存照片,拍照和分享
- (void)saveImage {
//AVCaptureConnection 攝像頭和照片的連接
NSLog(@"%@",self.output.connections);
//輸入設(shè)備? 獲取圖片
[self.output captureStillImageAsynchronouslyFromConnection:self.output.connections.firstObject completionHandler:^(CMSampleBufferRef imageDataSampleBuffer, NSError *error) {
if (error) {
NSLog(@"%@",error);
return ;
}
//獲取圖片的二進制數(shù)據(jù)
NSData *data = [AVCaptureStillImageOutput jpegStillImageNSDataRepresentation:imageDataSampleBuffer];
UIImage *image = [UIImage imageWithData:data];
//獲取預(yù)覽視圖的大小
CGRect rect = self.pre_Layer.bounds;
//開啟圖形上下文
UIGraphicsBeginImageContextWithOptions(rect.size, YES, 0);
//畫圖片? CGRectInset 矩形兩端裁剪 返回的是中間的大小
[image drawInRect:CGRectInset(rect, 0, -(self.view.bounds.size.height - rect.size.height) * 0.5)];
//畫水印圖片
[self.waterPrintImageView.image drawInRect:_waterPrintImageView.frame];
//運動距離的文字
[self.sportDistanceLabel.attributedText drawInRect:_sportDistanceLabel.frame];
//獲取最新的圖片
UIImage *finalImage = UIGraphicsGetImageFromCurrentImageContext();
//關(guān)閉圖形上下文
UIGraphicsEndImageContext();
//保存圖片到相冊
UIImageWriteToSavedPhotosAlbum(finalImage, self, @selector(image: didFinishSavingWithError:contextInfo:), nil);
}];
}
//保存圖片到相冊之后的回調(diào)? 成功失敗都會調(diào)用此方法
- (void)image:(UIImage *)image didFinishSavingWithError:(NSError *)error contextInfo:(void *)contextInfo {
[self stopSession];
NSString *str = (error == nil) ? @"保存成功" : @"保存失敗";
NSLog(@"%@",str);
self.tipLabel.text = str;
[UIView animateWithDuration:2 animations:^{
self.tipLabel.alpha = 1;
} completion:^(BOOL finished) {
self.tipLabel.alpha = 0;
}];
}
- (void)viewDidLoad {
[super viewDidLoad];
//? ? BOOL isEmptyTitle = (self.captureBtn.currentTitle == nil);? 為空 返回YES ;不為空 返回NO
[self setupSession];
//攝像頭輸入設(shè)備;如相數(shù)據(jù)輸出;拍攝會話連接前兩個;取景框,預(yù)覽圖層,也要加在會話中? ? 連接完成之后,將會話給layer,layer使用會話
//? ? [self dismissViewControllerAnimated:YES completion:nil];
}
- (BOOL)prefersStatusBarHidden {
return YES;
}
@end