You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Swift中用PDFKit写入图片到PDF出现模糊,如何优化?

问题:PDF中生成的QR码模糊

我通过以下Swift代码生成包含QR码的PDF,但绘制出的QR码非常模糊。尝试过调整PDF渲染器边界和绘制尺寸,问题仍未解决。核心代码如下:

import Foundation
import PDFKit
import SwiftUI

struct PDFPreviewView  : View {
    @State private var showShareSheet : Bool = false
    
    var pdfData: Data? {
        LabelPDFCreator().pdfData()
    }
    
    var body: some View {
        VStack {
            PdfViewUI(data: pdfData)
        }
        .navigationTitle(Text("Your Labels"))
        .navigationBarTitleDisplayMode(.inline)
        .sheet(isPresented: $showShareSheet, content: {
            if let data = pdfData {
                ShareView(activityItems: [data])
            }
        })
        .toolbar {
            Button {
                self.showShareSheet.toggle()
            } label: {
                Label("Options", systemImage: "square.and.arrow.up")
            }
        }
    }
}

struct PdfViewUI : UIViewRepresentable {

    private var data: Data?
    
    private let autoScales : Bool
    
    init(data : Data?, autoScales : Bool = true ) {
        self.data = data
        self.autoScales = autoScales
    }

    func makeUIView(context: Context) -> PDFView {
        let pdfView = PDFView()

        pdfView.autoScales =  self.autoScales
       
        if let data = self.data {
            pdfView.document = PDFDocument(data: data)
        }
        
        return pdfView
    }

    func updateUIView(_ uiView: PDFView, context: Context) {
        // Empty
    }
}

class LabelPDFCreator : NSObject {
    static let DPI = 72.0
    
    private var pageRect : CGRect
    private var renderer : UIGraphicsPDFRenderer?
    
    let context = CIContext()
    let filter = CIFilter.qrCodeGenerator()

    override init() {
        let format = UIGraphicsPDFRendererFormat()
        
        let pageRect = CGRect(x: 0, y: 0, width: (8.5 * LabelPDFCreator.DPI), height: (11.0 * LabelPDFCreator.DPI))
        self.pageRect = pageRect
        self.renderer = UIGraphicsPDFRenderer(bounds: self.pageRect,
                                             format: format)
        super.init()
    }
    
    func pdfData() -> Data? {
        if let renderer = self.renderer {
            let data = renderer.pdfData { ctx in
                ctx.beginPage()

                let image = generateQRCode(from: UUID().uuidString)
                let imageWidthHeight = 1.0 * LabelPDFCreator.DPI
                                    
                image.draw(in: CGRect(x: LabelPDFCreator.DPI, y : LabelPDFCreator.DPI, width: imageWidthHeight, height: imageWidthHeight))
            }
            return data
        }
        return nil
    }
    
    func generateQRCode(from id: String) -> UIImage {
        filter.message = Data(id.utf8)
        
        if let outputImage = filter.outputImage {
            if let cgImage = context.createCGImage(outputImage, from: outputImage.extent) {
                return UIImage(cgImage: cgImage)
            }
        }
        
        return UIImage(systemName: "xmark.circle") ?? UIImage()
    }
}
解决方案:提升QR码分辨率与PDF渲染精度

QR码模糊的核心原因是原始生成的QR码尺寸过小,放大后丢失细节;其次PDF的渲染DPI设置偏低,不足以支撑清晰的打印/显示效果。可以通过以下两点修改解决:

1. 生成高分辨率QR码

默认CIFilter.qrCodeGenerator()生成的QR码尺寸极小(通常仅23x23像素),直接拉伸绘制会导致模糊。需要对生成的CIImage进行缩放,提升原始分辨率:

修改generateQRCode(from:)方法:

func generateQRCode(from id: String) -> UIImage {
    filter.message = Data(id.utf8)
    filter.errorCorrectionLevel = "H" // 可选:提升QR码容错率,同时让图案更密集清晰
    
    guard let outputImage = filter.outputImage else {
        return UIImage(systemName: "xmark.circle") ?? UIImage()
    }
    
    // 按4倍比例缩放原始QR码,生成高分辨率图片(数值可按需调整,越大越清晰)
    let scale: CGFloat = 4.0
    let scaledImage = outputImage.transformed(by: CGAffineTransform(scaleX: scale, y: scale))
    
    guard let cgImage = context.createCGImage(scaledImage, from: scaledImage.extent) else {
        return UIImage(systemName: "xmark.circle") ?? UIImage()
    }
    
    return UIImage(cgImage: cgImage)
}

2. 提升PDF的DPI设置

默认72DPI是屏幕显示的标准,若用于打印或高清显示,建议将DPI调整为300(印刷行业标准),让PDF页面拥有足够多的像素点承载清晰的QR码:

修改LabelPDFCreator中的DPI常量:

static let DPI = 300.0

修改后效果

调整后,QR码的原始分辨率大幅提升,PDF页面的像素密度也足够支撑清晰显示/打印,模糊问题即可解决。

内容的提问来源于stack exchange,提问作者jonbirke0927

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.18 08:48:11