C# - 转换ARGB颜色到RGB555(C# - Convert ARGB Color to RG

2019-10-17 21:22发布

我有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));
}

一个朋友写了这个方法对我来说(位转移是一个有点超过我的头),这将是扭转这种代码的最有效方法是什么?

感谢您的任何意见,我一直在试图寻找了几天的答案,所以任何见解将是呼吸新鲜空气!

编辑

这个问题已经解决了一段时间,但我想我会回来更新我的职务与最终结果 - 感谢所有谁回答!

public struct Color555 : IEquatable<Color555>, IComparable<Color555>, IEquatable<ushort>, IComparable<ushort>
{
    public static readonly Color555 MinValue = ushort.MinValue;
    public static readonly Color555 MaxValue = ushort.MaxValue;

    private readonly ushort _Value;

    public Color555(Color value)
    {
        uint c = (uint)value.ToArgb();
        _Value = (ushort)(((c >> 16) & 0x8000 | (c >> 9) & 0x7C00 | (c >> 6) & 0x03E0 | (c >> 3) & 0x1F));
    }

    public Color555(ushort value)
    {
        _Value = value;
    }

    public override int GetHashCode()
    {
        return _Value.GetHashCode();
    }

    public override bool Equals(object obj)
    {
        return (obj is ushort && Equals((ushort)obj)) || (obj is Color555 && Equals((Color555)obj));
    }

    public bool Equals(ushort other)
    {
        return _Value == other;
    }

    public bool Equals(Color555 other)
    {
        return _Value == other._Value;
    }

    public int CompareTo(Color555 other)
    {
        return _Value.CompareTo(other._Value);
    }

    public int CompareTo(ushort other)
    {
        return _Value.CompareTo(other);
    }

    public override string ToString()
    {
        return String.Format("{0}", _Value);
    }

    public string ToString(string format)
    {
        return String.Format(format, _Value);
    }

    public string ToString(IFormatProvider provider)
    {
        return String.Format(provider, "{0}", _Value);
    }

    public string ToString(string format, IFormatProvider provider)
    {
        return String.Format(provider, format, _Value);
    }

    public int ToArgb()
    {
        return ToColor().ToArgb();
    }

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

        return Color.FromArgb((a * 0x1FE00) | rgb | ((rgb >> 5) & 0x070707));
    }

    public static bool operator ==(Color555 l, Color555 r)
    {
        return l.Equals(r);
    }

    public static bool operator !=(Color555 l, Color555 r)
    {
        return !l.Equals(r);
    }

    public static implicit operator Color555(Color value)
    {
        return new Color555(value);
    }

    public static implicit operator Color555(ushort value)
    {
        return new Color555(value);
    }

    public static implicit operator ushort(Color555 value)
    {
        return value._Value;
    }
}

Answer 1:

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

甲RGB555彩色每个像素使用5个比特(与不具有alpha通道),所以红色,绿色和蓝色可从0-31的每个取的值。

从一个转换到另一个,我们需要到值0-31的值0-255映射。 这显然是一种有损的过程; 我们根本不能代表一切可能的Color和许多不同的Color值将被映射到相同的Color555

该简单的映射只是截断,在这里我们除以8并丢弃剩余部分。 这将映射0-7为0,8-15为1,...,248-255〜31这可以作为一个向右的三位位位移写入。

然后,我们需要将值组合成一个单一的16位的值,它是由红色和绿色分量左移来完成。

(出现您的示例代码基于高位被设置alpha通道,所以我们可以以相同的方式向后转换alpha通道在这种情况下,我们需要对映射256个可能值,以2:0或1。我“VE选择为在半整除alpha通道;还有其他可能的映射)。

全部放在一起,它应该是这样的:

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


Answer 2:

为什么不使用呢?

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


文章来源: C# - Convert ARGB Color to RGB555