如何通过降低分辨率在 Swift 中减小 png 图像的文件大小

问题描述 投票:0回答:1

我正在寻找通过调整图像大小而不是进一步压缩来减小 PNG 文件的文件大小的方法。

这里有很多示例代码通过将 UIImage 转换为 JPEG 来压缩 UIImage

像这样

如何调整 UIImage 的大小以减小上传图片的大小

extension UIImage {
    func resized(withPercentage percentage: CGFloat, isOpaque: Bool = true) -> UIImage? {
        let canvas = CGSize(width: size.width * percentage, height: size.height * percentage)
        let format = imageRendererFormat
        format.opaque = isOpaque
        return UIGraphicsImageRenderer(size: canvas, format: format).image {
            _ in draw(in: CGRect(origin: .zero, size: canvas))
        }
    }
    func resized(toWidth width: CGFloat, isOpaque: Bool = true) -> UIImage? {
        let canvas = CGSize(width: width, height: CGFloat(ceil(width/size.width * size.height)))
        let format = imageRendererFormat
        format.opaque = isOpaque
        return UIGraphicsImageRenderer(size: canvas, format: format).image {
            _ in draw(in: CGRect(origin: .zero, size: canvas))
        }
    }
}

此代码允许您选择一个尺寸来调整图像大小,但它不允许您控制文件大小。

这里是一个缩小到特定大小的例子,但是因为它使用 JPEG 数据,所以失去了透明度 在上传到 Parse as PFFile 之前如何压缩或减小图像的大小? (斯威夫特)

extension UIImage {
    func resized(withPercentage percentage: CGFloat, isOpaque: Bool = true) -> UIImage? {
        let canvas = CGSize(width: size.width * percentage, height: size.height * percentage)
        let format = imageRendererFormat
        format.opaque = isOpaque
        return UIGraphicsImageRenderer(size: canvas, format: format).image {
            _ in draw(in: CGRect(origin: .zero, size: canvas))
        }
    }

    func compress(to kb: Int, allowedMargin: CGFloat = 0.2) -> Data {
        let bytes = kb * 1024
        var compression: CGFloat = 1.0
        let step: CGFloat = 0.05
        var holderImage = self
        var complete = false
        while(!complete) {
            if let data = holderImage.jpegData(compressionQuality: 1.0) {
                let ratio = data.count / bytes
                if data.count < Int(CGFloat(bytes) * (1 + allowedMargin)) {
                    complete = true
                    return data
                } else {
                    let multiplier:CGFloat = CGFloat((ratio / 5) + 1)
                    compression -= (step * multiplier)
                }
            }
            
            guard let newImage = holderImage.resized(withPercentage: compression) else { break }
            holderImage = newImage
        }
        return Data()
    }
}

我拥有的是 png 图像,其中我保留了透明度,同时将文件大小保持在 500k 以下(硬限制 - 因为服务器限制它)

我怎样才能快速做到这一点?

swift core-graphics
1个回答
0
投票

你可以像那样对你的图像进行下采样

extension UIImage {
    var asSmallImage: UIImage? {
        let sourceOptions = [kCGImageSourceShouldCache: false] as CFDictionary
        
        guard let cgImage = self.cgImage else { return nil }
        
        guard let imgData = cgImage.isPNG ? self.pngData() : self.jpegData(compressionQuality: 0.75) else { return nil }
        
        guard let source = CGImageSourceCreateWithData(imgData as CFData, sourceOptions) else { return nil }
        
        let downsampleOptions = [
            kCGImageSourceCreateThumbnailFromImageAlways: true,
            kCGImageSourceCreateThumbnailWithTransform: true,
            kCGImageSourceThumbnailMaxPixelSize: 1_000,
        ] as CFDictionary

        guard let cgImage = CGImageSourceCreateThumbnailAtIndex(source, 0, downsampleOptions) else { return nil }

        let data = NSMutableData()
        guard let imageDestination = CGImageDestinationCreateWithData(data, kUTTypeJPEG, 1, nil) else { return nil }

        // Don't compress PNGs, they're too pretty
        let destinationProperties = [kCGImageDestinationLossyCompressionQuality: cgImage.isPNG ? 1.0 : 0.75] as CFDictionary
        CGImageDestinationAddImage(imageDestination, cgImage, destinationProperties)
        CGImageDestinationFinalize(imageDestination)

        let image = UIImage(data: data as Data)
        return image
    }
}

在这里您可以修改 kCGImageSourceThumbnailMaxPixelSize 属性来调整图像大小。

信用:我跟着它

© www.soinside.com 2019 - 2024. All rights reserved.