Photoshop color formula for brightness

I have figured out how to increase the “Value” of a color by using HSV, now I was looking to know if anyone knew what the formula photoshop uses for the operation increase brightness.

In photoshop there is an option to increase brightness: Image > Adjustments > Brightness/Contrast

here are the results of using brightness VS increasing value in HSV:

As you see the brightness operation is treating each shade of color in a different way while the value operation is increasing the value of each color at a flat rate, as such the result on the bottom produces more “washed with white” colors than when increasing brightness.

I wonder if anyone could point me in the direction of the formula that is being used here by photoshop when you increase the brightness of a color. I’m interested purely in math, I want to have an input RGB color and an “amount of brightness increase” and return an output RGB color back. ( For reference in the above image I increased the brightness by 150)

Thanks!

Keeping in mind that brightness is effectively a term of perception and not an actual property of color itself, there may be more than one way to skin that cat and it probably is not a single formula but rather it likely depends on what color-space you are working in. I can’t say for certain what formula(s) they use but more than likely they follow some kind of industry standard for each model. For example, here are some ways to calculate luminescence for an an RGB color in the sRGB color space. Relative luminance - WCAG WG

Look into contrast.

contrast I believe takes all the colours and then let’s you stretch or squeeze them to their contrast difference.

take an RGB for example, look at the lowest values and the highest values, and modify the values of all colour relative to any changes made to the highest and lowest values.

Brightness and contrast are not aspects of a color, but of the image as a whole. There are numerous ways to achieve this but most of the approaches tend to be naive while proper ones need to work with full image histograms and also take human perception into account. Even Photoshop’s B&C evolved drastically, and that’s why you have the ‘legacy’ checkbox (at least in CS6 which I use). The reason why this “legacy” algorithm is still there is because it was a really powerful tool to isolate or visualize color variance, exactly through naive B&C.

When we speak of individual colors, brightness is really, really, simple: you just push the mean of the RGB values up or down. This also means that individual RGB channels will start to clip the minimum or maximum when the offset is extreme, so you have to “clamp” the output. This will, however, make this operation irreversible.

Unlike Color32, Color struct doesn’t clamp the values on its own, I believe, but be careful because I don’t know how it behaves if a value is greater than 1. Certain parts of the API might consider such a color as HDR.

Also btw, there is no contrast with a single color. Contrast only works with a multitude of colors, and again, there are many ways to introduce it, most likely as a shader effect. Well unless you’re making a Photoshop-like application, then you need to process everything on the CPU.

1 Like

I tried using L from HSL and it is probably what they were using at least in cs5.1

Nope, the brightness and contrast dialog is its own thing. It has nothing to do with the individual colors, especially not HSL. However B&C is specifically an RGB effect only, and so if the color space isn’t RGB the colors are temporarily converted to RGB (via profile), the appropriate technique is applied, before being converted back again. Many of the photo/video effects in PS are exclusively RGB.

As I said, the legacy B&C works “naively” and you can very easily inspect what exactly it does if you turn on the Info palette and use the eye dropper to inspect the RGB values. Change the brightness and observe what happens to the colors. It literally applies the input offset to each of the channels, then clamps the result to prevent clipping.

The contrast is somewhat more involved, here are the two links explaining it more detail:
Brightness
Contrast

Photoshop never, NEVER, works with any of the colors in the HSL. It doesn’t have the HSL color space as a backing data model. HSL (or HSB as they call it) is only ever used in color pickers, because it’s more intuitive for the artists. The actual backing modes are Greyscale, RGB, Lab, CMYK, and Indexed (edit: Bitmap is Greyscale crunched to 2 bits, and I think Duotone and Multichannel are just variants of CMYK; both are used in the printing context anyway, with spot colors). Of these, Lab is the only one which has a bigger gamut than RGB (you obviously can’t experience this in practice, because our monitors are RGB anyway). There is also a 16-bit channel RGB (edit: and 32-bit), but this is intended for very specific uses in high-fidelity digital photography.

Finally, the modern (non-legacy) B&C behavior is much more complicated and much more aware of the actual image content, working in such away not to clip or “overburn” the image, which is actually extremely desirable when working with real photography, or else it becomes very easy to lose information, which is why a professional photographer would never touch the legacy B&C.

I am a technical artist and an ex-prepress guy. I look at all these from the point of data alone.

3 Likes

Here’s the extension method that does exactly what PS legacy brightness does

using UnityEngine;

static public class ColorExtensions {

  static public Color AdjustBrightness(this Color color, float value)
    => new Color(
      Mathf.Clamp01(color.r + value),
      Mathf.Clamp01(color.g + value),
      Mathf.Clamp01(color.b + value),
      color.a
    );

}

That’s all there is to it.

myColor.AdjustBrightness(-.05f); // darkens
myColor.AdjustBrightness(.1f); // brightens
2 Likes

On the topic of contrast, based on the RGB’s individual values if the value were closer to white they’ll go towards white, closer to black they’ll go towards black.

Using lerp should take every rgb towards their destination by an equal fraction as to end up white or black at the same time as the others.
That will require 3 lerps, or 4 if you include alpha. Which doesn’t normally get included in contrast.

If you wanted RGB with 0-1.0 or RGB32 0-255 contrast should be an easy job.
Take Orion’s script and ask a colour if it’s above 50% of its measure, and if so lerp me up to my max by the step requested. Or on the opposite lerp me down.
You should end up with a contrast.

Could you please help me understand, if that’s the case, why I can crop a portion of an image in Photoshop, apply a non-legacy Brightness/Contrast adjustment layer, and compare that to the original uncropped image and get the same results? I thought all of Photoshop’s adjustment layers were, by definition, pixel-local (not aware of the rest of the image), and this test seems to confirm that. If it required context of the full image, it definitely seems like the cropped version would result in a different output compared to the larger image. Thanks.

The small selected region at the right was picked since it has a moderately similar luminance range which would exaggerate any globally-contextual contrast calculation. That region was cropped (and the resulting canvas was flattened), given a +100 contrast with non-legacy B/C, then copied. It was then placed back on top of its original location in the source image, which was also given the +100 contrast. There is zero difference between the lower pixels and the cropped region.

If you operate on a small region, the histograms will take into account only that small region. Non-legacy B&C supposedly takes into account the histogram information. It’s not something I invented, I was merely describing how Adobe itself documents its behavior. Now maybe there are situations or parametric contexts in which yet another algorithms take place, or there are further rules and constraints, I wouldn’t know. I never said I did. I can only guarantee what the legacy one does.