Author Topic: [SOLVED] Make underexposed zebra point, user adjustable  (Read 4822 times)

Audionut

  • Global Moderator
  • Hero Member
  • *****
  • Posts: 3657
  • Blunt and to the point
[SOLVED] Make underexposed zebra point, user adjustable
« on: May 16, 2014, 06:39:51 PM »
The relevant line of code.

zebra.c
Code: [Select]
int underexposed = ev_to_raw(- (raw_info.dynamic_range - 100) / 100.0);
I can change the code and produce wanted results (for myself), but I don't understand the maths, to make this a user adjustable feature, with accurate code.

Ideally, I would like options ranging from -6 EV through -11 EV, representing the EV from saturation.  And add some transparency, so that we can see the detail behind the zebras, and also represent the original SNR=1 EV shadow point with opaque zebras.

I am stuck on exactly what ev_to_raw is doing.  I assume it is converting the EV to raw, but I don't understand the maths for this conversion.

Code: [Select]
int FAST ev_to_raw(float ev)
{
    int raw_max = MIN(raw_info.white_level, 16383) - raw_info.black_level;
    return raw_info.black_level + powf(2, ev) * raw_max;
}

raw_max, I understand.  Minimum white level value, of either the reported white level, or 16383, minus black level.

But powf, is well above my comprehension level.  And if I place the maths into wolfram, like so.

Code: [Select]
2048 + powf(2, 11) * 15000
I get no useful result.


The next problem, I don't understand how raw_info.dynamic_range is being calculated.

Code: [Select]
raw_info.dynamic_range = compute_dynamic_range(black_mean, black_stdev_x100, raw_info.white_level)
There are 3 values in the brackets, but I don't understand what is being done with 3 values separated by commas.

edit:  If I understand correctly, it is simply an EV?

Code: [Select]
static int compute_dynamic_range(int black_mean, int black_stdev_x100, int white_level)
{
    /**
     * A = full well capacity / read-out noise
     * DR in dB = 20 log10(A)
     * DR in stops = dB / 6 = log2(A)
     * I guess noise level is the RMS value, which is identical to stdev
     *
     * This is quite close to DxO measurements (within +/- 0.5 EV),
     * except at very high ISOs where there seems to be noise reduction applied to raw data
     */

#ifdef RAW_DEBUG_DR
    int mean = black_mean * 100;
    int stdev = black_stdev_x100;
    bmp_printf(FONT_MED, 50, 100, "mean=%d.%02d stdev=%d.%02d white=%d", mean/100, mean%100, stdev/100, stdev%100, white_level);
    white_level = autodetect_white_level(15000);
#endif

    int dr = (int)roundf((log2f(white_level - black_mean) - log2f(black_stdev_x100 / 100.0)) * 100);

#ifdef RAW_DEBUG_DR
    bmp_printf(FONT_MED, 50, 120, "=> dr=%d.%02d", dr/100, dr%100);
#endif

    /* dual ISO enabled? */
    dr += dual_iso_get_dr_improvement();

    return dr;
}

dmilligan

  • Developer
  • Hero Member
  • *****
  • Posts: 3218
  • 60Da / 1100D / EOSM
Re: Make underexposed zebra point, user adjustable
« Reply #1 on: May 16, 2014, 07:13:17 PM »
Code: [Select]
2048 + powf(2, 11) * 15000
just type "2048 + 2^11 * 15000" into google

(btw that should be -11)

dmilligan

  • Developer
  • Hero Member
  • *****
  • Posts: 3218
  • 60Da / 1100D / EOSM
Re: Make underexposed zebra point, user adjustable
« Reply #2 on: May 16, 2014, 07:15:58 PM »
really, I just want to be able to turn it off, but +1 for this request anyway :)

Audionut

  • Global Moderator
  • Hero Member
  • *****
  • Posts: 3657
  • Blunt and to the point
Re: Make underexposed zebra point, user adjustable
« Reply #3 on: May 16, 2014, 07:26:59 PM »
Looks like I need to add an off switch.  Thanks.

dmilligan

  • Developer
  • Hero Member
  • *****
  • Posts: 3218
  • 60Da / 1100D / EOSM
Re: Make underexposed zebra point, user adjustable
« Reply #4 on: May 16, 2014, 07:36:14 PM »
I think raw_info.dynamic_range is 'fixed point' in units of 100 (so it can be an integer), so like raw_info.dynamic_range = 100 => 1EV, so that explains the "- (raw_info.dynamic_range - 100) / 100.0" part. So we're basically doing ev_to_raw(-(DR - 1ev)). ev_to_raw is simply computing: BL + 2ev * (WL - BL)

So if we give it -(DR - 1ev) that should give us the raw value corresponding to 1ev above the bottom of the dynamic range. If you wanted to make it 2ev above the bottom then it would be: "ev_to_raw(- (raw_info.dynamic_range - 200) / 100.0)".

Someone feel free to correct me if I have this wrong

Audionut

  • Global Moderator
  • Hero Member
  • *****
  • Posts: 3657
  • Blunt and to the point
Re: Make underexposed zebra point, user adjustable
« Reply #5 on: May 29, 2014, 06:01:35 PM »
One quirk I have discovered by changing the value you describe "ev_to_raw(- (raw_info.dynamic_range - 200) / 100.0)", the ETTR reading in the histogram gets borked.  Only noticed while making the raw based exposure feedback tutorial.
I cannot recall if this happened when changing the last value in that bracket, probably, but I'll double check.

Don't expect this function from me soon, I still need to work out how to make this a user variable.