代码地址如下:
http://www.demodashi.com/demo/12551.html

一、效果预览:



功能描述:WSLNativeScanTool是在利用原生API的条件下封装的二维码扫描工具,支持二维码的扫描、识别图中二维码、生成自定义颜色和中心图标的二维码、监测环境亮度、打开闪光灯这些功能;WSLScanView是参照微信封装的一个扫一扫界面,支持线条颜色、大小、动画图片、矩形扫描框样式的自定义;这个示例本身就是仿照微信的扫一扫功能实现的。

二、实现

主要代码如下:

  • 初始化扫描识别对象
- (AVCaptureSession *)session{

    if (_session == nil){
//获取摄像设备
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()];
//设置采集扫描区域的比例 默认全屏是(0,0,1,1)
//rectOfInterest 填写的是一个比例,输出流视图preview.frame为 x , y, w, h, 要设置的矩形快的scanFrame 为 x1, y1, w1, h1. 那么rectOfInterest 应该设置为 CGRectMake(y1/y, x1/x, h1/h, w1/w)。
CGFloat x = CGRectGetMinX(self.scanFrame)/ CGRectGetWidth(self.preview.frame);
CGFloat y = CGRectGetMinY(self.scanFrame)/ CGRectGetHeight(self.preview.frame);
CGFloat width = CGRectGetWidth(self.scanFrame)/ CGRectGetWidth(self.preview.frame);
CGFloat height = CGRectGetHeight(self.scanFrame)/ CGRectGetHeight(self.preview.frame);
output.rectOfInterest = CGRectMake(y, x, height, width); // 创建环境光感输出流
AVCaptureVideoDataOutput *lightOutput = [[AVCaptureVideoDataOutput alloc] init];
[lightOutput setSampleBufferDelegate:self queue:dispatch_get_main_queue()]; _session = [[AVCaptureSession alloc] init];
//高质量采集率
[_session setSessionPreset:AVCaptureSessionPresetHigh];
[_session addInput:input];
[_session addOutput:output];
[_session addOutput:lightOutput]; //设置扫码支持的编码格式(这里设置条形码和二维码兼容)
output.metadataObjectTypes = @[AVMetadataObjectTypeQRCode,
AVMetadataObjectTypeEAN13Code,
AVMetadataObjectTypeEAN8Code,
AVMetadataObjectTypeCode128Code];
} return _session;
}
  • 扫描出结果的代理方法
#pragma mark -- AVCaptureMetadataOutputObjectsDelegate
//扫描完成后执行
-(void)captureOutput:(AVCaptureOutput *)captureOutput didOutputMetadataObjects:(NSArray *)metadataObjects fromConnection:(AVCaptureConnection *)connection{ if (metadataObjects.count > 0){
AVMetadataMachineReadableCodeObject *metadataObject = [metadataObjects firstObject];
// 扫描完成后的字符
// NSLog(@"扫描出 %@",metadataObject.stringValue);
if(self.scanFinishedBlock != nil){
self.scanFinishedBlock(metadataObject.stringValue);
}
}
}
#pragma mark- AVCaptureVideoDataOutputSampleBufferDelegate的方法
//扫描过程中执行,主要用来判断环境的黑暗程度
- (void)captureOutput:(AVCaptureOutput *)captureOutput didOutputSampleBuffer:(CMSampleBufferRef)sampleBuffer fromConnection:(AVCaptureConnection *)connection{ if (self.monitorLightBlock == nil) {
return;
} CFDictionaryRef metadataDict = CMCopyDictionaryOfAttachments(NULL,sampleBuffer, kCMAttachmentMode_ShouldPropagate);
NSDictionary *metadata = [[NSMutableDictionary alloc] initWithDictionary:(__bridge NSDictionary*)metadataDict];
CFRelease(metadataDict);
NSDictionary *exifMetadata = [[metadata objectForKey:(NSString *)kCGImagePropertyExifDictionary] mutableCopy];
float brightnessValue = [[exifMetadata objectForKey:(NSString *)kCGImagePropertyExifBrightnessValue] floatValue]; // NSLog(@"环境光感 : %f",brightnessValue); // 根据brightnessValue的值来判断是否需要打开和关闭闪光灯
AVCaptureDevice *device = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo];
BOOL result = [device hasTorch];// 判断设备是否有闪光灯
if ((brightnessValue < 0) && result) {
// 环境太暗,可以打开闪光灯了
}else if((brightnessValue > 0) && result){
// 环境亮度可以
}
if (self.monitorLightBlock != nil) {
self.monitorLightBlock(brightnessValue);
} }

三、用法

  • 实例化WSLNativeScanTool工具类和WSLScanView界面类;用法很简单,头文件里注释的也挺详细的。
//输出流视图
UIView *preview = [[UIView alloc] initWithFrame:CGRectMake(0, 0, self.view.frame.size.width, self.view.frame.size.height - 0)];
[self.view addSubview:preview];
__weak typeof(self) weakSelf = self;
//构建扫描样式视图
_scanView = [[WSLScanView alloc] initWithFrame:CGRectMake(0, 0, self.view.frame.size.width, self.view.frame.size.height - 0)];
_scanView.scanRetangleRect = CGRectMake(60, 120, (self.view.frame.size.width - 2 * 60), (self.view.frame.size.width - 2 * 60));
_scanView.colorAngle = [UIColor greenColor];
_scanView.photoframeAngleW = 20;
_scanView.photoframeAngleH = 20;
_scanView.photoframeLineW = 2;
_scanView.isNeedShowRetangle = YES;
_scanView.colorRetangleLine = [UIColor whiteColor];
_scanView.notRecoginitonArea = [UIColor colorWithRed:0 green:0 blue:0 alpha:0.5];
_scanView.animationImage = [UIImage imageNamed:@"scanLine"];
_scanView.myQRCodeBlock = ^{
[WSLNativeScanTool createQRCodeImageWithString:@"https://www.jianshu.com/u/e15d1f644bea" andSize:CGSizeMake(250, 250) andBackColor:[UIColor whiteColor] andFrontColor:[UIColor orangeColor] andCenterImage:[UIImage imageNamed:@"piao"]];
createQRCodeController.qrString = @"https://www.jianshu.com/u/e15d1f644bea";
};
_scanView.flashSwitchBlock = ^(BOOL open) {
[weakSelf.scanTool openFlashSwitch:open];
};
[self.view addSubview:_scanView];
//初始化扫描工具
_scanTool = [[WSLNativeScanTool alloc] initWithPreview:preview andScanFrame:_scanView.scanRetangleRect];
_scanTool.scanFinishedBlock = ^(NSString *scanString) {
NSLog(@"扫描结果 %@",scanString);
[weakSelf.scanTool sessionStopRunning];
[weakSelf.scanTool openFlashSwitch:NO];
};
_scanTool.monitorLightBlock = ^(float brightness) {
NSLog(@"环境光感 : %f",brightness);
if (brightness < 0) {
// 环境太暗,显示闪光灯开关按钮
[weakSelf.scanView showFlashSwitch:YES];
}else if(brightness > 0){
// 环境亮度可以,且闪光灯处于关闭状态时,隐藏闪光灯开关
if(!weakSelf.scanTool.flashOpen){
[weakSelf.scanView showFlashSwitch:NO];
}
}
};
[_scanTool sessionStartRunning];
[_scanView startScanAnimation];

四、项目结构

五、其他补充

暂没

iOS 原生二维码扫描和生成

代码地址如下:
http://www.demodashi.com/demo/12551.html

注:本文著作权归作者,由demo大师代发,拒绝转载,转载需要作者授权

最新文章

  1. prototype,__proto__,constructor
  2. C#~异步编程再续~大叔所理解的并行编程(Task&amp;Parallel)
  3. AJAX实现跨域的三种方法
  4. u3d_shader_surface_shader_4
  5. Spring -配置集合属性
  6. Magicodes.WeiChat——WeChatOAuthTest(网页授权获取用户基本信息)
  7. Rhel6-heartbeat配置文档
  8. mysql 非安装版本就可以用, 用于打包用
  9. snprintf 返回值
  10. 转:java实例化对象的过程
  11. MOBA服务器开发第一阶段完成总结
  12. hdu 4609 (FFT求解三角形)
  13. python中的time模块和datetime模块
  14. Pip无法卸载某些包:Cannot uninstall &#39;PyYAML&#39;.
  15. pygame 笔记-4 代码封装&amp;发射子弹
  16. maven中经常使用的插件
  17. InfluxDB学习之InfluxDB的基本操作| Linux大学
  18. 微信正式开放内测“小程序”,不开发APP的日子真的来了?
  19. substr和substring,slice和splice的区别,js字符串截取和数组截取
  20. Reference Type Casting

热门文章

  1. python mysql创建表
  2. Django和SQLAlchemy区别
  3. centos6源码编译安装lnmp环境
  4. [BZOJ1052][HAOI2007]覆盖问题 二分+贪心
  5. J.U.C并发框架源码阅读(八)ArrayBlockingQueue
  6. OpenCV和Boost C++库的安装
  7. selenium IE自动化问题汇总
  8. 牛客网 牛客练习赛7 B.购物-STL(priority_queue)
  9. Python的程序结构[1] -&gt; 方法/Method[0] -&gt; 类实例方法、私有方法和抽象方法
  10. JSK 18: 跳跃游戏