point to calculate RGBA 32bit pixel

May 7, 2017    RGBA Rust Boxblur

Point

When we calculate the RGBA 32 bits pixel, you should prefrom 2~3 things beforehand.

  • extracting channel to deal with channel within 8bits
    • masking every channel
    • bit shiftting
  • joining channel

What dose extracting and joining channel mean? That is relevent to structure of pixel Let’s check pixel data structure.

Pixel data structure

This time we focus on word-order RGBA.

RGBA 32 bits pixel is composed of 4 channels which are red, green, blue and alpha.

In the 32 bits each channel has 8 bits, so first 8 bits is a red, scond 8 bits is a green, third 8 bits is a blue and last 8 bits is a alpha like following picture.


HexRGBAbits
ref: RGBA_color_space

Why we would be better not to calculate just as it is? That could lead overflow and could affect other channels And It’s annoying to care color’s position when operate like adding or substructing.

So Let’s think box blur case.

Case box blur

This algorithm average core pixel and around pixels value and then core pixel will get this value.

Here is 1 step.

[[1, 10, 6],       [[1, 10, 6],
 [8, *0, 2],  ==>   [8, *6, 2],
 [1, 15, 7]]        [1, 15, 7]]

Actually the pixel(the element) is hexdecimal or decimal value.

For example 0xB7410E00 (3074493952 in decimal) when we define pixel type as unsigned integer, we cannot sum 9 value, because most of the language and proceccer calculate unsigned integer within 2^32 == 4294967296.

And even if we can calculate number over 2^32, result will be defferent color.

[[#ffffffff, #ffffffff, #ffffffff],
 [#ffffffff, *#00000000, #ffffffff],
 [#ffffffff, #ffffffff, #ffffffff]]

Center color is black and other is white. So after box blur will be grey intuitively. if we do that, result is (4294967295 * 8 + 0) / 9 =~ 3817748706 3817748706 is near orange:#E38E38E2 (#E38E38 and alpha is almost 0.94)

Normally place after the decimal point is ignored when we calculate each channel, but it affects other channel if we do at the same time.

Soooooooooooo we have to calculate each channel.

How do we extract channel

First step is masking

fn red_masking(pixel: u32) -> u32 { (0xff000000 & pixel) };
fn green_masking(pixel: u32) -> u32 { (0x00ff0000 & pixel) };
fn blue_masking(pixel:  u32) -> u32 { (0x0000ff00 & pixel) };
fn alpha_masking(pixel: u32) -> u32 { (0x000000ff & pixel) };

We remove unnecessary channels by using logical conjunction with 0 and left channel by using full value.

Last step is bit shiftting. Following code is adding it to the above code.

fn red(pixel: u32) -> u32 { (0xff000000 & pixel) >> 24 };
fn green(pixel: u32) -> u32 { (0x00ff0000 & pixel) >> 16 };
fn blue(pixel:  u32) -> u32 { (0x0000ff00 & pixel) >> 8 };
fn alpha(pixel: u32) -> u32 { (0x000000ff & pixel) >> 0 };

This operation convert every channels to value which is limited within 0 ~ 255. Generally that help we not care about which channel is what’s place to add or substruct value.

In blur case that prevent computer from overflow, when we average red value. And prevent result of upper place channel from affecting lower place channel.

joining channels

After each channel is calculated, we need conjunction

  fn rgba(r: u32, g: u32, b: u32, a: u32) -> u32 {
    (r << 24) | (g << 16) | (b << 8) | (a << 0)
  }

Recorvering each channel and conjanction with logical sum



comments powered by Disqus