转载

详细易懂的二维码的扫描、识别与生成

ios7之前我们实现二维码扫描是借助第三方(ZBar,ZXing等)来实现的,在ios7之后系统自己提供二维码扫描的方法,性能也要比第三方更好。

今天就来介绍一下原生二维码的使用,包括扫描二维码,从图片扫描二维码和生成二维码。讲解中只展示部分代码,具体请看Github Demo,里面的代码不多,也很容易看懂。

扫描二维码

二维码扫描需要用到AVFoundation.framework,需要用先创建一个AVCaptureSession,然后设置输入输出流,以及扫描区域和支持的格式:

//获取摄像设备 AVCaptureDevice *device = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo]; //创建输入流 AVCaptureDeviceInput *input = [AVCaptureDeviceInput deviceInputWithDevice:device error:nil]; if (!input) {     return nil; } //创建输出流 AVCaptureMetadataOutput *output = [[AVCaptureMetadataOutput alloc] init]; //设置代理 在主线程里刷新 [output setMetadataObjectsDelegate:self queue:dispatch_get_main_queue()]; //设置扫描区域的比例 CGFloat width = 300 / CGRectGetHeight(self.view.frame); CGFloat height = 300 / CGRectGetWidth(self.view.frame); output.rectOfInterest = CGRectMake((1 - width) / 2, (1- height) / 2, width, height);  AVCaptureSession *session = [[AVCaptureSession alloc] init]; //高质量采集率 [session setSessionPreset:AVCaptureSessionPresetHigh]; [session addInput:input]; [session addOutput:output];  //设置扫码支持的编码格式(这里设置条形码和二维码兼容) output.metadataObjectTypes = @[AVMetadataObjectTypeQRCode,                                AVMetadataObjectTypeEAN13Code,                                AVMetadataObjectTypeEAN8Code,                                AVMetadataObjectTypeCode128Code];

然后用这个session生成一个AVCaptureVideoPreviewLayer加到某个view的layer上,就可以实时显示摄像头捕捉的内容了:

AVCaptureVideoPreviewLayer *layer = [AVCaptureVideoPreviewLayer layerWithSession:self.session]; layer.videoGravity = AVLayerVideoGravityResizeAspectFill; layer.frame = self.view.layer.bounds; [self.view.layer insertSublayer:layer atIndex:0];

然后调用[self.session startRunning];开始捕获,当扫描出结果后会调用下面的代理方法,其中metadataObject.stringValue就是扫描后的结果。

#pragma mark - AVCaptureMetadataOutputObjectsDelegate -(void)captureOutput:(AVCaptureOutput *)captureOutput didOutputMetadataObjects:(NSArray *)metadataObjects fromConnection:(AVCaptureConnection *)connection {     if (metadataObjects.count > 0)     {                 AVMetadataMachineReadableCodeObject *metadataObject = [metadataObjects firstObject];     }

}

为了在黑夜也可以很好的扫描,可以设置一个闪光灯的开关:

#pragma mark - 开关闪光灯 - (void)rightBarButtonDidClick:(UIBarButtonItem *)item {     self.flashOpen = !self.flashOpen;      AVCaptureDevice *device = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo];      if ([device hasTorch] && [device hasFlash])     {         [device lockForConfiguration:nil];          if (self.flashOpen)         {             device.torchMode = AVCaptureTorchModeOn;             device.flashMode = AVCaptureFlashModeOn;         }         else         {             device.torchMode = AVCaptureTorchModeOff;             device.flashMode = AVCaptureFlashModeOff;         }          [device unlockForConfiguration];     } }

详细易懂的二维码的扫描、识别与生成

扫描二维码

从图片扫描

有时候我们需要从图片中扫描二维码,或者从相册选择一张图片,代码如下,具体可以看demo。其中feature.messageString就是扫描后的结果。

- (void)findQRCodeFromImage:(UIImage *)image {     CIDetector *detector = [CIDetector detectorOfType:CIDetectorTypeQRCode                                               context:nil                                               options:@{CIDetectorAccuracy:CIDetectorAccuracyHigh}];      NSArray *features = [detector featuresInImage:[CIImage imageWithCGImage:image.CGImage]];     if (features.count >= 1)     {         CIQRCodeFeature *feature = [features firstObject];     } }

详细易懂的二维码的扫描、识别与生成

从图片扫描

生成二维码

生成二维码的代码很简单,代码如下。

/** 生成指定大小的黑白二维码 */ - (UIImage *)createQRImageWithString:(NSString *)string size:(CGSize)size {     NSData *stringData = [string dataUsingEncoding:NSUTF8StringEncoding];      CIFilter *qrFilter = [CIFilter filterWithName:@"CIQRCodeGenerator"];     //    NSLog(@"%@",qrFilter.inputKeys);     [qrFilter setValue:stringData forKey:@"inputMessage"];     [qrFilter setValue:@"M" forKey:@"inputCorrectionLevel"];      CIImage *qrImage = qrFilter.outputImage;     //放大并绘制二维码 (上面生成的二维码很小,需要放大)     CGImageRef cgImage = [[CIContext contextWithOptions:nil] createCGImage:qrImage fromRect:qrImage.extent];     UIGraphicsBeginImageContext(size);     CGContextRef context = UIGraphicsGetCurrentContext();     CGContextSetInterpolationQuality(context, kCGInterpolationNone);     //翻转一下图片 不然生成的QRCode就是上下颠倒的     CGContextScaleCTM(context, 1.0, -1.0);     CGContextDrawImage(context, CGContextGetClipBoundingBox(context), cgImage);     UIImage *codeImage = UIGraphicsGetImageFromCurrentImageContext();     UIGraphicsEndImageContext();      CGImageRelease(cgImage);      return codeImage; }

详细易懂的二维码的扫描、识别与生成

黑白二维码

上面默认生成的时黑白二维码,不过我们也可以改颜色:

/** 为二维码改变颜色 */ - (UIImage *)changeColorForQRImage:(UIImage *)image backColor:(UIColor *)backColor frontColor:(UIColor *)frontColor {     CIFilter *colorFilter = [CIFilter filterWithName:@"CIFalseColor"                                        keysAndValues:                              @"inputImage",[CIImage imageWithCGImage:image.CGImage],                              @"inputColor0",[CIColor colorWithCGColor:frontColor.CGColor],                              @"inputColor1",[CIColor colorWithCGColor:backColor.CGColor],                              nil];      return [UIImage imageWithCIImage:colorFilter.outputImage]; }

详细易懂的二维码的扫描、识别与生成

为二维码改变颜色

有的二维码也会在中心加一个小图片,例如用户头像,代码如下:

/** 在二维码中心加一个小图 */ - (UIImage *)addSmallImageForQRImage:(UIImage *)qrImage {     UIGraphicsBeginImageContext(qrImage.size);     [qrImage drawInRect:CGRectMake(0, 0, qrImage.size.width, qrImage.size.height)];     UIImage *image = [UIImage imageNamed:@"small"];     CGFloat imageW = 50;     CGFloat imageX = (qrImage.size.width - imageW) * 0.5;     CGFloat imgaeY = (qrImage.size.height - imageW) * 0.5;     [image drawInRect:CGRectMake(imageX, imgaeY, imageW, imageW)];     UIImage *result = UIGraphicsGetImageFromCurrentImageContext();     UIGraphicsEndImageContext();     return result; }

详细易懂的二维码的扫描、识别与生成

中心加小图的二维码

其实也可以扫描条形码,大家可以对着条形码试一试,代码都是通用的。

正文到此结束
Loading...