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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.19 04:26:05