5

すべてのアイコンが PNG である Silverlight アプリケーションに取り組んでいます。

これらすべてのアイコンの色は、アルファ値に応じて黒または黒から灰色になります。すべての PNG には透明な背景があります。

私のアプリケーション内で、黒またはグレーからピクセル単位で色を変更したいと考えています。たとえば、赤 (黒の前) または明るい赤 (グレーの前) に変更します。

すべてのピクセルのバイトを見ていくと、完全な黒のピクセルはすべてアルファ値が 255 であることがわかりました。黒の場合、RGB 値はすべて 0 です。

私の考えは、すべてのピクセルの色を変更するが、アルファ値を保持して、PNG が元の外観を維持することでした。

この目的のために、次のような小さな関数を作成しました。

private static WriteableBitmap ColorChange(WriteableBitmap wbmi, System.Windows.Media.Color color)
    {
        for (int pixel = 0; pixel < wbmi.Pixels.Length; pixel++)
        {
            if (wbmi.Pixels[pixel] != 0)
            {
                byte[] colorArray   = BitConverter.GetBytes(wbmi.Pixels[pixel]);
                byte blue           = colorArray[0];
                byte green          = colorArray[1];
                byte red            = colorArray[2];
                byte alpha          = colorArray[3];

                if (alpha > 0)
                {

                    //HERE, I change the color, but keep the alpha
                    //
                    wbmi.Pixels[pixel] = Gui.Colors.ToInt.Get(color,alpha);

                    colorArray  = BitConverter.GetBytes(wbmi.Pixels[pixel]);
                    blue        = colorArray[0];
                    green       = colorArray[1];
                    red         = colorArray[2];
                    alpha       = colorArray[3];

                    String colorString = "blue: " + blue.ToString() + "green: " + green.ToString() + "red: " + red.ToString() + "alpha: " + alpha.ToString();
                    System.Diagnostics.Debug.WriteLine(colorString);
                }
            }
        }
        return wbmi;
    }

そして、色を変更するがアルファを維持するための小さなヘルパー クラス:

namespace Gui.Colors
{
public class ToInt
{

    public static int Get(System.Windows.Media.Color color, Byte alpha)
    {
        color.A = alpha;
        return color.A << 24 | color.R << 16 | color.G << 8 | color.B;
    }
}
}

私の問題は、アルファが 255 (グレー) 未満のピクセルが問題であることを明確に確認できることです。アルファ値は保持され、色は変更されていますが、ピクセルは異なって見え、透明ではなくなります。これにより、エッジがぼろぼろに見えます。

長い話、短い質問:私のコードを見て - 問題は何ですか? 元の PNG の透明度を使用して、ピクセルごとの色変換を行うにはどうすればよいですか?

私の英語を許してください。私は英語のネイティブスピーカーではありません。

4

1 に答える 1

6

このケースは解決しました。Rene Schulte によって書かれた WriteableBitmapExtensions クラスを見つけました。

この拡張クラスは、次の機能を提供します (さらに多くの...):

private const float PreMultiplyFactor = 1 / 255f;

public static void SetPixeli(this WriteableBitmap bmp, int index, byte a, Color color)
  {
     float ai = a * PreMultiplyFactor;
     bmp.Pixels[index] = (a << 24) | ((byte)(color.R * ai) << 16) | ((byte)(color.G * ai) << 8) | (byte)(color.B * ai);
  }

色を変更するルーチンは次のようになります。

    /// <summary>
    /// Changes the color of every pixel in a WriteableBitmap with an alpha value > 0 to the desired color.
    /// </summary>
    /// <param name="wbmi"></param>
    /// <param name="color"></param>
    /// <returns></returns>
    private static WriteableBitmap ColorChange(WriteableBitmap wbmi, System.Windows.Media.Color color)
    {
        for (int pixel = 0; pixel < wbmi.Pixels.Length; pixel++)
        {
            byte[] colorArray = BitConverter.GetBytes(wbmi.Pixels[pixel]);
            byte blue         = colorArray[0];
            byte green        = colorArray[1];
            byte red          = colorArray[2];
            byte alpha        = colorArray[3];

            if (alpha > 0)
            {
                wbmi.SetPixeli(pixel, alpha, color);
            }
        }

        wbmi.Invalidate();
        return wbmi;
    }

Rene Schulte の作品はこちらからダウンロードできます。

http://dotnet.dzone.com/sites/all/files/WriteableBitmapExtensions.zip

プロジェクト全体は次の場所にあります。

http://writeablebitmapex.codeplex.com/

ここSOでこの質問に誰も答えなかったので、大砲はRene Schulteに敬意を表します。YMMD!:)

ちなみに、私はNounProjectの SVG を使用しており、それらを目的のサイズの PNG に変換してから、このメソッドを使用して色を付けています。NounProject のシンボルはすべて黒なので、高品質のシンボルを取得するのに適しています。

于 2013-05-05T13:13:13.063 に答える