Swift(十一):QRScanner 二维码生成、识别、扫描
2016-08-11 本文已影响297人
IMSong
一 、生成二维码
小诗一首//
// showQRController.swift
// QRCode
//
// Created by HMC on 16/8/11.
// Copyright © 2016年 SKing. All rights reserved.
//
import UIKit
import CoreImage
class showQRController: UIViewController {
@IBOutlet weak var QRImageView: UIImageView!
override func viewDidLoad() {
super.viewDidLoad()
QRImageView.image = createQR("香雨如酥贵如珠,万家未觉身却无。 一心只为他人事,浓绿艳妆为谁梳?", iconImageName: "123")
}
}
extension showQRController {
func createQR(string : String?,iconImageName: String?) -> UIImage? {
//创建二维码滤镜 固定格式 参数必须为 : CIQRCodeGenerator
let filter = CIFilter(name: "CIQRCodeGenerator")
//复位滤镜,以便下次使用
filter?.setDefaults()
//KVC 设置输入值 ps:key 固定为inputMessage ,value 必须为 nsdata 类型
guard string != nil else {
return nil
}
let inputData = string!.dataUsingEncoding(NSUTF8StringEncoding)
filter?.setValue(inputData, forKey: "inputMessage")
//设置纠错率 一般设置为M
filter?.setValue("M", forKey: "inputCorrectionLevel")
//接收滤镜返回的图片,由于太小 需要拉伸放大
guard let image = filter?.outputImage else {
return nil
}
//颜色滤镜
let colorFilter = CIFilter(name: "CIFalseColor")
colorFilter?.setDefaults()
colorFilter?.setValue(image, forKey: "inputImage")
//前景色
colorFilter?.setValue(CIColor(red: 225/255.0, green: 77/255.0,blue: 0), forKey: "inputColor0")
//背景色
colorFilter?.setValue(CIColor(red: 1, green: 1,blue: 1), forKey: "inputColor1")
guard let colorImage = colorFilter?.outputImage else{
return nil
}
//放大25倍 重绘
let matrix = CGAffineTransformMakeScale(25, 25)
//将 CIImage 转换为 UIImage
let QRImage = UIImage(CIImage:colorImage.imageByApplyingTransform(matrix))
//判定 icon 是否为空
guard iconImageName != nil else {
return nil
}
//重新绘制中心小图
if let iconImage = UIImage(named: iconImageName!) {
let rect = CGRectMake(0, 0, QRImage.size.width, QRImage.size.height)
UIGraphicsBeginImageContext(rect.size)
QRImage.drawInRect(rect)
let iconSize = CGSizeMake(rect.size.width * 0.25, rect.size.height * 0.25)
let x = (rect.width - iconSize.width ) * 0.5
let y = (rect.height - iconSize.height ) * 0.5
iconImage.drawInRect(CGRectMake(x,y,iconSize.width,iconSize.height))
let resultImage = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
return resultImage
}
return QRImage
}
}
二 、识别二维码
识别结果//
// detectorViewController.swift
// QRCode
//
// Created by HMC on 16/8/12.
// Copyright © 2016年 SKing. All rights reserved.
//
import UIKit
class detectorViewController: UIViewController {
@IBOutlet weak var imageView: UIImageView!
override func viewDidLoad() {
super.viewDidLoad()
// 获得 image
guard let image = imageView.image else{
return
}
//转换为 CIImage
let ciImage = CIImage(image: image)
//创建探测器
let detector = CIDetector(ofType: CIDetectorTypeQRCode, context: nil, options: [CIDetectorAccuracy : CIDetectorAccuracyHigh])
//返回结果
let features = detector.featuresInImage(ciImage!)
//遍历结果
for feature in features {
let qrcode = feature as! CIQRCodeFeature
print(qrcode.messageString)
//alert 显示识别出的内容
let alert = UIAlertController(title: "识别内容", message:qrcode.messageString, preferredStyle: .Alert)
let action = UIAlertAction(title: "关闭", style: .Default, handler: { (action : UIAlertAction) in
self.dismissViewControllerAnimated(true, completion: nil)
})
alert.addAction(action)
presentViewController(alert, animated: true, completion: nil)
}
}
}
三 、扫描二维码
扫描前 扫描后//
// scanQRViewController.swift
// QRCode
//
// Created by HMC on 16/8/15.
// Copyright © 2016年 SKing. All rights reserved.
//
import UIKit
import AVFoundation
class scanQRViewController: UIViewController {
lazy var session = AVCaptureSession()
/// 扫描网格 距离 框的底部的长度
@IBOutlet weak var lineToBottom: NSLayoutConstraint!
/// 扫描框和扫描线的背景 View
@IBOutlet weak var scanBackground: UIView!
//扫描框
@IBOutlet weak var scanDeadLine: UIImageView!
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
startScan()
}
override func viewDidAppear(animated: Bool) {
super.viewDidAppear(animated)
startAnimationOfLine()
}
}
// MARK: - 有关的 UI 和动画
extension scanQRViewController{
/**
开始扫描
*/
func startScan(){
//获取摄像头
let hardWareDevice = AVCaptureDevice.defaultDeviceWithMediaType(AVMediaTypeVideo)
//输入
guard let input = try? AVCaptureDeviceInput(device: hardWareDevice) else{
return
}
//输出
let output = AVCaptureMetadataOutput()
//设置输出的代理
output.setMetadataObjectsDelegate(self, queue: dispatch_get_main_queue())
//连接输入输出
//session = AVCaptureSession()
guard session.canAddInput(input) else{
return
}
guard session.canAddOutput(output) else {
return
}
session.addInput(input)
session.addOutput(output)
//输出的二维码识别的码制(所有的码)
output.metadataObjectTypes = output.availableMetadataObjectTypes
//设置扫描的区域 0.0-1.0
// let screenBounds = UIScreen.mainScreen().bounds
// let x :CGFloat = scanBackground.frame.origin.x / screenBounds.size.width
// let y :CGFloat = scanBackground.frame.origin.y / screenBounds.size.height
// let width :CGFloat = scanBackground.frame.size.width / screenBounds.size.width
// let height :CGFloat = scanBackground.frame.size.height / screenBounds.size.height
// output.rectOfInterest = CGRectMake(y, x, height, width)
//添加摄像头图层 (其实不是必须的)
let captureLayer = AVCaptureVideoPreviewLayer(session: session)
captureLayer.frame = view.layer.bounds
view.layer.insertSublayer(captureLayer, atIndex: 0)
// 启动回话: 此时开始采集数据,输出对象
session.startRunning()
}
/**
动画的设置
*/
func startAnimationOfLine() {
//初始化线的位置
lineToBottom.constant = scanBackground.frame.height
loadViewIfNeeded()
//设置结束位置
lineToBottom.constant = -scanBackground.frame.height
//设置动画
UIView.animateWithDuration(3, animations: {
//设置重复
UIView.setAnimationRepeatCount(MAXFLOAT)
self.view.layoutIfNeeded()
}) { (bool : Bool) in
print("回扫")
}
}
}
// MARK: - AVCaptureMetadataOutputObjectsDelegate
extension scanQRViewController : AVCaptureMetadataOutputObjectsDelegate {
func captureOutput(captureOutput: AVCaptureOutput!, didOutputMetadataObjects metadataObjects: [AnyObject]!, fromConnection connection: AVCaptureConnection!) {
guard metadataObjects.count > 0 else{
return
}
for obj in metadataObjects {
guard obj.isKindOfClass(AVMetadataMachineReadableCodeObject) else{
return
}
let tmpObj = obj as! AVMetadataMachineReadableCodeObject
//print(tmpObj.stringValue)
//print(tmpObj.corners)
let alert = UIAlertController(title: "识别结果", message: tmpObj.stringValue, preferredStyle: .Alert)
let action = UIAlertAction(title: "好", style: .Default, handler: { (action: UIAlertAction) in
self.dismissViewControllerAnimated(true, completion: nil)
})
alert.addAction(action)
presentViewController(alert, animated: true, completion: nil)
}
}
}