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

如何在Swift中通过降分辨率缩小PNG图片大小(保留透明)

实现思路

核心是迭代缩小图片尺寸,每次生成PNG数据后检查文件大小,直到满足≤500KB的要求。PNG是无损格式,调整尺寸是最直接且不丢失透明度的压缩方式,步骤如下:

  1. 先判断原图PNG数据是否已符合大小要求,符合则直接返回
  2. 若不符合,逐步按比例缩小图片
  3. 每次缩小后生成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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.26 20:10:26