Increasing Brightness

Recently, I did some graphics programming. The task I gave myself was to highlight a JPEG by drawing a box around an interesting part of the image. The puzzle was which color to make the box so that it would stand out.

My first color choice was black, but if the image is mostly black, the box wouldn’t show up. The same logic follows for white and other colors as well.

For example, I tried bright green, but the results were ugly. I tried a box made of two rectangles, one white and one black, but on a larger image canvas, this box wasn’t that obvious. So my solution was instead to use existing pixels to draw the box, making each pixel brighter by 10 percent.

In a JPEG image, pixels are stored as three values: red, green, and blue. Each value ranges from 0 to 255, which in C fits into an unsigned char variable. Ten percent of 255 is 25, so for each color value in the pixel, I would add 25 to increase brightness. (I’m sure that nerdy graphics programmers would claim that this method doesn’t increase brightness but blah-blah-blah. Whatever. Work with me here.)

The problem, of course, is that you cannot increase a pixel’s color element value beyond 255; if you add 25 to a pixel value of 250, for example, you get 275. This result is an overflow. In C, adding 25 to an unsigned char value of 250 yields 19, not 275; the value wraps within the confines of the unsigned char.

This month’s Exercise is to take a line of pixels stored in a structure and increase each value by 10 percent without going over 255. Use the code below as a skeleton to craft your solution:

#include <stdio.h>

int main()
{
    struct color {
        unsigned char r;
        unsigned char g;
        unsigned char b;
    };
    struct color pixels[15] = {
        {247, 63, 29},{251,100, 33},{250,146, 38},
        {252,196, 46},{252,223, 51},{250,225, 56},
        {196,225, 53},{134,252, 49},{ 66,221, 48},
        { 63,251,158},{ 60,253,233},{ 54,236,250},
        { 35,181,249},{  0,104,249},{  0, 54,251}
    };

/* your solution here */

    return(0);
}

Click here to view my solution, but please work on this puzzle yourself before you see what I’ve done.

6 thoughts on “Increasing Brightness

  1. A while ago I wrote a set of functions to convert between RGB decimal, RGB hexadecimal and HSL. It’s very fiddly, you need a lot of intermediate variables and if/elses. However, if you want to alter lightness “properly” I think you need to convert RGB to HSL, change the “L” value and convert back to RGB.

    I can’t think of a way of doing mathematics directly on the RGB values to alter brightness but there may be a way, I am not one of the “nerdy graphics programmers” you refer to!

    In C, adding 25 to an unsigned char value of 250 yields 19, not 275; the value wraps within the confines of the unsigned char.

    I think this might actually be the best solution. It would mean very light colours are converted to very dark colours which is what you need for selecting a part of an image.

    Thinking about it further, I think the ideal solution would be to convert pixels with a lightness of more than 50% to black, and those with a lightness less than 50% to white, which would give maximum contrast. Gimp uses animated black and white alternating lines, and another application I have used in the past (I think it was Paint Shop Pro) uses black and yellow.

    A long time ago I started looking into writing code for opening and editing JPEG files, naively thinking it was just a case of reading, editing and saving a load of RGB values. Completely wrong of course – they have a load of metadata (usually including EXIF) as well as a very sophisticated compression algorithm. One day I’ll get round to looking at libjpeg which seems to be the most popular C library for this.

  2. In England there’s half an inch of snow on the ground which here is classified as “severe weather”. We don’t get much snow so when we do everyone panics and the country grinds to a halt. Therefore I’m stuck at home with nothing better to do than add 25 to an array of numbers. (A friend who lives in the Cascade Mountains of Oregon actually owns his own slow blower – presumably common in those parts.)

    Anyway, here’s my solution. Probably way too complicated as usual.

    #include <stdio.h>

    int main()
    {
        struct color
        {
            unsigned char r;
            unsigned char g;
            unsigned char b;
        };

        struct color pixels[15] =
        {
            {247, 63, 29},{251,100, 33},{250,146, 38},
            {252,196, 46},{252,223, 51},{250,225, 56},
            {196,225, 53},{134,252, 49},{ 66,221, 48},
            { 63,251,158},{ 60,253,233},{ 54,236,250},
            { 35,181,249},{  0,104,249},{  0, 54,251}
        };

        int i = 0;
        int l = 0;
        char c = 0;
        unsigned char unbrightened = 0;
        unsigned char brightened = 0;

        // set l (length) to array size / 3
        for(i = 0, l = sizeof(pixels) / 3; i < l; i++)
        {
            // loop through rgb
            for(c = 0; c < 3; c++)
            {
                // retrieve current r, g or b using pointer arithmetic
                // this avoid repeating code 3 times for r, g and b
                unbrightened = *(&(pixels[i].r) + c);

                // adding 25 might result in wrapping round to lower value…
                brightened = unbrightened + 25;

                // so check here
                brightened = brightened < unbrightened ? 255 : brightened;

                printf(“%-6s”, c == 0 ? “Red” : c == 1 ? “Green” : “Blue”);

                printf(“%4d%4d”, unbrightened, brightened);

                // mark values which rolled round
                if(unbrightened > 230)
                    puts(” *”);
                else
                    puts(“”);
            }

            puts(“—————–“);
        }
    }

  3. Ah! See? I knew someone would know the proper way to increase brightness. I’m just lightening the pixel values.

  4. Oh, btw, does that array of RGB values represent a real (very small!) image?

    No, they’re just values I pulled from a rainbow picture. The color values shift from one end of the spectrum to another, but they don’t really form a specific image.

Leave a Reply