您的位置:首页 > 其它

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

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

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

二维码扫描需要用到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;

}



中心加小图的二维码

其实也可以扫描条形码,大家可以对着条形码试一试,代码都是通用的。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: