仅供参考
struct QrCode {
/// 创建带图标、颜色、圆角和边框的二维码图片
///
/// - Parameters:
/// - qrString: 二维码中需要编码的字符串内容
/// - icon: 可选的中心图标图片(用于品牌 logo、头像等)
/// - iconSizeRatio: 图标在二维码中所占比例(默认 0.25,表示 25% 宽度)
/// - iconCornerRadius: 图标圆角比例(默认 0,无圆角;如 0.2 表示圆角为宽度的 20%)
/// - iconBorderWidth: 图标边框宽度(默认 0,无边框)
/// - iconBorderColor: 图标边框颜色(默认白色)
/// - foregroundColor: 二维码前景色(默认黑色)
/// - backgroundColor: 二维码背景色(默认白色)
/// - Returns: 合成后的二维码图像,如果失败返回 nil
static func createQRForString(qrString: String?,
icon: UIImage? = nil,
iconSizeRatio: CGFloat = 0.25,
iconCornerRadius: CGFloat = 0,
iconBorderWidth: CGFloat = 0,
iconBorderColor: UIColor = .white,
foregroundColor: UIColor = .black,
backgroundColor: UIColor = .white) -> UIImage? {
// 安全校验字符串和转换为 UTF-8 编码的数据
guard let qrString = qrString,
let stringData = qrString.data(using: .utf8, allowLossyConversion: false),
let qrFilter = CIFilter(name: "CIQRCodeGenerator") else {
return nil
}
// 配置二维码生成器:设置输入字符串和容错级别(H:最高级,30%)
qrFilter.setValue(stringData, forKey: "inputMessage")
qrFilter.setValue("H", forKey: "inputCorrectionLevel")
// 获取生成的二维码原始图像(CIImage)
guard let qrCIImage = qrFilter.outputImage else {
return nil
}
// 使用“CIFalseColor”滤镜设置二维码颜色(前景色和背景色)
guard let colorFilter = CIFilter(name: "CIFalseColor") else {
return nil
}
colorFilter.setDefaults()
colorFilter.setValue(qrCIImage, forKey: "inputImage")
colorFilter.setValue(CIColor(color: foregroundColor), forKey: "inputColor0") // 前景色(二维码本体)
colorFilter.setValue(CIColor(color: backgroundColor), forKey: "inputColor1") // 背景色
// 获取带颜色的二维码图像
guard let outputImage = colorFilter.outputImage else {
return nil
}
// 使用仿射变换将二维码放大,避免模糊(默认 scale 10 倍)
let scaleX: CGFloat = 10
let qrCIImageScaled = outputImage.transformed(by: CGAffineTransform(scaleX: scaleX, y: scaleX))
let qrUIImage = UIImage(ciImage: qrCIImageScaled)
// 如果没有图标,直接返回二维码图像
guard let icon = icon else {
return qrUIImage
}
// 准备图标尺寸(占二维码整体尺寸的比例)
let qrSize = qrUIImage.size
let iconSize = CGSize(width: qrSize.width * iconSizeRatio,
height: qrSize.height * iconSizeRatio)
// 开始绘图上下文,准备将二维码与图标合成
UIGraphicsBeginImageContextWithOptions(qrSize, false, 0.0)
// 绘制二维码背景图
qrUIImage.draw(in: CGRect(origin: .zero, size: qrSize))
// 计算图标绘制位置(居中)
let iconX = (qrSize.width - iconSize.width) / 2
let iconY = (qrSize.height - iconSize.height) / 2
let iconRect = CGRect(x: iconX, y: iconY, width: iconSize.width, height: iconSize.height)
// 绘制圆角图标,并裁剪路径
let path = UIBezierPath(roundedRect: iconRect, cornerRadius: iconSize.width * iconCornerRadius)
path.addClip() // 剪裁成圆角路径
// 在路径中绘制图标
icon.draw(in: iconRect)
// 如果需要边框,绘制边框(可设颜色和宽度)
if iconBorderWidth > 0 {
iconBorderColor.setStroke()
path.lineWidth = iconBorderWidth
path.stroke()
}
// 从上下文获取合成后的图像
let finalImage = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
return finalImage
}
}