Search code examples
iosalgebra

Map 0-1 values exponentially to a list of shutter speeds


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.


Solution

  • 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.