Swift中如何通过CGContext压缩PDF大小?图片转PDF后体积过大
解决UIImage转PDF体积过大的问题
你当前的代码直接将原始CGImage绘制到PDF中,未对图像做压缩处理——原始图片文件虽小,但CGImage在内存中是未压缩的位图数据,写入PDF时会保留这种高体积的原始数据,导致PDF体积暴涨。以下是两种可行的压缩方案:
方案一:先压缩图片再生成PDF
先将UIImage转成带压缩的JPEG数据,再基于压缩后的图片生成PDF,能大幅降低体积:
// 图片压缩工具函数 func compressImage(_ image: UIImage, quality: CGFloat = 0.5) -> UIImage? { guard let imageData = image.jpegData(compressionQuality: quality) else { return nil } return UIImage(data: imageData) } // 修改后的PDF生成函数 func createPDF(image: UIImage, compressionQuality: CGFloat = 0.5) -> NSData? { guard let compressedImage = compressImage(image, quality: compressionQuality) else { return nil } let pdfData = NSMutableData() let pdfConsumer = CGDataConsumer(data: pdfData as CFMutableData)! var mediaBox = CGRect(x: 0, y: 0, width: compressedImage.size.width, height: compressedImage.size.height) let pdfContext = CGContext(consumer: pdfConsumer, mediaBox: &mediaBox, nil)! pdfContext.beginPage(mediaBox: &mediaBox) if let cgImage = compressedImage.cgImage { pdfContext.draw(cgImage, in: mediaBox) } pdfContext.endPage() return pdfData }
compressionQuality参数范围0-1,值越小压缩率越高,可根据画质需求调整。- 若图片含透明通道,JPEG压缩会丢失透明效果,此时可改用PNG格式(将
jpegData替换为pngData(),但PNG是无损压缩,需配合缩小图片尺寸进一步降体积)。
方案二:直接在PDF生成时设置压缩参数
通过CGContext的初始化参数,指定图像压缩规则,无需提前压缩图片:
import MobileCoreServices // 需要导入这个框架来使用UTType常量 func createCompressedPDF(image: UIImage) -> NSData? { let pdfData = NSMutableData() let pdfConsumer = CGDataConsumer(data: pdfData as CFMutableData)! var mediaBox = CGRect(x: 0, y: 0, width: image.size.width, height: image.size.height) // 设置PDF图像压缩参数:JPEG格式,质量0.5 let pdfOptions: [CFString: Any] = [ kCGImageDestinationLossyCompressionQuality: 0.5, kCGImageDestinationType: kUTTypeJPEG ] let pdfContext = CGContext(consumer: pdfConsumer, mediaBox: &mediaBox, pdfOptions as CFDictionary)! pdfContext.beginPage(mediaBox: &mediaBox) if let cgImage = image.cgImage { pdfContext.draw(cgImage, in: mediaBox) } pdfContext.endPage() return pdfData }
这种方式让PDF在写入图像时自动应用压缩,逻辑更简洁,同样可通过调整kCGImageDestinationLossyCompressionQuality控制画质与体积的平衡。
内容的提问来源于stack exchange,提问作者Nishant Chandwani
相关产品推荐
相关产品推荐

