How to adjust luminosity / contrast properly ?
category: code [glöplog]
Adjusting luminosity and contrast of an image is particularly helpful in demos/intros, especially for procedural graphics.
The most obvious way coming to my mind :
Take the following picture :
If I apply algorithm I get this :
Ugh. What is wrong there ? The bright pixels are now even more white and image looks "burned".
If I take a look at histogram, all pixels have been shift to the right, and most of them are now stuck at max value.
To do that, I applied luminosity/contrast with photoshop, with checking "Legacy mode" option. This use same technique as code explained above.
If I apply adjustement in PS, using exactly same settings but without that "Legacy mode" (so what is done by default) I get this :
Which is A LOT better.
My question is : what kind of algorithm does photoshop (or most other tools) use to apply luminosity and contrast to the image ?
In case of PS, this is probably something protected by a patents, but a better approach than what i described here (which is horrible) or something that is very close to PS would be very helpful.
The most obvious way coming to my mind :
Code:
color.rgb = clamp(color.rgb + luminosity, 0.0, 1.0);
color.rgb = clamp(0.5 + (color.rgb - 0.5) * contrast, 0.0, 1.0);
Take the following picture :
If I apply algorithm I get this :
Ugh. What is wrong there ? The bright pixels are now even more white and image looks "burned".
If I take a look at histogram, all pixels have been shift to the right, and most of them are now stuck at max value.
To do that, I applied luminosity/contrast with photoshop, with checking "Legacy mode" option. This use same technique as code explained above.
If I apply adjustement in PS, using exactly same settings but without that "Legacy mode" (so what is done by default) I get this :
Which is A LOT better.
My question is : what kind of algorithm does photoshop (or most other tools) use to apply luminosity and contrast to the image ?
In case of PS, this is probably something protected by a patents, but a better approach than what i described here (which is horrible) or something that is very close to PS would be very helpful.
By the looks of it, it's prolly compresses the range instead of just clipping it, kinda like a soft limiter. Instead of clamp, try some function that converges to 1.0 instead of just clipping.
This is the result of simply mapping the color (in the range 0..1) to sin(color * (PI/2)):
Doesn't look all that bad and adding an exponent for the sine would let you have some control over the end result.
Doesn't look all that bad and adding an exponent for the sine would let you have some control over the end result.
pow(sin(color * (PI/2), 1.3) yields a practically identical result to the PS image above.
Tigrou: I would expect the legacy vs non-legacy modes to mostly be about gamma-correction.
I don't really know anything about this stuff, but wouldn't you do at least luminosity adjustments on non-gamma corrected values, like:
linear.rgb = pow(color.rgb, 1.0/gamma);
linear.rgb = linear.rgb + luminosity;
color.rgb = clamp(pow(color.rgb, gamma), 0.0, 1.0);
linear.rgb = pow(color.rgb, 1.0/gamma);
linear.rgb = linear.rgb + luminosity;
color.rgb = clamp(pow(color.rgb, gamma), 0.0, 1.0);
Some simple functions i use for this kind of stuff (these will go out of 0..1 range so clamp if you need to):
that's from memory, and may be wrong :)
Code:
// brightness (0 = no brightness, 1 = normal, >1 = brighter
colour *= brightness;
// contrast (0 = flat grey, 1 = normal, >1 = higher contrast
colour = (colour - 0.5) * contrast + 0.5;
// gamma (1 = normal, <1 = brighter, >1 = darker
colour = pow(colour, gamma);
// saturation (0 = b+w, 1 = normal, >1 = high saturation)
float luminance = (colour.r + colour.g + colour.b) / 3.;
colour = (colour - luminance) * saturation + luminance;
that's from memory, and may be wrong :)
The problem with those gammas is that they brighten the dark colors, too, which was - apparently - not desired.
What chock said! Except SRGB gamma encoding is a bit more cumbersome than a pow, but DX/GL can do that for you.
Hi it's me again. I tried some of algorithms on the page (thank you for this). Most the of time it gives better results that just adding/multiplying but still far from what i'm looking for.
I believe PS algorithm is something really other than that. For example if i took picture and lower considerably the brightness here is what i get (no contrast have been added):
Bright points are still there. It almost looks like bumpmapping :)
Algorithm seems to be : the more the point is bright , the less you adjust it (so dark get a lot darker, and light points get slightly darker).
I believe PS algorithm is something really other than that. For example if i took picture and lower considerably the brightness here is what i get (no contrast have been added):
Bright points are still there. It almost looks like bumpmapping :)
Algorithm seems to be : the more the point is bright , the less you adjust it (so dark get a lot darker, and light points get slightly darker).
That's really looking like Gamma. Sure you tried it correctly?