С# — преобразовать цвет ARGB в RGB555

У меня есть алгоритм, который преобразует значения 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;
    }
}

person Vorspire    schedule 24.03.2013    source источник
comment
как насчет ToArgb   -  person Chase Florell    schedule 24.03.2013
comment
Первым шагом было бы понять это. Если вы не можете понять сдвиг битов и не хотите этого делать, вы не заслуживаете использования этого кода.   -  person Jonathon Reinhart    schedule 24.03.2013
comment
Вы знаете, что вы не можете получить точные данные, так как вы выбрасываете данные, верно?   -  person boxed    schedule 24.03.2013
comment
@JonathonReinhart прав. Возьмите общую идею, которую вы пытаетесь реализовать, и не усложняйте ее. Цвет не трудно понять в общей схеме вещей.   -  person Chase Florell    schedule 24.03.2013
comment
@Chase Florell - я хочу преобразовать ARGB в RGB555, метод, который я опубликовал, уже делает то, что вы предлагаете.   -  person Vorspire    schedule 24.03.2013
comment
@Jonathon Reinhart - я не помню, чтобы я что-то говорил о нежелании учиться, поэтому любые советы по пониманию этого были бы глотком свежего воздуха - не то чтобы я ожидал, что кто-то придет и сделает это за меня. Я не просто какой-то копипастный разработчик, так уж получилось, что мне наконец-то понадобилось задать вопрос на общедоступном веб-сайте после 10 лет самостоятельных размышлений.   -  person Vorspire    schedule 24.03.2013
comment
На самом деле, после повторного прочтения комментария @JonathonReinhart я хотел бы отменить свой голос. Я пропустил чтение, не стоит использовать этот код, следует подумать о чем-то другом... честно говоря, я не читал дальше первой строки. Виноват. Я думаю, что есть много способов содрать шкуру с кошки, и если вы хотите научиться, это здорово. Я скажу, что раз в вашем методе используется FromArgb, то логично, что реверс должен быть ToArgb. У меня нет перед собой IDE, чтобы возиться с ней, но это должно быть хорошей отправной точкой.   -  person Chase Florell    schedule 24.03.2013
comment
@ChaseFlorell Перечитав свой собственный комментарий, я согласен, что он был немного резким. Слишком часто на этом сайте пользователи с 1 представителем спрашивают, пожалуйста, дайте мне вопросы по кодам. Но мое общее сообщение остается прежним: первым шагом к обращению этого алгоритма будет его понимание. Вы говорите, что побитовый сдвиг немного выше моего понимания, поэтому я думаю, что первым шагом будет понимание двоичных чисел и побитового сдвига. Затем вы увидите, что функция извлекает 5-битные числа из 16-битного ввода. Вы действительно не проявили никаких усилий в этом вопросе, что спровоцировало мой разочарованный комментарий.   -  person Jonathon Reinhart    schedule 24.03.2013
comment
@JonathonReinhart - я полностью понимаю ваше разочарование, я понимаю, как работает побитовое смещение, но когда я пытаюсь положить ручку на бумагу, цифры меня смущают. Я очень хочу учиться, просто это занимает немного больше времени, чем у большинства, когда дело доходит до математики.   -  person Vorspire    schedule 24.03.2013
comment
Когда вы говорите изменить этот код, что вы имеете в виду? Будете ли вы предоставлять только цвета, которые были результатом этого кода, или вам нужна функция, которая работает со всеми цветами? В последнем случае вам также нужно подумать о том, как вы хотите обрабатывать цвета, которые не совпадают точно.   -  person jswolf19    schedule 24.03.2013
comment
@ jswolf19. Желаемым результатом было бы, чтобы Color555 был посредником между UInt16 и System.Drawing.Color. var c = новый Color555 (Color.Green); Я говорю «обратный», потому что он по существу противоположен методу «ToColor».   -  person Vorspire    schedule 24.03.2013


Ответы (2)


Color использует 32 бита на пиксель: по 8 бит для значений альфа, красного, зеленого и синего. (Это означает, что значения для каждого компонента могут находиться в диапазоне от 0 до 255.)

Цвет RGB555 использует 5 бит на пиксель (и имеет нет альфа-канала), поэтому красный, зеленый и синий могут принимать значения от 0 до 31.

Чтобы преобразовать одно в другое, нам нужно сопоставить значения 0-255 со значениями 0-31. Очевидно, что это будет процесс с потерями; мы просто не можем представить все возможные Color, и многие разные значения Color будут сопоставлены с одним и тем же Color555.

Самое простое отображение — это просто усечение, когда мы делим на 8 и отбрасываем остаток. Это отображает 0-7 в 0, 8-15 в 1, ..., 248-255 в 31. Это можно записать как битовый сдвиг вправо на три бита.

Затем нам нужно объединить значения в одно 16-битное значение, что достигается путем сдвига красного и зеленого компонентов влево.

(Похоже, ваш пример кода устанавливает альфа-канал на основе старшего бита, поэтому мы можем преобразовать альфа-канал в обратном направлении таким же образом. В этом случае нам нужно сопоставить 256 возможных значений с 2: 0 или 1. I решили разделить альфа-канал ровно пополам; есть и другие возможные отображения.)

Собрав все вместе, должно получиться так:

public Color555(Color color)
{
    _Value = (ushort) ((color.A >= 128 ? 0x8000 : 0x0000) |
        ((color.R & 0xF8) << 7) | ((color.G & 0xF8) << 2) | (color.B >> 3));
}
person Bradley Grainger    schedule 24.03.2013
comment
Предоставленный код, кажется, использует самый старший бит в качестве альфа-флага, для чего он стоит. - person jswolf19; 24.03.2013

Почему бы не использовать это?

{
    Color c = ColorTranslator.FromHtml("#555");
    string s = ColorTranslator.ToHtml(c);
}
person Alina B.    schedule 24.03.2013
comment
Я собираюсь хорошенько взглянуть на ColorTranslator, спасибо, что поделились этим. Но, глядя на документацию, я не уверен, что это даст желаемые результаты - придется провести некоторое тестирование. - person Vorspire; 24.03.2013
comment
RGB 555 очень ОЧЕНЬ отличается от ...Html('#555'); - person Chase Florell; 24.03.2013
comment
@ user2203880 взгляните на эту ссылку, чтобы получить качественную информацию о том, что вы пытаетесь сделать. msdn.microsoft.com/en -нас/библиотека/окна/рабочий стол/ - person Chase Florell; 24.03.2013