iOS 二維碼和條形碼掃描,獲取焦點及焦距拉近縮放

? ? ? 對于現在的App應用來說,掃描二維碼和條形碼這個功能是再正常不過的一個功能了,在早期開發這些功能的時候,大家或多或少的都接觸過ZXing和ZBar這類的第三方庫,但從iOS7以后,蘋果就給我們提供了系統原生的API來支持我們掃描獲取二維碼,ZXing和ZBar在使用中或多或少有不盡如人意的地方,再之停止更新很久了,所以今天我們就來聊聊如何用系統原生的方法掃描獲取二維碼,強大的AVFoundation框架給我們提供了掃描私有方法和代理方法。

? ? ?首先獲取流媒體信息我們需要AVCaptureSession對象來管理輸入流和輸出流,AVCaptureVideoPreviewLayer對象來顯示信息,基本流程如下圖所示

??

AVCaptureSession管理輸入(AVCaptureInput)和輸出(AVCaptureOutput)流,包含開啟和停止會話方法。

AVCaptureDeviceInput是AVCaptureInput的子類,可以作為輸入捕獲會話,用AVCaptureDevice實例初始化。

AVCaptureDevice代表了物理捕獲設備如:攝像機。用于配置等底層硬件設置相機的自動對焦模式。

AVCaptureMetadataOutput是AVCaptureOutput的子類,處理輸出捕獲會話。捕獲的對象傳遞給一個委托實現AVCaptureMetadataOutputObjectsDelegate協議。協議方法在指定的派發隊列(dispatch queue)上執行。

AVCaptureVideoPreviewLayerCALayer的一個子類,顯示捕獲到的相機輸出流。

好了看下實現過程:

添加代理 <AVCaptureMetadataOutputObjectsDelegate>

/** 設備 */

@property (nonatomic, strong) AVCaptureDevice * device;

/** 輸入輸出的中間橋梁 */

@property (nonatomic, strong) AVCaptureSession * session;

/** 相機圖層 */

@property (nonatomic, strong) AVCaptureVideoPreviewLayer * previewLayer;

/** 掃描支持的編碼格式的數組 */

@property (nonatomic, strong) NSMutableArray * metadataObjectTypes;

/** 遮罩層 */

@property (nonatomic, strong) ZFMaskView * maskView;

@property(nonatomic,strong) AVCaptureMetadataOutput * metadataOutput ;//輸出流

@property(nonatomic,strong)AVCaptureDeviceInput * input;//創建輸入流

這里介紹下掃描支持的編碼格式

/*

//設置支持的掃描類型

由于本項目只支持條形碼掃描,故先屏蔽掉二維碼掃描功能

AVMetadataObjectTypeQRCode,AVMetadataObjectTypeAztecCode,

*/

- (NSMutableArray *)metadataObjectTypes{

if (!_metadataObjectTypes) {

_metadataObjectTypes = [NSMutableArray arrayWithObjects:AVMetadataObjectTypeCode128Code, AVMetadataObjectTypeCode39Code, AVMetadataObjectTypeCode39Mod43Code, AVMetadataObjectTypeCode93Code, AVMetadataObjectTypeEAN13Code, AVMetadataObjectTypeEAN8Code, ?/ ?/我國商品碼主要就是這和 EAN8

AVMetadataObjectTypePDF417Code, AVMetadataObjectTypeUPCECode, nil];

// >= iOS 8

if (floor(NSFoundationVersionNumber) > NSFoundationVersionNumber_iOS_7_1) {

[_metadataObjectTypes addObjectsFromArray:@[AVMetadataObjectTypeInterleaved2of5Code, AVMetadataObjectTypeITF14Code, AVMetadataObjectTypeDataMatrixCode]];

}

}

? ? return _metadataObjectTypes;

}

/**

*? 掃描初始化

*/

- (void)capture{

//獲取攝像設備

self.device = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo];

//創建輸入流

AVCaptureDeviceInput * input = [AVCaptureDeviceInput deviceInputWithDevice:self.device error:nil];

//創建輸出流

_metadataOutput = [[AVCaptureMetadataOutput alloc] init];

//設置代理 在主線程里刷新

[_metadataOutput setMetadataObjectsDelegate:self queue:dispatch_get_main_queue()];

//初始化鏈接對象

self.session = [[AVCaptureSession alloc] init];

//高質量采集率

self.session.sessionPreset = AVCaptureSessionPresetHigh;

[self.session addInput:input];

[self.session addOutput:_metadataOutput];

self.previewLayer = [AVCaptureVideoPreviewLayer layerWithSession:self.session];

self.previewLayer.frame = CGRectMake(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT);

self.previewLayer.videoGravity = AVLayerVideoGravityResizeAspectFill;

self.previewLayer.backgroundColor = [UIColor yellowColor].CGColor;

[self.view.layer addSublayer:self.previewLayer];

//設置掃描支持的編碼格式(如下設置條形碼和二維碼兼容)

_metadataOutput.metadataObjectTypes = self.metadataObjectTypes;

//開始捕獲

[self.session startRunning];

}

下一步,獲取掃描結果

#pragma mark - AVCaptureMetadataOutputObjectsDelegate-(void)captureOutput:(AVCaptureOutput*)captureOutput didOutputMetadataObjects:(NSArray*)metadataObjects fromConnection:(AVCaptureConnection*)connection

{if(metadataObjects.count>0) {? ? ?

? ?[self.session stopRunning];

?AVMetadataMachineReadableCodeObject*metadataObject = ?metadataObjects[0];

?NSLog(@"%@",metadataObject.stringValue);?

? }}

小結一下:

如果你的項目只需要掃描二維碼,不考慮條形碼,metadataObjectTypes只需要AVMetadataObjectTypeQRCode就夠了,反之把這個去掉


? 下面我主要講講怎么把鏡頭拉近,提高掃描效果,你之前在界面中添加一個按鈕,添加事件。

#pragma mark - ?焦距

- (void)CameraScaleAction:(UIButton *)sender{

kCameraScale+=0.5; ? //去定義一個float類型,默認值為1.0

if(kCameraScale>2.5)

kCameraScale=1.0;

//改變焦距 ? 記住這里的輸出鏈接類型要選中這個類型,否則屏幕會花的

AVCaptureConnection *connect=[_metadataOutput connectionWithMediaType:AVMediaTypeVideo];

[CATransaction begin];

[CATransaction setAnimationDuration:0.2];

[sender setTitle:[NSString stringWithFormat:@"%.1fX",(float)kCameraScale] forState:UIControlStateNormal];

//主要是改變相機圖層的大小

[_previewLayer setAffineTransform:CGAffineTransformMakeScale(kCameraScale, kCameraScale)];

connect.videoScaleAndCropFactor= kCameraScale;

[CATransaction commit];

//超出的部分切掉,否則影響掃描效果

self.view.clipsToBounds=YES;

self.view.layer.masksToBounds=YES;

}



這是對比圖,

如果想獲取焦點需要給view添加一個手勢

////對焦

-(void)foucus:(UITapGestureRecognizer *)sender

{

if(_input.device.position==AVCaptureDevicePositionFront)

return;

if(sender.state==UIGestureRecognizerStateRecognized)

{

CGPoint location=[sender locationInView:self.view];

//對焦

__weak typeof(self) weakSelf=self;

[self focusOnPoint:location completionHandler:^{

weakSelf.focalReticule.center=location;

weakSelf.focalReticule.alpha=0.0;

weakSelf.focalReticule.hidden=NO;

[UIView animateWithDuration:0.3 animations:^{

weakSelf.focalReticule.alpha=1.0;

}completion:^(BOOL finished) {

[UIView animateWithDuration:0.3 animations:^{

weakSelf.focalReticule.alpha=0.0;

}];

}];

}];

}

}

////對某一點對焦

-(void)focusOnPoint:(CGPoint)point completionHandler:(void(^)())completionHandler{

AVCaptureDevice *device = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo];;

CGPoint pointOfInterest = CGPointZero;

CGSize frameSize = self.view.bounds.size;

pointOfInterest = CGPointMake(point.y / frameSize.height, 1.f - (point.x / frameSize.width));

if ([device isFocusPointOfInterestSupported] && [device isFocusModeSupported:AVCaptureFocusModeAutoFocus])

{

NSError *error;

if ([device lockForConfiguration:&error])

{

if ([device isWhiteBalanceModeSupported:AVCaptureWhiteBalanceModeAutoWhiteBalance])

{

[device setWhiteBalanceMode:AVCaptureWhiteBalanceModeAutoWhiteBalance];

}

if ([device isFocusModeSupported:AVCaptureFocusModeContinuousAutoFocus])

{

[device setFocusMode:AVCaptureFocusModeAutoFocus];

[device setFocusPointOfInterest:pointOfInterest];

}

if([device isExposurePointOfInterestSupported] && [device isExposureModeSupported:AVCaptureExposureModeContinuousAutoExposure])

{

[device setExposurePointOfInterest:pointOfInterest];

[device setExposureMode:AVCaptureExposureModeContinuousAutoExposure];

}

[device unlockForConfiguration];

if(completionHandler)

completionHandler();

}

}

else{

if(completionHandler)

completionHandler();

}

} ? ? ? ? ? ? ? ??

好了,歡迎大家指正

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 229,362評論 6 537
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 99,013評論 3 423
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 177,346評論 0 382
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,421評論 1 316
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 72,146評論 6 410
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 55,534評論 1 325
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,585評論 3 444
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,767評論 0 289
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 49,318評論 1 335
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 41,074評論 3 356
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 43,258評論 1 371
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,828評論 5 362
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,486評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,916評論 0 28
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 36,156評論 1 290
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,993評論 3 395
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 48,234評論 2 375

推薦閱讀更多精彩內容