1.简介
- 二维条码/二维码是用某种特定的几何图形按一定规律在平面分布的黑白相间的图形记录数据符号信息的
- 在编码上巧妙地利用构成计算机内部逻辑基础的“0”、“1”比特流的概念,使用若干个与二进制相对应的几何形体来表示文字数值信息
- 通过图象输入设备或光电扫描设备自动识读以实现信息自动处理
2.特点
- 每种码制有其特定的字符集
- 每个字符占有一定的宽度
- 具有一定的校验功能
3.功能
- 信息获取(名片、地图、WIFI密码、资料)
- 网站跳转(跳转到微博、手机网站、网站)
- 广告推送(用户扫码,直接浏览商家推送的视频、音频广告)
- 手机电商(用户扫码、手机直接购物下单)
- 防伪溯源(用户扫码、即可查看生产地;同时后台可以获取最终消费地)
- 优惠促销(用户扫码,下载电子优惠券,抽奖)
- 会员管理(用户手机上获取电子会员信息、VIP服务)
- 手机支付(扫描商品二维码,通过银行或第三方支付提供的手机端通道完成支付)
4.优点
- 高密度编码,信息容量大:可容纳多达1850个大写字母或2710个数字或1108个字节,或500多个汉字,比普通条码信息容量约高几十倍
- 编码范围广:该条码可以把图片、声音、文字、签字、指纹等可以数字化的信息进行编码,用条码表示出来;可以表示多种语言文字;可表示图像数据
- 容错能力强,具有纠错功能:这使得二维条码因穿孔、污损等引起局部损坏时,照样可以正确得到识读,损毁面积达50%仍可恢复信息 4.译码可靠性高:它比普通条码译码错误率百万分之二要低得多,误码率不超过千万分之一 5.可引入加密措施:保密性、防伪性好 6.成本低,易制作,持久耐用 7.条码符号形状、尺寸大小比例可变 8.二维条码可以使用激光或CCD阅读器识读
5.关于二维码的实际知识从下面几个地方来说
- 了解二维码的原理
- 掌握二维码的扫描实现过程
- 掌握二维码的生成过程
一.了解二维码的原理
-
1.1.用户界面搭建,纯代码搭建
用户界面搭建
-
1.2.重点说一下图片的拉伸处理,在出来的线里面拖动调整拉伸范围
图片的拉伸处理
-
1.3.冲击波的核心代码(动画)
//纵向移动(沿着Y轴) transform.translation.y func addLayerAnimationTranformTranslationY(layer: CALayer,fromalue:Int,toValue:Int) { let animation = CABasicAnimation(keyPath: "transform.translation.y") animation.fromValue = fromalue animation.toValue = toValue animation.duration = 2.0 animation.repeatCount = MAXFLOAT //这里我们可以添加可以不添加,添加一个缓慢进出的动画效果(int/out)。当不添加时,匀速运动,会使用kCAMediaTimingFunctionLinear;当添加时,layer会在开始和结束时比较缓慢 animation.timingFunction = CAMediaTimingFunction(name: kCAMediaTimingFunctionEaseInEaseOut) layer.add(animation, forKey: "addLayerAnimationTranformTranslationY") }
二.扫描二维码
-
2.1.第三方框架
-
ZXingAndroid使用多 -
ZBariOS使用多
提示:以上两个框架都是老牌二维码框架,不过都不支持64位 - 目前在 iOS 开发中普遍使用苹果的
AVFoundation框架,但是不支持图片识别功能 -
AVFoundation只支持通过摄像头扫描识别
-
-
2.2.识别原理
识别原理
-
2.3.代码实现
// MARK: 懒加载关于二维码扫描的一些知识 // 1.拿到会话 private lazy var session: AVCaptureSession = AVCaptureSession() // 2.拿到输入设备 private lazy var deviceInput: AVCaptureInput? = { // 获取摄像头 let device = AVCaptureDevice.defaultDevice(withMediaType: AVMediaTypeVideo) do{ // 创建输入对象 let input = try AVCaptureDeviceInput(device: device) return input }catch{ return nil } }() // 3.拿到输出对象 private lazy var deviceOutput: AVCaptureMetadataOutput = AVCaptureMetadataOutput() // 4.创建预览图层 private lazy var previewLayer: AVCaptureVideoPreviewLayer = { let layer = AVCaptureVideoPreviewLayer(session: self.session) layer?.frame = UIScreen.main.bounds return layer! }() // MARK: 开始扫描 private func startScan(){ // 1.判断是否能够将输入添加到会话中 if !session.canAddInput(deviceInput) { return } // 2.判断是否能够将输出添加到会话中 if !session.canAddOutput(deviceOutput) { return } // 3.将输入和输出添加到会话中 session.addInput(deviceInput) //print(output.metadataObjectTypes) session.addOutput(deviceOutput) // 4.设置输出能够解析的数据类型 // 注意: 设置输出能够解析的数据类型,一定要在输出对象添加到会话之后设置,否则会报错 // 设置系统所有的数据类型都能解析 deviceOutput.metadataObjectTypes = deviceOutput.availableMetadataObjectTypes // 5.设置输出对象的代理,只要解析成功就会通知代理 deviceOutput.setMetadataObjectsDelegate(self, queue: DispatchQueue.main) // 6.添加预览图层,也就是把摄像头照到的地方显示出来 view.layer.insertSublayer(previewLayer, at: 0) // 7.开始扫描 session.startRunning() } // MARK: 相册扫描的代理方法回调 extension QRCodeViewController: AVCaptureMetadataOutputObjectsDelegate{ func captureOutput(_ captureOutput: AVCaptureOutput!, didOutputMetadataObjects metadataObjects: [Any]!, from connection: AVCaptureConnection!){ // 拿出来二维码里面放的东西 guard let objc = metadataObjects.last as? AVMetadataMachineReadableCodeObject else { return } // 打印最后的值 print(objc.stringValue) } }
注意: 记得遵守协议AVCaptureMetadataOutputObjectsDelegate
-
2.4.绘制线条(暂时有点问题)
- bounds
- corners
Bounds&Corners
- 2.4.我的名片生成
我的名片效果
代码如下:
import UIKit
class QRCodeCardViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
view.backgroundColor = UIColor.white
// 1. 设置标题
view.addSubview(tittleLabel)
view.addSubview(backClick)
// 2. 添加图片容器
view.addSubview(icon)
// 3. 布局图片容器
// 4. 生成二维码
let qrcodeImage = createQrimage()
// 5. 将生成好的二维码添加到容器上
icon.image = qrcodeImage
}
private func createQrimage() -> UIImage {
// 1.创建滤镜 // CIQRCodeGenerator 不能写错
let filter = CIFilter(name: "CIQRCodeGenerator")
// 2.还原滤镜的默认属性
filter?.setDefaults()
// 3.设置需要生成的二维码数据
filter?.setValue("joanking".data(using: String.Encoding.utf8), forKey: "inputMessage")
// 4.取出生成好的图片
let ciImage = filter?.outputImage
let backGroungImage = createNonInterpolatedUIImageFormCIImage(image: ciImage!, size: 200)
// 5.创建一个头像
let icon = UIImage(named: "6.jpg")
// 6.合成图片(将二维码和图片进行合并)
let newImage = createImage(bgImage: backGroungImage, iconImage: icon!)
// 7.返回生成好的二维码
return newImage
}
private func createImage(bgImage: UIImage,iconImage: UIImage) -> UIImage{
// 1.开启图文上下文
UIGraphicsBeginImageContext(bgImage.size)
// 2.绘制背景图片
bgImage.draw(in: CGRect(origin: CGPoint.zero, size: bgImage.size))
// 3.绘制头像
let width1: CGFloat = 50
let height1: CGFloat = width1
let x = (bgImage.size.width - width1)*0.5
let y = (bgImage.size.height - height1)*0.5
iconImage.draw(in: CGRect(x: x, y: y, width: width1, height: height1))
// 4.取出绘制好的图片
let newImage = UIGraphicsGetImageFromCurrentImageContext()
// 5.关闭上下文
UIGraphicsEndImageContext()
// 6.返回合成好的图片
return newImage!
}
//MARK: - 根据CIImage生成指定大小的高清UIImage
func createNonInterpolatedUIImageFormCIImage(image: CIImage, size: CGFloat) -> UIImage {
//CIImage没有frame与bounds属性,只有extent属性
let ciextent: CGRect = image.extent.integral
let scale: CGFloat = min(size/ciextent.width, size/ciextent.height)
let context = CIContext(options: nil) //创建基于GPU的CIContext对象,性能和效果更好
let bitmapImage: CGImage = context.createCGImage(image, from: ciextent)! //CIImage->CGImage
let width = ciextent.width * scale
let height = ciextent.height * scale
let cs: CGColorSpace = CGColorSpaceCreateDeviceGray() //灰度颜色通道
let info_UInt32 = CGImageAlphaInfo.none.rawValue
let bitmapRef = CGContext(data: nil, width: Int(width), height: Int(height), bitsPerComponent: 8, bytesPerRow: 0, space: cs, bitmapInfo: info_UInt32)! //图形上下文,画布
bitmapRef.interpolationQuality = CGInterpolationQuality.none //写入质量
bitmapRef.scaleBy(x: scale, y: scale) //调整“画布”的缩放
bitmapRef.draw(bitmapImage, in: ciextent) //绘制图片
let scaledImage: CGImage = bitmapRef.makeImage()! //保存
return UIImage(cgImage: scaledImage)
}
// MARK: 添加二维码图片的容器
private lazy var icon: UIImageView = {
let imageview = UIImageView()
imageview.frame = CGRect(x: JKscreenW/2.0-100, y: JKscreenH/2.0-100, width: 200, height: 200)
imageview.backgroundColor = UIColor.brown
return imageview
}()
// MARK: 添加标题
private lazy var tittleLabel: UILabel = {
let tittle = UILabel(frame: CGRect(x: JKscreenW/2.0-100, y: 34, width: 200, height: 16))
tittle.text = "我的名片"
tittle.font = UIFont.systemFont(ofSize: 16)
tittle.textAlignment = NSTextAlignment.center
tittle.textColor = UIColor.JKTextGayColor()
return tittle
}()
// MARK: 添加返回按钮
private lazy var backClick: UIButton = {
let back = UIButton(frame: CGRect(x: 12, y: 33, width: 40, height: 18))
back.setTitle("返回", for: UIControlState.normal)
back.titleLabel?.font = UIFont.systemFont(ofSize: 16)
back.setTitleColor(UIColor.black, for: UIControlState.normal)
//back.layer.cornerRadius = 2
//back.backgroundColor = UIColor.JKTextGayColor()
back.addTarget(self, action: #selector(QRCodeCardViewController.backBtn), for: UIControlEvents.touchUpInside)
return back
}()
// MARK: 返回的点击事件
func backBtn() {
dismiss(animated: true, completion: nil)
}
}













网友评论