anshul
anshul

Reputation: 992

Understanding ImageProcessing code

I am new to android ndk.I have started learning through the image processing example by
ruckus and by IBM blog. I am not getting few lines below.Can any one please help me to understand the code snippet?`

static void brightness(AndroidBitmapInfo* info, void* pixels, float brightnessValue){
    int xx, yy, red, green, blue;
    uint32_t* line;

    for(yy = 0; yy < info->height; yy++){
            line = (uint32_t*)pixels;
            for(xx =0; xx < info->width; xx++){


              //extract the RGB values from the pixel
                red     = (int) ((line[xx] & 0x00FF0000) >> 16);
                green   = (int)((line[xx] & 0x0000FF00) >> 8);
                blue    = (int) (line[xx] & 0x00000FF );

        //manipulate each value
        red = rgb_clamp((int)(red * brightnessValue));
        green = rgb_clamp((int)(green * brightnessValue));
        blue = rgb_clamp((int)(blue * brightnessValue));

        // set the new pixel back in
        line[xx] =
          ((red << 16) & 0x00FF0000) |
          ((green << 8) & 0x0000FF00) |
          (blue & 0x000000FF);
            }

            pixels = (char*)pixels + info->stride;
        }
}
`
    static int rgb_clamp(int value) {
  if(value > 255) {
    return 255;
  }
  if(value < 0) {
    return 0;
  }
  return value;
}

How the RGB value are getting extracted and wht does this rgb_clamp do.Why are we setting new Pixell back and how does pixels = (char*)pixels + info->stride; works? I am not a c/c++ guys and not having much knowledge of Image processing. Thanks

Upvotes: 1

Views: 391

Answers (2)

AquilaRapax
AquilaRapax

Reputation: 1099

At first lets talk about one pixel. As far as i can see, it is a composition of at least 3 channels: r,g and b, which are all stored in one uint32_t value and has the format 0x00RRGGBB(32bit / 4 channels = 8bit per channel and thus a value range from 0..255). So, to get the separated r, g and b-values you need to mask them out, which is done in the three lines below //extract the RGB values. For example the red component... With the mask 0x00FF0000 and the & operator, you set every bit to 0 except the bits that are set in the red channel. But when you just mask them out with 0x00RRGGBB & 0x00FF0000 = 0x00RR0000, you would get a very big number. To get a value between 0 and 255 you also have to shift the bits to the right and that is what is done with the >>-operator. So for the latter example: After applying the mask, you get 0x00RR0000, and shifting this 16 bit right (>> 16)gives you 0x000000RR, which is a number between 0 and 255. The same happens with the green channel, but with an 8bit right shift and since the blue value is already on the "right" bit position, there is no need to shift.

Second question: What rgb_clamp does is easy to explain. It ensures, that your r,g or b-value, multiplied with your brightness factor, never exceeds the value range 0..255.

After the multiplication with the brightness factor, the new values are written back into memory, which happens in the reverse order of the above described extraction, this time shifting them leftwards and removing bits, that we don't want with the mask.

After one line of your image is processed, the info->stride is added, since for optimization purposes, the memory probably is aligned to fill 32byte boundaries and thus a single line can be longer than only image width and thus the "rest" of bytes are added to the pointer.

Upvotes: 4

Redivider
Redivider

Reputation: 144

First and foremost I suggest you read the C book here: http://publications.gbdirect.co.uk/c_book/

Next I'll go through your questions.

  1. How are the RGB values extracted

    line is set to point to pixels parameter:

    line = (uint32_t*)pixels;

    That is pixels is an array of 32 bit unsigned integers

    Then for the height and width of the bitmap the RGB values are extracted using a combination of bitwise ANDing (&) and bit shifting right (>>).

    Lets see how you get red:

    red = (int) ((line[xx] & 0x00FF0000) >> 16);

    Here we get the current line, then AND with 0x00FF0000 as mask, this gets the bits 24-16 from the line. So using RGB code #123456 as an example we will be left with 0x00120000 in the red variable. But it's still in the 24-16 bit position so we right shift 16 bits to shift the bits down to 0x00000012.

    We do this for the green and blue values, adjusting the AND mask and number of bits to shift right.

    More information on binary arithmetic can be found here: http://publications.gbdirect.co.uk/c_book/chapter2/expressions_and_arithmetic.html

  2. What does rgb_clamp do

    This function simply ensures the red, green, or blue values are 0 or above or 255 and below.

    If the parameter to rbg_clamp is -20 the it will return 0, which will be used to set the RGB value. If the parameter is rbg_clamp is 270 it will return 255.

    RGB values for each colour must not exceed 225 or be below 0. In this example 255 being the brightest and 0 being the darkest value.

  3. Why are we setting pixel back

    It appears we are changing the brightness of the pixel, and setting the value back ready to be displayed.

  4. How does pixels = (char*)pixels + info->stride; work?

    Without knowing the structure of info variable of AndroidBitmapInfo type, I would guess info->stride refers to the width of the bitmap in bytes so line will become the next line on the next loop iteration.

Hope that helps

Upvotes: 2

Related Questions