I am trying to shrink the size of an image using the code below after converting the UIImage to a compressed JPEG representation and back to a UIImage the UIImage file is still to large how can I shrink the file size of the UIImage?
func changeFileSize()->UIImage{
var needToCompress:Bool = true
var compressingValue:CGFloat = 1.0
let bcf = ByteCountFormatter()
while needToCompress && compressingValue > 0.0{
let data = image.jpegData(compressionQuality: compressingValue)!
if data.count < 1024 * 100{
needToCompress = false
image = UIImage(data: data)
bcf.allowedUnits = [.useKB] // optional: restricts the units to MB only
bcf.countStyle = .file
var newImage = UIImage(data: data)
let string = bcf.string(fromByteCount: Int64(newImage!.jpegData(compressionQuality: compressingValue)!.count))
print("Image Pixels: \(CGSize(width: newImage!.size.width*newImage!.scale, height: newImage!.size.height*newImage!.scale))")
print("final formatted result to be returned: \(string)")
print("New comrpession value: \(compressingValue)")
return UIImage(data: (newImage?.jpegData(compressionQuality: compressingValue))!)!
break
}
else{
compressingValue -= 0.1
bcf.allowedUnits = [.useKB] // optional: restricts the units to MB only
bcf.countStyle = .file
let string = bcf.string(fromByteCount: Int64(image.jpegData(compressionQuality: compressingValue)!.count))
print("formatted result: \(string)")
print("New comrpession value: \(compressingValue)")
}
}
bcf.allowedUnits = [.useKB] // optional: restricts the units to MB only
bcf.countStyle = .file
let string = bcf.string(fromByteCount: Int64(image.jpegData(compressionQuality: 1.0)!.count))
print("formatted result: \(string)")
compressionLabel.text = string
print("Image Pixels: \(CGSize(width: image.size.width*image.scale, height: image.size.height*image.scale))")
return image
}
The JPEG (or PNG) data just tells UIImage how to re-create the original image. Your code is good at reducing the size of the JPEG data, but that has no effect on the actual image UIKit will render from said JPEG data. Compressing the JPEG data is good for saving locally or sending to an API, but it won't help you save memory during runtime (which I assume is what you want).
Instead the process you may be looking for is down-sampling. Which will reduce the actual pixels contained in the image, instead of reducing the size of the JPEG representation like you are currently doing.
You can downsample by making a thumbnail like this:
Here's a quick test to show it working:
There is indeed a WWDC 2018 video that discusses much of these details, and shows how to solve the original problem. WWDC18 - Image and Graphics Best Practices. In fact, the code above is a modification of the code provided in the WWDC video. Cheers.