C#-将ARGB颜色转换为RGB555

C#-将ARGB颜色转换为RGB555,c#,.net,colors,converter,bit-shift,C#,.net,Colors,Converter,Bit Shift,我有一个将RGB555值转换为System.Drawing.Color对象的算法 public static Color ToColor(ushort color) { int a = color & 0x8000; int r = color & 0x7C00; int g = color & 0x03E0; int b = color & 0x1F; int rgb = (r << 9) | (g <&

我有一个将RGB555值转换为System.Drawing.Color对象的算法

public static Color ToColor(ushort color)
{
    int a = color & 0x8000;
    int r = color & 0x7C00;
    int g = color & 0x03E0;
    int b = color & 0x1F;
    int rgb = (r << 9) | (g << 6) | (b << 3);

    return Color.FromArgb((a * 0x1FE00) | rgb | ((rgb >> 5) & 0x070707));
}
公共静态颜色到颜色(ushort颜色)
{
int a=颜色&0x8000;
int r=颜色&0x7C00;
int g=颜色&0x03E0;
int b=颜色&0x1F;
int rgb=(r>16)&0x8000(c>>9)&0x7C00(c>>6)&0x03E0(c>>3)&0x1F);
}
公共颜色555(ushort值)
{
_价值=价值;
}
公共覆盖int GetHashCode()
{
返回_Value.GetHashCode();
}
公共覆盖布尔等于(对象对象对象)
{
返回(obj是ushort&&Equals((ushort)obj))| |(obj是Color555&&Equals((Color555)obj));
}
公共布尔等于(ushort其他)
{
返回_值==其他;
}
公共布尔等于(Color555其他)
{
返回_值==其他。_值;
}
公共整数比较(Color555其他)
{
返回_值。比较到(其他._值);
}
公共int比较(ushort其他)
{
返回_值。比较到(其他);
}
公共重写字符串ToString()
{
返回String.Format(“{0}”,_值);
}
公共字符串到字符串(字符串格式)
{
返回String.Format(格式,_值);
}
公共字符串到字符串(IFormatProvider提供程序)
{
返回String.Format(提供程序“{0}”,_值);
}
公共字符串到字符串(字符串格式,IFormatProvider)
{
返回String.Format(提供程序、格式、值);
}
公共int ToArgb()
{
返回到颜色();
}
公共颜色ToColor()
{
int a=_值&0x8000;
int r=_值&0x7C00;
int g=_值&0x03E0;
int b=_值&0x1F;
int rgb=(r为什么不使用这个

{
    Color c = ColorTranslator.FromHtml("#555");
    string s = ColorTranslator.ToHtml(c);
}
为什么不用这个

{
    Color c = ColorTranslator.FromHtml("#555");
    string s = ColorTranslator.ToHtml(c);
}

Color
每像素使用32位:alpha、红色、绿色和蓝色值各使用8位。(这意味着每个组件的值可以从0到255。)

一种颜色每像素使用5位(并且没有alpha通道),因此红色、绿色和蓝色都可以取0-31之间的值

要从一个转换到另一个,我们需要将值0-255映射到值0-31。这显然是一个有损的过程;我们无法表示所有可能的
Color
,许多不同的
Color
值将映射到相同的
Color555

最简单的映射就是截断,在这里我们除以8并丢弃余数。这将0-7映射到0,8-15映射到1,…,248-255映射到31。这可以写成三位右移

然后我们需要将这些值组合成一个16位的值,这是通过将红色和绿色分量向左移动来实现的

(您的示例代码似乎是基于高位设置alpha通道,因此我们可以以相同的方式向后转换alpha通道。在这种情况下,我们需要将256个可能的值映射到2:0或1。我选择将alpha通道精确地分成两半;还有其他可能的映射。)

把所有这些放在一起,它应该看起来像:

public Color555(Color color)
{
    _Value = (ushort) ((color.A >= 128 ? 0x8000 : 0x0000) |
        ((color.R & 0xF8) << 7) | ((color.G & 0xF8) << 2) | (color.B >> 3));
}
public Color555(彩色)
{
_值=(ushort)((color.A>=128?0x8000:0x0000)|
((color.R&0xF8)3));
}

A
Color
每像素使用32位:alpha、红色、绿色和蓝色值各8位。(这意味着每个组件的值可以从0到255。)

一种颜色每像素使用5位(并且没有alpha通道),因此红色、绿色和蓝色都可以取0-31之间的值

要从一个转换到另一个,我们需要将值0-255映射到值0-31。这显然是一个有损的过程;我们无法表示所有可能的
Color
,许多不同的
Color
值将映射到相同的
Color555

最简单的映射就是截断,在这里我们除以8并丢弃余数。这将0-7映射到0,8-15映射到1,…,248-255映射到31。这可以写成三位右移

然后我们需要将这些值组合成一个16位的值,这是通过将红色和绿色分量向左移动来实现的

(您的示例代码似乎是基于高位设置alpha通道,因此我们可以以相同的方式向后转换alpha通道。在这种情况下,我们需要将256个可能的值映射到2:0或1。我选择将alpha通道精确地分成两半;还有其他可能的映射。)

把所有这些放在一起,它应该看起来像:

public Color555(Color color)
{
    _Value = (ushort) ((color.A >= 128 ? 0x8000 : 0x0000) |
        ((color.R & 0xF8) << 7) | ((color.G & 0xF8) << 2) | (color.B >> 3));
}
public Color555(彩色)
{
_值=(ushort)((color.A>=128?0x8000:0x0000)|
((color.R&0xF8)3));
}

第一步应该是理解它。如果你不能掌握位移位,并且没有这样做的意愿,你就不应该使用这个代码。你知道你不能取回准确的数据,因为你把数据扔掉了,对吗?@JonathonReinhart是对的。接受你试图完成的总体想法,然后去做不要把它复杂化了。色彩在事物的大格局中并不难搞清楚。@Jonathon Reinhart-我不记得说过什么不想学习的话,因此说任何关于理解它的建议都是一种新鲜空气-不像我期待有人来帮我做的那样。我不只是一个复制粘贴开发人员佩尔,在我自己搞清楚了10年之后,我终于需要在一个公共网站上问一个问题了。那么第一步应该是理解它。如果你不能掌握位转移,并且没有这样做的愿望,你就不应该使用这个代码。你知道你无法获得准确的数据a既然你把数据扔掉了,对吗?@JonathonReinhart是对的。考虑一下你试图完成的整体想法,不要把它过于复杂化。从总体上看,颜色并不难搞清楚。@Jonathon Reinhart-我不这么认为