背景
條形碼、二維碼是日常生活中用的較多的功能,我們在開發(fā)中之前用的都是ZXing、Zbar這兩個開源庫。不過在iOS7之后,蘋果系統(tǒng)自己實現(xiàn)了一套api,終于可以丟棄第三方,用上蘋果爸爸自己的功能了。
首先說說ZXing、Zbar這兩個開源庫。由于ZXing是用java實現(xiàn)的,Zbar是用C語音實現(xiàn)了,所以Zbar的識別效率遠遠高于ZXing,所以Zbar一般都是開發(fā)者的首選。不過iOS7系統(tǒng)出現(xiàn)自己的api后,系統(tǒng)的自然成為了首選。
按照識別速度來排序的話:系統(tǒng)api>Zbar>ZXing。系統(tǒng)的api識別速度非常的快,而且有效距離比其他兩個也大。最主要是系統(tǒng)自帶的api在識別條形碼的時候即使成90度垂直狀,仍然可以很快的識別出來。所以疑問來了,那就直接用系統(tǒng)api就行了唄。
話說本人也是這么想的,不過在實際過程中發(fā)現(xiàn)一個重大的問題!!有一些條形碼居然識別不了!經(jīng)過分析此條形碼的Code是EAN-128Code這是國內自己定義的,所以蘋果不支持。但是實際情況線下還挺多這種條形碼的,所以最后不得不換成Zbar。
Zbar脫坑記
Zbar的集成非常簡單,通過Cocopods直接導入即可。然后通過以下代碼使用
self.readerView = [[ZBarReaderView alloc] init];
self.readerView.frame = CGRectMake(0,0, preView.frame.size.width, preView.frame.size.height);
self.readerView.tracksSymbols = NO;
self.readerView.readerDelegate = self;
self.readerView.torchMode = 0;
self.readerView.allowsPinchZoom = NO;
ZBarImageScanner *scanner = self.readerView.scanner;
[scanner setSymbology:0 config:ZBAR_CFG_ENABLE to:0];
[scanner setSymbology:ZBAR_CODE128 config:ZBAR_CFG_ENABLE to:1];
[scanner setSymbology:ZBAR_CODE93 config:ZBAR_CFG_ENABLE to:1];
[scanner setSymbology:ZBAR_CODE39 config:ZBAR_CFG_ENABLE to:1];
很簡單,大功告成!
問題1
遇到第一個問題則是,發(fā)現(xiàn)同一個單號再次掃描反應非常遲鈍,而且掃描速度不是非常的快。這個時候點進去ZBarReaderView看了一下屬性。發(fā)現(xiàn)
// this flag still works, but its use is deprecated
@property (nonatomic) BOOL enableCache;
初步懷疑跟這個屬性有關,所以通過設置此屬性為NO,然后再次測試,發(fā)現(xiàn)此問題解決。同時掃描速度提速了
再次提速
雖然通過設置enableCache屬性能夠加快掃描速度,不過感覺還是有點慢,因為Zbar默認是全屏幕掃,即當條形碼出現(xiàn)在預覽框就可以識別到。
通過觀察屬性發(fā)現(xiàn)了scanCrop,縮小掃描區(qū)域
self.readerView.scanCrop = CGRectMake((_previewH/2-150)/_previewH, 0, 300/_previewH, 1);//中間區(qū)域高度為300的掃描區(qū)域
這個掃描區(qū)域的設置要非常的注意。我們預覽框看到的圖片與實際圖片不一樣,它是一個90度放倒的圖片。說白了就是我們預覽框x、y坐標對應實際照片的y、x坐標;高對應寬,寬對應高。而且這里所有的值都是小于1的。scanCrop默認值是(0,0,1,1)所以會是全屏掃描
不過通過設置下來,近距離掃描確實已經(jīng)非常快了。但是滿足不了我們的要求。得離著20cm左右掃描速度非??欤x著遠了識別速度非常的慢,甚至識別不了。
ZBarReaderView所有的屬性都翻了一個遍,也沒有發(fā)現(xiàn)相關屬性。
最終迫不得已只能去翻看Zbar源碼,試試能不能改善了
終極優(yōu)化
在網(wǎng)上轉了一圈沒搜到相關信息,所以只能研究研究代碼。
通過翻看代碼發(fā)現(xiàn),其實Zbar可以通俗的講分成兩部分。通過1、通過預覽獲取圖片數(shù)據(jù);2、通過C語言核心邏輯去解析
第二步通過確認沒有問題,所以問題出在第一步。由于第一步其實有點老生常談,所以看了代碼之后馬上發(fā)現(xiàn)了問題。即ZBarReaderViewImpl_Capture代碼的實現(xiàn)
此代碼很多年沒有維護了,所以獲取預覽圖片的時候,也是按照當時設備最大分辨率設置。隨著時間的發(fā)展,設備分辨率也提高了非常多
原來代碼
if ([session canSetSessionPreset:AVCaptureSessionPreset640x480])
{
[session setSessionPreset:AVCaptureSessionPreset640x480];
}
else if ([session canSetSessionPreset:AVCaptureSessionPreset352x288])
{
[self.session setSessionPreset:AVCaptureSessionPreset352x288];
}
原來代碼支持圖片的分辨率最高是640*480非常的小
改后的代碼
if ([session canSetSessionPreset:AVCaptureSessionPreset1920x1080]) {
[session setSessionPreset:AVCaptureSessionPreset1920x1080];
}
if ([session canSetSessionPreset:AVCaptureSessionPreset1280x720])
{
[session setSessionPreset:AVCaptureSessionPreset1280x720];
}
else if ([session canSetSessionPreset:AVCaptureSessionPreset640x480])
{
[session setSessionPreset:AVCaptureSessionPreset640x480];
}
else if ([session canSetSessionPreset:AVCaptureSessionPreset352x288])
{
[self.session setSessionPreset:AVCaptureSessionPreset352x288];
}
我們增加了圖片的分辨率即可。此時可以高效、快速、遠距離的識別到條形碼了。
總結
解決這個問題也是循序漸進式,通過自己的努力最終解決了問題。當我們在使用第三方的代碼庫的時候,遇到問題還是要多看看源碼,只有這樣我們才能了然于胸。遇到問題解決起來也會游刃有余。