60 lines
2.1 KiB
Swift
60 lines
2.1 KiB
Swift
//
|
||
// QRCodeGenerator.swift
|
||
// suixinkan
|
||
//
|
||
|
||
import CoreImage
|
||
import UIKit
|
||
|
||
/// 圆角样式二维码生成器,对齐 Android `QrCodeUtils.generateStyledQrBitmap`。
|
||
enum QRCodeGenerator {
|
||
|
||
private static let defaultPixelSize = 580
|
||
private static let defaultCornerRadius: CGFloat = 24
|
||
|
||
/// 根据内容生成带圆角背景的二维码图片。
|
||
static func generateStyledQRCode(
|
||
content: String,
|
||
pixelSize: Int = defaultPixelSize,
|
||
backgroundColor: UIColor = AppColor.inputBackground,
|
||
cornerRadius: CGFloat = defaultCornerRadius
|
||
) -> UIImage? {
|
||
guard !content.isEmpty,
|
||
let qrImage = makeQRCodeImage(from: content, pixelSize: pixelSize) else {
|
||
return nil
|
||
}
|
||
|
||
let size = CGSize(width: pixelSize, height: pixelSize)
|
||
let format = UIGraphicsImageRendererFormat()
|
||
format.scale = 1
|
||
let renderer = UIGraphicsImageRenderer(size: size, format: format)
|
||
return renderer.image { context in
|
||
let rect = CGRect(origin: .zero, size: size)
|
||
let path = UIBezierPath(roundedRect: rect, cornerRadius: cornerRadius)
|
||
backgroundColor.setFill()
|
||
path.fill()
|
||
|
||
context.cgContext.saveGState()
|
||
path.addClip()
|
||
qrImage.draw(in: rect)
|
||
context.cgContext.restoreGState()
|
||
}
|
||
}
|
||
|
||
private static func makeQRCodeImage(from content: String, pixelSize: Int) -> UIImage? {
|
||
guard let filter = CIFilter(name: "CIQRCodeGenerator") else { return nil }
|
||
let data = Data(content.utf8)
|
||
filter.setValue(data, forKey: "inputMessage")
|
||
filter.setValue("M", forKey: "inputCorrectionLevel")
|
||
guard let outputImage = filter.outputImage else { return nil }
|
||
|
||
let scale = CGFloat(pixelSize) / outputImage.extent.width
|
||
let scaledImage = outputImage.transformed(by: CGAffineTransform(scaleX: scale, y: scale))
|
||
let context = CIContext()
|
||
guard let cgImage = context.createCGImage(scaledImage, from: scaledImage.extent) else {
|
||
return nil
|
||
}
|
||
return UIImage(cgImage: cgImage)
|
||
}
|
||
}
|