1

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

2 に答える 2

2

AColorはピクセルあたり 32 ビットを使用します。アルファ、赤、緑、青の値にそれぞれ 8 ビットです。(これは、各コンポーネントの値が 0 から 255 の範囲であることを意味します。)

RGB555カラーは 1 ピクセルあたり 5 ビットを使用するため (アルファ チャネルはありません)、赤、緑、青はそれぞれ 0 ~ 31 の値を取ることができます。

一方から他方に変換するには、値 0 ~ 255 を値 0 ~ 31 にマッピングする必要があります。これは明らかに損失の多いプロセスです。可能なすべてを表すことはできずColor、多くの異なるColor値が同じ にマッピングされますColor555

最も単純なマッピングは切り捨てで、8 で割って余りを破棄します。これは、0 ~ 7 を 0、8 ~ 15 を 1、...、248 ~ 255 を 31 にマップします。これは、3 ビット右へのビットシフトとして書き込むことができます。

次に、これらの値を 1 つの 16 ビット値に結合する必要があります。これは、赤と緑のコンポーネントを左にシフトすることによって実現されます。

(サンプル コードは、上位ビットに基づいてアルファ チャネルを設定しているように見えるため、同じ方法でアルファ チャネルを逆方向​​に変換できます。この場合、256 の可能な値を 2: 0 または 1 にマップする必要があります。アルファ チャネルを正確に半分に分割することを選択しました。他にも可能なマッピングがあります。)

すべてをまとめると、次のようになります。

public Color555(Color color)
{
    _Value = (ushort) ((color.A >= 128 ? 0x8000 : 0x0000) |
        ((color.R & 0xF8) << 7) | ((color.G & 0xF8) << 2) | (color.B >> 3));
}
于 2013-03-24T06:06:42.403 に答える
-1

これを使ってみませんか?

{
    Color c = ColorTranslator.FromHtml("#555");
    string s = ColorTranslator.ToHtml(c);
}
于 2013-03-24T05:27:32.997 に答える