C#中将Int转换为颜色,用于Silverlight的WriteableBitmap

10
在Silverlight 3中,现在有一个WriteableBitmap可以提供get/put像素的功能。可以通过以下方式实现:
// 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;

基本上,设置一个像素涉及到设置它的颜色,这是通过按位移动 alpha、red、blue 和 green 值来转换为整数的。

我的问题是,如何将一个整数转换回颜色?在这个例子中缺少什么东西:

// getting a pixel example
int colorAsInt = bitmap.Pixels[0];
Color c;
// TODO:: fill in the color c from the integer ??
感谢您可能提供的任何帮助,我对位运算不熟悉,我相信其他人在某个时候也会遇到这个障碍。
7个回答

7

使用反射器,我发现在标准的.NET调用中(Silverlight不可用),如何解析R、G、B:

System.Drawing.ColorTranslator.FromWin32()

我猜测如何获取Alpha通道,这个方法可以解决:

Color c2 = Color.FromArgb((byte)((colorAsInt >> 0x18) & 0xff), 
                          (byte)((colorAsInt >> 0x10) & 0xff), 
                          (byte)((colorAsInt >> 8) & 0xff), 
                          (byte)(colorAsInt & 0xff));

4
你可以使用BitConverter.GetBytes()将你的整数转换为字节数组,这样就可以与Silverlight具有的FromArgb重载一起使用...
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]); 

第二个建议非常好,但是位是反过来的,这样做可以: Color.FromArgb(bytes[3], bytes[2], bytes[1], bytes[0]); - SmartyP
这对于操作位图像素来说会非常慢(不可接受)。 - Sam Harwell
糟糕 - 已更新示例。感谢您指出这个问题 :) - Scott Ivey

2
未涵盖的内容是,WriteableBitmap 使用预乘的 ARGB32 格式,所以如果你有一个半透明像素,则 R、G 和 B 值从 0 到 Alpha 值进行缩放。
要获取颜色值,您需要做相反的操作,将其缩放回 0 到 255。如下所示:
r = (byte)(r * (255d / alpha))

0
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));
}

并使用:

Color c = colorAsInt.ToColor()

0

我觉得像这样应该可以工作:

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;
}

一旦您获得了字节,使用任何不同的颜色 API 都可以轻松获取颜色。


0

你可能正在寻找ColorTranslator类, 但我不确定它是否在SilverLight中可用或者你需要的是什么。不过这绝对是一个值得了解的好东西。

编辑:这里有一个人的建议(使用反射来复制该类,从此你就拥有了一个已经为人所熟知的转换器)。


使用反射的建议很好,让我能够读取R、G、B值,经过更多的修改后,我也成功解析了alpha通道。我添加了一个答案,只使用了位移操作。 - SmartyP

-1
Color.FromArgb(intVal)

3
需要澄清的是,在Silverlight中没有FromArgb(int)方法,只有FromArgb(byte,byte,byte,byte)方法,这是我问题的一部分。 - SmartyP

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接