二維碼的掃描,識別相冊二維碼以及制作

1??二維碼的掃描

掃描.png

??二維碼的掃描模塊,都會有個掃描的動畫,首先我們將動畫做出來,如何布局(創(chuàng)建了DimensionViewController和對應(yīng)的storyboard),對于實現(xiàn)重復(fù)掃描動畫很關(guān)鍵.首先我們在彈出掃描頁面放入一個view,約束固定大小以及垂直和水平的約束;接下來是在view放入二維碼掃描的邊框圖片qrcode_border,按住command鍵選中view和邊框,設(shè)置他們上下左右的距離都為0;最后我們放上沖擊波的圖片wave,設(shè)置它與view的約束關(guān)系為左,上右的距離為0,同時設(shè)置他們等高.接下來我們需要把?view的高度codeHeight,wave的top的約束codeScanTop, view的橫向約束viewCenterY?拖線成為對應(yīng)的屬性.

private func startAnimate() {
        //設(shè)置沖擊波底部和視圖底部對齊
        codeScanTop.constant = -codeHeight.constant
        view.layoutIfNeeded()
        UIView.animateWithDuration(2.0) {
          //設(shè)置動畫重復(fù)無數(shù)次
            UIView.setAnimationRepeatCount(MAXFLOAT)
            self.codeScanTop.constant = self.codeHeight.constant
            self.view.layoutIfNeeded()
        }
    }

??識別掃描的二維碼,代碼某些部分相對固定,不需要死記硬背哦,需要的童鞋也可以改成OC代碼使用嘞.

  //MARK:懶加載
    //輸入對象
    private lazy var input:AVCaptureDeviceInput = {
        let device = AVCaptureDevice.defaultDeviceWithMediaType(AVMediaTypeVideo)
        return try! AVCaptureDeviceInput(device:device)
    }()
    //會話
    private lazy var session: AVCaptureSession = AVCaptureSession()
    //輸出對象
    private lazy var output: AVCaptureMetadataOutput = {
        let output = AVCaptureMetadataOutput()
        //默認(rèn)值為CGRectMake(0, 0, 1, 1),這個是傳入的比例,橫屏的左上角作為原點
        output.rectOfInterest = CGRectMake((0.5-(110-self.viewCenterY.constant/2)/self.view.bounds.size.height),(0.5-110/self.view.bounds.size.width), 260/self.view.bounds.size.height, 260/self.view.bounds.size.width)
        return output
    }()
    //預(yù)覽圖層
    private lazy var previewLayer : AVCaptureVideoPreviewLayer = {
        return AVCaptureVideoPreviewLayer(session :self.session)
    }()
 //專門用于描邊的圖層
    private lazy var lineLayer : CALayer = CALayer()
 //MARK:內(nèi)部控制方法,掃描二維碼
    private func startCode(){
        //判斷輸入能否添加到對話
        if !session.canAddInput(input) {
            DMLog("輸入沒有添加")
            return
        }
        //判斷輸出能否添加到會話中
        if !session.canAddOutput(output) {
            DMLog("輸出沒有添加")
            return
        }
        //添加輸入和輸出會話中
        session.addInput(input)
        session.addOutput(output)
        //設(shè)置輸出能夠解析的數(shù)據(jù)類型
        //設(shè)置數(shù)據(jù)類型一定要在輸出對象添加到會話之后才能設(shè)置
        output.metadataObjectTypes = output.availableMetadataObjectTypes
        //設(shè)置監(jiān)聽輸出解析到的數(shù)據(jù)
        output.setMetadataObjectsDelegate(self, queue: dispatch_get_main_queue())
        //添加預(yù)覽圖預(yù)覽圖層
        view.layer.insertSublayer(previewLayer, atIndex: 0)
        previewLayer.frame = view.bounds
        //視圖上加載的是二維碼的描邊
        view.layer.addSublayer(lineLayer)
        lineLayer.frame = view.bounds
        //開始掃描
        session.startRunning()
    }

接下來還需要執(zhí)行相對應(yīng)的代理方法,對掃描的消息進行相應(yīng)的處理,還有掃描到二維碼我們需要進行相應(yīng)的描邊,這樣可以定位到掃描的二維碼,即使當(dāng)你手機是成角度掃描的時候,依舊可以掃描出形狀(比如四邊形),這里用貝塞爾曲線畫圖

extension DimensionViewController:AVCaptureMetadataOutputObjectsDelegate{
 func captureOutput(captureOutput: AVCaptureOutput!, didOutputMetadataObjects metadataObjects: [AnyObject]!, fromConnection connection: AVCaptureConnection!){
        //只要掃描到就會調(diào)用
        message.text = metadataObjects.last?.stringValue
        //DMLog(metadataObjects.last?.stringValue)
        //DMLog(metadataObjects.last)
        //corners { 0.4,0.9 0.5,0.9 0.5,0.6 0.4,0.7 },是二維碼邊線的四個點
        //轉(zhuǎn)換后corners { 140.3,238.3 141.7,317.6 220.6,318.9 222.4,238.8 },
        cleanLayers()
        guard let meta = metadataObjects.last as? AVMetadataObject else{
            DMLog("沒有掃描到二維碼")
            return
        }
        let objc = previewLayer.transformedMetadataObjectForMetadataObject(meta)
        guard let newObj = objc as? AVMetadataMachineReadableCodeObject else{
            return
        }
        //DMLog(newObj)
        //對掃描二維碼進行描邊
        drawLine(newObj)
    }
    private func drawLine(objc : AVMetadataMachineReadableCodeObject){
        //安全校驗
        guard let arr = objc.corners else{
            return
        }
        //創(chuàng)建圖層,用于保存繪制的矩形
        let layer = CAShapeLayer()
        layer.lineWidth = 3
        layer.strokeColor = UIColor.orangeColor().CGColor
        layer.fillColor = UIColor.clearColor().CGColor //填充顏色
        //創(chuàng)建UIBezierPat,繪制矩形,
        //let path = UIBezierPath.init(rect: CGRect(x: 100,y: 100,width: 220,height: 220))
        //貝塞爾曲線:將點移動到某一點;連接其他點,關(guān)閉路徑
        var point : CGPoint = CGPointZero
        var index = 0
        //把數(shù)組字典中的xy轉(zhuǎn)化為CGPoint
CGPointMakeWithDictionaryRepresentation(arr[index++] as! CFDictionary, &point)
        let  path = UIBezierPath()
        path.moveToPoint(point)
        //連接
        while index < arr.count {   CGPointMakeWithDictionaryRepresentation(arr[index++] as! CFDictionary, &point)
            path.addLineToPoint(point)
        }
        path.closePath()
        layer.path = path.CGPath
        lineLayer.addSublayer(layer)
    }
    private func cleanLayers(){
        //清除掃描二維碼出現(xiàn)多個圖層
        guard let subLayers = lineLayer.sublayers else{
            return
        }
        for layer in subLayers {
            layer.removeFromSuperlayer()
        }
    }
}

??接下來就到了識別相冊中的二維碼了,請看以下代碼

//從相冊中識別二維碼
        if !UIImagePickerController.isSourceTypeAvailable(UIImagePickerControllerSourceType.PhotoLibrary) {
            return
        }
        let imagePicker = UIImagePickerController()
        imagePicker.delegate = self
        presentViewController(imagePicker, animated: true, completion: nil)

extension DimensionViewController : UIImagePickerControllerDelegate,UINavigationControllerDelegate{
    //實現(xiàn)該代理方法,選中一張圖片時系統(tǒng)不會自動關(guān)閉
    func imagePickerController(picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : AnyObject]){
        guard let image = info["UIImagePickerControllerOriginalImage"] as? UIImage else{
            return
        }
        let cimage = CIImage(image:image)
        //創(chuàng)建一個探測器
        let detector = CIDetector(ofType: CIDetectorTypeQRCode,context: nil,options: [CIDetectorAccuracy : CIDetectorAccuracyHigh]) //最后一個參數(shù)是掃描的精確度
        let result = detector.featuresInImage(cimage!)
        //去除探測的數(shù)據(jù)
        for result in result{
            let codeInfo = (result as! CIQRCodeFeature).messageString
//這里的message是一個table,顯示掃描到的信息的
            message.text = codeInfo
        }
        picker.dismissViewControllerAnimated(true, completion: nil)
    }
}

??制作二維碼哦,可以填入自己預(yù)設(shè)的消息,比如"小敏萌萌噠"??,這些代碼都是非常固定,需要的時候復(fù)制粘貼下就可以了哦.

class CreatQrCodeViewController: UIViewController {

    @IBOutlet weak var qrCodeImage: UIImageView!
    override func viewDidLoad() {
        super.viewDidLoad()
        //創(chuàng)建濾鏡
        let filter = CIFilter(name: "CIQRCodeGenerator")
        //還原默認(rèn)屬性
        filter?.setDefaults()
        //設(shè)置需要生成二維碼的數(shù)據(jù)到濾鏡中
        filter?.setValue("小敏萌萌噠".dataUsingEncoding(NSUTF8StringEncoding), forKeyPath: "InputMessage")
        //從濾鏡中取出生成好的二維碼
        guard let ciImage = filter?.outputImage else{
            DMLog("沒有二維碼")
            return
        }
        qrCodeImage.image =  createNonInterpolatedUIImageFormCIImage(ciImage, size: 220)
    }
    /**
     生成高清二維碼
     
     - parameter image: 需要生成原始圖片
     - parameter size:  生成的二維碼的寬高
     */
    private func createNonInterpolatedUIImageFormCIImage(image: CIImage, size: CGFloat) -> UIImage {
        let extent: CGRect = CGRectIntegral(image.extent)
        let scale: CGFloat = min(size/CGRectGetWidth(extent), size/CGRectGetHeight(extent))
        // 1.創(chuàng)建bitmap;
        let width = CGRectGetWidth(extent) * scale
        let height = CGRectGetHeight(extent) * scale
        let cs: CGColorSpaceRef = CGColorSpaceCreateDeviceGray()!
        let bitmapRef = CGBitmapContextCreate(nil, Int(width), Int(height), 8, 0, cs, 0)!
        let context = CIContext(options: nil)
        let bitmapImage: CGImageRef = context.createCGImage(image, fromRect: extent)
        CGContextSetInterpolationQuality(bitmapRef,  CGInterpolationQuality.None)
        CGContextScaleCTM(bitmapRef, scale, scale);
        CGContextDrawImage(bitmapRef, extent, bitmapImage);
        // 2.保存bitmap到圖片
        let scaledImage: CGImageRef = CGBitmapContextCreateImage(bitmapRef)!
        return UIImage(CGImage: scaledImage)
    }
}

以上??

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末瓣喊,一起剝皮案震驚了整個濱河市灸眼,隨后出現(xiàn)的幾起案子穴张,更是在濱河造成了極大的恐慌黍瞧,老刑警劉巖,帶你破解...
    沈念sama閱讀 217,084評論 6 503
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件摊阀,死亡現(xiàn)場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機绣版,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,623評論 3 392
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來歼疮,“玉大人杂抽,你說我怎么就攤上這事『啵” “怎么了缩麸?”我有些...
    開封第一講書人閱讀 163,450評論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長赡矢。 經(jīng)常有香客問我杭朱,道長,這世上最難降的妖魔是什么吹散? 我笑而不...
    開封第一講書人閱讀 58,322評論 1 293
  • 正文 為了忘掉前任弧械,我火速辦了婚禮,結(jié)果婚禮上空民,老公的妹妹穿的比我還像新娘刃唐。我一直安慰自己,他們只是感情好界轩,可當(dāng)我...
    茶點故事閱讀 67,370評論 6 390
  • 文/花漫 我一把揭開白布画饥。 她就那樣靜靜地躺著,像睡著了一般浊猾。 火紅的嫁衣襯著肌膚如雪荒澡。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,274評論 1 300
  • 那天与殃,我揣著相機與錄音单山,去河邊找鬼碍现。 笑死,一個胖子當(dāng)著我的面吹牛米奸,可吹牛的內(nèi)容都是我干的昼接。 我是一名探鬼主播,決...
    沈念sama閱讀 40,126評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼悴晰,長吁一口氣:“原來是場噩夢啊……” “哼慢睡!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起铡溪,我...
    開封第一講書人閱讀 38,980評論 0 275
  • 序言:老撾萬榮一對情侶失蹤漂辐,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后棕硫,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體髓涯,經(jīng)...
    沈念sama閱讀 45,414評論 1 313
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,599評論 3 334
  • 正文 我和宋清朗相戀三年哈扮,在試婚紗的時候發(fā)現(xiàn)自己被綠了纬纪。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 39,773評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡滑肉,死狀恐怖包各,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情靶庙,我是刑警寧澤问畅,帶...
    沈念sama閱讀 35,470評論 5 344
  • 正文 年R本政府宣布,位于F島的核電站六荒,受9級特大地震影響护姆,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜恬吕,卻給世界環(huán)境...
    茶點故事閱讀 41,080評論 3 327
  • 文/蒙蒙 一签则、第九天 我趴在偏房一處隱蔽的房頂上張望须床。 院中可真熱鬧铐料,春花似錦、人聲如沸豺旬。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,713評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽族阅。三九已至篓跛,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間坦刀,已是汗流浹背愧沟。 一陣腳步聲響...
    開封第一講書人閱讀 32,852評論 1 269
  • 我被黑心中介騙來泰國打工蔬咬, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人沐寺。 一個月前我還...
    沈念sama閱讀 47,865評論 2 370
  • 正文 我出身青樓林艘,卻偏偏與公主長得像,于是被迫代替她去往敵國和親混坞。 傳聞我的和親對象是個殘疾皇子狐援,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,689評論 2 354

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

  • Android 自定義View的各種姿勢1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 172,095評論 25 707
  • 發(fā)現(xiàn) 關(guān)注 消息 iOS 第三方庫、插件究孕、知名博客總結(jié) 作者大灰狼的小綿羊哥哥關(guān)注 2017.06.26 09:4...
    肇東周閱讀 12,098評論 4 62
  • 綃帷冷啥酱,珠簾靜,舒爾輕喚無人應(yīng)厨诸。妝奩亂镶殷,人慵倦,無心懵懂泳猬,惹了卿怨批钠。念。念得封。念埋心。 紫毫重,青蘿病忙上,夜來欺我當(dāng)爐夢拷呆。...
    宋懷眾閱讀 460評論 5 3
  • 所有的成功都不可能是一帆風(fēng)順的,哪怕是你認(rèn)為絕對能成功的事情疫粥,其中的經(jīng)歷也需要絕大努力還有堅持茬斧,以及百分之百的信念。
    尚善若水007閱讀 202評論 0 0
  • 最近馬蘇又因拍攝《男人裝》封面火了娄蔼,那性感的小蠻腰和翹臀著實惹火。 馬蘇生于1981年底哗,已經(jīng)37歲岁诉,但是看起來卻像...
    摳摳網(wǎng)閱讀 874評論 0 0