AVFoundation框架实现二维码的扫描、二维码的生成
AVFoundation框架实现二维码的扫描、二维码的生成
业界小白 发表于11个月前
AVFoundation框架实现二维码的扫描、二维码的生成
  • 发表于 11个月前
  • 阅读 16
  • 收藏 0
  • 点赞 0
  • 评论 0

腾讯云 十分钟定制你的第一个小程序>>>   

AVFoundation框架简单介绍:用来完成拍照和录制视频功能

AVFoundation框架的常用类:

AVCaptureDevice :该对象代表物理输入设备,包括摄像头和麦克风.开发者可通过该对象来配置底层物理设备的属性.需要指出的是,

我们不能直接创建该类的实例,只能通过该类的 devices、defaultDeviceWithMediaType:(NSString *)mediaType、devicesWithMediaType:(NSString *)mediaType方法 来获取对应的输入设备数组,接下来即 可获取前置摄像头、后置摄像头或麦克风。

AVCaptureSession :该对象负责把AVCaptureDevice捕捉得到的视频或声音数据输出到输出设备中.不管执行实时的还是离线的录制,开发者都必须创建AVCaptureSession对象,并为该对象添加输入设备(负责捕捉数据)和输出端(负责接收数据).

AVCaptureDeviceInput  :它是AVCaptureInput的子类,使用该对象从AVCaptureDevice设备获取数据,该对象将会被添加给AVCaptureSession管理.

AVCaptureScreenInput :它是AVCaptureInput的子类,使用该对象从屏幕获取数据(用于录制屏幕动作).该对象将会被添加给AVCaptureSeesion管理

AVCaptureAudioDataOutput、AVCaptureAudioPreviewOutput、AVCaptureFileOutput 、AVCaptureStillImageOutput、AVCaptureVideoDataOutput:它们都是AVCaptureOutput的子类,用于接收各种数据.该对象也会被添加给AVCaptureSession管理.其中AVCaptureFileOutput依然代表输出到文件的输出端,

AVCaptureAudioFileOutput 、AVCaptureMovieFileOutput :它们都是AVCaptureFileOutput的子类,分别代表输出到音频文件、电影文件的输出端。

AVCaptureVideoPreviewLayer:该对象是CALayer的子类,开发者只要创建它的实例,并为它设置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()];
        // 设置扫描区域的frame
//        CGFloat width = 300 / CGRectGetHeight(self.view.frame);
//        CGFloat height = 300 / CGRectGetWidth(self.view.frame);
        /* 假如你的屏幕的frame 为  x , y,  w, h,  你要设置的矩形快的frame  为  x1, y1, w1, h1.   那么你的 rectOfInterest 应该设置为   CGRectMake(y1/y, x1/x, h1/h, w1/w)
         */
//        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];
        
#warning 必须先添加到session然后才能设置,否则会崩溃
        // 设置扫码支持的编码格式(这里设置条形码和 二维码兼容)
        output.metadataObjectTypes = @[AVMetadataObjectTypeQRCode,
                                       AVMetadataObjectTypeEAN13Code,
                                       AVMetadataObjectTypeEAN8Code,
                                       AVMetadataObjectTypeCode128Code];
// 创建一个预览层
    AVCaptureVideoPreviewLayer *layer = [AVCaptureVideoPreviewLayer layerWithSession:self.session];
    /* AVLayerVideoGravityResizeAspect 保持视频的宽高比并使播放内容自动适应播放窗口的大小。
     * AVLayerVideoGravityResizeAspectFill 以播放内容填充而不是适应播放窗口的大小。
     * AVLayerVideoGravityResize  会拉伸播放内容以适应播放窗口。
     */
    layer.videoGravity = AVLayerVideoGravityResizeAspectFill;
    layer.frame = self.view.layer.bounds;
    [self.view.layer insertSublayer:layer atIndex:0];
#pragma mark - 输出流的代理(扫描结果)
- (void)captureOutput:(AVCaptureOutput *)captureOutput didOutputMetadataObjects:(NSArray *)metadataObjects fromConnection:(AVCaptureConnection *)connection{
    
    if (metadataObjects.count > 0) {
        
        // 停止扫描
        [self.session stopRunning];
        
        AVMetadataMachineReadableCodeObject *metadataObject = [metadataObjects firstObject];
        NSLog(@"扫描结果:%@", metadataObject.stringValue);
        
        [self showAlertWithTitle:@"查询结果" message:metadataObject.stringValue handler:^(UIAlertAction *action) {
            
            [self.session startRunning];
            
        }];
        
        
    }
    
    
}
// 开关闪光灯(操作前必须锁定)
- (void)shan{
    self.isOpen = !self.isOpen;
    
    AVCaptureDevice *device = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo];
    // 判断闪光灯是否能用
    if ([device hasTorch]) {
        // 加锁
        [device lockForConfiguration:nil];
        if (self.isOpen) {
            self.navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc] initWithTitle:@"关闭闪光灯" style:UIBarButtonItemStylePlain target:self action:@selector(shan)];
            
            device.torchMode = AVCaptureTorchModeOn;
            
        }else{
            
            self.navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc] initWithTitle:@"打开闪光灯" style:UIBarButtonItemStylePlain target:self action:@selector(shan)];
            device.torchMode = AVCaptureTorchModeOff;
        }
        // 解锁
        [device unlockForConfiguration];
    }
    
}

二维码生成:(黑白色)

- (UIImage *)creatImageWithString:(NSString *)string size:(CGSize)size{
    
    // 创建滤镜
    CIFilter *filter = [CIFilter filterWithName:@"CIQRCodeGenerator"];
    // 还原默认设置(清空滤镜,因为滤镜有可能保存上一次的设置)
    [filter setDefaults];
    // 创建二维码需要保存的数据
    NSData *data = [string dataUsingEncoding:NSUTF8StringEncoding];
    // 设置数据
    [filter setValue:data forKey:@"inputMessage"];
    // 生成二维码,获取生成后的二维码图片
    CIImage *image = [filter outputImage];
    
    // 放大并绘制二维码(上面生成的二维码很小,需要放大)
    CGImageRef imageRef = [[CIContext contextWithOptions:nil] createCGImage:image fromRect:image.extent];
    UIGraphicsBeginImageContext(size);
    CGContextRef context = UIGraphicsGetCurrentContext();
    CGContextSetInterpolationQuality(context, kCGInterpolationNone);
    // 翻转一下图片,不然生成的QRCode就是上下颠倒的
    CGContextScaleCTM(context, 1.0, -1.0);
    CGContextDrawImage(context, CGContextGetClipBoundingBox(context), imageRef);
    UIImage *contextImage = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();
    CGImageRelease(imageRef);
    
    return contextImage;
}

改变生成的二维码的颜色(基于生成的二维码)

UIImage *image = self.imageV.image;
        
        UIGraphicsBeginImageContext(image.size);
        
        [image drawInRect:CGRectMake(0, 0, image.size.width, image.size.height)];
        
        UIImage *img = [UIImage imageNamed:@"023"];
        
        CGFloat imageW = 50;
        CGFloat imageX = (image.size.width - imageW) * 0.5;
        CGFloat imgaeY = (image.size.height - imageW) * 0.5;
        
        [img drawInRect:CGRectMake(imageX, imgaeY, imageW, imageW)];
        
        UIImage *result = UIGraphicsGetImageFromCurrentImageContext();
        UIGraphicsEndImageContext();
        self.imageV.image = result;

在二维码中间添加个图片

UIImage *image = [self creatImageWithString:self.textF.text size:self.imageV.frame.size];
        
        UIColor *back = [UIColor blueColor];
        UIColor *font = [UIColor orangeColor];
        CIFilter *colorFilter = [CIFilter filterWithName:@"CIFalseColor"
                                           keysAndValues:
                                 @"inputImage",[CIImage imageWithCGImage:image.CGImage],
                                 @"inputColor0",[CIColor colorWithCGColor:font.CGColor],
                                 @"inputColor1",[CIColor colorWithCGColor:back.CGColor],
                                 nil];
        
        self.imageV.image = [UIImage imageWithCIImage:colorFilter.outputImage];

 

共有 人打赏支持
粉丝 2
博文 45
码字总数 46231
×
业界小白
如果觉得我的文章对您有用,请随意打赏。您的支持将鼓励我继续创作!
* 金额(元)
¥1 ¥5 ¥10 ¥20 其他金额
打赏人
留言
* 支付类型
微信扫码支付
打赏金额:
已支付成功
打赏金额: