iOS QRCode(二维码)操作

来源:互联网 发布:文明太空mac汉化 编辑:程序博客网 时间:2024/05/16 12:51

扫描主要使用的是AVFoundation 使用起来也非常的简单 正常的初始化流程如下

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970
@interface Example1Controller()<AVCaptureMetadataOutputObjectsDelegate,UIAlertViewDelegate>@property (nonatomic, strong) UIView *scanRectView;@property (strong, nonatomic) AVCaptureDevice            *device;@property (strong, nonatomic) AVCaptureDeviceInput       *input;@property (strong, nonatomic) AVCaptureMetadataOutput    *output;@property (strong, nonatomic) AVCaptureSession           *session;@property (strong, nonatomic) AVCaptureVideoPreviewLayer *preview;@end@implementation Example1Controller- (void)viewDidLoad {    [super viewDidLoad];    // Do any additional setup after loading the view.        self.device = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo];        self.input = [AVCaptureDeviceInput deviceInputWithDevice:self.device error:nil];        self.output = [[AVCaptureMetadataOutput alloc]init];    [self.output setMetadataObjectsDelegate:self queue:dispatch_get_main_queue()];        self.session = [[AVCaptureSession alloc]init];    [self.session setSessionPreset:([UIScreen mainScreen].bounds.size.height<500)?AVCaptureSessionPreset640x480:AVCaptureSessionPresetHigh];    [self.session addInput:self.input];    [self.session addOutput:self.output];    self.output.metadataObjectTypes=@[AVMetadataObjectTypeQRCode];    self.output.rectOfInterest = scanRect;        self.preview = [AVCaptureVideoPreviewLayer layerWithSession:self.session];    self.preview.videoGravity = AVLayerVideoGravityResizeAspectFill;    self.preview.frame = [UIScreen mainScreen].bounds;    [self.view.layer insertSublayer:self.preview atIndex:0];        //开始捕获    [self.session startRunning];    }- (void)captureOutput:(AVCaptureOutput *)captureOutput didOutputMetadataObjects:(NSArray *)metadataObjects fromConnection:(AVCaptureConnection *)connection{    if ( (metadataObjects.count==0) )    {        return;    }        if (metadataObjects.count>0) {                [self.session stopRunning];                AVMetadataMachineReadableCodeObject *metadataObject = metadataObjects.firstObject;        //输出扫描字符串                UIAlertView *alert = [[UIAlertView alloc] initWithTitle:metadataObject.stringValue message:@"" delegate:self cancelButtonTitle:@"ok" otherButtonTitles: nil];                [alert show];    }}- (void)alertView:(UIAlertView *)alertView willDismissWithButtonIndex:(NSInteger)buttonIndex{    [self.session startRunning];}

AVFoundation的部分我就不多介绍了 只要按照上面的代码初始化 即可实现二维码扫描的功能 是不是很简单?

不过这里还不能完全满足我们的要求 因为如果运行以后你会发现 现在是全屏扫描 而不是像我们印象中的那种在屏幕中间有个框 只有在框中的二维码才会被扫描到 不过其实改起来也很简单 AVCaptureMetadataOutput有个属性rectOfInterest就是做这个事情的

12345678910111213141516
@interface AVCaptureMetadataOutput : AVCaptureOutput /*! @property rectOfInterest @abstractSpecifies a rectangle of interest for limiting the search area for visual metadata.  @discussionThe value of this property is a CGRect that determines the receiver's rectangle of interest for each frame of video.  The rectangle's origin is top left and is relative to the coordinate space of the device providing the metadata.  Specifying a rectOfInterest may improve detection performance for certain types of metadata. The default value of this property is the value CGRectMake(0, 0, 1, 1).  Metadata objects whose bounds do not intersect with the rectOfInterest will not be returned. */@property(nonatomic) CGRect rectOfInterest NS_AVAILABLE_IOS(7_0);@end

可以看到 rectOfInterest的值的范围都是0-1 是按比例取值而不是实际尺寸 不过其实也很简单 只要换算一下就好了 接下来我们添加取景框

123456789101112131415
CGSize windowSize = [UIScreen mainScreen].bounds.size;CGSize scanSize = CGSizeMake(windowSize.width*3/4, windowSize.width*3/4);CGRect scanRect = CGRectMake((windowSize.width-scanSize.width)/2, (windowSize.height-scanSize.height)/2, scanSize.width, scanSize.height);//计算rectOfInterest 注意x,y交换位置scanRect = CGRectMake(scanRect.origin.y/windowSize.height, scanRect.origin.x/windowSize.width, scanRect.size.height/windowSize.height,scanRect.size.width/windowSize.width);self.output.rectOfInterest = scanRect;self.scanRectView = [UIView new];[self.view addSubview:self.scanRectView];self.scanRectView.frame = CGRectMake(0, 0, scanSize.width, scanSize.height);self.scanRectView.center = CGPointMake(CGRectGetMidX([UIScreen mainScreen].bounds), CGRectGetMidY([UIScreen mainScreen].bounds));self.scanRectView.layer.borderColor = [UIColor redColor].CGColor;self.scanRectView.layer.borderWidth = 1;

这里唯一要注意的一点是 rectOfInterest 都是按照横屏来计算的 所以当竖屏的情况下 x轴和y轴要交换一下

读取


读取主要用到CoreImage 不过要强调的是读取二维码的功能只有在iOS8之后才支持
读取的代码实现就更简单了

123456789
UIImage * srcImage = qrcodeImage;CIContext *context = [CIContext contextWithOptions:nil];CIDetector *detector = [CIDetector detectorOfType:CIDetectorTypeQRCode context:context options:@{CIDetectorAccuracy:CIDetectorAccuracyHigh}];CIImage *image = [CIImage imageWithCGImage:srcImage.CGImage];NSArray *features = [detector featuresInImage:image];CIQRCodeFeature *feature = [features firstObject];NSString *result = feature.messageString;





生成


生成也是用到CoreImage 其步骤稍微多一点 代码如下

12345678910111213141516171819202122232425262728293031323334
NSString *text = self.tfCode.text;NSData *stringData = [text dataUsingEncoding: NSUTF8StringEncoding];//生成CIFilter *qrFilter = [CIFilter filterWithName:@"CIQRCodeGenerator"];[qrFilter setValue:stringData forKey:@"inputMessage"];[qrFilter setValue:@"M" forKey:@"inputCorrectionLevel"];UIColor *onColor = [UIColor redColor];UIColor *offColor = [UIColor blueColor];//上色CIFilter *colorFilter = [CIFilter filterWithName:@"CIFalseColor"                                   keysAndValues:                         @"inputImage",qrFilter.outputImage,                         @"inputColor0",[CIColor colorWithCGColor:onColor.CGColor],                         @"inputColor1",[CIColor colorWithCGColor:offColor.CGColor],                         nil];CIImage *qrImage = colorFilter.outputImage;//绘制CGSize size = CGSizeMake(300, 300);CGImageRef cgImage = [[CIContext contextWithOptions:nil] createCGImage:qrImage fromRect:qrImage.extent];UIGraphicsBeginImageContext(size);CGContextRef context = UIGraphicsGetCurrentContext();CGContextSetInterpolationQuality(context, kCGInterpolationNone);CGContextScaleCTM(context, 1.0, -1.0);CGContextDrawImage(context, CGContextGetClipBoundingBox(context), cgImage);UIImage *codeImage = UIGraphicsGetImageFromCurrentImageContext();UIGraphicsEndImageContext();CGImageRelease(cgImage);

  • 首先通过[CIFilter filterWithName:@"CIQRCodeGenerator"]生成QRCode
  • 然后通过[CIFilter filterWithName:@"CIFalseColor"]上色(当然这一步不是必须的 如果仅仅需要白底黑块的QRCode 可以跳过这一步)
  • 最后无损放大并绘制QRCode (上面两步生成的QRCode很小 大概是31*31 如果不放大 就会很模糊)

这里要注意的是 在最后一步一定要使用CGContextScaleCTM(context, 1.0, -1.0)来翻转一下图片 不然生成的QRCode就是上下颠倒

原文参考:再见ZXing 使用系统原生代码处理QRCode


0 0
原创粉丝点击