序言:扫描二维码用到了AVFoundation,而从照片中检测和提取二维码信息则用到CoreImage。
- 先看下效果页面:
WechatIMG1.png
-
源码示例地址:扫描二维码
-
技术要点1: 建立CaptureSession并startRunning
func setupCaptureSession() {
captureDevice = AVCaptureDevice.default(for: AVMediaType.video)
do {
try captureInput = AVCaptureDeviceInput.init(device: captureDevice!)
}catch {
}
mataOutput = AVCaptureMetadataOutput.init()
mataOutput?.setMetadataObjectsDelegate(self, queue: DispatchQueue.main)
captureSession = AVCaptureSession.init()
if ((captureSession?.canAddInput(captureInput!))!) {
captureSession?.addInput(captureInput!)
}
if ((captureSession?.canAddOutput(mataOutput!))!) {
captureSession?.addOutput(mataOutput!)
}
if ((captureSession?.canSetSessionPreset(AVCaptureSession.Preset.high))!) {
captureSession?.sessionPreset = .high
}
mataOutput?.metadataObjectTypes = [AVMetadataObject.ObjectType.qr]
capturePreView = AVCaptureVideoPreviewLayer.init(session: captureSession!)
capturePreView?.frame = self.view.frame
self.view.layer.insertSublayer(capturePreView!, at: 0)
captureSession?.startRunning()
let rect = capturePreView!.metadataOutputRectConverted(fromLayerRect: self.interestRect)
mataOutput?.rectOfInterest = rect
}
需要重点提到的一个坑是:
在这行代码前面【 let rect = capturePreView!.metadataOutputRectConverted(fromLayerRect: self.interestRect)】
一定要先执行【
captureSession?.startRunning()】
否则【metadataOutputRectConverted返回的rect是{0,0,0,0}】,这样就没办法捕捉到二维码信息了
- 技术要点2: 运用CIDetector进行检测照片中的二维码信息
func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey : Any]) {
picker.dismiss(animated: true) {
let img = info[UIImagePickerController.InfoKey.originalImage] as! UIImage
let decteor = CIDetector.init(ofType: CIDetectorTypeQRCode, context: nil, options: [CIDetectorAccuracy: CIDetectorAccuracyHigh])
//let ciimg = img.ciImage
//let ciimg = CIImage.init(image: img)
//let ciimg = CIImage.init(data: img.pngData()!)
let ciimg = CIImage.init(cgImage: img.cgImage!)
let fetures = decteor?.features(in: ciimg)
if (fetures?.count)! > 0 {
if let qrFeture = fetures?.first as? CIQRCodeFeature {
self.endScan()
if (self.resultDelegate != nil) {
self.resultDelegate?.tt_handleQRScanResult(result: qrFeture.messageString!)
}
self.navigationController?.popViewController(animated: true)
}
}else {
print("没有二维码信息")
}
}
}
- 技术要点3: 控制设备手电筒torch
@objc func openLamp(_ sender: UIButton) {
if ((captureDevice?.hasTorch)!) {
if (!torchTag) {
try? captureDevice?.lockForConfiguration()
try? captureDevice?.setTorchModeOn(level: 0.6)
captureDevice?.unlockForConfiguration()
torchTag = true
}else {
try? captureDevice?.lockForConfiguration()
captureDevice?.torchMode = .off
captureDevice?.unlockForConfiguration()
torchTag = false
}
}
}
网友评论