iOS開發(fā)技巧之自定義相機

1狱杰、首先聲明以下對象

import <AVFoundation/AVFoundation.h>

//捕獲設備瘦材,通常是前置攝像頭,后置攝像頭仿畸,麥克風(音頻輸入)
@property (nonatomic, strong) AVCaptureDevice *device;

//AVCaptureDeviceInput 代表輸入設備宇色,他使用AVCaptureDevice 來初始化
@property (nonatomic, strong) AVCaptureDeviceInput *input;

//輸出圖片
@property (nonatomic ,strong) AVCaptureStillImageOutput *imageOutput;

//session:由他把輸入輸出結合在一起,并開始啟動捕獲設備(攝像頭)
@property (nonatomic, strong) AVCaptureSession *session;

//圖像預覽層颁湖,實時顯示捕獲的圖像
@property (nonatomic ,strong) AVCaptureVideoPreviewLayer *previewLayer;

2宣蠕、初始化各個對象

  • (void)cameraDistrict
    {
    // AVCaptureDevicePositionBack 后置攝像頭
    // AVCaptureDevicePositionFront 前置攝像頭
    self.device = [self cameraWithPosition:AVCaptureDevicePositionFront];
    self.input = [[AVCaptureDeviceInput alloc] initWithDevice:self.device error:nil];

self.imageOutput = [[AVCaptureStillImageOutput alloc] init];

self.session = [[AVCaptureSession alloc] init];
// 拿到的圖像的大小可以自行設定
// AVCaptureSessionPreset320x240
// AVCaptureSessionPreset352x288
// AVCaptureSessionPreset640x480
// AVCaptureSessionPreset960x540
// AVCaptureSessionPreset1280x720
// AVCaptureSessionPreset1920x1080
// AVCaptureSessionPreset3840x2160
self.session.sessionPreset = AVCaptureSessionPreset640x480;
//輸入輸出設備結合
if ([self.session canAddInput:self.input]) {
[self.session addInput:self.input];
}
if ([self.session canAddOutput:self.imageOutput]) {
[self.session addOutput:self.imageOutput];
}
//預覽層的生成
self.previewLayer = [[AVCaptureVideoPreviewLayer alloc] initWithSession:self.session];
self.previewLayer.frame = CGRectMake(0, 64, SCREEN_WIDTH, SCREEN_HEIGHT-64);
self.previewLayer.videoGravity = AVLayerVideoGravityResizeAspectFill;
[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];
}

}

根據(jù)前后置位置拿到相應的攝像頭:

  • (AVCaptureDevice *)cameraWithPosition:(AVCaptureDevicePosition)position{
    NSArray *devices = [AVCaptureDevice devicesWithMediaType:AVMediaTypeVideo];
    for ( AVCaptureDevice *device in devices )
    if ( device.position == position ){
    return device;
    }
    return nil;
    }

3甥捺、拍照拿到相應圖片:

  • (void)photoBtnDidClick
    {
    AVCaptureConnection *conntion = [self.imageOutput connectionWithMediaType:AVMediaTypeVideo];
    if (!conntion) {
    NSLog(@"拍照失敗!");
    return;
    }
    [self.imageOutput captureStillImageAsynchronouslyFromConnection:conntion completionHandler:^(CMSampleBufferRef imageDataSampleBuffer, NSError *error) {
    if (imageDataSampleBuffer == nil) {
    return ;
    }
    NSData *imageData = [AVCaptureStillImageOutput jpegStillImageNSDataRepresentation:imageDataSampleBuffer];
    self.image = [UIImage imageWithData:imageData];
    [self.session stopRunning];
    [self.view addSubview:self.cameraImageView];
    }

4抢蚀、保存照片到相冊:

pragma - 保存至相冊

  • (void)saveImageToPhotoAlbum:(UIImage*)savedImage
    {

UIImageWriteToSavedPhotosAlbum(savedImage, self, @selector(image:didFinishSavingWithError:contextInfo:), NULL);

}
// 指定回調(diào)方法

  • (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];
}

5、前后置攝像頭的切換

  • (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:self.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);
    }
    }
    }

6唱逢、相機的其它參數(shù)設置
//AVCaptureFlashMode 閃光燈
//AVCaptureFocusMode 對焦
//AVCaptureExposureMode 曝光
//AVCaptureWhiteBalanceMode 白平衡
//閃光燈和白平衡可以在生成相機時候設置
//曝光要根據(jù)對焦點的光線狀況而決定,所以和對焦一塊寫
//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;
    }];
    }];
    }

}

7、遇到的一些坑和解決辦法

  1. 前后置攝像頭的切換

前后值不能切換屋休,各種嘗試找了半天沒找到有原因坞古。后來發(fā)現(xiàn)我在設置圖片尺寸的時候設置為1080P [self.session canSetSessionPreset: AVCaptureSessionPreset1920x1080] ,前置攝像頭并不支持這么大的尺寸劫樟,所以就不能切換前置攝像頭痪枫。我驗證了下 前置攝像頭最高支持720P,720P以內(nèi)可自由切換。

當然也可以在前后置攝像頭切換的時候叠艳,根據(jù)前后攝像頭來設置不同的尺寸奶陈,這里不在贅述。

2)焦點位置

CGPoint focusPoint = CGPointMake( point.y /size.height ,1-point.x/size.width );
setExposurePointOfInterest:focusPoint 函數(shù)后面Point取值范圍是取景框左上角(0附较,0)到取景框右下角(1吃粒,1)之間。官方是這么寫的:

The value of this property is a CGPoint that determines the receiver's focus point of interest, if it has one. A value of (0,0) indicates that the camera should focus on the top left corner of the image, while a value of (1,1) indicates that it should focus on the bottom right. The default value is (0.5,0.5).

?著作權歸作者所有,轉載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末拒课,一起剝皮案震驚了整個濱河市徐勃,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌早像,老刑警劉巖僻肖,帶你破解...
    沈念sama閱讀 217,185評論 6 503
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異扎酷,居然都是意外死亡檐涝,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,652評論 3 393
  • 文/潘曉璐 我一進店門法挨,熙熙樓的掌柜王于貴愁眉苦臉地迎上來谁榜,“玉大人,你說我怎么就攤上這事凡纳∏灾玻” “怎么了?”我有些...
    開封第一講書人閱讀 163,524評論 0 353
  • 文/不壞的土叔 我叫張陵荐糜,是天一觀的道長巷怜。 經(jīng)常有香客問我,道長暴氏,這世上最難降的妖魔是什么延塑? 我笑而不...
    開封第一講書人閱讀 58,339評論 1 293
  • 正文 為了忘掉前任,我火速辦了婚禮答渔,結果婚禮上关带,老公的妹妹穿的比我還像新娘。我一直安慰自己沼撕,他們只是感情好宋雏,可當我...
    茶點故事閱讀 67,387評論 6 391
  • 文/花漫 我一把揭開白布芜飘。 她就那樣靜靜地躺著,像睡著了一般磨总。 火紅的嫁衣襯著肌膚如雪嗦明。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,287評論 1 301
  • 那天蚪燕,我揣著相機與錄音娶牌,去河邊找鬼。 笑死邻薯,一個胖子當著我的面吹牛裙戏,可吹牛的內(nèi)容都是我干的乘凸。 我是一名探鬼主播厕诡,決...
    沈念sama閱讀 40,130評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼营勤!你這毒婦竟也來了灵嫌?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 38,985評論 0 275
  • 序言:老撾萬榮一對情侶失蹤葛作,失蹤者是張志新(化名)和其女友劉穎寿羞,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體赂蠢,經(jīng)...
    沈念sama閱讀 45,420評論 1 313
  • 正文 獨居荒郊野嶺守林人離奇死亡绪穆,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,617評論 3 334
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了虱岂。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片玖院。...
    茶點故事閱讀 39,779評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖第岖,靈堂內(nèi)的尸體忽然破棺而出难菌,到底是詐尸還是另有隱情,我是刑警寧澤蔑滓,帶...
    沈念sama閱讀 35,477評論 5 345
  • 正文 年R本政府宣布郊酒,位于F島的核電站,受9級特大地震影響键袱,放射性物質(zhì)發(fā)生泄漏燎窘。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,088評論 3 328
  • 文/蒙蒙 一蹄咖、第九天 我趴在偏房一處隱蔽的房頂上張望褐健。 院中可真熱鬧,春花似錦比藻、人聲如沸铝量。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,716評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽慢叨。三九已至纽匙,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間拍谐,已是汗流浹背烛缔。 一陣腳步聲響...
    開封第一講書人閱讀 32,857評論 1 269
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留轩拨,地道東北人践瓷。 一個月前我還...
    沈念sama閱讀 47,876評論 2 370
  • 正文 我出身青樓,卻偏偏與公主長得像亡蓉,于是被迫代替她去往敵國和親晕翠。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 44,700評論 2 354

推薦閱讀更多精彩內(nèi)容

  • 相機屬于系統(tǒng)硬件砍濒,這就需要我們來手動調(diào)用iPhone的相機硬件淋肾,分為以下步驟: 1、首先聲明以下對象 #impor...
    清蘂翅膀的技術閱讀 1,602評論 0 0
  • 1爸邢、首先聲明以下對象 #import//捕獲設備樊卓,通常是前置攝像頭,后置攝像頭杠河,麥克風(音頻輸入)@propert...
    zhong_JF閱讀 489評論 0 0
  • 相機屬于系統(tǒng)硬件碌尔,這就需要我們來手動調(diào)用iPhone的相機硬件,分為以下步驟: 1券敌、首先聲明以下對象 #impor...
    傻傻小蘿卜閱讀 634評論 0 2
  • 目錄相機基本實現(xiàn)步驟捕捉會話——AVCaptureSession捕捉輸入——AVCaptureDeviceInpu...
    cdcyd閱讀 34,303評論 33 163
  • //捕獲設備唾戚,通常是前置攝像頭,后置攝像頭陪白,麥克風(音頻輸入) @property(nonatomic, stro...
    那風吹過年華閱讀 690評論 0 0