Swift 4 Binary Approach to compress image
I believe it is quite late to answer this question but here is my solution to the question which is optimized I am using Binary search to find the optimal value. So, for example, say by normal subtraction approach to reach 62% would require 38 compression attempts, the *Binary search** approach would reach the required solution in max log(100) = around 7 attempts.
However, would also like to inform you that the UIImageJPEGRepresentation
function does not behave linearly especially when the number reaches near 1. Here is the screen grab where we can see that the image stops compressing after the float value is > 0.995. The behaviour is quite unpredictable so better to have a delta buffer that would handle such cases.

Here is the code for it
extension UIImage {
func resizeToApprox(sizeInMB: Double, deltaInMB: Double = 0.2) -> Data {
let allowedSizeInBytes = Int(sizeInMB * 1024 * 1024)
let deltaInBytes = Int(deltaInMB * 1024 * 1024)
let fullResImage = UIImageJPEGRepresentation(self, 1.0)
if (fullResImage?.count)! < Int(deltaInBytes + allowedSizeInBytes) {
return fullResImage!
}
var i = 0
var left:CGFloat = 0.0, right: CGFloat = 1.0
var mid = (left + right) / 2.0
var newResImage = UIImageJPEGRepresentation(self, mid)
while (true) {
i += 1
if (i > 13) {
print("Compression ran too many times ") // ideally max should be 7 times as log(base 2) 100 = 6.6
break
}
print("mid = \(mid)")
if ((newResImage?.count)! < (allowedSizeInBytes - deltaInBytes)) {
left = mid
} else if ((newResImage?.count)! > (allowedSizeInBytes + deltaInBytes)) {
right = mid
} else {
print("loop ran \(i) times")
return newResImage!
}
mid = (left + right) / 2.0
newResImage = UIImageJPEGRepresentation(self, mid)
}
return UIImageJPEGRepresentation(self, 0.5)!
}
}