425-882-1032 info@3sharp.com

I have an app on the Windows Phone 7 marketplace, called Pictomaphone. Ever since I first started work it (almost a year ago) I’ve given much thought (too much, really) to how to convert from an Int32 to a usable ARGB color.

If you are unfamiliar with the problem – in Silverlight, there is a class “WriteableBitmap” that gives you access to the pixels in an image. On the phone, it is the only way to edit images. The problem is, the pixel array in the class only gives you back a single Int32 for each color. You have to unpack it yourself to get the individual Alpha, Red, Green and Blue channels out.

The Int32 is laid out like this:

ColorB Byte Layout

Probably the easiest way to handle this is to use the BitConverter class to get the bytes.


int pixel = image.Pixels[0];

byte[] color = BitConverter.GetBytes(pixel);

And there you go, color[0] would be the Blue value and so on. The problem is, the BitConverter class isn’t exactly speedy. While fine for a one-time go, or maybe even a couple hundred, it is too slow to bother with when iterating over an entire image. This goes double on the phone.

So, the next thing to do is to use some math to get the values out.

int pixel = image.Pixels[0];
int alpha = pixel >> 24 & 255;
int red = pixel >> 16 & 255;
int green = pixel >> 8 & 255;
int blue = pixel & 255;

Not so bad, and it happens to be super fast. Of course, you have to do the opposite to get the Int32 back in…

pixel = alpha << 24 | red << 16 | green << 8 | blue;

Which is all fine and dandy. In fact, this is the method I used for a long time, because it does work very well.

But, I couldn’t leave well enough alone. I kept thinking there had to be something easier. Something that works in safe code and doesn’t require me to code the math out… and there is.

[StructLayout(LayoutKind.Explicit)]
public struct ColorB
{
  // total int value

  [FieldOffset(0)]
  public int Value;

  // the bytes from the int

  [FieldOffset(0)]
  public byte Blue;

  [FieldOffset(1)]
  public byte Green;

  [FieldOffset(2)]
  public byte Red;

  [FieldOffset(3)]
  public byte Alpha;

}

This is the struct I am currently using in my app. You set the Value field equal to the Int32 and then the bits are just there. You can do all the math you want on the bytes and when you are ready, you set the original Int32 pixel equal to the Value field again. No converting, no worries.

In fact, I went one step further, because I’m lazy, and added a few constructors and implicit conversions to the struct.


public ColorB(int value)

{
  // initialize bytes first so the compiler won’t get mad
  Blue = Green = Red = Alpha = 0;
  this.Value = value;
}
public static implicit operator ColorB(int value)
{
  return new ColorB(value);
}
public static implicit operator int(ColorB color)
{
  return color.Value;
}

So now, the ColorB struct is an Int32 and vise-versa. You’ll notice that the constructor initializes the bytes first, before setting the value. This is because the compiler doesn’t notice the LayoutKind.Explicit flag and throws exceptions if you try to build.

In my testing on a WP7 device, using the struct was marginally slower (10-20 milliseconds over a 2 megapixel image) when reading an image in… and faster when writing it back out.

I’ve now switched my entire code-base over to using the struct. To me, it is a cleaner solution and easier to work with.

As a side note, since Vectors get SIMD enhancements in WP7.5, I tried using them also, to see if there was a speed improvement. There wasn’t, integer math was still faster than the SIMD float math. Oh well, float would have been nice, since some of the equations I use are simpler when done on a float scaled between 0 and 1. But, the speed ultimately made me can that idea.

Now, if only someone over at Microsoft would allow us to use custom Pixel Shaders (which Silverlight and WPF already support) to apply effects on the Phone… oh man would that be fast! The phone GPU supports it, so do Android and iPhone. Hopefully the time will come. There is some crazy stuff I could do in a shader that just isn’t fast enough on the CPU to bother with right now.