創(chuàng)建帶圖標、顏色、圓角和邊框的二維碼圖片

僅供參考

struct QrCode {
    
    /// 創(chuàng)建帶圖標、顏色、圓角和邊框的二維碼圖片
    ///
    /// - Parameters:
    ///   - qrString: 需要編碼的字符串內(nèi)容
    ///   - icon: 可選的中心圖標(如品牌 logo、頭像)
    ///   - iconSizeRatio: 圖標相對二維碼寬度的比例,默認 0.25
    ///   - iconCornerRadius: 圖標圓角比例(0~1,0 表示無圓角)
    ///   - iconBorderWidth: 圖標邊框?qū)挾?,默認 0
    ///   - iconBorderColor: 圖標邊框顏色,默認白色
    ///   - foregroundColor: 二維碼前景色(二維碼本體顏色)
    ///   - backgroundColor: 二維碼背景色
    ///   - scale: 放大倍數(shù),避免二維碼模糊,默認 10
    /// - Returns: 最終生成的二維碼 UIImage,失敗返回 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,
        scale: CGFloat = 10
    ) -> UIImage? {
        
        // MARK: 1. 基礎(chǔ)安全校驗
        guard let qrString = qrString,
              !qrString.isEmpty,
              let stringData = qrString.data(using: .utf8, allowLossyConversion: false),
              let qrFilter = CIFilter(name: "CIQRCodeGenerator") else {
            return nil
        }
        
        // MARK: 2. 配置二維碼生成器(inputMessage: 字符串,inputCorrectionLevel: 容錯率)
        qrFilter.setValue(stringData, forKey: "inputMessage")
        qrFilter.setValue("H", forKey: "inputCorrectionLevel") // H 表示最高容錯率 30%
        
        // 獲取二維碼 CIImage
        guard let qrCIImage = qrFilter.outputImage else { return nil }
        
        // MARK: 3. 設(shè)置二維碼顏色(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 coloredQRImage = colorFilter.outputImage else { return nil }
        
        // MARK: 4. 使用仿射變換放大二維碼,避免縮放時模糊
        let transformedQR = coloredQRImage.transformed(by: CGAffineTransform(scaleX: scale, y: scale))
        
        // MARK: 5. 使用 CIContext 柵格化 CIImage → CGImage
        let context = CIContext()
        guard let cgImage = context.createCGImage(transformedQR, from: transformedQR.extent) else { return nil }
        
        // 生成最終二維碼 UIImage
        let qrUIImage = UIImage(cgImage: cgImage, scale: UIScreen.main.scale, orientation: .up)
        
        // 如果不需要添加中心圖標,直接返回二維碼
        guard let icon = icon else { return qrUIImage }
        
        // MARK: 6. 計算中心圖標尺寸與位置
        let qrSize = qrUIImage.size
        let validIconRatio = min(max(iconSizeRatio, 0.0), 1.0) // 確保 0~1
        let iconSize = CGSize(width: qrSize.width * validIconRatio,
                              height: qrSize.height * validIconRatio)
        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)
        
        // MARK: 7. 繪制二維碼與圖標合成
        UIGraphicsBeginImageContextWithOptions(qrSize, false, 0.0)
        
        // 繪制二維碼背景圖
        qrUIImage.draw(in: CGRect(origin: .zero, size: qrSize))
        
        // 繪制圖標圓角路徑
        let cornerRadius = iconSize.width * max(0, min(iconCornerRadius, 1))
        let path = UIBezierPath(roundedRect: iconRect, cornerRadius: cornerRadius)
        path.addClip() // 將繪圖上下文裁剪為圓角
        
        // 繪制圖標
        icon.draw(in: iconRect)
        
        // 如果有邊框,則繪制邊框
        if iconBorderWidth > 0 {
            iconBorderColor.setStroke()
            path.lineWidth = iconBorderWidth
            path.stroke()
        }
        
        // 獲取最終圖像
        let finalImage = UIGraphicsGetImageFromCurrentImageContext()
        UIGraphicsEndImageContext()
        
        return finalImage
    }
}


最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容