iOS_最全的二維碼篇


二維碼掃面當(dāng)下很流行,也帶來(lái)了很多的便利趴酣。我也不是在吹捧梨树,你也許你也發(fā)現(xiàn),幾乎凡是個(gè)APP岖寞,都有掃描二維碼的功能÷账模現(xiàn)在網(wǎng)上的資料很多,我也是閑的蛋疼仗谆,在做一個(gè)美團(tuán)的高仿項(xiàng)目指巡,涉及到二維碼的掃描功能,iOS7之前隶垮,開(kāi)發(fā)者進(jìn)行掃碼編程時(shí)藻雪,一般會(huì)借助第三方庫(kù)。常用的是ZBarSDKa和ZXingObjC狸吞,iOS7之后勉耀,系統(tǒng)的AVMetadataObject類(lèi)中,為我們提供了解析二維碼的接口蹋偏。經(jīng)過(guò)測(cè)試便斥,使用原生API掃描和處理的效率非常高,遠(yuǎn)遠(yuǎn)高于第三方庫(kù)威始。我查了很多的資料枢纠,網(wǎng)上關(guān)于用系統(tǒng)原生類(lèi)來(lái)實(shí)現(xiàn)二維碼掃描的資料還是很多的,但都不是很全黎棠。所以我把一套功能的實(shí)現(xiàn)分享出來(lái)晋渺,希望你們喜歡。(剛來(lái)簡(jiǎn)書(shū)葫掉,文章的排版還不是很熟些举,蛋疼!,還有就是打開(kāi)項(xiàng)目時(shí)俭厚,要是不是真機(jī)仿真户魏,要先注釋掉beginScanning()方法,要不程序會(huì)崩潰)

這里是Swift版的,如果你想使用OC來(lái)實(shí)現(xiàn)叼丑,翻譯過(guò)去我相信也不是難事关翎。

OC也可以參考:http://yimouleng.com/2016/01/13/ios-QRCode/

這里包含:

  • 1、窗口的搭建
  • 2鸠信、二維碼的掃描
  • 3纵寝、從相冊(cè)中讀取二維碼
  • 4、生成二維碼
  • 5星立、長(zhǎng)按識(shí)別二維碼

其中二維碼的掃描主要是用到AVFoundation這個(gè)框架中的AVCaptureSession爽茴,讀取二維碼和識(shí)別二維碼是同個(gè)原理,只是處理方式不同绰垂,主要用到的是CIDetector類(lèi)室奏,而生成二維碼要用到CoreImage框架中的CIFilter濾鏡類(lèi),值得一提的是CoreImage非常強(qiáng)大劲装,這是iOS中關(guān)于圖片處理的幾乎所有內(nèi)容集合胧沫,即圖片的處理幾乎都在CoreImage中,CIFilter也非常值得一究占业,mac上應(yīng)該在CoreQuartz中绒怨。CoreImageCIFilter的內(nèi)容很多,我可能會(huì)在另外的文章中去分享谦疾。(我并不是大神南蹂,不敢吹牛逼說(shuō)給大家講解,只是分享和大家相互學(xué)習(xí))

詳情看看我的源碼:
美團(tuán)的高仿項(xiàng)目 更多模塊中的“掃一掃”


1餐蔬、窗口的搭建

這是UI的東西碎紊,很簡(jiǎn)單,想怎么弄就怎么弄樊诺,只要你happy就ok仗考,這是我的代碼:

1.1、設(shè)置導(dǎo)航條:setupNavView()词爬,editItemAction()中因?yàn)樵趇OS9+平臺(tái)秃嗜,所以用UIAlertController來(lái)列出多個(gè)ActionSheet功能

func setupNavView() {
    
self.navigationController?.navigationBar.barTintColor = UIColor.clearColor()
        self.title = "二維碼/條形碼"
        //設(shè)置標(biāo)題顏色
        let navigationTitleAttribute = NSDictionary(object: UIColor.whiteColor(), forKey: NSForegroundColorAttributeName)
        self.navigationController?.navigationBar.titleTextAttributes = navigationTitleAttribute as? [String : AnyObject]
        
        //1.返回
        let backBtn = UIButton(type: UIButtonType.Custom)
        backBtn.frame = CGRectMake(20, 30, 25, 25);
        
        backBtn.setBackgroundImage(UIImage(named: "qrcode_scan_titlebar_back_nor"), forState:UIControlState.Normal);
        backBtn.contentMode = UIViewContentMode.ScaleAspectFit
        backBtn.addTarget(self, action: #selector(QRCodeScanViewController.backBtnAction), forControlEvents: UIControlEvents.TouchUpInside)
        
        let backItem = UIBarButtonItem(customView: backBtn)
        self.navigationItem.leftBarButtonItem = backItem
        
        let editItem = UIBarButtonItem(barButtonSystemItem: .Edit, target: self, action: #selector(QRCodeScanViewController.editItemAction))
        self.navigationItem.rightBarButtonItem = editItem
        
        
        
       //  deprecated  //
//        //2.相冊(cè)
//        let albumBtn = UIButton(type: UIButtonType.Custom)
//        albumBtn.frame = CGRectMake(0, 0, 35, 49)
//        albumBtn.center = CGPointMake(self.view.bounds.width / 2, 20 + 49 / 2.0)
//        albumBtn.setBackgroundImage(UIImage(named: "qrcode_scan_btn_photo_down"), forState: UIControlState.Normal)
//        albumBtn.contentMode=UIViewContentMode.ScaleAspectFit
//        albumBtn.addTarget(self, action: #selector(QRCodeScanViewController.openAlbum), forControlEvents: UIControlEvents.TouchUpInside)//        self.view.addSubview(albumBtn)
//        
//        //3.閃光燈
//        let flashBtn = UIButton(type: UIButtonType.Custom)
//        flashBtn.frame = CGRectMake(self.view.bounds.width - 55, 20, 35, 49)
//        flashBtn.setBackgroundImage(UIImage(named: "qrcode_scan_btn_flash_down"), forState: UIControlState.Normal)
//        flashBtn.contentMode=UIViewContentMode.ScaleAspectFit
//        flashBtn.addTarget(self, action: #selector(QRCodeScanViewController.openFlash(_:)), forControlEvents: UIControlEvents.TouchUpInside)
//        self.view.addSubview(flashBtn)
func editItemAction() {
        
        let actionSheet = UIAlertController(title: nil, message: nil, preferredStyle: .ActionSheet)
        let action1 = UIAlertAction(title: "從相冊(cè)選取二維碼", style: .Default) {
            [unowned self]
            (act) in
            self.openAlbum()
        }
        
        let action2 = UIAlertAction(title: "打開(kāi)閃光燈", style: .Default) {
            [unowned self]
            (act) in
            self.openFlash()
        }
        
        let action3 = UIAlertAction(title: "生成二維碼", style: .Default) {
            [unowned self]
            (act) in
            
            let inputVC = UIAlertController(title: "輸入信息", message: nil, preferredStyle: .Alert)
            let cancelAction = UIAlertAction(title: "取消", style: .Cancel, handler: nil)
            let okayAction = UIAlertAction(title: "確定", style: .Default){
                [unowned self]
                (act) in
                ///生成二維碼圖片
                let QRCodeImage = self.createQRCodeImage(withImage: UIImage(named: "icon_mine_default_portrait")!, string: self.textInfo!)
                
                ///展示在界面上
                let imageBtn = UIButton(frame: CGRectMake(0, 64, SCREENWIDTH, SCREENHEIGHT - 64))
                imageBtn.setImage(QRCodeImage, forState: .Normal)
                imageBtn.addTarget(self, action: #selector(self.imageBtnAction(_:)), forControlEvents: .TouchUpInside)
                imageBtn.backgroundColor = THEMECOLOR
                self.view.addSubview(imageBtn)
                
                ///保存到相冊(cè)
                //UIImageWriteToSavedPhotosAlbum(QRCodeImage, self, #selector(self.image(_: didFinishSavingWithError: contextInfo: )), nil)
                
                inputVC.dismissViewControllerAnimated(true, completion: { 
                    print("生成二維碼")
                })
            }
            
            inputVC.addAction(cancelAction)
            inputVC.addAction(okayAction)
            
            inputVC.addTextFieldWithConfigurationHandler({ (textField) in
                textField.borderStyle = .None
                textField.placeholder = "輸入需要保存的信息"
                textField.delegate = self
                textField.becomeFirstResponder()
            })
            
            self.presentViewController(inputVC, animated: true, completion: {
                print("輸入信息可以生成二維碼")
            })
        }
        
        let action4 = UIAlertAction(title: "取消", style: .Cancel, handler: nil)
        
        actionSheet.addAction(action1)
        actionSheet.addAction(action2)
        actionSheet.addAction(action3)
        actionSheet.addAction(action4)
        
        self.presentViewController(actionSheet, animated: true, completion: nil)
    }
    

1.3、遮罩(蒙板)的設(shè)置:setupMaskView()

 let kMargin = CGFloat(50)
    
    
    func setupMaskView() {
        
        maskView = UIView()
        maskView.layer.borderColor = UIColor(red: CGFloat(0), green: CGFloat(0), blue: CGFloat(0), alpha: CGFloat(0.7)).CGColor
        maskView.layer.borderWidth = kMargin
        
        let maskViewSize = CGSizeMake(self.view.extWidth(), self.view.extWidth())///正方形顿膨,下面會(huì)露出來(lái)锅锨,還要添加補(bǔ)充遮罩
        maskView.frame = CGRectMake(0, 64, maskViewSize.width, maskViewSize.height)
        self.view.addSubview(maskView)
        
        ///補(bǔ)充遮罩
        let mask = UIView(frame: CGRectMake(0, maskView.extY() + maskView.extHeight(), SCREENWIDTH, SCREENHEIGHT - (maskView.extY() + maskView.extHeight())))
        mask.backgroundColor = UIColor(red: CGFloat(0), green: CGFloat(0), blue: CGFloat(0), alpha: CGFloat(0.7))
        self.view.addSubview(mask)
        
    }

1.4、掃描區(qū)域的設(shè)置:setupScanWindowView()

 func setupScanWindowView() {
        
        let scanWindowH = maskView.extWidth() - kMargin * 2 ///kMargin為黑色邊框的寬度恋沃,
        let scanWindowW = scanWindowH
        
        scanWindow =  UIView(frame: CGRectMake(kMargin, kMargin + 64, scanWindowW, scanWindowH))///隱形的框
        scanWindow.clipsToBounds = true
        self.view.addSubview(scanWindow)
        
        scanNetImageView = UIImageView(image: UIImage(named: "scan_net"))
        scanNetImageView.extSetY(-1 * scanNetImageView.extHeight())
        scanWindow.addSubview(scanNetImageView)
        
        let buttonWH = CGFloat(18)
        let topLift = UIImageView(frame: CGRectMake(0, 0, buttonWH, buttonWH))
        topLift.image = UIImage(named: "scan_1")
        let topRight = UIImageView(frame: CGRectMake(scanWindowW - buttonWH, 0, buttonWH, buttonWH))
        topRight.image = UIImage(named: "scan_2")
        let bottomLeft = UIImageView(frame: CGRectMake(0, scanWindowH - buttonWH, buttonWH, buttonWH))
        bottomLeft.image = UIImage(named: "scan_3")
        let bottomRight = UIImageView(frame: CGRectMake(topRight.frame.origin.x, bottomLeft.frame.origin.y, buttonWH, buttonWH))
        bottomRight.image = UIImage(named: "scan_4")
        
        scanWindow.addSubview(topLift)
        scanWindow.addSubview(topRight)
        scanWindow.addSubview(bottomLeft)
        scanWindow.addSubview(bottomRight)
        
        self.view.addSubview(scanWindow)
    }
    

2必搞、二維碼的掃描

主要用的的是AVCaptureSession類(lèi),然后設(shè)置inputoutput即可囊咏,值得一提的是掃碼支持的類(lèi)型:output.metadataObjectTypes恕洲。iOS已經(jīng)提供了很多塔橡,但是并不全,不過(guò)包含了常用的二維碼AVMetadataObjectTypeQRCode和條形碼AVMetadataObjectTypeCode128Code

func beginScanning() {///要真機(jī)
        ///模擬圖片動(dòng)起來(lái)
        ///way 1霜第、UIView Animation
        UIView.animateWithDuration(1.5, delay: 0, options: UIViewAnimationOptions.Repeat, animations: {
            [unowned self] in
            self.scanNetImageView.transform = CGAffineTransformTranslate(self.scanNetImageView.transform, 0, self.scanWindow.extHeight())
            }, completion: nil)
        
        ///way 2葛家、coreAnimation
        
        
        //初始化鏈接對(duì)象
        session = AVCaptureSession()
        //高質(zhì)量采集率
        session.sessionPreset = AVCaptureSessionPresetHigh
        
        let preLayer = AVCaptureVideoPreviewLayer(session: session)///注意session存放的地方
        preLayer.frame = self.view.bounds
        self.view.layer.insertSublayer(preLayer, atIndex: 0)
        
        /*
         * AVCaptureDevice 獲取攝像設(shè)備
         * AVCaptureDeviceInput 創(chuàng)建輸入流
         * AVCaptureMetadataOutput 創(chuàng)建輸出了
         */
        
        let device = AVCaptureDevice.defaultDeviceWithMediaType(AVMediaTypeVideo)
        var input: AVCaptureDeviceInput?
        do {
            
            input = try AVCaptureDeviceInput(device: device)
            ///add input
            
        }catch let error as NSError {
            // 發(fā)生了錯(cuò)誤
            print(error.localizedDescription)
        }
        catch {
            print("--input未知錯(cuò)誤--")
        }
        ///add input
        session.addInput(input)
        
        let output = AVCaptureMetadataOutput()
        ///add delegate
        output.setMetadataObjectsDelegate(self, queue: dispatch_get_main_queue())//主隊(duì)列(主線程)
        
        ///設(shè)置“感興趣”區(qū)域(敏感區(qū)域)
        let interestRect = preLayer.metadataOutputRectOfInterestForRect(scanWindow.frame)///掃描區(qū) 到 metadata輸出區(qū)
        ///值等于CGRectMake(scanWindow.extY() / SCREENHEIGHT, scanWindow.extX() / SCREENWIDTH, scanWindow.extHeight() / SCREENHEIGHT, scanWindow.extWidth() / SCREENWIDTH)
        ///把一個(gè)在 preview layer 坐標(biāo)系中的rect 轉(zhuǎn)換成一個(gè)在 metadata output 坐標(biāo)系中的rect
        
        output.rectOfInterest = interestRect ///注意,這個(gè)并不是掃描區(qū)的坐標(biāo)尺寸
        
        session.addOutput(output)
        
        //設(shè)置掃碼支持的類(lèi)型
        output.metadataObjectTypes = [AVMetadataObjectTypeDataMatrixCode,
                                      AVMetadataObjectTypeAztecCode,
                                      AVMetadataObjectTypeQRCode,
                                      AVMetadataObjectTypePDF417Code, 
                                      AVMetadataObjectTypeEAN13Code,
                                      AVMetadataObjectTypeEAN8Code,
                                      AVMetadataObjectTypeCode128Code]
        
        ///常用的碼制有:PDF417二維條碼泌类、Datamatrix二維條碼癞谒、QR Code、Code 49刃榨、Code 16K弹砚、Code one等,
        ///除了這些常見(jiàn)的二維條碼之外枢希,還有Vericode條碼迅栅、Maxicode條碼、CP條碼晴玖、Codablock F條碼、 Ultracode條碼及Aztec條碼为流。
        
        
        
        ///start grab
        session.startRunning()
   
    }

3呕屎、從相冊(cè)中讀取二維碼

主要用到的是CIDetector檢測(cè)器類(lèi),然后獲取feature對(duì)象敬察。


/***********照片讀取**************/
    
    func openAlbum(){//相冊(cè)
        
        if(UIImagePickerController.isSourceTypeAvailable(UIImagePickerControllerSourceType.PhotoLibrary)){
        
            ///1.初始化相冊(cè)拾取器
            let pikController = UIImagePickerController()
            ///2.設(shè)置代理
            pikController.delegate = self//兩個(gè)代理
            //3.設(shè)置資源:
            /**
            UIImagePickerControllerSourceTypePhotoLibrary,相冊(cè)
            UIImagePickerControllerSourceTypeCamera,相機(jī)
            UIImagePickerControllerSourceTypeSavedPhotosAlbum,照片庫(kù)
            */
            pikController.sourceType = UIImagePickerControllerSourceType.SavedPhotosAlbum
            //4.隨便給他一個(gè)轉(zhuǎn)場(chǎng)動(dòng)畫(huà)
            pikController.modalTransitionStyle = UIModalTransitionStyle.FlipHorizontal
            self.presentViewController(pikController, animated: true, completion: nil)
            
        }else{
            
            let alertVC = UIAlertController(title: "提示", message: "設(shè)備不支持訪問(wèn)相冊(cè)秀睛,請(qǐng)?jiān)谠O(shè)置->隱私->照片中進(jìn)行設(shè)置!", preferredStyle: UIAlertControllerStyle.Alert)
            let action = UIAlertAction(title: "OK", style: .Cancel, handler: nil)
            alertVC.addAction(action)
            
            self.presentViewController(alertVC, animated: true, completion: nil)
        
        }
        
    }
    
    ///imagePickerControllerdelegate func
    func imagePickerController(picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : AnyObject]) {
        ///1.獲取選擇的圖片
        let image = info[UIImagePickerControllerOriginalImage]
        ///2.初始化一個(gè)監(jiān)測(cè)器
        let detector = CIDetector(ofType: CIDetectorTypeQRCode, context: nil, options: [ CIDetectorAccuracy : CIDetectorAccuracyHigh ])
        picker.dismissViewControllerAnimated(true) { () -> Void in
            ///監(jiān)測(cè)到的結(jié)果數(shù)組
            let features = detector.featuresInImage(CIImage(CGImage: (image?.CGImage)!))
            
            if features.count >= 1 {
                /**結(jié)果對(duì)象 */
                ///CIQRCodeFeature
                let feature = features[0] as! CIQRCodeFeature
                let scannedResult = feature.messageString
                
                let alertVC = UIAlertController(title: "提示", message: scannedResult, preferredStyle: UIAlertControllerStyle.Alert)
                self.presentViewController(alertVC, animated: true, completion: nil)

            }else {
                let alertVC = UIAlertController(title: "提示", message: "該圖片沒(méi)有包含一個(gè)二維碼莲祸!", preferredStyle: UIAlertControllerStyle.Alert)
                let action = UIAlertAction(title: "OK", style: .Cancel, handler: nil)
                alertVC.addAction(action)
                
                self.presentViewController(alertVC, animated: true, completion: nil)
            }
        }
    }
    

4蹂安、生成二維碼

生成二維碼處理過(guò)程有點(diǎn)復(fù)雜,首先要導(dǎo)入CoreImage锐帜,然后用CIFilter生成圖片田盈,nameCIQRCodeGenerator就是二維碼濾鏡,CICode128BarcodeGenerator就是條形碼濾鏡缴阎,當(dāng)然還有很多濾鏡允瞧,如下面會(huì)用到的顏色濾鏡nameCIFalseColor

4.1蛮拔、原生二維碼的生成

 /***********生成二維碼圖片**************/ ///coreImage
    
    func createQRCodeImage(withImage image: UIImage, string: String) -> UIImage {
        
        /// 1. 實(shí)例化二維碼濾鏡
        let filter = CIFilter(name: "CIQRCodeGenerator")///CICode128BarcodeGenerator ///條形碼
        ///注意
        
        /// 2. 恢復(fù)濾鏡的默認(rèn)屬性
        filter?.setDefaults()
        
        /// 3. 將字符串轉(zhuǎn)換成二進(jìn)制數(shù)據(jù)述暂,(生成二維碼所需的數(shù)據(jù))
        let data = string.dataUsingEncoding(NSUTF8StringEncoding)
        
        /// 4. 通過(guò)KVO把二進(jìn)制數(shù)據(jù)添加到濾鏡inputMessage中
        filter?.setValue(data, forKey: "inputMessage")
        filter?.setValue("H", forKey: "inputCorrectionLevel")
        
        /// 5. 獲得濾鏡輸出的圖像
        let outputImage = filter?.outputImage ///CIImage
        
        /// 6. 將CIImage轉(zhuǎn)換成UIImage,并放大顯示
        //let originQRCodeImage = UIImage(CIImage: outputImage!, scale: 0.07, orientation: UIImageOrientation.Up) ///原生二維碼圖片 ///這樣將圖片放大會(huì)變得模糊
        //return originQRCodeImage
        
        ///進(jìn)行重繪
        let newQRCodeImage = createUIimageWithCGImage(ciImage: outputImage!, widthAndHeightValue: 300)
        
        return newQRCodeImage
    }

如果你直接用這行代碼返回圖片

let originQRCodeImage = UIImage(CIImage: outputImage!, scale: 0.07, orientation: UIImageOrientation.Up) ///原生二維碼圖片 ///這樣將圖片放大會(huì)變得模糊
return originQRCodeImage

得到的圖片將會(huì)很模糊建炫,因?yàn)檫@是將圖片進(jìn)行放大了畦韭,但圖片將0.07改為了1,看到的圖片將會(huì)很小肛跌。

所以還得處理一下:

func createUIimageWithCGImage(ciImage image: CIImage, widthAndHeightValue wh: CGFloat) -> UIImage {
        let ciRect = CGRectIntegral(image.extent)///根據(jù)容器得到適合的尺寸
        let scale = min(wh / ciRect.width, wh / ciRect.height)
        
        ///獲取bitmap
        
        let width  = size_t(ciRect.width * scale)
        let height  = size_t(ciRect.height * scale)
        let cs = CGColorSpaceCreateDeviceGray()///灰度顏色通道 ///CGColorSpaceRef
        
        let info_UInt32 = CGImageAlphaInfo.None.rawValue
        let bitmapRef = CGBitmapContextCreate(nil, width, height, 8, 0, cs, info_UInt32)
        
        let contex = CIContext(options: nil)
        let bitmapImageRef = contex.createCGImage(image, fromRect: CGRectMake(ciRect.origin.x, ciRect.origin.y, ciRect.size.width, ciRect.size.height)) ///CGImageRef
        
        CGContextSetInterpolationQuality(bitmapRef, CGInterpolationQuality.High)///寫(xiě)入質(zhì)量高艺配,時(shí)間長(zhǎng)
        CGContextScaleCTM(bitmapRef, scale, scale) ///調(diào)整“畫(huà)布”的縮放
        CGContextDrawImage(bitmapRef, ciRect, bitmapImageRef) ///繪制圖片
        
        ///保存
        let scaledImage = CGBitmapContextCreateImage(bitmapRef)
        
        ///bitmapRef和bitmapImageRef不用主動(dòng)釋放察郁,Core Foundation自動(dòng)管理
        
        //let originImage = UIImage(CGImage: scaledImage!) ///原生灰度圖片(灰色)
        
        let ciImage = CIImage(CGImage: scaledImage!)
        
        ///添加濾鏡
        let colorFilter = CIFilter(name: "CIFalseColor")///顏色濾鏡
        colorFilter!.setDefaults()
        colorFilter!.setValue(ciImage, forKey:kCIInputImageKey)
        
        colorFilter!.setValue(CIColor(red: 33.0 / 225.0, green: 192.0 / 225.0, blue: 174.0 / 225.0, alpha: 1.0), forKey:"inputColor0")///二維碼元素(像素)
        colorFilter!.setValue(CIColor(red: 1.0, green: 1.0, blue: 1.0, alpha: 1), forKey:"inputColor1")///背景
        
        let colorImgae = colorFilter!.outputImage
        let newQRCodeImage = UIImage(CIImage: colorImgae!)
        
        return newQRCodeImage
        
    }

這樣將會(huì)得到彩色的二維碼,效果也還不錯(cuò)妒挎,這里又添加colorFilter這樣濾鏡绳锅,達(dá)到著色的效果。iOS其實(shí)可以混合多個(gè)濾鏡來(lái)實(shí)現(xiàn)很多不能的效果酝掩,手機(jī)自帶的圖片處理就是基于濾鏡來(lái)完成鳞芙,如果你有使用過(guò)PS,或了解過(guò)知識(shí)期虾,這就很容易理解了原朝。如果去掉這部分代碼得到的將會(huì)是灰色的圖片。

其實(shí)重新著色镶苞,還可以通過(guò)喳坠,context來(lái)重繪或者通過(guò)改變每個(gè)像素的的顏色值來(lái)達(dá)到目的,但是難度會(huì)遠(yuǎn)比添加一個(gè)濾鏡要復(fù)雜的多茂蚓,而且壕鹉,Swift中通過(guò)指針來(lái)處理數(shù)據(jù),寫(xiě)法將會(huì)更加復(fù)雜聋涨,這是因?yàn)镾wift是一門(mén)語(yǔ)法安全性語(yǔ)言晾浴。也沒(méi)有*P這樣的寫(xiě)法。

關(guān)于CIFilter的更多知識(shí)牍白,我就會(huì)在后續(xù)文章中分享脊凰,你們也可以通過(guò)資料去學(xué)習(xí),總之茂腥,這部分知識(shí)還是很容易理解的狸涌,也比較有趣。

更新的CIFilter文章:點(diǎn)擊這里 會(huì)教你獲取更清晰的二維碼最岗。

最后帕胆,想了解更多詳情:請(qǐng)查看我的demo,記得給個(gè)Star仑性,??????

下載:點(diǎn)擊這里

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末惶楼,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子诊杆,更是在濱河造成了極大的恐慌歼捐,老刑警劉巖,帶你破解...
    沈念sama閱讀 206,311評(píng)論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件晨汹,死亡現(xiàn)場(chǎng)離奇詭異豹储,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)淘这,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,339評(píng)論 2 382
  • 文/潘曉璐 我一進(jìn)店門(mén)剥扣,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)巩剖,“玉大人,你說(shuō)我怎么就攤上這事钠怯〖涯В” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 152,671評(píng)論 0 342
  • 文/不壞的土叔 我叫張陵晦炊,是天一觀的道長(zhǎng)鞠鲜。 經(jīng)常有香客問(wèn)我,道長(zhǎng)断国,這世上最難降的妖魔是什么贤姆? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 55,252評(píng)論 1 279
  • 正文 為了忘掉前任,我火速辦了婚禮稳衬,結(jié)果婚禮上霞捡,老公的妹妹穿的比我還像新娘。我一直安慰自己薄疚,他們只是感情好碧信,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,253評(píng)論 5 371
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著街夭,像睡著了一般音婶。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上莱坎,一...
    開(kāi)封第一講書(shū)人閱讀 49,031評(píng)論 1 285
  • 那天,我揣著相機(jī)與錄音寸士,去河邊找鬼檐什。 笑死,一個(gè)胖子當(dāng)著我的面吹牛弱卡,可吹牛的內(nèi)容都是我干的乃正。 我是一名探鬼主播,決...
    沈念sama閱讀 38,340評(píng)論 3 399
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼婶博,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼瓮具!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起凡人,我...
    開(kāi)封第一講書(shū)人閱讀 36,973評(píng)論 0 259
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤名党,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后挠轴,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體传睹,經(jīng)...
    沈念sama閱讀 43,466評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 35,937評(píng)論 2 323
  • 正文 我和宋清朗相戀三年岸晦,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了欧啤。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片睛藻。...
    茶點(diǎn)故事閱讀 38,039評(píng)論 1 333
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖邢隧,靈堂內(nèi)的尸體忽然破棺而出店印,到底是詐尸還是另有隱情,我是刑警寧澤倒慧,帶...
    沈念sama閱讀 33,701評(píng)論 4 323
  • 正文 年R本政府宣布按摘,位于F島的核電站,受9級(jí)特大地震影響迫靖,放射性物質(zhì)發(fā)生泄漏院峡。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,254評(píng)論 3 307
  • 文/蒙蒙 一系宜、第九天 我趴在偏房一處隱蔽的房頂上張望照激。 院中可真熱鬧,春花似錦盹牧、人聲如沸俩垃。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 30,259評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)口柳。三九已至,卻和暖如春有滑,著一層夾襖步出監(jiān)牢的瞬間跃闹,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 31,485評(píng)論 1 262
  • 我被黑心中介騙來(lái)泰國(guó)打工毛好, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留望艺,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 45,497評(píng)論 2 354
  • 正文 我出身青樓肌访,卻偏偏與公主長(zhǎng)得像找默,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子吼驶,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,786評(píng)論 2 345

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