swift搬运工
条码识别效率低下,还没有解决
//
// ViewController.swift
// QRCodeDemo
//
// Created by xf-bao on 16/8/30.
// Copyright © 2016年 xf-bao. All rights reserved.
//
//private let kBounds = UIScreen.mainScreen().bounds
//private let kBoundsSize = kBounds.size
//let kWidth = kBoundsSize.width
//let kHeight = kBoundsSize.height
import UIKit
import AVFoundation // 二维码、条码扫码库
import Photos
/**
* 扫码控制器
*/
class ScanCodeController: UIViewController {
// 输入数据源
var input: AVCaptureDeviceInput!
// 数据输出源
var output: AVCaptureMetadataOutput!
// var output1D: AVCaptureMetadataOutput!
// var output2D: AVCaptureMetadataOutput!
// 输入输出中间桥梁,负责把捕获的音频视频数据输出到输出设备中
var session: AVCaptureSession!
// 相机拍摄预览图层
var layerView: AVCaptureVideoPreviewLayer!
// 预览图层尺寸
var layerViewSize: CGSize = CGSizeZero
// 有效扫码范围
// var recognitionFrame: CGRect = CGRect(x: 20, y: (20+44)/2+(kHeight-(kWidth-20-20))/2, width: kWidth-20-20, height: kWidth-20-20)
var recognitionFrame = CGRect(x: kWidth*0.1, y: 64/2+(kHeight-kWidth*0.8)/2, width: kWidth*0.8, height: kWidth*0.8)
// 扫码动画视图
var aniView: UIImageView!
// MARK: 初始化扫码器
func defaultInitScan() {
let device = AVCaptureDevice.defaultDeviceWithMediaType(AVMediaTypeVideo)
do {
//let w = kWidth
//let h = kHeight-20-44
// let perH = w*0.8/h
// 输入源
try self.input = AVCaptureDeviceInput(device: device)
// 输出源
self.output = AVCaptureMetadataOutput()
self.output.setMetadataObjectsDelegate(self, queue: dispatch_get_main_queue())
// self.output.rectOfInterest = CGRectMake(0.1, (1-perH)/2, 0.8, perH);
// session设置
self.session = AVCaptureSession()
self.session.sessionPreset = AVCaptureSessionPresetHigh
self.session.addInput(self.input)
self.session.addOutput(self.output)
// 设置扫码的格式 注意这个地方有先后顺序
// self.output.metadataObjectTypes = self.output.availableMetadataObjectTypes
self.output.metadataObjectTypes = [
// 一维码
AVMetadataObjectTypeUPCECode, // 美国统一代码委员会制定,主要用于美国和加拿大地区
AVMetadataObjectTypeCode39Code,
AVMetadataObjectTypeCode39Mod43Code,
AVMetadataObjectTypeEAN13Code, // 通用商品条码
AVMetadataObjectTypeEAN8Code, // 通用商品条码
AVMetadataObjectTypeCode93Code,
AVMetadataObjectTypeCode128Code,
AVMetadataObjectTypeInterleaved2of5Code,
AVMetadataObjectTypeITF14Code,
AVMetadataObjectTypeAztecCode,
// 二维码
AVMetadataObjectTypePDF417Code,
AVMetadataObjectTypeDataMatrixCode,
AVMetadataObjectTypeQRCode,
]
// 扫码视图
self.layerView = AVCaptureVideoPreviewLayer(session: self.session)
self.layerView.videoGravity = AVLayerVideoGravityResizeAspectFill
self.layerView.frame = CGRectMake(0, 64, kWidth, kHeight-64)
self.layerViewSize = self.layerView.frame.size
self.view.layer.addSublayer(self.layerView)
// 开始扫码
self.session.startRunning()
do {
try device.lockForConfiguration()
// // 滤镜的设置吗?不是很确定
// let torchMode: AVCaptureTorchMode = device.torchMode
// device.torchMode = (torchMode == .Off) ? .On : .Off
// device.torchMode = .Off
// 放大焦距
// MARK: 通过设置焦距来解决条码扫码效率低的问题 看来问题还是没有解决
if device.activeFormat.videoMaxZoomFactor > 2 {
device.videoZoomFactor = 2
} else {
device.videoZoomFactor = device.activeFormat.videoMaxZoomFactor
}
device.unlockForConfiguration()
} catch {
print(error)
}
} catch {
print(error)
}
}
// 扫码框和动画
func drawRecognitionView() {
let borderWidth: CGFloat = 2
let recognitionView = UIView(frame: self.recognitionFrame)
self.view.addSubview(recognitionView)
recognitionView.backgroundColor = UIColor.clearColor()
recognitionView.layer.borderColor = UIColor.whiteColor().CGColor
recognitionView.layer.borderWidth = borderWidth
let color = UIColor(red: 0, green: 0, blue: 0, alpha: 0.5)
let colour = UIColor(red: 68.0/255.0, green: 164.0/255.0, blue: 252.0/255.0, alpha: 1)
let per: CGFloat = 0.1
let topView = UIView(frame: CGRect(x: 0, y: 0, width: kWidth, height: CGRectGetMinY(recognitionView.frame)))
self.view.addSubview(topView)
topView.backgroundColor = color
let leftView = UIView(frame: CGRect(x: 0, y: CGRectGetMinY(recognitionView.frame), width: CGRectGetMinX(recognitionView.frame), height: CGRectGetHeight(recognitionView.bounds)))
self.view.addSubview(leftView)
leftView.backgroundColor = color
let bottomView = UIView(frame: CGRect(x: 0, y: CGRectGetMaxY(recognitionView.frame), width: kWidth, height: kHeight-CGRectGetMaxY(recognitionView.frame)))
self.view.addSubview(bottomView)
bottomView.backgroundColor = color
let rightView = UIView(frame: CGRect(x: CGRectGetMaxX(recognitionView.frame), y: CGRectGetMinY(recognitionView.frame), width: kWidth-CGRectGetMaxX(recognitionView.frame), height: CGRectGetHeight(recognitionView.frame)))
self.view.addSubview(rightView)
rightView.backgroundColor = color
let topLeftView = UIView(frame: CGRect(x: CGRectGetMinX(recognitionView.frame)-10, y: CGRectGetMinY(recognitionView.frame)-10, width: CGRectGetWidth(recognitionView.bounds)*per, height: 10))
self.view.addSubview(topLeftView)
topLeftView.backgroundColor = colour
let topRightView = UIView(frame: CGRect(x: CGRectGetMaxX(recognitionView.frame)-CGRectGetWidth(recognitionView.bounds)*per+10, y: CGRectGetMinY(recognitionView.frame)-10, width: CGRectGetWidth(recognitionView.bounds)*per, height: 10))
self.view.addSubview(topRightView)
topRightView.backgroundColor = colour
let leftTopView = UIView(frame: CGRect(x: CGRectGetMinX(recognitionView.frame)-10, y: CGRectGetMinY(recognitionView.frame)-10, width: 10, height: CGRectGetWidth(recognitionView.bounds)*per))
self.view.addSubview(leftTopView)
leftTopView.backgroundColor = colour
let leftBottomView = UIView(frame: CGRect(x: CGRectGetMinX(recognitionView.frame)-10, y: CGRectGetMaxY(recognitionView.frame)-CGRectGetWidth(recognitionView.bounds)*per+10, width: 10, height: CGRectGetWidth(recognitionView.bounds)*per))
self.view.addSubview(leftBottomView)
leftBottomView.backgroundColor = colour
let bottomLeftView = UIView(frame: CGRect(x: CGRectGetMinX(recognitionView.frame)-10, y: CGRectGetMaxY(recognitionView.frame), width: CGRectGetWidth(recognitionView.bounds)*per, height: 10))
self.view.addSubview(bottomLeftView)
bottomLeftView.backgroundColor = colour
let bottomRightView = UIView(frame: CGRect(x: CGRectGetMaxX(recognitionView.frame)-CGRectGetWidth(recognitionView.bounds)*per+10, y: CGRectGetMaxY(recognitionView.frame), width: CGRectGetWidth(recognitionView.bounds)*per, height: 10))
self.view.addSubview(bottomRightView)
bottomRightView.backgroundColor = colour
let rightTopView = UIView(frame: CGRect(x: CGRectGetMaxX(recognitionView.frame), y: CGRectGetMinY(recognitionView.frame)-10, width: 10, height: CGRectGetWidth(recognitionView.bounds)*per))
self.view.addSubview(rightTopView)
rightTopView.backgroundColor = colour
let rightBottomView = UIView(frame: CGRect(x: CGRectGetMaxX(recognitionView.frame), y: CGRectGetMaxY(recognitionView.frame)-CGRectGetWidth(recognitionView.bounds)*per+10, width: 10, height: CGRectGetWidth(recognitionView.bounds)*per))
self.view.addSubview(rightBottomView)
rightBottomView.backgroundColor = colour
let im = UIImage(named: "smx_")!
let imw = CGFloat(CGImageGetWidth(im.CGImage))
let imh = CGFloat(CGImageGetHeight(im.CGImage))
let factw = CGRectGetWidth(recognitionView.bounds)
let facth = factw * imh / imw
self.aniView = UIImageView(frame: CGRect(x: CGRectGetMinX(recognitionView.frame), y: CGRectGetMinY(recognitionView.frame), width: factw, height: facth))
self.view.addSubview(self.aniView)
self.aniView.image = im
self.aniView.contentMode = .ScaleAspectFit
let beginPt = self.aniView.center
let endPt = CGPoint(x: beginPt.x, y: CGRectGetMaxY(recognitionView.frame)-CGRectGetHeight(self.aniView.bounds)/2)
UIView.animateWithDuration(3, delay: 0, options: [.CurveLinear, .Repeat, .Autoreverse], animations: {
[unowned self] in
self.aniView.center = endPt
}) { (finish) in
}
}
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
self.navigationItem.title = "My Scan Code"
//let scannerBarButtonItem = UIBarButtonItem(image: UIImage(named: "sm_")!, style: .Plain, target: self, action: #selector(ScanCodeController.startScaning))
let libraryBarButtonItem = UIBarButtonItem(title: "相册", style: .Plain, target: self, action: #selector(ScanCodeController.scanLibrary))
//self.navigationItem.rightBarButtonItems = [libraryBarButtonItem, scannerBarButtonItem]
self.navigationItem.rightBarButtonItem = libraryBarButtonItem
self.defaultInitScan()
self.drawRecognitionView()
}
override func viewWillDisappear(animated: Bool) {
super.viewWillDisappear(animated)
if self.session.running {
self.session.stopRunning()
}
}
// MARK: 浏览相册,选择相册中的二维码图片
func scanLibrary() {
if !ScanCodeController.photoLibraryIsAvailable() {
return ;
}
let imagePickVC = UIImagePickerController()
imagePickVC.delegate = self
imagePickVC.sourceType = .SavedPhotosAlbum
self.presentViewController(imagePickVC, animated: true, completion: nil)
}
// 开始扫码
func startScaning() {
if !self.session.running {
self.session.startRunning()
}
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}
extension ScanCodeController: AVCaptureMetadataOutputObjectsDelegate {
func captureOutput(captureOutput: AVCaptureOutput!, didOutputMetadataObjects metadataObjects: [AnyObject]!, fromConnection connection: AVCaptureConnection!) {
if metadataObjects.count > 0 {
// 停止扫码
// if self.session.running {
// self.session.stopRunning()
// }
// 结果对象
let metadataObject = metadataObjects.last as! AVMetadataMachineReadableCodeObject
// 显示结果
let alertVC = UIAlertController(title: nil, message: metadataObject.stringValue, preferredStyle: .Alert)
let action = UIAlertAction(title: "确定", style: .Cancel, handler: { [unowned alertVC](_) in
alertVC.dismissViewControllerAnimated(true, completion: nil)
})
alertVC.addAction(action)
self.presentViewController(alertVC, animated: true, completion: nil)
}
}
}
extension ScanCodeController: UIImagePickerControllerDelegate, UINavigationControllerDelegate {
func imagePickerController(picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : AnyObject]) {
var resultStr: String = ""
// 选择图片
let im = info[UIImagePickerControllerOriginalImage] as! UIImage
// 二维码识别
// CIDetectorTypeText CIDetectorTypeQRCode
let detectorQR = CIDetector(ofType: CIDetectorTypeQRCode, context: nil, options: [CIDetectorAccuracy : CIDetectorAccuracyHigh])
// 开始识别
let featuresQR = detectorQR.featuresInImage(CIImage(image: im)!)
let featureQR = featuresQR.last as? CIQRCodeFeature
if let feature = featureQR {
resultStr = "[QRCode] " + feature.messageString
}
// // 文本识别
// let detectorText = CIDetector(ofType: CIDetectorTypeText, context: nil, options: [CIDetectorAccuracy : CIDetectorAccuracyHigh])
//
// // 开始识别
// let featuresText = detectorText.featuresInImage(CIImage(image: im)!)
//
// let featureText = featuresText.last as? CITextFeature
//
// if let feature = featureText {
// if resultStr.isEmpty {
// resultStr += "\n"
// }
// resultStr += ("[Text] " + "")
// for fea in feature.subFeatures {
// print(fea)
// }
// }
picker.dismissViewControllerAnimated(true) {
[unowned self] in
var alertVC: UIAlertController? = nil
if !resultStr.isEmpty {
// 显示结果
alertVC = UIAlertController(title: nil, message: resultStr, preferredStyle: .Alert)
} else {
alertVC = UIAlertController(title: nil, message: "不能识别的图片", preferredStyle: .Alert)
}
let action = UIAlertAction(title: "确定", style: .Cancel, handler: { [weak alertVC](_) in
alertVC!.dismissViewControllerAnimated(true, completion: nil)
})
alertVC!.addAction(action)
self.presentViewController(alertVC!, animated: true, completion: nil)
}
self.startScaning()
}
func imagePickerControllerDidCancel(picker: UIImagePickerController) {
self.startScaning()
picker.dismissViewControllerAnimated(true, completion: nil)
}
}
extension ScanCodeController {
// MARK: 相机是否可用
class func cameraIsAvailable() -> Bool {
let status = AVCaptureDevice.authorizationStatusForMediaType(AVMediaTypeVideo)
if status == .Restricted || status == .Denied {
UIApplication.sharedApplication().openURL(NSURL(string: UIApplicationOpenSettingsURLString)!)
return false
} else {
return true
}
}
// MARK: 相册是否可用
class func photoLibraryIsAvailable() -> Bool {
let status = PHPhotoLibrary.authorizationStatus()
if status == .Restricted || status == .Denied {
UIApplication.sharedApplication().openURL(NSURL(string: UIApplicationOpenSettingsURLString)!)
return false
} else {
return true
}
}
}