1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
|
import UIKit class ViewController : UIViewController { override func viewDidLoad()
{ super .viewDidLoad() let qrcodeImg
= UIImage (named: "codeBg.png" ) let ciImage: CIImage = CIImage (image:qrcodeImg!)! let context
= CIContext (options: nil ) let detector: CIDetector = CIDetector (ofType: CIDetectorTypeQRCode , context:
context, options: [ CIDetectorAccuracy : CIDetectorAccuracyHigh ]) let features=detector.featuresInImage(ciImage) print ( "掃描到二維碼個數:\(features.count)" ) //遍歷所有的二維碼,並框出 for feature in features as !
[ CIQRCodeFeature ]
{ print (feature.messageString) } } override func didReceiveMemoryWarning()
{ super .didReceiveMemoryWarning() } }
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
|
import UIKit class ViewController : UIViewController , UIImagePickerControllerDelegate , UINavigationControllerDelegate { override func viewDidLoad()
{ super .viewDidLoad() } //選取相冊 @IBAction func fromAlbum(sender: AnyObject )
{ //判斷設置是否支持圖片庫 if UIImagePickerController .isSourceTypeAvailable(. PhotoLibrary ){ //初始化圖片控制器 let picker
= UIImagePickerController () //設置代理 picker.delegate
= self //指定圖片控制器類型 picker.sourceType
= UIImagePickerControllerSourceType . PhotoLibrary //彈出控制器,顯示界面 self .presentViewController(picker,
animated: true ,
completion: { ()
-> Void in }) } else { print ( "讀取相冊錯誤" ) } } //選擇圖片成功後代理 func imagePickerController(picker: UIImagePickerController , didFinishPickingMediaWithInfo
info: [ String : AnyObject ])
{ //獲取選擇的原圖 let image
= info[ UIImagePickerControllerOriginalImage ] as ! UIImage //二維碼讀取 let ciImage: CIImage = CIImage (image:image)! let context
= CIContext (options: nil ) let detector: CIDetector = CIDetector (ofType: CIDetectorTypeQRCode , context:
context, options: [ CIDetectorAccuracy : CIDetectorAccuracyHigh ]) let features=detector.featuresInImage(ciImage) print ( "掃描到二維碼個數:\(features.count)" ) //遍歷所有的二維碼,並框出 for feature in features as !
[ CIQRCodeFeature ]
{ print (feature.messageString) } //圖片控制器退出 picker.dismissViewControllerAnimated( true ,
completion: { ()
-> Void in }) } override func didReceiveMemoryWarning()
{ super .didReceiveMemoryWarning() } } |
(1)掃描主要使用的是 AVFoundation,用起來方便簡單
(2)通過 AVCaptureMetadataOutput 的 rectOfInterest 屬性,可以設置探測探測區域。同時給這個探測區域添加個方框,只有在框中的二維碼纔會被掃描到。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
|
import UIKit import AVFoundation class ViewController : UIViewController , AVCaptureMetadataOutputObjectsDelegate , UIAlertViewDelegate { var scanRectView: UIView ! var device: AVCaptureDevice ! var input: AVCaptureDeviceInput ! var output: AVCaptureMetadataOutput ! var session: AVCaptureSession ! var preview: AVCaptureVideoPreviewLayer ! override func viewDidLoad()
{ super .viewDidLoad() } //通過攝像頭掃描 @IBAction func fromCamera(sender: AnyObject )
{ do{ self .device
= AVCaptureDevice .defaultDeviceWithMediaType( AVMediaTypeVideo ) self .input
= try AVCaptureDeviceInput (device:
device) self .output
= AVCaptureMetadataOutput () output.setMetadataObjectsDelegate( self ,
queue: dispatch_get_main_queue()) self .session
= AVCaptureSession () if UIScreen .mainScreen().bounds.size.height<500
{ self .session.sessionPreset
= AVCaptureSessionPreset640x480 } else { self .session.sessionPreset
= AVCaptureSessionPresetHigh } self .session.addInput( self .input) self .session.addOutput( self .output) self .output.metadataObjectTypes
= [ AVMetadataObjectTypeQRCode ] //計算中間可探測區域 let windowSize: CGSize = UIScreen .mainScreen().bounds.size; let scanSize: CGSize = CGSizeMake (windowSize.width*3/4, windowSize.width*3/4); var scanRect: CGRect = CGRectMake ((windowSize.width-scanSize.width)/2, (windowSize.height-scanSize.height)/2,
scanSize.width, scanSize.height); //計算rectOfInterest
注意x,y交換位置 scanRect
= CGRectMake (scanRect.origin.y/windowSize.height, scanRect.origin.x/windowSize.width, scanRect.size.height/windowSize.height, scanRect.size.width/windowSize.width); //設置可探測區域 self .output.rectOfInterest
= scanRect self .preview
= AVCaptureVideoPreviewLayer (session: self .session) self .preview.videoGravity
= AVLayerVideoGravityResizeAspectFill self .preview.frame
= UIScreen .mainScreen().bounds self .view.layer.insertSublayer( self .preview,
atIndex:0) //添加中間的探測區域綠框 self .scanRectView
= UIView (); self .view.addSubview( self .scanRectView) self .scanRectView.frame
= CGRectMake (0,
0, scanSize.width, scanSize.height); self .scanRectView.center
= CGPointMake ( CGRectGetMidX ( UIScreen .mainScreen().bounds), CGRectGetMidY ( UIScreen .mainScreen().bounds)); self .scanRectView.layer.borderColor
= UIColor .greenColor(). CGColor self .scanRectView.layer.borderWidth
= 1; //開始捕獲 self .session.startRunning() }catch
_ as NSError { //打印錯誤消息 let errorAlert
= UIAlertView (title: "提醒" , message: "請在iPhone的\"設置-隱私-相機\"選項中,允許本程序訪問您的相機" , delegate: self , cancelButtonTitle: "確定" ) errorAlert.show() } } //攝像頭捕獲 func captureOutput(captureOutput: AVCaptureOutput !, didOutputMetadataObjects
metadataObjects: [ AnyObject ]!, fromConnection
connection: AVCaptureConnection !)
{ var stringValue: String ? if metadataObjects.count
> 0 { let metadataObject
= metadataObjects[0] as ! AVMetadataMachineReadableCodeObject stringValue
= metadataObject.stringValue if stringValue
!= nil { self .session.stopRunning() } } self .session.stopRunning() //輸出結果 let alertView
= UIAlertView (title: "二維碼" ,
message: stringValue, delegate: self ,
cancelButtonTitle: "確定" ) alertView.show() } //消息框確認後消失 func alertView(alertView: UIAlertView ,
willDismissWithButtonIndex buttonIndex: Int )
{ //繼續掃描 self .session.startRunning() } override func didReceiveMemoryWarning()
{ super .didReceiveMemoryWarning() } } |