美文网首页Mac开发云集iOS之MAC端开发Mac OSX开发
macOS实现二维码图片生成及识别

macOS实现二维码图片生成及识别

作者: Supremodeamor | 来源:发表于2018-05-09 17:13 被阅读13次

    参考:

    网上世界,QRCode无处不在,生成和识别QRCode的功能在macOS项目开发中也很常见(比如识别桌面二维码及拖拽二维码图片到窗口自动识别这样的需求),本文是简单的实现方法。
    如果需要调用mac摄像头进行扫描二维码,可以使用ZXingObjC

    效果图

    思路

    1. 利用Core Image的二维码滤镜生成CIImage, CIImage可以与 NSImageUIImage互相转化,达成生成二维码图片的目的;
    2. Core Image为我们提供了CIDetector类,可以帮我们读取二维码信息。

    代码

    1. 生成二维码图片
    /// 生成原始二维码
        ///
        /// - Parameter message: 二维码信息
        /// - Returns: 二维码图片 CIImage
        private func generateOriginQRImage(message: String) -> CIImage? {
            let messageData = message.data(using: .utf8)
            // 创建二维码滤镜
            let qrCIFilter = CIFilter(name: "CIQRCodeGenerator")
            guard qrCIFilter != nil else {
                fatalError("QRCIFilter is nil")
            }
            qrCIFilter!.setValue(messageData, forKey: "inputMessage")
            //L7% M15% Q25% H%30% 纠错级别. 默认值是M
            qrCIFilter!.setValue("H", forKey: "inputCorrectionLevel")
            
            return qrCIFilter!.outputImage
        }
    
    1. 优化二维码图片

    步骤1中的方法生成的图片是模糊的(跟加了个模糊滤镜似的),需要根据你需要的尺寸进行放大,CIFalseColor滤镜则可以调整图片背景色和前景色。为了满足设置logo图的需求,我添加了图片合并的代码。
    另外由于CIImage无法直接转成NSImage,我借助CGImage类型做了一下桥梁。

        /// 创建二维码图片
        ///
        /// - Parameters:
        ///   - message: 二维码信息 String
        ///   - size: 生成图片的大小
        ///   - backgroundColor: 图片背景色
        ///   - foregroundColor: 二维码颜色
        ///   - fillImage: 修饰图片(logo图之类的)
        /// - Returns: 二维码图片 NSImage
        func createQRImage(message: String, size: NSSize = NSSize(width: 200, height: 200), backgroundColor: CIColor = .white, foregroundColor: CIColor = .black, fillImage: NSImage? = nil) -> NSImage? {
            guard let originImage = generateOriginQRImage(message: message) else {
                fatalError("failed to generate a QRImage")
            }
            
            let colorFilter = CIFilter(name: "CIFalseColor")
            //输入图片
            colorFilter!.setValue(originImage, forKey: "inputImage")
            //输入颜色
            colorFilter!.setValue(foregroundColor, forKey: "inputColor0")
            colorFilter!.setValue(backgroundColor, forKey: "inputColor1")
            
            guard let colorImage = colorFilter?.outputImage?.transformed(by: CGAffineTransform(scaleX: size.width/originImage.extent.width, y: size.height/originImage.extent.height)) else {
                fatalError("failed to generate the colorImage")
            }
            
            let image = NSImage(cgImage: convertCIImageToCGImage(inputImage: colorImage)!, size: size)
            
            if let fillImage = fillImage {
                let fillRect = CGRect(x: (size.width - size.width/4)/2, y: (size.height - size.height/4)/2, width: size.width/4, height: size.height/4)
                image.lockFocus()
                fillImage.draw(in: fillRect)
                image.unlockFocus()
            }
            
            return image
        }
    
        /// CIImage转成CGImage
        ///
        /// - Parameter inputImage: CIImage
        /// - Returns: CGImage
        private func convertCIImageToCGImage(inputImage: CIImage) -> CGImage? {
            let context = CIContext(options: nil)
            if let cgImage = context.createCGImage(inputImage, from: inputImage.extent) {
                return cgImage
            }
            return nil
        }
    
    1. 识别二维码图片
      在macOS项目中需要将NSImage转成CIImage, 然后使用CIDetector类进行二维码的检测识别和信息读取。
        /// 识别二维码
        ///
        /// - Parameter targetImage: 目标图片
        /// - Returns: 二维码信息字符串
        func recognizeQRCode(targetImage: NSImage) -> String? {
            
            let imageData = targetImage.tiffRepresentation(using: .none, factor: 0)
            let ciImage = CIImage(data: imageData!)
            /*创建探测器 options 是字典key:
             CIDetectorAccuracy 精度
             CIDetectorTracking 轨迹
             CIDetectorMinFeatureSize 最小特征尺寸
             CIDetectorNumberOfAngles 角度**/
            let detector = CIDetector(ofType: CIDetectorTypeQRCode, context: CIContext(), options: [CIDetectorAccuracy:CIDetectorAccuracyHigh])
            
            let featers = detector?.features(in: ciImage!) as? [CIQRCodeFeature]
            return featers?.last?.messageString
        }
    

    Demo下载地址:Demo

    相关文章

      网友评论

        本文标题:macOS实现二维码图片生成及识别

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