美文网首页
二维码的扫描,识别相册二维码以及制作

二维码的扫描,识别相册二维码以及制作

作者: U小姐咯 | 来源:发表于2016-08-16 16:31 被阅读523次

1⃣️二维码的扫描

扫描.png
🍓二维码的扫描模块,都会有个扫描的动画,首先我们将动画做出来,如何布局(创建了DimensionViewController和对应的storyboard),对于实现重复扫描动画很关键.首先我们在弹出扫描页面放入一个view,约束固定大小以及垂直和水平的约束;接下来是在view放入二维码扫描的边框图片qrcode_border,按住command键选中view和边框,设置他们上下左右的距离都为0;最后我们放上冲击波的图片wave,设置它与view的约束关系为左,上右的距离为0,同时设置他们等高.接下来我们需要把✨view的高度codeHeight,wave的top的约束codeScanTop, view的横向约束viewCenterY✨拖线成为对应的属性.
private func startAnimate() {
        //设置冲击波底部和视图底部对齐
        codeScanTop.constant = -codeHeight.constant
        view.layoutIfNeeded()
        UIView.animateWithDuration(2.0) {
          //设置动画重复无数次
            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()
        //默认值为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
    }()
    //预览图层
    private lazy var previewLayer : AVCaptureVideoPreviewLayer = {
        return AVCaptureVideoPreviewLayer(session :self.session)
    }()
 //专门用于描边的图层
    private lazy var lineLayer : CALayer = CALayer()
 //MARK:内部控制方法,扫描二维码
    private func startCode(){
        //判断输入能否添加到对话
        if !session.canAddInput(input) {
            DMLog("输入没有添加")
            return
        }
        //判断输出能否添加到会话中
        if !session.canAddOutput(output) {
            DMLog("输出没有添加")
            return
        }
        //添加输入和输出会话中
        session.addInput(input)
        session.addOutput(output)
        //设置输出能够解析的数据类型
        //设置数据类型一定要在输出对象添加到会话之后才能设置
        output.metadataObjectTypes = output.availableMetadataObjectTypes
        //设置监听输出解析到的数据
        output.setMetadataObjectsDelegate(self, queue: dispatch_get_main_queue())
        //添加预览图预览图层
        view.layer.insertSublayer(previewLayer, atIndex: 0)
        previewLayer.frame = view.bounds
        //视图上加载的是二维码的描边
        view.layer.addSublayer(lineLayer)
        lineLayer.frame = view.bounds
        //开始扫描
        session.startRunning()
    }

接下来还需要执行相对应的代理方法,对扫描的消息进行相应的处理,还有扫描到二维码我们需要进行相应的描边,这样可以定位到扫描的二维码,即使当你手机是成角度扫描的时候,依旧可以扫描出形状(比如四边形),这里用贝塞尔曲线画图

extension DimensionViewController:AVCaptureMetadataOutputObjectsDelegate{
 func captureOutput(captureOutput: AVCaptureOutput!, didOutputMetadataObjects metadataObjects: [AnyObject]!, fromConnection connection: AVCaptureConnection!){
        //只要扫描到就会调用
        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 },是二维码边线的四个点
        //转换后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
        }
        //创建图层,用于保存绘制的矩形
        let layer = CAShapeLayer()
        layer.lineWidth = 3
        layer.strokeColor = UIColor.orangeColor().CGColor
        layer.fillColor = UIColor.clearColor().CGColor //填充颜色
        //创建UIBezierPat,绘制矩形,
        //let path = UIBezierPath.init(rect: CGRect(x: 100,y: 100,width: 220,height: 220))
        //贝塞尔曲线:将点移动到某一点;连接其他点,关闭路径
        var point : CGPoint = CGPointZero
        var index = 0
        //把数组字典中的xy转化为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(){
        //清除扫描二维码出现多个图层
        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{
    //实现该代理方法,选中一张图片时系统不会自动关闭
    func imagePickerController(picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : AnyObject]){
        guard let image = info["UIImagePickerControllerOriginalImage"] as? UIImage else{
            return
        }
        let cimage = CIImage(image:image)
        //创建一个探测器
        let detector = CIDetector(ofType: CIDetectorTypeQRCode,context: nil,options: [CIDetectorAccuracy : CIDetectorAccuracyHigh]) //最后一个参数是扫描的精确度
        let result = detector.featuresInImage(cimage!)
        //去除探测的数据
        for result in result{
            let codeInfo = (result as! CIQRCodeFeature).messageString
//这里的message是一个table,显示扫描到的信息的
            message.text = codeInfo
        }
        picker.dismissViewControllerAnimated(true, completion: nil)
    }
}

🍓制作二维码哦,可以填入自己预设的消息,比如"小敏萌萌哒"😄,这些代码都是非常固定,需要的时候复制粘贴下就可以了哦.

class CreatQrCodeViewController: UIViewController {

    @IBOutlet weak var qrCodeImage: UIImageView!
    override func viewDidLoad() {
        super.viewDidLoad()
        //创建滤镜
        let filter = CIFilter(name: "CIQRCodeGenerator")
        //还原默认属性
        filter?.setDefaults()
        //设置需要生成二维码的数据到滤镜中
        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.创建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)
    }
}

以上😄

相关文章

网友评论

      本文标题:二维码的扫描,识别相册二维码以及制作

      本文链接:https://www.haomeiwen.com/subject/iqupsttx.html