Reputation:
In Silverlight 3 there is now a WriteableBitmap which provides get/put pixel abilities. This can be done like so:
// setting a pixel example
WriteableBitmap bitmap = new WriteableBitmap(400, 200);
Color c = Colors.Purple;
bitmap.Pixels[0] = c.A << 24 | c.R << 16 | c.G << 8 | c.B;
Basically, setting a Pixel involves setting its color, and that comes by bitshifting the alpha, red, blue, green values into an integer.
My question is, how would you turn an integer back to a Color? What goes in the missing spot in this example:
// getting a pixel example
int colorAsInt = bitmap.Pixels[0];
Color c;
// TODO:: fill in the color c from the integer ??
Thanks for any help you might have, I'm just not up on my bit shifting and I'm sure others will run into this roadblock at some point.
Upvotes: 10
Views: 17003
Reputation: 3460
What has not been covered is that WriteableBitmap
uses premultiplied ARGB32 so if you have a semitransparent pixel the R, G, and B values are scaled from 0 to the Alpha value.
To get the Color value back, you need to do the opposite and scale it back up to 0 to 255. Something as shown below.
r = (byte)(r * (255d / alpha))
Upvotes: 2
Reputation: 60041
I think something like this should work:
public byte[] GetPixelBytes(WriteableBitmap bitmap)
{
int[] pixels = bitmap.Pixels;
int length = pixels.Length * 4;
byte[] result = new byte[length]; // ARGB
Buffer.BlockCopy(pixels, 0, result, 0, length);
return result;
}
Once you have the bytes, getting colors is easy with any of the various Color APIs.
Upvotes: 0
Reputation: 4780
public static Color ToColor(this uint argb)
{
return Color.FromArgb((byte)((argb & -16777216) >> 0x18),
(byte)((argb & 0xff0000) >> 0x10),
(byte)((argb & 0xff00) >> 8),
(byte)(argb & 0xff));
}
and using:
Color c = colorAsInt.ToColor()
Upvotes: 0
Reputation: 41588
You could possibly use BitConverter.GetBytes() to convert your int to a byte array that would work with the overloads of FromArgb that silverlight has...
Color.FromArgb(BitConverter.GetBytes(intVal));
// or if that doesn't work
var bytes = BitConverter.GetBytes(intVal);
Color.FromArgb(bytes[3], bytes[2], bytes[1], bytes[0]);
Upvotes: 4
Reputation: 1359
using the reflector i found how R,G,B are parsed in the standard .net call (not available in Silverlight):
System.Drawing.ColorTranslator.FromWin32()
from that i guessed how to get the alpha channel as well, and this does the job:
Color c2 = Color.FromArgb((byte)((colorAsInt >> 0x18) & 0xff),
(byte)((colorAsInt >> 0x10) & 0xff),
(byte)((colorAsInt >> 8) & 0xff),
(byte)(colorAsInt & 0xff));
Upvotes: 7
Reputation: 99979
You might be looking for the ColorTranslator class, but I'm not sure it's available in SilverLight or what you need. It's absolutely a good one to be aware of though.
Edit: Here was one person's suggestion (use reflection to duplicate the class, so from then on you have a converter available that people are already familiar with).
Upvotes: 0