如何在Swift中通过降分辨率缩小PNG图片大小(保留透明)
实现思路
核心是迭代缩小图片尺寸,每次生成PNG数据后检查文件大小,直到满足≤500KB的要求。PNG是无损格式,调整尺寸是最直接且不丢失透明度的压缩方式,步骤如下:
- 先判断原图PNG数据是否已符合大小要求,符合则直接返回
- 若不符合,逐步按比例缩小图片
- 每次缩小后生成PNG数据并检查大小,直到达标或达到最小缩放阈值
Swift 实现代码
import UIKit extension UIImage { /// 将PNG图片缩小到指定KB以内,保留透明度(仅调整尺寸,不修改PNG编码压缩率) /// - Parameters: /// - targetKB: 目标文件大小(KB),默认500 /// - allowedMargin: 允许的误差范围,默认20%(即最多可到500*1.2=600KB) /// - Returns: 符合要求的PNG数据,失败则返回空Data func resizeToFitPNG(targetKB: Int = 500, allowedMargin: CGFloat = 0.2) -> Data { let targetBytes = targetKB * 1024 let maxAllowedBytes = Int(CGFloat(targetBytes) * (1 + allowedMargin)) // 先检查原图是否已经符合要求 if let originalData = self.pngData(), originalData.count <= maxAllowedBytes { return originalData } var currentImage = self var scale: CGFloat = 0.9 // 初始缩小比例 let scaleStep: CGFloat = 0.1 // 每次缩小的步长,可按需调整 // 最小缩到原图的10%,避免过度失真 while scale > 0.1 { guard let resizedImage = currentImage.resized(withPercentage: scale, isOpaque: false) else { break } if let pngData = resizedImage.pngData() { if pngData.count <= maxAllowedBytes { return pngData } } currentImage = resizedImage scale -= scaleStep } // 返回最后一次缩小后的PNG数据(或空) return currentImage.pngData() ?? Data() } // 按比例缩小图片,isOpaque设为false以保留透明度 func resized(withPercentage percentage: CGFloat, isOpaque: Bool = true) -> UIImage? { guard percentage > 0, percentage <= 1 else { return nil } let canvasSize = CGSize(width: size.width * percentage, height: size.height * percentage) let format = imageRendererFormat format.opaque = isOpaque return UIGraphicsImageRenderer(size: canvasSize, format: format).image { context in self.draw(in: CGRect(origin: .zero, size: canvasSize)) } } }
代码说明
- 透明度保留:调用
resized方法时传入isOpaque: false,确保渲染后的图片保留Alpha通道 - 迭代逻辑:从原图90%开始逐步缩小,每次递减10%,可根据需求调整
scaleStep(比如改成0.05实现更精细的缩放) - 边界处理:先校验原图大小避免无效操作,设置最小缩放比例防止图片过度失真
使用示例
// 假设你有一个UIImage实例 if let originalImage = UIImage(named: "your_png_image") { let compressedPNGData = originalImage.resizeToFitPNG(targetKB: 500) print("压缩后大小:\(compressedPNGData.count / 1024) KB") // 此处可将compressedPNGData用于上传或本地存储 }
内容的提问来源于stack exchange,提问作者erotsppa
相关产品推荐
相关产品推荐

