Pixel binary layout w alpha

May 21, 2013

Good Morning

This post will focus on pixels with an alpha component. A pixel with no alpha component is stored as RGB. When a pixel has an alpha component, it is stored as RGBA. A previous blog post covered RGB pixels, so this post will focus on the addition of the alpha channel.

Everyone has seen the visual effect of an alpha channel, think of a weatherman in front of a green screen. An alpha channel adds transparency and partial transparency to an image or video. The result is that an image can have pixels that are either fully or partially transparent, as seen in this example. Here the checkerboard background represents a transparent background.


Ghost_TransparentBG_400x300

When this ghostly image is rendered over a white background, it looks like this:


Ghost_WhiteBG_400x300

When rendered over a yellow background, the image looks like this:


Ghost_YellowBG_400x300

Note how the background color can be seen through the ghost, this is the partial transparency made possible by the alpha channel. With a RGB pixel, the colors are assumed to be fully opaque, meaning that the pixel color completely covers any existing color in the background. Fully opaque is indicated by the alpha value 255. When a pixel is fully transparent, this is indicated by the alpha value 0. All of the rest of the values in the range 1 to 254 indicate partial transparency. The alpha becomes less and less transparent the closer the alpha value gets to 255.

So, now we know the visual effect that is possible with an alpha channel. But, how exactly is storage of this channel information implemented? The additional A component is stored in the same way as the RGB components. The result is a RGBA pixel where the A alpha component is stored as a byte with a value in the range 0 to 255.

It is possible to store the RGBA components in multiple ways, here the binary layout described will be BGRA native endian layout that matches the little endian format of iOS devices. For now, the issue of pre-multiplied alpha channel vs non-premultiplied alpha channel is ignored in order to keep things simple.

The following shows C source code that will store 4 components as 32 bits of data. Each pixel is represented by a 32 bit word.


#include <stdint.h> // for uint32_t
#include <stdio.h> // for printf()

uint32_t rgba_to_pixel(uint8_t red, uint8_t green,
    uint8_t blue, uint8_t alpha)
{
  return (alpha << 24) | (red << 16) | (green << 8) | blue;
}

void print_pixel_rgba(char *desc, uint32_t pixel)
{
  uint32_t alpha = (pixel >> 24) & 0xFF;
  uint32_t red = (pixel >> 16) & 0xFF;
  uint32_t green = (pixel >> 8) & 0xFF;
  uint32_t blue = (pixel >> 0) & 0xFF;

  printf("%10s pixel 0x%.8X : (R G B A) (%d, %d, %d, %d)\n",
    desc, pixel, red, green, blue, alpha);
}
      
int main(int argc, char **argv)
{
  uint32_t red = rgba_to_pixel(255, 0, 0, 255);
  print_pixel_rgba("red", red);

  uint32_t green = rgba_to_pixel(0, 255, 0, 255);
  print_pixel_rgba("green", green);

  uint32_t blue = rgba_to_pixel(0, 0, 255, 255);
  print_pixel_rgba("blue", blue);

  uint32_t black = rgba_to_pixel(0, 0, 0, 127);
  print_pixel_rgba("50% black", black);

  uint32_t white = rgba_to_pixel(255, 255, 255, 191);
  print_pixel_rgba("75% white", white);

  return 0;
}

Compile the source with gcc like so:

$ gcc -o encode_decode_pixels_rgba encode_decode_pixels_rgba.c

$ ./encode_decode_pixels_rgba
       red pixel 0xFFFF0000 : (R G B A) (255, 0, 0, 255)
     green pixel 0xFF00FF00 : (R G B A) (0, 255, 0, 255)
      blue pixel 0xFF0000FF : (R G B A) (0, 0, 255, 255)
 50% black pixel 0x7F000000 : (R G B A) (0, 0, 0, 127)
 75% white pixel 0xBFFFFFFF : (R G B A) (255, 255, 255, 191)

The first 3 pixels, the red, green, and blue values are completely opaque. The black pixel is 1/2 transparent since the alpha value is 127 (aka 255/2). The white pixel has a alpha value that is 3/4 of the maximum 255, so it is less see through than the black pixel.

This example code shows how image data with an alpha could be stored at the pixel level. Common graphics formats like PNG use this exact pixel layout when storing pixels.