这儿每天分享一个 iOS 的新知识,快来重视我吧
前言
昨日的文章讲了二维码的生成办法,感兴趣能够先去看一下。
一个二维码通常会存储字符串内容,所以能够给 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)
设置自定义 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
加上 logo
和 logoSize
参数,贴一下终究代码:
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)
最终看下效果:
最终
向二维码增加 logo 之后会盖住一部分二维码,假如 logo 尺度过大,可能会导致无法正常识别。
假如你在运用过程中遇到这个问题,能够参阅下下边的解决办法,二维码生成的时分能够增加一个纠错等级,大概讲一讲:
CIQRCodeGenerator
过滤器支持以下两个参数:
-
inputMessage
: 一个Data
类型的值,代表要编码的数据。这是必须的参数,由于没有它,二维码就没有任何含义。 -
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 的新知识,快来重视我吧