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

