swift開發(fā)-二維碼掃描液样、二維碼生成、識別圖片中的二維碼

序言

在iOS7之前二維碼掃描主要是用的第三方庫巧还,如ZXing或者ZBar。使用起來比較麻煩坊秸,出錯也不容易調(diào)試麸祷。iOS7之后,蘋果自身提供了二維碼的掃描褒搔、生成功能阶牍,從效率上來說,原生的二維碼遠高于這些第三方框架星瘾。這里主要分享一下swift版二維碼的掃描走孽、生成以及識別圖片中的二維碼。這里是一個完整的demo琳状。

二維碼生成描述

主要用到CIFilter類磕瓷。CIFilter是Core Image中一個比較核心的有關(guān)濾鏡使用的類。
通常CIFilter對象需要一個或多個圖像作為輸入念逞,并產(chǎn)生CIImage類型的實體作為輸出困食。而這些輸出圖像的生產(chǎn)過程需要我們通過設置一些參數(shù)來實現(xiàn),而這些參數(shù)的設置和檢索都是利用鍵/值對的形式進行操作的翎承。
其中CIFlilter承載著所有設置好的濾鏡參數(shù)以CIImage為基礎硕盹,在CIContext對象中進行渲染。要提一下的是濾鏡的使用是可以疊加的叨咖,我們可以使用多種濾鏡處理同一個圖像瘩例。Core Image的渲染分為CPU和GPU兩種啊胶,其中使用CPU渲染可以在后臺進行,但是渲染速度沒有GPU快垛贤,而GPU是不能進行后臺渲染的它是實時的焰坪,在進行視頻幀渲染時我們就可以使用GPU進行渲染。

Simulator.png

生成二維碼代碼

 private func createQRCodeImage(content:String,size:CGSize)->UIImage {
        let stringData = content.data(using: String.Encoding.utf8)
        let qrFilter = CIFilter(name: "CIQRCodeGenerator")
        
        qrFilter?.setValue(stringData, forKey: "inputMessage")
        qrFilter?.setValue("H", forKey: "inputCorrectionLevel")
        
        let colorFilter = CIFilter(name: "CIFalseColor")
        colorFilter?.setDefaults()
        
        colorFilter?.setValuesForKeys(["inputImage" : (qrFilter?.outputImage)!,"inputColor0":CIColor.init(cgColor: UIColor.black.cgColor),"inputColor1":CIColor.init(cgColor: UIColor.white.cgColor)])
        
        let qrImage = colorFilter?.outputImage
        let cgImage = CIContext(options: nil).createCGImage(qrImage!, from: (qrImage?.extent)!)
        UIGraphicsBeginImageContext(size)
        let context = UIGraphicsGetCurrentContext()
        context!.interpolationQuality = .none
        context!.scaleBy(x: 1.0, y: -1.0)
        context?.draw(cgImage!, in: (context?.boundingBoxOfClipPath)!)
        let codeImage = UIGraphicsGetImageFromCurrentImageContext()
        UIGraphicsEndImageContext()
        return codeImage!
    }

往往實際應用中不會是單獨的二維碼南吮,還需要向二維碼中添加自己的logo琳彩。二維碼有很好的糾錯機制,我們可以直接向二維碼圖片中加入logo圖片部凑,建議logo面積不要超過二維碼有效面積的1/20露乏,否則會影響讀碼。

private func addIconToQRCodeImage(image:UIImage,icon:UIImage,iconSize:CGSize)->UIImage{
        UIGraphicsBeginImageContext(image.size)
        
        let imageWidth = image.size.width
        let imageHeight = image.size.height
        let iconWidth = iconSize.width
        let iconHeight = iconSize.height
        
        image.draw(in: CGRect(x: 0, y: 0, width: imageWidth, height: imageHeight))
        icon.draw(in: CGRect(x: (imageWidth-iconWidth)/2.0, y: (imageHeight-iconHeight)/2.0, width: iconWidth, height: iconHeight))
        let qrImage = UIGraphicsGetImageFromCurrentImageContext();
        UIGraphicsEndImageContext();
        return qrImage!
    }

二維碼掃描

二維碼掃描主要用AVFoundation涂邀。AVFoundation是一個很大基礎庫瘟仿,用來創(chuàng)建基于時間的視聽媒體,可以使用它來檢查,創(chuàng)建比勉、編輯或媒體文件劳较。也可以輸入流從設備和操作視頻實時捕捉和回放。
主要成員介紹:
AVCaptureSession 管理輸入(AVCaptureInput)和輸出(AVCaptureOutput)流浩聋,包含開啟和停止會話方法观蜗。
AVCaptureDeviceInputAVCaptureInput的子類,可以作為輸入捕獲會話,用AVCaptureDevice實例初始化衣洁。
AVCaptureDevice代表了物理捕獲設備如:攝像機墓捻。用于配置等底層硬件設置相機的自動對焦模式。
AVCaptureMetadataOutputAVCaptureOutput的子類坊夫,處理輸出捕獲會話砖第。捕獲的對象傳遞給一個委托實現(xiàn)AVCaptureMetadataOutputObjectsDelegate協(xié)議。協(xié)議方法在指定的派發(fā)隊列(dispatch queue)上執(zhí)行环凿。
AVCaptureVideoPreviewLayerCALayer的一個子類梧兼,顯示捕獲到的相機輸出流。

掃一掃.jpeg

import AVFoundation

 let session = AVCaptureSession()
var layer: AVCaptureVideoPreviewLayer?```

創(chuàng)建會話智听,讀取流:

private func scanQRCode(){
if !isCameraAvailable(){
showAlert("請使用真機", message: "您的設備沒有相機.", VC: self)
return
}
self.session.sessionPreset = AVCaptureSessionPresetHigh
do{
let input = try AVCaptureDeviceInput(device: self.device)
if self.session.canAddInput(input){
self.session.addInput(input)
}
}
catch{
showAlert("錯誤", message: "初始化失敗", VC: self)
return
}
self.layer = AVCaptureVideoPreviewLayer(session: self.session)
self.layer?.videoGravity = AVLayerVideoGravityResizeAspectFill
self.layer?.frame = self.view.frame
self.view.layer.addSublayer(self.layer!)
self.session.addObserver(self, forKeyPath: "running", options: .new, context: nil)
if AVCaptureDevice.authorizationStatus(forMediaType: AVMediaTypeVideo) == .authorized{
let output = AVCaptureMetadataOutput()
output.setMetadataObjectsDelegate(self, queue: DispatchQueue.main)
//設置掃描的有效區(qū)域
output.rectOfInterest = CGRect(x: 140.0/SCREEN_HEIGHT, y: 40.0/SCREEN_WIDTH, width: (SCREEN_WIDTH-80)/SCREEN_HEIGHT, height: (SCREEN_WIDTH-80)/SCREEN_WIDTH)
if self.session.canAddOutput(output) {
self.session.addOutput(output)
output.metadataObjectTypes = [AVMetadataObjectTypeQRCode]
}
self.setOverlayPickerView()
self.session.startRunning()
}else{
showAlert("提示", message: "Authorization is required to use the camera, please check your permission settings: Settings> Privacy> Camera", VC: self)
}
}


獲取捕獲數(shù)據(jù):

//二維碼掃描代理
func captureOutput(_ captureOutput: AVCaptureOutput!, didOutputMetadataObjects metadataObjects: [Any]!, from connection: AVCaptureConnection!) {
var stringValue:String?
if metadataObjects.count > 0 {
let metadataObject = metadataObjects[0] as! AVMetadataMachineReadableCodeObject
stringValue = metadataObject.stringValue

    }
    self.session.stopRunning()
    print("code is \(stringValue)")
    let result:JCQRResultViewController = JCQRResultViewController()
    result.urlString = stringValue!
    self.navigationController?.pushViewController(result, animated: true)
}
> 需要注意的是```rectOfInterest``` 這個屬性的每一個值取值范圍在0~1之間羽杰,代表的是對應軸上的比例大小。
![掃一掃.jpeg](http://upload-images.jianshu.io/upload_images/3288439-aa1fbcb29632c52e.jpeg?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)


識別圖片中的二維碼
-------------
識別圖片中的代碼非常簡單到推,用```CIDetector```一句代碼就好了忽洛。

fileprivate func readQRImage(_ image:UIImage)->String{
//二維碼讀取
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.features(in: ciImage)
print("掃描到二維碼個數(shù):(features.count)")

    var stringValue:String = ""
    
    if features.count<=0 {
        showAlert("提示", message: "無法解析圖片",VC: self)
    }else {
        //遍歷所有的二維碼,并框出
        for feature in features as! [CIQRCodeFeature] {
            print(feature.messageString)
            stringValue = feature.messageString!
        }
    }
    return stringValue
}
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末环肘,一起剝皮案震驚了整個濱河市欲虚,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌悔雹,老刑警劉巖复哆,帶你破解...
    沈念sama閱讀 206,968評論 6 482
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件欣喧,死亡現(xiàn)場離奇詭異,居然都是意外死亡梯找,警方通過查閱死者的電腦和手機唆阿,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,601評論 2 382
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來锈锤,“玉大人驯鳖,你說我怎么就攤上這事【妹猓” “怎么了浅辙?”我有些...
    開封第一講書人閱讀 153,220評論 0 344
  • 文/不壞的土叔 我叫張陵,是天一觀的道長阎姥。 經(jīng)常有香客問我记舆,道長,這世上最難降的妖魔是什么呼巴? 我笑而不...
    開封第一講書人閱讀 55,416評論 1 279
  • 正文 為了忘掉前任泽腮,我火速辦了婚禮,結(jié)果婚禮上衣赶,老公的妹妹穿的比我還像新娘诊赊。我一直安慰自己,他們只是感情好府瞄,可當我...
    茶點故事閱讀 64,425評論 5 374
  • 文/花漫 我一把揭開白布碧磅。 她就那樣靜靜地躺著,像睡著了一般摘能。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上敲街,一...
    開封第一講書人閱讀 49,144評論 1 285
  • 那天团搞,我揣著相機與錄音,去河邊找鬼多艇。 笑死逻恐,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的峻黍。 我是一名探鬼主播复隆,決...
    沈念sama閱讀 38,432評論 3 401
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼姆涩!你這毒婦竟也來了挽拂?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,088評論 0 261
  • 序言:老撾萬榮一對情侶失蹤骨饿,失蹤者是張志新(化名)和其女友劉穎亏栈,沒想到半個月后台腥,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 43,586評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡绒北,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,028評論 2 325
  • 正文 我和宋清朗相戀三年黎侈,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片闷游。...
    茶點故事閱讀 38,137評論 1 334
  • 序言:一個原本活蹦亂跳的男人離奇死亡峻汉,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出脐往,到底是詐尸還是另有隱情休吠,我是刑警寧澤,帶...
    沈念sama閱讀 33,783評論 4 324
  • 正文 年R本政府宣布钙勃,位于F島的核電站蛛碌,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏辖源。R本人自食惡果不足惜蔚携,卻給世界環(huán)境...
    茶點故事閱讀 39,343評論 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望克饶。 院中可真熱鬧酝蜒,春花似錦、人聲如沸矾湃。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,333評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽邀跃。三九已至霉咨,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間拍屑,已是汗流浹背途戒。 一陣腳步聲響...
    開封第一講書人閱讀 31,559評論 1 262
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留僵驰,地道東北人喷斋。 一個月前我還...
    沈念sama閱讀 45,595評論 2 355
  • 正文 我出身青樓,卻偏偏與公主長得像蒜茴,于是被迫代替她去往敵國和親星爪。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 42,901評論 2 345

推薦閱讀更多精彩內(nèi)容