I am attempting to a UISlider with a min value of 0 and a max value of 1 to control the exposure of a camera with a minimum shutter speed of 1/2 second and max shutter speed of 1/8192.
Here is the list of shutter values the user will see:
[2, 4, 8, 12, 16, 30, 40, 50, 64, 96, 128, 192, 240, 384, 480, 768, 1024, 1536, 2048, 4096, 8192]
(all being fractions of a second.)
The problem is, these values can't be mapped linearly. The difference in exposure is the same 1/2 to 1/4 as it is from 1/4096 to 1/8192. If it was mapped linearly, 0.5 would equate to roughly 4094, so a one step in shutter difference would take up half of the slider.
I am looking to map the values exponentially instead. 0.5 should roughly equal 128, .25 should equal 16, .75 should equal 6000.
func getShutterValue(sliderValue: Double) -> Int {
return Int(pow(2,Double(1+Int(sliderValue*12))))
}
print(getShutterValue(0)) // 2
print(getShutterValue(0.25)) // 16
print(getShutterValue(0.4992)) // 64
print(getShutterValue(0.5)) // 128
print(getShutterValue(0.75)) // 1024
print(getShutterValue(1)) // 8192
As asked in comments below: if you want to return shutter values in a continuous span [2.0, 8192.0], you can use the following modified getShutterValue(..)
function:
func getShutterValue(sliderValue: Double) -> Double {
return pow(2, 1+sliderValue*12)
}
print(getShutterValue(0)) // 2.0
print(getShutterValue(0.25)) // 16.0
print(getShutterValue(0.33)) // 31.12....
print(getShutterValue(0.4992)) // 127.15....
print(getShutterValue(0.5)) // 128.0
print(getShutterValue(0.75)) // 1024.0
print(getShutterValue(1)) // 8192.0
Note however that if you choose to use this approach, make sure to take care if you're planning to use the shutter values in some equatable comparison statement (==
), as floating point numbers have limited precision.