这儿每天分享一个 iOS 的新知识,快来重视我吧

前言

昨日的文章讲了二维码的生成办法,感兴趣能够先去看一下。

二维码 1: 怎么用 swift 生成二维码

一个二维码通常会存储字符串内容,所以能够给 String 创立一个扩展,以快捷运用:

extension String {
    func qrCodeImage(size: CGFloat) -> UIImage? {
        guard let filter = CIFilter(name: "CIQRCodeGenerator") else {
            return nil
        }
        let data = data(using: .utf8)
        filter.setValue(data, forKey: "inputMessage")
        guard let ciImage = filter.outputImage else {
            return nil
        }
        let scaleX = size / ciImage.extent.size.width
        let scaleY = size / ciImage.extent.size.height
        let transform = CGAffineTransform(scaleX: scaleX, y: scaleY)
        return UIImage(ciImage: ciImage.transformed(by: transform))
    }
}

那么运用的时分就很简略了:

let url = "http://weixin.qq.com/r/QR0qLvXE6D2UKbFNb0jF"
// 创立一个 200 x 200 的二维码
let imageView = UIImageView(image: url.qrCodeImage(size: 200))
view.addSubview(imageView)

今天来讲讲怎么自定义二维码的款式。

设置前景色和背景色

要设置前景色和背景色,首要用到 CIFalseColor 这个过滤器,简略原理是运用 CIFilter 创立一个名为 CIFalseColor 的过滤器,传入二维码图画和前景色 + 背景色,终究再从新的过滤器中生成新的图画:

extension String {
    /// 生成一个二维码
    /// - Parameters:
    ///   - size: 二维码的尺度
    ///   - foregroundColor: 二维码的前景色
    ///   - backgroundColor: 二维码的背景色
    /// - Returns: 终究生成的二维码图片
    func qrCodeImage(size: CGFloat,
                     foregroundColor: UIColor,
                     backgroundColor: UIColor) -> UIImage? {
        guard let filter = CIFilter(name: "CIQRCodeGenerator") else {
            return nil
        }
        let data = data(using: .utf8)
        filter.setValue(data, forKey: "inputMessage")
        let colorFilter = CIFilter(name: "CIFalseColor", parameters: [
            "inputImage": filter.outputImage as Any,
            "inputColor0": CIColor(color: foregroundColor),
            "inputColor1": CIColor(color: backgroundColor)
        ])
        guard let ciImage = colorFilter?.outputImage else {
            return nil
        }
        let scaleX = size / ciImage.extent.size.width
        let scaleY = size / ciImage.extent.size.height
        let transform = CGAffineTransform(scaleX: scaleX, y: scaleY)
        return UIImage(ciImage: ciImage.transformed(by: transform))
    }
}

然后咱们就能够生成一个带有自定义前景色和背景色的二维码了:

let url = "http://weixin.qq.com/r/QR0qLvXE6D2UKbFNb0jF"
// 创立一个 200 x 200 的二维码
let imageView = UIImageView(image: url.qrCodeImage(size: 200, foregroundColor: .red, backgroundColor: .blue))
view.addSubview(imageView)

二维码 2: 怎么用 swift 设置二维码的款式

设置自定义 logo

咱们常常见到二维码的中心会有个自定义 logo,那么怎么实现这个功能呢?实际上还是需要在 CIImage 上下功夫。

这次用到的是 CISourceOverCompositing,这个过滤器能够将两个图层兼并,为了运用方便,咱们给 CIImage 增加一个 addImage 的办法:

extension CIImage {
    /// 向 CIImage 中心增加一个图片
    /// - Parameters:
    ///   - image: 要增加的图片
    ///   - size: 图片尺度
    /// - Returns: 增加之后的图片
    func add(image: UIImage, size: CGFloat) -> CIImage? {
        guard let combinedFilter = CIFilter(name: "CISourceOverCompositing") else { return nil }
        guard let cgImage = image.cgImage else {
            return nil
        }
        let scaleX = size / image.size.width
        let scaleY = size / image.size.height
        let scaleTransform = CGAffineTransform(scaleX: scaleX, y: scaleY)
        let centerTransform = CGAffineTransform(translationX: extent.midX - (size / 2), y: extent.midY - (size / 2))
        combinedFilter.setValue(CIImage(cgImage: cgImage).transformed(by: scaleTransform).transformed(by: centerTransform), forKey: "inputImage")
        combinedFilter.setValue(self, forKey: "inputBackgroundImage")
        return combinedFilter.outputImage
    }
}

终究再给 qrCodeImage 加上 logologoSize 参数,贴一下终究代码:

extension String {
    /// 生成一个二维码
    /// - Parameters:
    ///   - size: 二维码的尺度
    ///   - foregroundColor: 二维码的前景色
    ///   - backgroundColor: 二维码的背景色
    ///   - logo: 要在二维码中心增加的 logo
    ///   - logoSize: logo 的尺度
    /// - Returns: 终究生成的二维码图片
    func qrCodeImage(size: CGFloat,
                     foregroundColor: UIColor,
                     backgroundColor: UIColor,
                     logo: UIImage,
                     logoSize: CGFloat) -> UIImage? {
        guard let filter = CIFilter(name: "CIQRCodeGenerator") else {
            return nil
        }
        let data = data(using: .utf8)
        filter.setValue(data, forKey: "inputMessage")
        let colorFilter = CIFilter(name: "CIFalseColor", parameters: [
            "inputImage": filter.outputImage as Any,
            "inputColor0": CIColor(color: foregroundColor),
            "inputColor1": CIColor(color: backgroundColor)
        ])
        guard let ciImage = colorFilter?.outputImage else {
            return nil
        }
        let scaleX = size / ciImage.extent.size.width
        let scaleY = size / ciImage.extent.size.height
        let transform = CGAffineTransform(scaleX: scaleX, y: scaleY)
        let newCIImage = ciImage.transformed(by: transform)
        guard let newImage = newCIImage.add(image: logo, size: logoSize) else {
            return nil
        }
        return UIImage(ciImage: newImage)
    }
}

这时分就能够运用这个办法往二维码上增加 logo 了:

let url = "http://weixin.qq.com/r/QR0qLvXE6D2UKbFNb0jF"
// 创立一个 200 x 200 的二维码
let qrImage = url.qrCodeImage(size: 200,
                              foregroundColor: .red,
                              backgroundColor: .blue,
                              logo: UIImage(named: "logo.png")!,
                              logoSize: 50)
let imageView = UIImageView(image: qrImage)
view.addSubview(imageView)

最终看下效果:

二维码 2: 怎么用 swift 设置二维码的款式

最终

向二维码增加 logo 之后会盖住一部分二维码,假如 logo 尺度过大,可能会导致无法正常识别。

假如你在运用过程中遇到这个问题,能够参阅下下边的解决办法,二维码生成的时分能够增加一个纠错等级,大概讲一讲:

CIQRCodeGenerator 过滤器支持以下两个参数:

  1. inputMessage: 一个 Data 类型的值,代表要编码的数据。这是必须的参数,由于没有它,二维码就没有任何含义。
  2. inputCorrectionLevel: 一个表明纠错等级的字符串。它能够是 “L”, “M”, “Q” 或 “H”。”L” 表明 7% 的代码字能够被修正。”M” 表明 15% 的代码字能够被修正。”Q” 表明 25% 的代码字能够被修正。”H” 表明 30% 的代码字能够被修正。这个参数是可选的,假如没有提供,那么将会运用默认等级 “M”。

例如:

let qrFilter = CIFilter(name: "CIQRCodeGenerator")
qrFilter?.setValue(data, forKey: "inputMessage") // 必须的参数
qrFilter?.setValue("Q", forKey: "inputCorrectionLevel") // 可选的参数

在这个例子中,咱们运用 “Q” 等级的纠错,这意味着即便二维码的 25% 被破坏,也仍然能够被成功读取。这在某些情况下可能会非常有用,例如当二维码可能会被部分遮挡或破坏,或者需要在二维码上增加 logo 时。

这儿每天分享一个 iOS 的新知识,快来重视我吧

本文同步自微信大众号 “iOS新知”,每天准时分享一个新知识,这儿仅仅同步,想要及时学到就来重视我吧!