12
votes

I know there is formula for going RGB -> Luminance, but I need given a brightness parameter to modify the RGB values of an image. How do I do that?

Thanks

7

7 Answers

22
votes

The easiest way is to multiply each of the R,G,B values by some constant - if the constant is >1 it will make it brighter, and if <1 it will be darker. If you're making it brighter then you must test each value to make sure it doesn't go over the maximum (usually 255).

Not only is this simpler than the translation from RGB to HSL and back again, but it more closely approximates what happens when you shine a different amount of light at a physical object.

19
votes

Map from RGB to HSL (Hue/saturation/luminance), keep the hue and saturation the same, and just modify the luminance and then do the backward mapping from HSL to RGB.

You can read more about the RGB to HSL and HSL to RGB transformations here.

4
votes

Adding to Mark Ransom's Answer: It would be better to use the said factor with a 255 constant and add it to the current color-value:

float brightnessFac = //between -1.0 and 1.0    
byte brightnessRed = red + (255f * brightnessFac);

If you just do with a factor between 0.0 and 1.0

byte brightnessRed = red * brightnessFac;

A value of 0 stays zero.

4
votes

My recommendation would be the same as ChrisA.'s answer, with one difference:

Use the HSP color space instead, as it is an approximation of Photoshop's algorithm and has better results.


For the sake of not just linking to HSP's site (which frankly should be more than enough; it's just that I don't like to answer without examples), here is my C# implementation, which follows the site's:

#region Definitions
//Perceived brightness to Red ratio.
private const double Pr = .299;
//Perceived brightness to Green ratio.
private const double Pg = .587;
//Perceived brightness to Blue ratio.
private const double Pb = .114;
#endregion

//Expected ranges: Hue = 0-359... Other values = 0-1
public static ColorRGB ToRGB(double hue, double saturation, double perceivedBrightness, double alpha) {
    //Check values within expected range
    hue = hue < 0 ? 0 : hue > 359 ? 359 : hue;
    saturation = saturation < 0 ? 0 : saturation > 1 ? 1 : saturation;
    perceivedBrightness = perceivedBrightness < 0 ? 0 : perceivedBrightness > 1 ? 1 : perceivedBrightness;
    alpha = alpha < 0 ? 0 : alpha > 1 ? 1 : alpha;
    //Conversion
    var minOverMax = 1 - saturation;
    double r, g, b;
    if (minOverMax > 0) {
        double part;
        if (hue < 0.166666666666667D) { //R>G>B
            hue = 6 * (hue - 0); part = 1 + hue * (1 / minOverMax - 1);
            b = perceivedBrightness / Math.Sqrt(Pr / minOverMax / minOverMax + Pg * part * part + Pb);
            r = b / minOverMax; g = b + hue * (r - b);
        }
        else if (hue < 0.333333333333333D) { //G>R>B
            hue = 6 * (-hue + 0.333333333333333D); part = 1 + hue * (1 / minOverMax - 1);
            b = perceivedBrightness / Math.Sqrt(Pg / minOverMax / minOverMax + Pr * part * part + Pb);
            g = b / minOverMax; r = b + hue * (g - b);
        }
        else if (hue < 0.5D) {   //  G>B>R
            hue = 6 * (hue - 0.333333333333333D); part = 1 + hue * (1 / minOverMax - 1);
            r = perceivedBrightness / Math.Sqrt(Pg / minOverMax / minOverMax + Pb * part * part + Pr);
            g = r / minOverMax; b = r + hue * (g - r);
        }
        else if (hue < 0.666666666666667D) { //B>G>R
            hue = 6 * (-hue + 0.666666666666667D); part = 1 + hue * (1 / minOverMax - 1);
            r = perceivedBrightness / Math.Sqrt(Pb / minOverMax / minOverMax + Pg * part * part + Pr);
            b = r / minOverMax; g = r + hue * (b - r);
        }
        else if (hue < 0.833333333333333D) { //B>R>G
            hue = 6 * (hue - 0.666666666666667D); part = 1 + hue * (1 / minOverMax - 1);
            g = perceivedBrightness / Math.Sqrt(Pb / minOverMax / minOverMax + Pr * part * part + Pg);
            b = g / minOverMax; r = g + hue * (b - g);
        }
        else { //R>B>G
            hue = 6 * (-hue + 1D); part = 1 + hue * (1 / minOverMax - 1);
            g = perceivedBrightness / Math.Sqrt(Pr / minOverMax / minOverMax + Pb * part * part + Pg);
            r = g / minOverMax; b = g + hue * (r - g);
        }
    }
    else {
        if (hue < 0.166666666666667D) { //R>G>B
            hue = 6 * (hue - 0D); r = Math.Sqrt(perceivedBrightness * perceivedBrightness / (Pr + Pg * hue * hue)); g = r * hue; b = 0;
        }
        else if (hue < 0.333333333333333D) { //G>R>B
            hue = 6 * (-hue + 0.333333333333333D); g = Math.Sqrt(perceivedBrightness * perceivedBrightness / (Pg + Pr * hue * hue)); r = g * hue; b = 0;
        }
        else if (hue < 0.5D) { //G>B>R
            hue = 6 * (hue - 0.333333333333333D); g = Math.Sqrt(perceivedBrightness * perceivedBrightness / (Pg + Pb * hue * hue)); b = g * hue; r = 0;
        }
        else if (hue < 0.666666666666667D) { //B>G>R
            hue = 6 * (-hue + 0.666666666666667D); b = Math.Sqrt(perceivedBrightness * perceivedBrightness / (Pb + Pg * hue * hue)); g = b * hue; r = 0;
        }
        else if (hue < 0.833333333333333D) { //B>R>G
            hue = 6 * (hue - 0.666666666666667D); b = Math.Sqrt(perceivedBrightness * perceivedBrightness / (Pb + Pr * hue * hue)); r = b * hue; g = 0;
        }
        else { //R>B>G
            hue = 6 * (-hue + 1D); r = Math.Sqrt(perceivedBrightness * perceivedBrightness / (Pr + Pb * hue * hue)); b = r * hue; g = 0;
        }
    }
    return new ColorRGB(r, g, b, alpha);
}

//Expected ranges: 0-1 on all components
public static ColorHSP FromRGB(double red, double green, double blue, double alpha) {
    //Guarantee RGB values are in the correct ranges
    red = red < 0 ? 0 : red > 1 ? 1 : red;
    green = green < 0 ? 0 : green > 1 ? 1 : green;
    blue = blue < 0 ? 0 : blue > 1 ? 1 : blue;
    alpha = alpha < 0 ? 0 : alpha > 1 ? 1 : alpha;
    //Prepare & cache values for conversion
    var max = MathExtensions.Max(red, green, blue);
    var min = MathExtensions.Min(red, green, blue);
    var delta = max - min;
    double h, s, p = Math.Sqrt(0.299 * red + 0.587 * green + 0.114 * blue);
    //Conversion
    if (delta.Equals(0)) h = 0;
    else if (max.Equals(red)) {
        h = (green - blue) / delta % 6;
    }
    else if (max.Equals(green)) h = (blue - red) / delta + 2;
    else h = (red - green) / delta + 4;
    h *= 60;
    if (h < 0) h += 360;
    if (p.Equals(0))
        s = 0;
    else
        s = delta / p;
    //Result
    return new ColorHSP(h, s, p, alpha);
}
0
votes
import java.io. * ;
import java.awt.Color;
import javax.imageio.ImageIO;
import java.io. * ;
import java.awt.image.BufferedImage;

class Psp {

    public static void main(String a[]) {
        try {

            File input = new File("abc.jpg");
            File output = new File("output1.jpg");
            BufferedImage picture1 = ImageIO.read(input); // original
            BufferedImage picture2 = new BufferedImage(picture1.getWidth(), picture1.getHeight(), BufferedImage.TYPE_INT_RGB);
            int width = picture1.getWidth();
            int height = picture1.getHeight();

            int factor = 50;
            for (int y = 0; y < height; y++) { //loops for images
                for (int x = 0; x < width; x++) {

                    Color c = new Color(picture1.getRGB(x, y));
                    int r = c.getRed() + factor;
                    int b = c.getBlue() + factor;
                    int g = c.getGreen() + factor;

                    if (r >= 256) {
                        r = 255;
                    } else if (r < 0) {
                        r = 0;
                    }

                    if (g >= 256) {
                        g = 255;
                    } else if (g < 0) {
                        g = 0;
                    }

                    if (b >= 256) {
                        b = 255;
                    } else if (b < 0) {
                        b = 0;
                    }
                    picture2.setRGB(x, y, new Color(r, g, b).getRGB());

                }
            }

            ImageIO.write(picture2, "jpg", output);
        } catch(Exception e) {
            System.out.println(e);
        }

    }

}
0
votes

You can try LookupTable and LookupOp; so that you can adjust the brightness of the pic by modifying of the LookupTable. To make a picture bright is just to add some value to the RGB.

BufferedImage dstImage = new BufferedImage(input.getWidth(), input.getHeight(),BufferedImage.TYPE_3BYTE_BGR);
        LookupTable lookupTable = new ShortLookupTable(0, data);
        LookupOp op = new LookupOp(lookupTable, null);
        op.filter(toBeTone, dstImage);
-3
votes

Adjusting the brightness of an image is one of the easiest image processing operations that can be done. All that is involved is adding the desired change in brightness to each of the red, green and blue colour components.

it would go something like this:

colour = GetPixelColour(x, y)
   newRed   = Truncate(Red(colour)   + brightness)
   newGreen = Truncate(Green(colour) + brightness)
   newBlue  = Truncate(Blue(colour)  + brightness)
   PutPixelColour(x, y) = RGB(newRed, newGreen, newBlue)

Code to ensures that the new values of red, green and blue are within the valid range.

Procedure Truncate(value)
      If value < 0 Then value = 0
      If value > 255 Then value = 255
      Return value
   EndProcedure