4

さまざまなレベルの透明度を持つ黒と白のRGBピクセルで構成された画像があるとします。次に、GDI +を使用してすべてのピクセルの透明度レベルを維持し、黒のピクセルだけを赤に変換して、白のピクセルは影響を受けないようにします。

カラーマップは次のようになると思います。

 |0 0 0 0 0|
 |0 0 0 0 0|
 |0 0 0 0 0|
 |0 0 0 1 0|
 |1 0 0 0 1|

しかし、各ピクセルを順番にループしてその色をテストする以外に、そのマップを黒いピクセルだけに適用するにはどうすればよいでしょうか。

4

3 に答える 3

7

主な質問に答えるには、行列は条件のない変換にすぎないため、特定の色を置き換えるために行列を使用する方法はありません

あなたの問題を解決するために:あなたが使用している組み合わせ(黒と白)のために、マトリックスを使用することができます!以下の詳細な回答を参照してください...

非常に良いリファレンス: カラー変換とカラーマトリックス


マトリックスの推測に非常に近いですが、すべてのRGBA値をそのまま保持しているわけではありません。ここを見てください:

  R   G   B   A   W
 ___________________
| 1 | 0 | 0 | 0 | 0 |
| 0 | 1 | 0 | 0 | 0 |
| 0 | 0 | 1 | 0 | 0 |
| 0 | 0 | 0 | 1 | 0 |
| 1 | 0 | 0 | 0 | 1 |
 ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯

対角線を通して、現在のRGBA値1維持しています。onを指定することで、その値を最大にすることもできます。1[4][0]

黒と白を使用する特定のケースでは、白のRGB値がすでに最大(255、255、255)になっているため、黒の色のみを置き換えることができます。

したがって、上記のマトリックスを通じて、基本的に次のように言っています。すべてのRGBを現在の値に保ちます、赤を常に255にします。


シーケンス(R、G、B、A)を使用し、上記のルールを適用する詳細な例:最大で赤= 255、それ以外はすべて同じ。

  • 見つかった(0、0、0、128)=結果(255、0、0、128);
  • 見つかった(0、0、0、192)=結果(255、0、0、192);
  • 見つかった(255、255、255、128)=結果(255、255、255、128);
  • 見つかった(255、255、255、255)=結果(255、255、255、255);

ご覧のとおり、赤のコンポーネントは常に最大に設定され、残りは維持されます。


サンプル画像:

サンプルの色変換

左側にはアルファ値が指定された元の色が含まれ、右側には上記の変換が適用された同じ画像が含まれています。左側の円は次のように構成されています。

                  R    G    B    A   |   R    G    B    A
               ______________________|_______________________
circle[0,0] = | (255,   0,   0,   0) | (255,   0,   0,  64) | = circle[0,1]
      [1,0] = | (  0,   0,   0,   0) | (  0,   0,   0,  64) | =       [1,1]
      [2,0] = | (255, 255, 255,   0) | (255, 255, 255,  64) | =       [2,1]
      [3,0] = | (255,   0,   0, 128) | (255,   0,   0, 255) | =       [3,1]
      [4,0] = | (  0,   0,   0, 128) | (  0,   0,   0, 255) | =       [4,1]
      [5,0] = | (255, 255, 255, 128) | (255, 255, 255, 255) | =       [5,1]
               ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯

サンプル画像を生成するためのC#コード:

using (Bitmap myBitmap = new Bitmap(102, 302))
{
    Graphics g = Graphics.FromImage(myBitmap);
    g.Clear(Color.Transparent);
    g.FillEllipse(new SolidBrush(Color.FromArgb(0, Color.Red)), new Rectangle(1, 1, 50, 50));
    g.FillEllipse(new SolidBrush(Color.FromArgb(0, Color.Black)), new Rectangle(1, 51, 50, 50));
    g.FillEllipse(new SolidBrush(Color.FromArgb(0, Color.White)), new Rectangle(1, 101, 50, 50));

    g.FillEllipse(new SolidBrush(Color.FromArgb(64, Color.Red)), new Rectangle(51, 1, 50, 50));
    g.FillEllipse(new SolidBrush(Color.FromArgb(64, Color.Black)), new Rectangle(51, 51, 50, 50));
    g.FillEllipse(new SolidBrush(Color.FromArgb(64, Color.White)), new Rectangle(51, 101, 50, 50));

    g.FillEllipse(new SolidBrush(Color.FromArgb(128, Color.Red)), new Rectangle(1, 151, 50, 50));
    g.FillEllipse(new SolidBrush(Color.FromArgb(128, Color.Black)), new Rectangle(1, 201, 50, 50));
    g.FillEllipse(new SolidBrush(Color.FromArgb(128, Color.White)), new Rectangle(1, 251, 50, 50));

    g.FillEllipse(new SolidBrush(Color.FromArgb(255, Color.Red)), new Rectangle(51, 151, 50, 50));
    g.FillEllipse(new SolidBrush(Color.FromArgb(255, Color.Black)), new Rectangle(51, 201, 50, 50));
    g.FillEllipse(new SolidBrush(Color.FromArgb(255, Color.White)), new Rectangle(51, 251, 50, 50));
    g.DrawRectangle(Pens.Black, 0, 0, myBitmap.Width - 1, myBitmap.Height - 1);

    e.Graphics.DrawImage(myBitmap, 0, 0);

    ColorMatrix colorMatrix = new ColorMatrix(
        new Single[][]
        {
            new [] { 1f, 0, 0, 0, 0 },
            new [] { 0f, 1, 0, 0, 0 },
            new [] { 0f, 0, 1, 0, 0 },
            new [] { 0f, 0, 0, 1, 0 },
            new [] { 1f, 0, 0, 0, 1 }
        });

    using (ImageAttributes imageAttr = new ImageAttributes())
    {
        imageAttr.SetColorMatrix(colorMatrix);

        Rectangle rect = new Rectangle(150, 0, myBitmap.Width, myBitmap.Height);
        e.Graphics.DrawImage(myBitmap, rect, 0, 0, myBitmap.Width, myBitmap.Height, GraphicsUnit.Pixel, imageAttr);
    }
}
于 2013-04-06T23:44:20.887 に答える
3

黒色は0で表され、白色は1で表されます。

黒のピクセルで数学を機能させるに、次のことを行う必要があります。

  1. 画像の色を反転します(透明度を失うことなく)。
  2. 白い色(元の黒)をアクア(赤の逆)に変換します。
  3. 色を元に戻します。

手順2のカラーマップは次のようになります。

|0 0 0 0 0|
|0 1 0 0 0|
|0 0 1 0 0|
|0 0 0 1 0|
|0 0 0 0 1|

結果は次のようになります。

  1. 黒は赤です。
  2. 白い色はまだ白い。
于 2013-04-07T10:10:41.950 に答える
2

説明した他の手法に加えて、カラーリマップテーブルを使用して、画像内の特定の個々の色(の短いリスト)を変換できます。再マップテーブルは、GraphicsオブジェクトのDrawImageメソッドに渡されるImageAttributesオブジェクトの一部です。MSDNドキュメントから:

GDI +が画像を描画すると、画像の各ピクセルが古い色の配列と比較されます。ピクセルの色が古い色と一致する場合、その色は対応する新しい色に変更されます。色はレンダリングのためにのみ変更されます—画像自体(ImageまたはBitmapオブジェクトに格納されている)の色の値は変更されません。

于 2013-04-07T12:29:53.913 に答える