二维码生成

//MARK: 传进去字符串,生成二维码图片(>=iOS7)  text:要生成的二维码内容   WH:二维码高宽
private func creatQRCodeImage(text: String,WH:CGFloat) -> UIImage{ //创建滤镜
let filter = CIFilter(name: "CIQRCodeGenerator")
//还原滤镜的默认属性
filter?.setDefaults()
//设置需要生成二维码的数据
filter?.setValue(text.data(using: String.Encoding.utf8), forKey: "inputMessage")
//从滤镜中取出生成的图片
let ciImage = filter?.outputImage
//这个清晰度好
let bgImage = createNonInterpolatedUIImageFormCIImage(image: ciImage!, size: WH) return bgImage
}

上面生成的image,需要用到一个方法,原因是直接生产的图片二维码清晰度不够,需要处理一下

//MARK: - 根据CIImage生成指定大小的高清UIImage
private func createNonInterpolatedUIImageFormCIImage(image: CIImage, size: CGFloat) -> UIImage { let extent: CGRect = image.extent.integral
let scale: CGFloat = min(size/extent.width, size/extent.height) let width = extent.width * scale
let height = extent.height * scale
let cs: CGColorSpace = CGColorSpaceCreateDeviceGray()
let bitmapRef = CGContext(data: nil, width: Int(width), height: Int(height), bitsPerComponent: , bytesPerRow: , space: cs, bitmapInfo: )! let context = CIContext(options: nil)
let bitmapImage: CGImage = context.createCGImage(image, from: extent)! bitmapRef.interpolationQuality = CGInterpolationQuality.none
bitmapRef.scaleBy(x: scale, y: scale)
bitmapRef.draw(bitmapImage, in: extent)
let scaledImage: CGImage = bitmapRef.makeImage()!
return UIImage(cgImage: scaledImage)
}

这样,我们就能得到想要的二维码图片了

有时,我们需要在二维码中间添加log水印等,我试过两种方法,第一种是直接用图形上下文UIGraphicsBeginImageContext这种实现,不够实现起来有点模糊,后来就直接用最原始方式了:直接add图片上去(也可能是我第一种实现有问题,这里大家可以自己试一下先)

添加log:(一些参数可以自己调,这里做个示例)

//MARK: - 根据背景图片和头像合成头像二维码
private func creatIconImage(iconImage:UIImage,sizeWH:CGFloat,superImgView:UIImageView){ let iconImgView = UIImageView(image: iconImage)
iconImgView.contentMode = .scaleAspectFit
iconImgView.frame = CGRect(x: (superImgView.bounds.size.width-sizeWH)/, y: (superImgView.bounds.size.height-sizeWH)/, width: sizeWH, height: sizeWH)
iconImgView.layer.cornerRadius =
iconImgView.layer.borderColor = UIColor.white.cgColor
iconImgView.layer.borderWidth =
iconImgView.layer.masksToBounds = true
superImgView.addSubview(iconImgView) }

二维码扫描

使用AVCaptureDevice,基于系统的AVFoundation框架,所以使用前,先import

import UIKit
import AVFoundation

1、定义扫描的一些属性

    //扫描定义属性
var device:AVCaptureDevice! = nil
var input:AVCaptureDeviceInput! = nil
var output:AVCaptureMetadataOutput! = nil
var session:AVCaptureSession! = nil
var preview:AVCaptureVideoPreviewLayer! = nil

2、设置扫描

/// 设置扫描参数
func setupCamera() {
DispatchQueue.global().async {
if (self.device == nil){
self.device = AVCaptureDevice.defaultDevice(withMediaType: AVMediaTypeVideo)
do{
self.input = try AVCaptureDeviceInput.init(device: self.device)
}catch{
print("self.input init error")
} self.output = AVCaptureMetadataOutput.init()
self.output.setMetadataObjectsDelegate(self, queue: DispatchQueue.main) self.session = AVCaptureSession.init()
self.session.canSetSessionPreset(AVCaptureSessionPresetHigh)
if self.session.canAddInput(self.input){
self.session .addInput(self.input)
self.canOpen = true
}else{
DispatchQueue.main.async {
let alert = UIAlertView(title: "提示", message: "打开相机权限", delegate: self, cancelButtonTitle: "取消", otherButtonTitles: "设置")
alert.show()
}
} if self.canOpen{
if self.session.canAddOutput(self.output){
self.session.addOutput(self.output)
}
// 只支持二维码
self.output.metadataObjectTypes = [AVMetadataObjectTypeQRCode] self.preview = AVCaptureVideoPreviewLayer(session: self.session)
self.preview.videoGravity = AVLayerVideoGravityResizeAspectFill
DispatchQueue.main.async {
self.preview.frame = CGRect(x: , y: , width: KScreenWidth, height: KScreenHeight)
self.view.layer.insertSublayer(self.preview, at: )
} } }
if self.canOpen{
DispatchQueue.main.async {
//开启定时器,构造移动动画效果
self.timer = Timer(timeInterval: 0.02, target: self, selector: #selector(self.lineAnimation), userInfo: nil, repeats: true)
RunLoop.current.add(self.timer!, forMode: .defaultRunLoopMode)
//开始采集数据
self.session.startRunning()
}
}
} }

扫描后,会触发一个代理,这里我们可以获取到扫描内容

// MARK: - 扫描二维码后的代理
extension QRCodeScanViewController:AVCaptureMetadataOutputObjectsDelegate{
func captureOutput(_ captureOutput: AVCaptureOutput!, didOutputMetadataObjects metadataObjects: [Any]!, from connection: AVCaptureConnection!) {
var strValue:String = ""
if metadataObjects.count>{
let obj:AVMetadataMachineReadableCodeObject = metadataObjects.first as! AVMetadataMachineReadableCodeObject
strValue = obj.stringValue
} self.session.stopRunning()
self.timer?.invalidate()
self.timer = nil self.playBeep() self.showQRCode(qrcodeString: strValue)
} }

以上都是一些核心代码,当然,我们还需要对它进行一些UI自定义,比如扫描背景色,扫描提示说明,红线的动画移动等

这里我就不一一贴出来了,文章最后会有获取源码的链接地址。

其实到这里,我们都可以依靠系统提供的API实现二维码的生成和扫描功能,最低要求的系统为iOS7。

下面,如果是从相册获取呢?

二维码相册读取

ios从相册读取二维码,在ios8以上,苹果依然提供了自带的识别图片二维码的功能,这种方式效率最好,也是最推荐的,但在兼容ios7时,我们就必须用其他方式实现。

选择第三方框架:

ZXingObjC  OR  ZBar   ??

这里我选择的是 ZXingObjC,相比于ZBar,这个库一直有人在维护,而且易用性相比后者 也好一点(个人觉得哈,当然也有很多人选择的ZBar,其实都差不多)。

1、pod导入ZXingObjc

pod 'ZXingObjC', '~> 3.0'

代码实现记录如下:

注意:这里我之前测试的代码是用oc写的,还没来得及转成swift3,大家先看思路哈,勿怪~~

2、从相册选择好图片  

-(void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary<NSString *,id> *)info{
UIImage *image = [info objectForKey:@"UIImagePickerControllerOriginalImage"]; [self dismissViewControllerAnimated:YES completion:^{ [self getInfoWithImage:image];
}]; }

3、解析图片二维码-(void)getInfoWithImage:(UIImage *)image{

//8系统以上用系统提供的方法
if(SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(@"8.0")){
CIDetector*detector = [CIDetector detectorOfType:CIDetectorTypeQRCode context:nil options:@{ CIDetectorAccuracy : CIDetectorAccuracyHigh }];
NSArray *features = [detector featuresInImage:[CIImage imageWithCGImage:image.CGImage]]; if (features.count >= ){ for (int index = ; index < [features count]; index ++) {
CIQRCodeFeature *feature = [features objectAtIndex:index];
NSString *scannedResult = feature.messageString;
NSLog(@"result:%@",scannedResult);
//进行自己业务处理
}
}else{
NSLog(@"no image");
} }else{
NSLog(@"ios8 以下系统");
CGImageRef imageToDecode=[image CGImage]; ZXLuminanceSource * source = [[ZXCGImageLuminanceSource alloc] initWithCGImage:imageToDecode];
ZXBinaryBitmap * bitmap = [ZXBinaryBitmap binaryBitmapWithBinarizer:[ZXHybridBinarizer binarizerWithSource:source]];
NSError *error = nil;
ZXDecodeHints *hints = [ZXDecodeHints hints];
ZXMultiFormatReader * reader = [ZXMultiFormatReader reader];
ZXResult *result = [reader decode:bitmap hints:hints error:&error]; if (result) {
NSString *contents = result.text;
NSLog(@"解析成功:%@",contents);
       //进行自己业务处理
     }else{
    NSLog(@" --- 解析失败");
     }
} }

系统 CIDetector识别二维码,我后面加了swift4版本写法,供参考

///  识别图片二维码,要求ios8系统及以上
///
/// - Parameter img: <#img description#>
func getQRCodeWithImage(img:UIImage) {
let detector = CIDetector(ofType: CIDetectorTypeQRCode, context: nil, options: [CIDetectorAccuracy:CIDetectorAccuracyHigh])
let features = detector?.features(in: CIImage(cgImage: img.cgImage!))
if features == nil || features!.count <= {
return
} for feature in features! {
if let qrcode = feature as? CIQRCodeFeature{
self.playBeep()
print(qrcode.messageString)
}
} }

最后,获取源码地址

点击这里获取源码

Enjoy~

iOS 读取相册二维码,兼容ios7(使用CIDetector 和 ZXingObjC)的更多相关文章

  1. iOS系统原生 二维码的生成、扫描和读取(高清、彩色)

    由于近期工作中遇到了个需求:需要将一些固定的字段 在多个移动端进行相互传输,所以就想到了 二维码 这个神奇的东东! 现在的大街上.连个摊煎饼的大妈 都有自己的二维码来让大家进行扫码支付.可见现在的二维 ...

  2. ios 中生成二维码和相册中识别二维码

    iOS 使用CIDetector扫描相册二维码.原生扫描 原生扫描 iOS7之后,AVFoundation让我们终于可以使用原生扫描进行扫码了(二维码与条码皆可)AVFoundation可以让我们从设 ...

  3. iOS中 扫描二维码/生成二维码详解 韩俊强的博客

    最近大家总是问我有没有关于二维码的demo,为了满足大家的需求,特此研究了一番,希望能帮到大家! 每日更新关注:http://weibo.com/hanjunqiang  新浪微博 指示根视图: se ...

  4. iOS中 扫描二维码/生成二维码具体解释 韩俊强的博客

    近期大家总是问我有没有关于二维码的demo,为了满足大家的需求,特此研究了一番,希望能帮到大家! 每日更新关注:http://weibo.com/hanjunqiang  新浪微博 指示根视图: se ...

  5. iOS开发-二维码

    二维码 从ios7开始集成了二维码的生成和读取功能 此前被广泛使用的zbarsdk目前不支持64位处理器 生成二维码的步骤: 倒入CoreImage框架 通过滤镜CIFilter生成二维码 二维码的内 ...

  6. 微信连WiFi关注公众号流程更新 解决ios微信扫描二维码不关注就能上网的问题

    前几天鼓捣了一下微信连WiFi功能,设置还蛮简单的,但ytkah发现如果是ios版微信扫描微信连WiFi生成的二维码不用关注公众号就可以直接上网了,而安卓版需要关注公众号才能上网,这样就少了很多ios ...

  7. iOS系统原生二维码条形码扫描

    本文讲述如何用系统自带的东东实现二维码扫描的功能:点击当前页面的某个按钮,创建扫描VIEW.细心的小伙伴可以发现 title被改变了,返回按钮被隐藏了.这个代码自己写就行了,与本文关系不大...绿色的 ...

  8. IOS原声二维码条形码扫描实现

    本文讲述如何用系统自带的东东实现二维码扫描的功能:点击当前页面的某个按钮,创建扫描VIEW.细心的小伙伴可以发现 title被改变了,返回按钮被隐藏了.这个代码自己写就行了,与本文关系不大...绿色的 ...

  9. C# vb .NET识别读取QR二维码

    二维码比条形码具有更多优势,有些场合使用二维码比较多,比如支付.那么如何在C#,.Net平台代码里读取二维码呢?答案是使用SharpBarcode! SharpBarcode是C#快速高效.准确的条形 ...

随机推荐

  1. 第 16 章 CSS 盒模型[下]

    学习要点: 1.元素可见性 2.元素盒类型 3.元素的浮动 主讲教师:李炎恢 本章主要探讨 HTML5 中 CSS 盒模型,学习怎样了解元素的外观配置以及文档的整体布局. 一.元素可见性 使用 vis ...

  2. 2016 年青岛网络赛---Family View(AC自动机)

    题目链接 http://acm.hdu.edu.cn/showproblem.php?pid=5880 Problem Description Steam is a digital distribut ...

  3. 2015暑假多校联合---Zero Escape(变化的01背包)

    题目链接 http://acm.hust.edu.cn/vjudge/contest/130883#problem/C Problem Description Zero Escape, is a vi ...

  4. Java基础复习笔记系列 五 常用类

    Java基础复习笔记系列之 常用类 1.String类介绍. 首先看类所属的包:java.lang.String类. 再看它的构造方法: 2. String s1 = “hello”: String ...

  5. [moka同学笔记]二、Yii2.0课程笔记(魏曦老师教程)

    一.在标签tags的model中 //使用正则表达式,把标签字符串转换成数组 public static function string2array($tags) { return preg_spli ...

  6. nginx+uwsgi 部署 django

    预装:nginx,  django Django站点tree |Site |-----Blog(自建的项目) |-----Manage.py |-----Site(setting url wsgi-. ...

  7. Jquery实际应用,判断radio,selelct,checkbox是否选中及选中的值

    jquery取radio单选按钮的值 $("input[name='items']:checked").val();  另:判断radio是否选中并取得选中的值 如下所示: fun ...

  8. 解决WindowsServer 2008 R2 未注册版一个小时自动强制关机

    仅用来学习交流,请大家购买正版,尊重正版版权. 安装了win2008R2,试了很多激活方法,终于激活后,不知道什么原因,过了一段时间后,每隔一段时间就自动关机,查了一下,发现是 wlms.exe在作祟 ...

  9. 前端安全之XSS攻击

    XSS(cross-site scripting跨域脚本攻击)攻击是最常见的Web攻击,其重点是“跨域”和“客户端执行”.有人将XSS攻击分为三种,分别是: 1. Reflected XSS(基于反射 ...

  10. 原生JS:Object对象详细参考

    Object对象详细参考 本文参考MDN做的详细整理,方便大家参考MDN JavaScript原生提供一个Object对象(注意起首的O是大写),所有其他对象都继承自这个对象. 构造函数: Objec ...