I'm looking for ways to reduce the file size of a PNG file via an image resize, not further compression.
There is a lot of sample code here that compresses a UIImage by turning it into a JPEG.
Like this:
How do I resize the UIImage to reduce upload image size
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))
}
}
}
This code allows you to pick a dimension to resize the image but it doesn't let you control the file size.
Here is an example of resizing down to a specific size but because it uses JPEG data it loses the transparency: How to compress of reduce the size of an image before uploading to Parse as PFFile? (Swift)
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()
}
}
What I have is a PNG image where I have to preserve transparency while keeping the file size below 500k (hard limit - because the server limits it).
How can I do that in Swift?