0

I am developing an image processing algorithm to adjust brightness, contrast, shadows, highlights, levels and gamma.

I'm having trouble modeling brightness to behave mostly linear (like the exposure adjustment) but compressing the highlights instead of saturating it.

This is the curve that I want: enter image description here

And this is the curve that I have in my current implementation. You can notice that it shifts from the linear line too early. I'd prefer a curve where it would happen in the highlights area: enter image description here

This is the code that I have right now:

fCnt += 1.0f; // fCnt->[-1,1]
fBri += 1.0f; // fBri->[-1,1]
fShd = (fShd/2.0f)*-0.6876f; // fShd -> [0,1]
fHlt /= 2.0f; // [0,1]
const float fRange = 1/(fWhite-fBlack); // fWhite, fBlack -> [0,1]
const float K = 1.0f/255;

float lut[256];
for(int i=0; i<256; ++i)
{
    float x = i*K; // map [0-255] uchar to [0-1] float
    // brightness 
    x = (1-pow(1-x, fBri));
    // contrast
    x = x <= 0.5f ? 0.5f*pow(x*2.0f, fCnt) : 1.0f - (0.5f*pow((1.0f - x)*2.0f, fCnt));
    // shadow
    x *= (qLn(x+0.0001f) * fShd + 1.0f);
    // highlights
    const float x2 = x*x;
    x *= (x <= 0.4 ? 1 : 1 + fHlt*(1.9434*x*x2 - 3.65455*x2 + 1.98107*x - 0.333037));
    // levels
    x = (x - fBlack) * fRange;
    // gamma [0,4]
    x = pow(min(0.0001f, x), fGamma);

    lut[i] = x;
}

for(int i=0; i<size; ++i)
    img[i] = clamp(img[i]*255.0f);
Adriel Jr
  • 2,451
  • 19
  • 25
  • 2
    This is a mathematics question rather than a programming question. – François Andrieux Mar 05 '18 at 15:50
  • 1
    @FrançoisAndrieux the question was given in a programming context and includes code. What more do you want? – Mark Ransom Mar 05 '18 at 17:08
  • @MarkRansom This question is purely mathematical. Perhaps it was presented in the concept of c++, but that's irrelevant with regard to my earlier comment. An answer (such as the one you posted) could be written using only mathematical concepts. Strictly speaking, the subject matter has nothing to do with computers, software or programming. It would be more appropriate (and would likely get a better response) at https://math.stackexchange.com/ – François Andrieux Mar 05 '18 at 18:29

1 Answers1

2

You can use a Bezier curve to get any arbitrary shape you want.

I obtained this picture from https://www.desmos.com/calculator/cahqdxeshd

enter image description here

Mark Ransom
  • 299,747
  • 42
  • 398
  • 622
  • Great idea! I was able to get something very close to what I wanted using Quadratic Bézier curve instead of Cubic. Thanks! – Adriel Jr Mar 05 '18 at 18:59