swift - 原生二维码的生成于扫描已经图片识别

补充部分(扫描界面):

扫面界面的组成部分一般有扫描区域部分,蒙版涂层部分,以及扫面动画部分组成

/*扫描动画部分*/

import UIKit


private let MarginTop:CGFloat = 10


class ScanAnimationView: UIView {


    var lineImage:UIImageView!

    var timer:Timer!

    var addCut:Int!

    /*初始化方法*/

    override init(frame: CGRect) {

        super.init(frame: frame)

        self.backgroundColor = UIColor.clear

        self.lineImage = UIImageView.init(image: UIImage(named: "homeScanLine"))

        self.addSubview(self.lineImage)

        lineImage.frame = CGRect(x: 0, y: MarginTop, width: self.bounds.size.width, height: 10)

        

    }

    required init?(coder aDecoder: NSCoder) {

        super.init(coder: aDecoder)

    }

    

    override func draw(_ rect: CGRect) {

        self.drawScanView(rect)

    }

    

    /*绘制四个小角度*/

    func drawScanView(_ rect:CGRect) -> Void {

        let width:CGFloat = self.frame.size.width

        let height:CGFloat = self.frame.size.height

        let lineHeight:CGFloat = width / 15

        let lineWidth:CGFloat = width / 15

        

        let ctx:CGContext! = UIGraphicsGetCurrentContext();

        ctx.setStrokeColor(UIColor.green.cgColor)

        ctx.setLineWidth(3.5)

        /*左上角*/

        let leftTopPath:CGMutablePath = CGMutablePath.init()

        leftTopPath.move(to: CGPoint(x: 0, y: lineHeight))

        leftTopPath.addLine(to: CGPoint(x: 0, y: 0))

        leftTopPath.addLine(to: CGPoint(x: lineWidth, y: 0))

        ctx.addPath(leftTopPath)

        ctx.strokePath()

        

        /*右上角*/

        let rightTopPath:CGMutablePath = CGMutablePath.init()

        rightTopPath.move(to: CGPoint(x: width - lineWidth, y: 0))

        rightTopPath.addLine(to: CGPoint(x: width, y: 0))

        rightTopPath.addLine(to: CGPoint(x: width, y: lineHeight))

        ctx.addPath(rightTopPath)

        ctx.strokePath()

        

        /*右下脚*/

        let rightBottomPath:CGMutablePath = CGMutablePath.init()

        rightBottomPath.move(to: CGPoint(x: width, y: height - lineWidth))

        rightBottomPath.addLine(to: CGPoint(x: width, y: height))

        rightBottomPath.addLine(to: CGPoint(x: width - lineWidth, y: height))

        ctx.addPath(rightBottomPath)

        ctx.strokePath()

        

        /*左下角*/

        let leftBottomPath:CGMutablePath = CGMutablePath.init()

        leftBottomPath.move(to: CGPoint(x: lineWidth, y: height))

        leftBottomPath.addLine(to: CGPoint(x: 0, y: height))

        leftBottomPath.addLine(to: CGPoint(x: 0, y: height - lineHeight))

        ctx.addPath(leftBottomPath)

        ctx.strokePath()

    }

    func startAnimation() -> Void {

        if self.timer != nil{

            self.timer.invalidate()

        }

        self.timer = Timer.init(timeInterval: 0.01, repeats: true, block: { (time:Timer) in

            if self.lineImage.frame.origin.y > self.frame.size.height - MarginTop {

                self.addCut = -1

            } else if self.lineImage.frame.origin.y <= MarginTop {

                self.addCut = 1

            }

            self.lineImage.frame = CGRect(x: self.lineImage.frame.origin.x, y: self.lineImage.frame.origin.y + CGFloat(self.addCut), width: self.lineImage.frame.size.width, height: self.lineImage.frame.size.height)

        })

        RunLoop.main.add(self.timer, forMode: .defaultRunLoopMode)

    }

    func stopAnimation() -> Void {

        self.timer.invalidate()

    }

}

/*扫面区域于扫描容器部分*/

// 声明文件

@property (nonatomic,strong) UILabel *label;

- (instancetype)initMaskViewWithFrame:(CGRect)maskFrame

                        withScanFrame:(CGRect)scanFrame;

@end


// 实现文件

- (instancetype)initMaskViewWithFrame:(CGRect)maskFrame

                        withScanFrame:(CGRect)scanFrame

{

    self = [super initWithFrame:maskFrame];

    if (self) {

        self.backgroundColor = [UIColor colorWithRed:0 green:0 blue:0 alpha:0.5];

        UIBezierPath *maskPath = [UIBezierPath bezierPathWithRect:CGRectMake(0, 0, self.frame.size.width, self.frame.size.height)];

        

        [maskPath appendPath:[[UIBezierPath bezierPathWithRoundedRect:scanFrame cornerRadius:1] bezierPathByReversingPath]];

        CAShapeLayer *maskLayer = [[CAShapeLayer alloc] init];

        maskLayer.path = maskPath.CGPath;

        self.layer.mask = maskLayer;

    }

    

    return self;

}

二维码的扫描和识别部分:

所使用到的几个类:

1、AVCaptureDevice:

此类用于对摄像头设备的操作,用于获取摄像头设备

2、AVCaptureDeviceInput

此类用于连接摄像头视频捕捉操作

3、AVCaptureMetadataOutput

此类用于摄像头视频流输出操作

4、AVCaptureSession

此类事摄像头提供的对外使用基础硬件的接口类,用于输入输出流于摄像头的绑定操作

5、AVCaptureVideoPreviewLayer

预览视图展示


/*必须类实现(用于摄像头视频捕捉于输入输出)*/

lazy var device:AVCaptureDevice = {

        let dev:AVCaptureDevice! = AVCaptureDevice.default(for: AVMediaType.video)

        return dev

    }()

    

    lazy var input:AVCaptureDeviceInput = {

        let inp:AVCaptureDeviceInput = try! AVCaptureDeviceInput.init(device: self.device)

        return inp

    }()

    

    lazy var outPut:AVCaptureMetadataOutput = {

        let out:AVCaptureMetadataOutput = AVCaptureMetadataOutput.init()

        out.setMetadataObjectsDelegate(self, queue: DispatchQueue.main)

        return out

    }()

    

    lazy var session:AVCaptureSession = {

        let sess:AVCaptureSession = AVCaptureSession.init()

        return sess

    }()

    

    lazy var displayLayer:AVCaptureVideoPreviewLayer = {

        let MarginTop:CGFloat = self.getNavigationBarHeight() + self.getStatusBarHeight()

        let layer:AVCaptureVideoPreviewLayer = AVCaptureVideoPreviewLayer.init(session: self.session)

        layer.frame = CGRect(x: 0, y: MarginTop, width: self.view.frame.size.width, height: self.view.frame.size.height - MarginTop)

        layer.videoGravity = .resizeAspectFill

        return layer

    }()

/*扫面容器界面于动画界面*/

lazy var scanView:ScanAnimationView = {

        let view:ScanAnimationView = ScanAnimationView.init(frame: CGRect(x: self.view.center.x - self.view.frame.size.height/4,

                                                                          y: self.view.center.y-self.view.frame.size.height/4,

                                                                          width: self.view.frame.size.height/2,

                                                                          height: self.view.frame.size.height/2))

        return view

    }()

    

    lazy var maskView:QRMaskView = {

        let MarginTop:CGFloat = self.getNavigationBarHeight() + self.getStatusBarHeight()

        self.scanFrame = CGRect(x: self.scanView.frame.origin.x,

                                y: self.scanView.frame.origin.y - MarginTop,

                                width: self.scanView.frame.size.width,

                                height: self.scanView.frame.size.height)

        let view:QRMaskView = QRMaskView.init(maskViewWithFrame: CGRect(x: 0, y: MarginTop, width: self.view.frame.size.width, height: self.view.frame.size.height - MarginTop), withScanFrame: scanFrame)

        return view

    }()


/*扫面动画界面于扫描容器界面加入视图并开启扫描*/

self.view.addSubview(self.scanView)

self.view.addSubview(self.maskView)

self.scanView.startAnimation()

        /*开始扫描*/

if self.session.canAddInput(self.input) {

   self.session.addInput(self.input)

}

if self.session.canAddOutput(self.outPut) {

   self.session.addOutput(self.outPut)

  self.outPut.metadataObjectTypes = [.qr,.code39,.code128,.code39Mod43,.ean8,.code93]

        }

        self.view.layer.insertSublayer(self.displayLayer, at: 0)

        self.session.startRunning()


/*扫描结果

    扫描结果需要遵循于实现AVCaptureMetadataOutputObjectsDelegate代理方法

 */

/*扫描结果代理方法*/

    func metadataOutput(_ output: AVCaptureMetadataOutput, didOutput metadataObjects: [AVMetadataObject], from connection: AVCaptureConnection) {

        var stringValue:String?

        if metadataObjects.count > 0 {

            self.session.stopRunning()

            if let metadataObject = metadataObjects.first as? AVMetadataMachineReadableCodeObject{

                // 扫描结果

                stringValue = metadataObject.stringValue

                self.navigationController?.popViewController(animated: true)

            }

        }

    }


/*相册二维码识别*/

二维码图片识别采用的是图像识别中的一个简单功能

CIDetector *detector = [CIDetector detectorOfType:CIDetectorTypeQRCode context:nil options:@{ CIDetectorAccuracy : CIDetectorAccuracyHigh }];

     NSArray *features = [detector featuresInImage:[CIImage imageWithCGImage:image.CGImage]];

     if (features.count >=1)

     {

     CIQRCodeFeature *feature = [features objectAtIndex:0];

     NSString *scanResult = feature.messageString;

     

     NSLog(@"%@",scanResult);

     }

二维码的生成部分:

此部分我使用的是ZXing第三方进行二维码生成,以解决原生清晰度不符合的问题

func creatMyQRCode() -> Void {

        let writer:ZXMultiFormatWriter = ZXMultiFormatWriter.init()

        let result:ZXBitMatrix = try! writer.encode("textMyQRCode", format: kBarcodeFormatQRCode, width: Int32(ImageSize), height: Int32(ImageSize))

        let zxImage:ZXImage = ZXImage.init(matrix: result)

        self.imageView.image = UIImage(cgImage: zxImage.cgimage)

    }


二维码生成部分使用原生会出现清晰度问题,有哪位大神有较好的方法可以交流一下



猜你喜欢

转载自blog.csdn.net/die_word/article/details/80480177
今日推荐