文档章节

AVFoundation框架实现二维码的扫描、二维码的生成

 业界小白
发布于 2016/11/15 17:52
字数 1133
阅读 280
收藏 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
博文 57
码字总数 65012
作品 0
洛阳
iOS工程师
私信 提问
加载中
请先登录后再评论。
Netty那点事(三)Channel与Pipeline

Channel是理解和使用Netty的核心。Channel的涉及内容较多,这里我使用由浅入深的介绍方法。在这篇文章中,我们主要介绍Channel部分中Pipeline实现机制。为了避免枯燥,借用一下《盗梦空间》的...

黄亿华
2013/11/24
2W
22
访问安全控制解决方案

本文是《轻量级 Java Web 框架架构设计》的系列博文。 今天想和大家简单的分享一下,在 Smart 中是如何做到访问安全控制的。也就是说,当没有登录或 Session 过期时所做的操作,会自动退回到...

黄勇
2013/11/03
3.5K
8
用vertx实现高吞吐量的站点计数器

工具:vertx,redis,mongodb,log4j 源代码地址:https://github.com/jianglibo/visitrank 先看架构图: 如果你不熟悉vertx,请先google一下。我这里将vertx当作一个容器,上面所有的圆圈要...

jianglibo
2014/04/03
4.2K
3
SQLServer实现split分割字符串到列

网上已有人实现sqlserver的split函数可将字符串分割成行,但是我们习惯了split返回数组或者列表,因此这里对其做一些改动,最终实现也许不尽如意,但是也能解决一些问题。 先贴上某大牛写的s...

cwalet
2014/05/21
9.7K
0
beego API开发以及自动化文档

beego API开发以及自动化文档 beego1.3版本已经在上个星期发布了,但是还是有很多人不了解如何来进行开发,也是在一步一步的测试中开发,期间QQ群里面很多人都问我如何开发,我的业余时间实在...

astaxie
2014/06/25
2.7W
22

没有更多内容

加载失败,请刷新页面

加载更多

您如何加速Eclipse? - How can you speed up Eclipse?

问题: How can you make the experience with Eclipse faster? 如何使Eclipse体验更快? For instance: I disable all the plugins I don't need (Mylyn, Subclipse, …). 例如: 我禁用了所......

fyin1314
16分钟前
9
0
百度地图SDK新版内测邀请

本文作者:用****9 百度地图开放平台为开发者提供七大基础服务能力,其中地图SDK和导航SDK是开发者广泛使用的重要基础服务,为了满足开发者更多使用需求以及提升开发者集成后的应用效果,本次...

百度开发者中心
前天
21
0
获取JavaScript数组中的所有唯一值(删除重复项) - Get all unique values in a JavaScript array (remove duplicates)

问题: I have an array of numbers that I need to make sure are unique. 我需要确定一个唯一的数字数组。 I found the code snippet below on the internet and it works great until th......

javail
今天
11
0
如何检查字符串是否为空? - How to check if the string is empty?

问题: Does Python have something like an empty string variable where you can do: Python是否有类似空字符串变量的内容可以在其中执行: if myString == string.empty: Regardless, wh......

富含淀粉
今天
19
0
您如何存储未跟踪的文件? - How do you stash an untracked file?

问题: I have changes to a file, plus a new file, and would like to use git stash to put them away while I switch to another task. 我对一个文件进行了更改,再加上一个新文件,并希......

技术盛宴
今天
39
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部