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
相关产品推荐
相关产品推荐

