[CSDN博客轉(zhuǎn)移]IOS下使用AVFoundation實現(xiàn)條形碼和二維碼掃描

昨天收到一個需求要給項目增加一個二維碼掃描的功能啤它,然后就找了一些AVFoundation的資料拼拼湊湊把功能完成了,中間也遇到了一些小坑舱痘。想了下轉(zhuǎn)IOS也有一段時間了好久不發(fā)博客了变骡,就寫一篇博客當做時給自己成長的一次記錄吧!同時也分享下代碼和大家一起學習進步芭逝,有哪里做得不到位的還希望各位大神多指教塌碌。

廢話不多說,先來說下大致的需求旬盯,首先實現(xiàn)二維碼的掃描識別功能 誊爹,頁面仿造微信掃碼,需求如下圖:

說下大致實現(xiàn)思路:

UI:基本比較簡單整個圖層的下方是從攝像頭采集到的圖像瓢捉,沒關鍵難點就在于四周半透明中間全透明的視圖,以及掃描的線條办成。

關于半透明視圖:我的實現(xiàn)方式是創(chuàng)建一個全透明的view定義好一個識別區(qū)然后在識別區(qū)的上下左右用Quartz2D分別畫4個半透明的矩形某弦。感覺比較挫靶壮,本來想用Quartz2d的API處理下,愣是只找到截取沒找到裁圖螃壤,希望有更好思路的大神可以指教下奸晴!

//填充區(qū)域顏色

[[UIColor colorWithRed:0 green:0 blue:0 alpha:0.65] set];

//掃碼區(qū)域上面填充

CGRect notScanRect = CGRectMake(0, 0, self.frame.size.width, _scanFrame.origin.y);

CGContextFillRect(context, notScanRect);

//掃碼區(qū)域左邊填充

rect = CGRectMake(0, _scanFrame.origin.y, _scanFrame.origin.x,_scanFrame.size.height);

CGContextFillRect(context, rect);

//掃碼區(qū)域右邊填充

rect = CGRectMake(CGRectGetMaxX(_scanFrame), _scanFrame.origin.y, _scanFrame.origin.x,_scanFrame.size.height);

CGContextFillRect(context, rect);

//掃碼區(qū)域下面填充

rect = CGRectMake(0, CGRectGetMaxY(_scanFrame), self.frame.size.width,self.frame.size.height - CGRectGetMaxY(_scanFrame));

CGContextFillRect(context, rect);

掃描的線條動畫:這個實現(xiàn)的方式多種多樣,我就說下我的實現(xiàn)涕刚,就是一條美工提供好的線條然后用timer調(diào)setNeedsDisplay副女。在drawRect中改變圖片的frame 再繪制到界面上。

@interface QRCodeAreaView()

/**

*? 記錄當前線條繪制的位置

*/

@property (nonatomic,assign) CGPoint position;

/**

*? 定時器

*/

@property (nonatomic,strong)NSTimer? *timer;

@end

@implementation QRCodeAreaView

- (void)drawRect:(CGRect)rect {

CGPoint newPosition = self.position;

newPosition.y += 1;

//判斷y到達底部沟涨,從新開始下降

if (newPosition.y > rect.size.height) {

newPosition.y = 0;

}

//重新賦值position

self.position = newPosition;

// 繪制圖片

UIImage *image = [UIImage imageNamed:@"line"];

[image drawAtPoint:self.position];

}

-(instancetype)initWithFrame:(CGRect)frame{

if (self = [super initWithFrame:frame]) {

self.backgroundColor = [UIColor clearColor];

UIImageView *areaView = [[UIImageView alloc]initWithImage:[UIImage imageNamed:@"frame_icon"]];

areaView.width = self.width;

areaView.height = self.height;

[self addSubview:areaView];

self.timer = [NSTimer scheduledTimerWithTimeInterval:0.01 target:self selector:@selector(setNeedsDisplay) userInfo:nil repeats:YES];

}

return self;

}

-(void)startAnimaion{

[self.timer setFireDate:[NSDate date]];

}

-(void)stopAnimaion{

[self.timer setFireDate:[NSDate distantFuture]];

}

@end

說下二維碼的識別:借助AVfoundation的強大API整體實現(xiàn)還是相當簡單的诀浪,識別效率真的是杠杠的睛竣。

/**

*? 初始化二維碼掃描

*/

//獲取攝像設備

AVCaptureDevice * device = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo];

//創(chuàng)建輸入流

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

//創(chuàng)建輸出流

AVCaptureMetadataOutput * output = [[AVCaptureMetadataOutput alloc]init];

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

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

//設置識別區(qū)域

//深坑,這個值是按比例0~1設置验夯,而且X挥转、Y要調(diào)換位置,width域仇、height調(diào)換位置

output.rectOfInterest = CGRectMake(_areaView.y/screen_height, _areaView.x/screen_width, _areaView.height/screen_height, _areaView.width/screen_width);

//初始化鏈接對象

session = [[AVCaptureSession alloc]init];

//高質(zhì)量采集率

[session setSessionPreset:AVCaptureSessionPresetHigh];

[session addInput:input];

[session addOutput:output];

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

output.metadataObjectTypes=@[AVMetadataObjectTypeQRCode,AVMetadataObjectTypeEAN13Code, AVMetadataObjectTypeEAN8Code, AVMetadataObjectTypeCode128Code];

AVCaptureVideoPreviewLayer * layer = [AVCaptureVideoPreviewLayer layerWithSession:session];

layer.videoGravity=AVLayerVideoGravityResizeAspectFill;

layer.frame=self.view.layer.bounds;

[self.view.layer insertSublayer:layer atIndex:0];

//開始捕獲

[session startRunning];

#pragma 二維碼掃描的回調(diào)

-(void)captureOutput:(AVCaptureOutput *)captureOutput didOutputMetadataObjects:(NSArray *)metadataObjects fromConnection:(AVCaptureConnection *)connection{

if (metadataObjects.count>0) {

[session stopRunning];//停止掃描

[_areaView stopAnimaion];//暫停動畫

AVMetadataMachineReadableCodeObject * metadataObject = [metadataObjects objectAtIndex : 0 ];

//輸出掃描字符串

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

}

}

但是中間也有一個坑就是眾所周知的rectOfInterest屬性,真想吐槽下apple干嘛不弄個正常人思維的東西择镇?第一次使用的朋友同時又想提高識別效率腻豌,做出和大平臺那樣的中間區(qū)域識別的效果一看rect肯定和我一樣興奮,不就是設置個rect嘛苏携。按照正常rect設置完成后右冻,你會發(fā)現(xiàn)你的程序失效了。點開這個方法的幫助不難看到

The default value of this property is the value CGRectMake(0, 0, 1, 1).? Metadata objects whose bounds do not intersect with the rectOfInterest will not be returned.

官方這是在告訴你這個rect范圍時0~1跪但,我們立馬能想到計算X比例不就是當前X坐標/屏幕寬度嘛忆首?可是事實不是详幽,這個就是最操蛋的地方唇聘。我百度了一個多小時終于搞明白了(當初學習的博客找不到了,過后找到了再注明轉(zhuǎn)載)宪肖,原來這個XY是要翻過來的么介,同時width height也是要反過來壤短,于是這個rect應該是CGRectMake(Y/屏幕高度, X/屏幕高度,heidth/屏幕高度,width/屏幕寬度)。最最坑爹的是這個設置設置完了以后屏幕上沒有任何可視效果桶现。我也是在中間畫了一個半透明矩形拿一個二維碼各個角度識別才測試出來的骡和。

//設置識別區(qū)域

//深坑,這個值是按比例0~1設置婆赠,而且X、Y要調(diào)換位置妙黍,width、height調(diào)換位置

output.rectOfInterest = CGRectMake(_areaView.y/screen_height, _areaView.x/screen_width, _areaView.height/screen_height, _areaView.width/screen_width);

//掃描區(qū)域

CGRect areaRect = CGRectMake((screen_width - 218)/2, (screen_height - 218)/2, 218, 218);

完整項目地址:https://github.com/CharmingLee/QRCodeController.git

https://git.oschina.net/CharmingLee/QRCodeController.git

最后編輯于
?著作權歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末捉撮,一起剝皮案震驚了整個濱河市堵泽,隨后出現(xiàn)的幾起案子睬愤,更是在濱河造成了極大的恐慌,老刑警劉巖光督,帶你破解...
    沈念sama閱讀 206,968評論 6 482
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件船老,死亡現(xiàn)場離奇詭異,居然都是意外死亡薪韩,警方通過查閱死者的電腦和手機观谦,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,601評論 2 382
  • 文/潘曉璐 我一進店門替蔬,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人凶异,你說我怎么就攤上這事∥秩模” “怎么了?”我有些...
    開封第一講書人閱讀 153,220評論 0 344
  • 文/不壞的土叔 我叫張陵抖拦,是天一觀的道長拗踢。 經(jīng)常有香客問我,道長,這世上最難降的妖魔是什么蓄髓? 我笑而不...
    開封第一講書人閱讀 55,416評論 1 279
  • 正文 為了忘掉前任肢执,我火速辦了婚禮,結(jié)果婚禮上拙徽,老公的妹妹穿的比我還像新娘。我一直安慰自己淳蔼,他們只是感情好,可當我...
    茶點故事閱讀 64,425評論 5 374
  • 文/花漫 我一把揭開白布旦袋。 她就那樣靜靜地躺著,像睡著了一般祭阀。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,144評論 1 285
  • 那天,我揣著相機與錄音,去河邊找鬼黔攒。 笑死,一個胖子當著我的面吹牛赏胚,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 38,432評論 3 401
  • 文/蒼蘭香墨 我猛地睜開眼眯亦,長吁一口氣:“原來是場噩夢啊……” “哼乱顾!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,088評論 0 261
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后套才,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 43,586評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡疾掰,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,028評論 2 325
  • 正文 我和宋清朗相戀三年拂檩,在試婚紗的時候發(fā)現(xiàn)自己被綠了凯旋。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 38,137評論 1 334
  • 序言:一個原本活蹦亂跳的男人離奇死亡趣惠,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出侍瑟,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 33,783評論 4 324
  • 正文 年R本政府宣布督暂,位于F島的核電站,受9級特大地震影響肪凛,放射性物質(zhì)發(fā)生泄漏翘鸭。R本人自食惡果不足惜拱烁,卻給世界環(huán)境...
    茶點故事閱讀 39,343評論 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧念脯,春花似錦、人聲如沸惯吕。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,333評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春届巩,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,559評論 1 262
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人煌集。 一個月前我還...
    沈念sama閱讀 45,595評論 2 355
  • 正文 我出身青樓卷拘,卻偏偏與公主長得像,于是被迫代替她去往敵國和親瓣蛀。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 42,901評論 2 345

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