二維碼已是很成熟的應用了,正好此次的應用用到二維碼開發,天然而然地用第三方的ZXing,遇到很多坑,主要就是ZXing的掃碼,差評!最後用AVFoundation實現,很容易的功能,我仍是太天真了,不知道ZXing/ObjC是怎麼騙到靠2000個星星的.git
公司產品要實現二維碼功能,這個早已成熟的功能第一想法確定是用第三方的,github上一查,ZXing的星星最多,那就它了.
把整個項目copy下來先demo跑起來,下了很久,100多M啊,真大.但其實用不到那麼多的,對於只須要生成,掃描二維碼,只須要:
pod 'ZXingObjC/QRCode'github
ZXEncodeHints *hints = [ZXEncodeHints hints]; hints.encoding = NSUTF8StringEncoding; hints.margin = @(0); ZXQRCodeWriter *writer = [[ZXQRCodeWriter alloc] init]; ZXBitMatrix *result = [writer encode:url format:kBarcodeFormatQRCode width:200*[UIScreen screenScale] height:200*[UIScreen screenScale] hints:hints error:nil]; codeImageView.image = [UIImage imageWithCGImage:[[ZXImage imageWithMatrix:result] cgimage]];
_capture = [[ZXCapture alloc] init]; _capture.camera = self.capture.back; _capture.focusMode = AVCaptureFocusModeContinuousAutoFocus; self.capture.delegate = self; [self.view.layer addSublayer:self.capture.layer]; #pragma mark - ZXCaptureDelegate Methods - (void)captureResult:(ZXCapture *)capture result:(ZXResult *)result { //能夠獲得掃描成功的二維碼 }
CGImageRef imageToDecode = image.CGImage; ZXLuminanceSource *source = [[ZXCGImageLuminanceSource alloc] initWithCGImage:imageToDecode]; ZXBinaryBitmap *bitmap = [ZXBinaryBitmap binaryBitmapWithBinarizer:[ZXHybridBinarizer binarizerWithSource:source]]; NSError *error = nil; ZXDecodeHints *hints = [ZXDecodeHints hints]; ZXQRCodeReader *reader = [[ZXQRCodeReader alloc] init]; ZXResult *result = [reader decode:bitmap hints:hints error:&error]; if (result) { self.resultLabel.text = result.text; } else { self.resultLabel.text = @"沒法識別"; }
徹底按照Demo來的,生成二維碼沒有問題,二維碼識別也沒問題,可是二維碼掃描就是掃描不出來,明明是照搬Demo的啊,一步一步調試,就是找不到緣由.
最後直接把ZXingBbjC文件夾拖進去,不用pod了,結果就好了,逗我?
性能
在掃碼的下面加了個按鈕,用於打開相冊直接取二維碼識別,總是按了沒反應,我點擊區域明明設了很大了啊.最後滾燙的手機給了我提示,我一看cpu使用率,直接爆掉了,怪不到按鈕響應不了.我已經無力吐槽了.
網上是這麼說的:url
ZXing掃描,是拿到攝像頭的每一幀,而後對其根據以下公式作灰度化
f(i,j)=0.30R(i,j)+0.59G(i,j)+0.11B(i,j))
以後作全局直方圖二值化的方法,最後按照 ISO/IEC 18004 規範進行解析。
這樣效率很是低,在instrument下面能夠看到CPU佔用遠遠高於 AVFoundation。並且全局直方圖二值化致使精準度並不高。這個庫還會帶來一大堆C++的東西,在純iOS7的工程下,不推薦使用.調試
個人結論是,在純iOS工程下,絕對不要使用ZXing掃描.rest
AVFoundation是系統自帶的,網上分析了它的很多問題,不過僅僅對於二維碼掃描,他仍是很是好用的,cpu使用率很是低.
網上有好多類似的Demo,對於掃描區域,主要是要設rectOfInterest.但它不是簡單的Frame設置,須要轉換,有個方法[previewLayer metadataOutputRectOfInterestForRect:frame],網上也推薦用這個方法,可是我用了不行,返回的是CGRectZero,還沒找到緣由,因此我直接本身設:
CGRectMake(y的起點/屏幕的高,x的起點/屏幕的寬,掃描的區域的高/屏幕的高,掃描的區域的寬/屏幕的寬)
這樣就沒問題啦.code
[self.view.layer insertSublayer:previewLayer atIndex:0]; CGRect frame = self.scanRectView.frame; frame.size = CGSizeMake(2 * frame.size.width, 2 * frame.size.height); //metadataOutput.rectOfInterest = [previewLayer metadataOutputRectOfInterestForRect:frame]; //返回的CGRectZero,小夥伴們能夠試試看行不行 metadataOutput.rectOfInterest = CGRectMake(frame.origin.y/SCREEN_HEIGHT, frame.origin.x/SCREEN_WIDTH, frame.size.height/SCREEN_HEIGHT, frame.size.width/SCREEN_WIDTH); [_captureSession startRunning];
這是系統自帶的圖片解碼,很是簡單,不過效率很低,會有卡頓,這裏仍是推薦用ZXing的解碼,效率更高orm
NSData *imageData = UIImagePNGRepresentation(image); CIImage *ciImage = [CIImage imageWithData:imageData]; CIDetector *detector = [CIDetector detectorOfType:CIDetectorTypeQRCode context:nil options:@{CIDetectorAccuracy: CIDetectorAccuracyLow}]; NSArray *feature = [detector featuresInImage:ciImage]; for (CIQRCodeFeature *result in feature) { self.resultLabel.text = result.messageString; return; }
實現了個小Demo,分別用ZXing和AVFoundation實現二維碼的生成和掃描,能夠明顯看到二者的性能比較,github地址,歡迎你們交流blog