美文网首页
二维码学习

二维码学习

作者: 冷武橘 | 来源:发表于2020-08-27 15:46 被阅读0次

一、生成一个二维码

    //1、创建一个二维码滤镜
    CIFilter *filter = [CIFilter filterWithName:@"CIQRCodeGenerator”];

 恢复滤镜的默认设置     
  [filter setDefaults];
    //2、设置滤镜输入内容
    [filter setValue:data forKey:@"inputMessage”];
    
    //3、直接从二维码滤镜中获取需要的二维码图片
    CIImage *outputImage = [filter  outputImage];
    UIImage * image = [UIImage imageWithCIImage:outputImage];
    imageView.image =image;
    NSLog(@"%@",NSStringFromCGSize(image.size));
  • 1、通过滤镜CIFilter生成二维码
  • 2、如果想要给滤镜设置输入数据,只能通过KVC的形式,设置inputMessage。输入的数据,只能是NSData
  • 3、直接获取的二维码图片的size是{27, 27},直接在imageView上显示会显得模糊,因此大多数时候我们需要借助位图处理放大图片,获取一个高清图片。
  CIImage *outputImage = [filter  outputImage];
  imageView.image = [self createNonInterpolatedUIImageFormCIImage:outputImage withSize:300];
 

/**
 *  根据CIImage生成指定大小的UIImage
 *
 *  @param image CIImage
 *  @param size  图片宽度
 */
- (UIImage *)createNonInterpolatedUIImageFormCIImage:(CIImage *)image withSize:(CGFloat) size
{
    CGRect extent = CGRectIntegral(image.extent);
    CGFloat scale = MIN(size/CGRectGetWidth(extent), size/CGRectGetHeight(extent));
    
    // 1.创建bitmap;
    size_t width = CGRectGetWidth(extent) * scale;
    size_t height = CGRectGetHeight(extent) * scale;
    CGColorSpaceRef cs = CGColorSpaceCreateDeviceGray();
    CGContextRef bitmapRef = CGBitmapContextCreate(nil, width, height, 8, 0, cs, (CGBitmapInfo)kCGImageAlphaNone);
    CIContext *context = [CIContext contextWithOptions:nil];
    CGImageRef bitmapImage = [context createCGImage:image fromRect:extent];
    CGContextSetInterpolationQuality(bitmapRef, kCGInterpolationNone);
    CGContextScaleCTM(bitmapRef, scale, scale);
    CGContextDrawImage(bitmapRef, extent, bitmapImage);
    
    // 2.保存bitmap到图片
    CGImageRef scaledImage = CGBitmapContextCreateImage(bitmapRef);
    CGContextRelease(bitmapRef);
    CGImageRelease(bitmapImage);
    return [UIImage imageWithCGImage:scaledImage];
}

二维码部分被遮挡时,还是被识别的,这是因为二维码是有纠错率(inputCorrectionLevel):L,M,Q,H 。 L水平7%的字码可被修正,M水平15%的字码可被修正,Q水平25%的字码可被修正,H水平30%的字码可被修正。


- (void)viewDidLoad {
    [super viewDidLoad];
    UIImageView *imageView = [[UIImageView alloc]init];
    [self.view addSubview:imageView];
    imageView.frame = CGRectMake(10, 100, 300, 300);
    imageView.backgroundColor = [UIColor redColor];
    NSString *str = @"你好,世界”;
    NSData*data = [str dataUsingEncoding:NSUTF8StringEncoding];
    //1、创建一个二维码滤镜
    CIFilter *filter = [CIFilter filterWithName:@"CIQRCodeGenerator”];
    [filter setDefaults];
    //2、设置滤镜输入内容
    [filter setValue:data forKey:@"inputMessage”];
    [filter setValue:@"H" forKey:@"inputCorrectionLevel”];
    //3、直接从二维码滤镜中获取需要的二维码图片
    CIImage *outputImage = [filter  outputImage];
    UIImage *image = [self createNonInterpolatedUIImageFormCIImage:outputImage withSize:300];
    UIImage *iconImage = [UIImage imageNamed:@"1”];
    UIImage *newImage = [self creatnewImage:image smallImage:iconImage size:60];
    
    imageView.image = newImage;
}

#pragma mark -  多张图重新绘制成一张图
- (UIImage *)creatnewImage:(UIImage*)bigImage smallImage:(UIImage*)smallimage size:(CGFloat)size{
    UIGraphicsBeginImageContext(bigImage.size);
    [bigImage drawInRect:CGRectMake(0, 0, bigImage.size.width, bigImage.size.height)];
    CGFloat x = (bigImage.size.width -size)/2;
    CGFloat y = (bigImage.size.height-size)/2;
    [smallimage drawInRect:CGRectMake(x, y, size, size)];
    UIImage *newImage =UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();
    return newImage;
}

二、识别图片二维码

   //01、创建一个探测器
   CIContext *contex = [[CIContext alloc]init];
   CIDetector *detecor =[CIDetector detectorOfType:CIDetectorTypeQRCode context:contex options:@{CIDetectorAccuracy :CIDetectorAccuracyHigh}];
   
   //02、直接开始识别图片,获取特征
   CIImage *ciImage =  [[CIImage alloc]initWithImage:[UIImage imageNamed:@"0”]];
   NSArray *features = [detecor featuresInImage:ciImage];
   if (features.count>0) {
       //03、读取特征
       [features  enumerateObjectsUsingBlock:^(id  _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
           CIQRCodeFeature *feature = obj;
           NSLog(@"当前当前二维码的内容是%@",feature.messageString);
       }];
   }else{
       NSLog(@"无法识别当前二维码”);
   }

三、二维码扫描

3.1、扫描动画

其实实现冲击波的动画效果,就需要一个图片和以下做个简单的动画


qrcode_scanline_qrcode@2x.png

    UIImageView *imageView = [[UIImageView alloc]init];
    imageView.image = [UIImage imageNamed:@"qrcode_border"];
    [self.view addSubview:imageView];
    imageView.clipsToBounds = YES;
    imageView.frame = CGRectMake(60, 100, 200, 200);
    imageView.backgroundColor = [UIColor colorWithRed:255/255.0f green:127/255.0 blue:0/255.f alpha:1];
    UIImageView *animationImageView = [[UIImageView alloc]init];
    [imageView addSubview:animationImageView];
    animationImageView.frame = CGRectMake(0, -imageView.frame.size.height, imageView.frame.size.width, imageView.frame.size.height);
    animationImageView.image = [UIImage imageNamed:@"qrcode_scanline_qrcode@2x"];
    self.animationImageView  = animationImageView;
   [self beginAnmition];


- (void)beginAnmition{
    [UIView animateWithDuration:2  delay:0 options:UIViewAnimationOptionRepeat                     animations:^{
        self.animationImageView.frame = CGRectMake(0, 0, self.animationImageView.frame.size.width, self.animationImageView.frame.size.height);
         
    } completion:nil];
}

3.2、扫描功能实现

  • 1、扫描输出数据
   // 1. 获取摄像头设备
    AVCaptureDevice *device = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo];
    
  // 2. 把摄像头设备当做输入设备
    AVCaptureDeviceInput  *inputDevice = [AVCaptureDeviceInput deviceInputWithDevice:device error:nil];
    
    // 3. 设置"元数据"处理, -> 输出
    AVCaptureMetadataOutput *output = [[AVCaptureMetadataOutput alloc] init];
    
     // 3.1 设置元数据处理代理, 接收处理好的结果
    [output setMetadataObjectsDelegate:self queue:dispatch_get_main_queue()];
    
    // 4. 创建一个会话, 连接输入和输出
    AVCaptureSession *session =  [[AVCaptureSession alloc]init];
    // 4.1 添加输入, 和输出
    if ([session canAddInput:inputDevice]&&[session canAddOutput:output]) {
        [session addInput:inputDevice];
        [session addOutput:output];
    }
    
    // 4.2 设置输出处理的编码类型
    // output.availableMetadataObjectTypes
    // 注意: 设置元数据处理类型, 一定要写在元数据输出添加到会话之后, 否则, 无效, 扫描不到结果
    output.metadataObjectTypes = @[AVMetadataObjectTypeQRCode];
    [session startRunning];
    self.seesion = session;
     
#pragma mark - 获得扫描结果
- (void)captureOutput:(AVCaptureOutput *)output didOutputMetadataObjects:(NSArray<__kindof AVMetadataObject *> *)metadataObjects fromConnection:(AVCaptureConnection *)connection{
    [metadataObjects enumerateObjectsUsingBlock:^(__kindof AVMetadataObject * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
        if ([obj isKindOfClass:[AVMetadataMachineReadableCodeObject class]]) {
            AVMetadataMachineReadableCodeObject *codeObject = obj;
            NSLog(@"%@",codeObject.stringValue);
         }
     }];
}


  • 2、添加一个视频预览图层
    AVCaptureVideoPreviewLayer *preLayer = [[AVCaptureVideoPreviewLayer alloc]initWithSession:session];
    preLayer.frame = self.view.bounds;
    [self.view.layer insertSublayer:preLayer atIndex:0];
  • 3、限定扫描区域
    一般的,扫描区域就是预览视图previewLayer的frame对应的矩形框,一般是设置全屏。如果我们想要设置一个有效区域怎么办,如同支付宝、微信等将扫码区域限制在一个小正方形内。这就要用到输出流AVCaptureMetadataOutput的一个rectOfInterest属性。
    CGRect bounds = [UIScreen mainScreen].bounds;
    CGFloat x = self.imageView.frame.origin.x/bounds.size.width;
    CGFloat y = self.imageView.frame.origin.y/bounds.size.height;
    CGFloat w = self.imageView.frame.size.width/bounds.size.width;
    CGFloat h = self.imageView.frame.size.height/bounds.size.height;
    output.rectOfInterest  = CGRectMake(y, x, h, w);

rectOfInterest 的默认值是 CGRectMake(0, 0, 1, 1),它的坐标值范围是0–1,而且坐标系:0,0是右上角(横屏状态下的坐标)

相关文章

网友评论

      本文标题:二维码学习

      本文链接:https://www.haomeiwen.com/subject/jzhnjktx.html