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

Swift中如何更高效地从UIImage生成固定大小的JPEG?

优化Swift中JPEG图片压缩效率的方法

你的问题我太懂了——线性递减压缩比的方式确实会做很多无用功,尤其是当图片一开始就远大于200KB的时候,要反复压缩好多次。其实我们可以利用二分查找法来快速定位合适的压缩比,因为JPEG的压缩比和生成的文件大小基本是单调相关的,这样能把压缩次数从最多9次(0.1到1每次减0.1)降到最多10次左右(二分的精度足够高),效率提升明显。

下面是具体的实现代码,逻辑很清晰:

func compressImageToTargetSize(_ image: UIImage, targetSize: Int) -> Data? {
    // 定义压缩比的上下边界,避免无限循环或过低质量
    var low: CGFloat = 0.1
    var high: CGFloat = 1.0
    var bestData: Data?
    
    // 最多循环10次,二分查找的精度已经足够(2^10=1024,精度到0.001左右)
    for _ in 0..<10 {
        let midRatio = (low + high) / 2
        guard let data = image.jpegData(compressionQuality: midRatio) else {
            continue
        }
        
        if data.count <= targetSize {
            // 当前压缩比满足要求,尝试更高的压缩比(获得更好的画质)
            bestData = data
            low = midRatio
        } else {
            // 当前压缩比生成的文件太大,降低压缩比
            high = midRatio
        }
    }
    
    // 如果循环结束还没找到合适的,就用最低压缩比再试一次
    if bestData == nil {
        bestData = image.jpegData(compressionQuality: 0.1)
    }
    
    return bestData
}

// 使用示例:把你的edited图片压缩到200KB以内
if let compressedData = compressImageToTargetSize(edited, targetSize: 200 * 1024) {
    // 处理压缩后的data
}

代码说明:

  • 二分查找的核心是每次取当前范围的中间值作为压缩比,根据生成的文件大小调整范围:如果满足大小要求,就尝试更高的压缩比(保留更好的画质);如果太大,就降低压缩比。
  • 限制循环次数到10次是因为再多次循环带来的精度提升已经微乎其微,完全满足实际需求。
  • 最后做了兜底处理,确保即使最低压缩比还是超大小,也能返回一个结果。

这种方法相比你的原代码,能大幅减少压缩的次数,尤其是对于大图片来说,效率提升非常明显~

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.27 09:30:12