C# - Convert ARGB Color to RGB555

删除回忆录丶 提交于 2019-12-11 06:39:49

问题


I have an algorithm that converts RGB555 values to a System.Drawing.Color object;

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

A friend wrote this method for me (bitwise shifting is a bit over my head), what would be the most efficient way to reverse this code?

Thanks for any advice, I've been trying to find an answer for a few days, so any insight would be a breath of fresh air!

EDIT

This problem has been solved for a while, but I thought I'd come back and update my post with the final results - Thanks to all who answered!

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

回答1:


A Color uses 32 bits per pixel: 8 bits each for the alpha, red, green, and blue values. (This means that the values for each component can range from 0 to 255.)

A RGB555 color uses 5 bits per pixel (and has no alpha channel), so red, green and blue can each take a value from 0-31.

To convert from one to the other, we need to map the values 0-255 on to the values 0-31. This will obviously be a lossy process; we simply can't represent every possible Color and many different Color values will be mapped to the same Color555.

The simplest mapping is just truncation, where we divide by 8 and discard the remainder. This maps 0-7 to 0, 8-15 to 1, ..., 248-255 to 31. This can be written as a rightwards bitshift by three bits.

We then need to combine the values into a single 16-bit value, which is accomplished by shifting the red and green components to the left.

(Your sample code appears to be setting the alpha channel based on the high bit, so we can convert the alpha channel backwards in the same manner. In this case, we need to map 256 possible values on to 2: 0 or 1. I've chosen to divide the alpha channel exactly in half; there are other possible mappings.)

Putting it all together, it should look like:

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



回答2:


Why not use this?

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


来源:https://stackoverflow.com/questions/15595457/c-sharp-convert-argb-color-to-rgb555

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!