二维码已是很成熟的应用了,正好此次的应用用到二维码开发,天然而然地用第三方的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