-1

ビットマップのピクセルを特定の色から新しい特定の色に再色付けする小さな関数があります。

私がコードで抱えている問題は次のとおりです。

1)この関数は、しきい値があるため考慮すべきではない白いピクセルを再マッピングする結果を提供します...(この計算を間違って定義していない限り)

2)特定の色が指定されている場合、たとえばLimeGreenの奇妙な結果が関数から返された画像に表示されます(これは、加算または減算の場合のバイトタイプのオーバーフローによるものと思われます)

私が使用しているベースイメージはここにあります:

http://www.freeimagehosting.net/uploads/c8745a9de1.png

私が得た結果はここで見つけることができます:

freeimagehosting.net/uploads/fa48e5a0eb.png(remapColorとしてColor.Magenta、newColorとしてColor.Redで呼び出され、白いピクセルが影響を受け、グラデーションの終わりが正しく色付けされていないようです)

freeimagehosting.net/uploads/8faec6a569.png(remapColorとしてColor.Magenta、newColorとしてColor.Yellowで呼び出され、白いピクセルが影響を受け、グラデーションの終わりが正しく色付けされていないようです)

freeimagehosting.net/uploads/2efd4c04aa.png(remapColorとしてColor.Magenta、newColorとしてColor.Blueで呼び出され、グラデーションが正しく色付けされていないようです)

freeimagehosting.net/uploads/defdf04e16.png(remapColorとしてColor.Magenta、newColorとしてColor.Tealで呼び出され、白いピクセルが影響を受け、グラデーションが正しく計算されていないようです)

このコードのために私が持っている関数は以下の通りです:提案ごとに更新されました

public unsafe static Bitmap RecolorImage(Bitmap original, Color remapColor, Color newColor)
    {
        Bitmap result = new Bitmap(original.Width, original.Height);

        //lock the original bitmap in memory
        BitmapData originalData = original.LockBits(
           new Rectangle(0, 0, original.Width, original.Height),
           ImageLockMode.ReadOnly, PixelFormat.Format32bppArgb);

        //lock the new bitmap in memory
        BitmapData newData = result.LockBits(
           new Rectangle(0, 0, original.Width, original.Height),
           ImageLockMode.WriteOnly, PixelFormat.Format32bppArgb);

        //set the number of bytes per pixel
        int pixelSize = 4;

        int rthreshold = 128;
        int gthreshold = 128;
        int bthreshold = 128;

        for (int y = 0; y < original.Height; y++)
        {
            //get the data from the original image
            byte* oRow = (byte*)originalData.Scan0 + (y * originalData.Stride);

            //get the data from the new image
            byte* nRow = (byte*)newData.Scan0 + (y * newData.Stride);

            for (int x = 0; x < original.Width; x++)
            {
                //examine the rgb values
                byte r = (byte)((oRow[x * pixelSize]));
                byte g = (byte)((oRow[x * pixelSize + 1]));
                byte b = (byte)((oRow[x * pixelSize + 2]));
                byte a = (byte)((oRow[x * pixelSize + 3]));

                if (a > 0 && 
                    Math.Abs(remapColor.R - r) <= rthreshold &&
                    Math.Abs(remapColor.B - b) <= bthreshold &&
                    Math.Abs(remapColor.G - g) <= gthreshold 
                    )
                {
                    if (newColor.R == 0)
                    {
                        r = 0;
                    }
                    else
                    {
                        if (newColor.R > remapColor.R)
                            r = (byte)(r - newColor.R);
                        else
                            r = (byte)(r + newColor.R);
                    }

                    if (newColor.G == 0)
                    {
                        g = 0;
                    }
                    else
                    {
                        if (newColor.G > remapColor.G)
                            g = (byte)(g - newColor.G);
                        else
                            g = (byte)(g + newColor.G);
                    }

                    if (newColor.B == 0)
                    {
                        b = 0;
                    }
                    else
                    {
                        if (newColor.B > remapColor.B)
                            b = (byte)(b - newColor.B);
                        else
                            b = (byte)(b + newColor.B);
                    }
                }


                //set the new image's pixel remaped pixel color
                nRow[x * pixelSize] = b; //B
                nRow[x * pixelSize + 1] = g; //G
                nRow[x * pixelSize + 2] = r; //R
                nRow[x * pixelSize + 3] = a; //A
            }
        }

        original.UnlockBits(originalData);
        result.UnlockBits(newData);


        return result;
    }        

何が...

私がやろうとしていることは可能ですか?

信頼できますか?

私のコードにバグがありますか?

グラデーションを使用してビットマップでこの「再マッピング可能な手法」を実現するためのより良い方法はありますか?

お時間をいただきありがとうございます。

4

2 に答える 2

0

しきい値テストが正しくないようです。行を取る:

remapColor.R - r <= rthreshold

現在のピクセルが白の場合、r255になり、テストは、何が何であっても、常に真にremapColor.Rなりrthresholdます。

うまくいくかもしれないと思いますMath.Abs(remapColor.R - r)

そして、あなたはおそらくあなたのバイト値が範囲外であることについて正しいでしょう。しきい値テストを修正すると、それが起こらなくなる可能性があります。それ以外の場合は、境界チェックインを行って、どこで発生しているかを確認してください。

于 2010-07-13T18:17:19.383 に答える
0

色空間とその裏付けとなる理論に関するさまざまな資料を研究すれば可能かもしれないが、私はこれを決定した。これには、しきい値の計算とremapColorへの正規化よりも少し時間がかかるようです。

ラスタービットマップイメージに対してこのタイプの変更を実行する代わりに、グラフィックをベクトル形式で変更することを提案します。

プロセスは次のようになります。

グラフィックは、デザイナーが作業しているイメージングスイートで作成されます。

それらはベクター形式で保存されます。たとえば、SVGを使用すると、カスタマイズ可能なパスに名前を付けたり、トラバースしたり、SVGレンダリングエンジン( http://svg.codeplex.com/)を使用してプログラムで(必要に応じて色以上に)変更したりできます。

このソリューションでは、サポートされている場合はSVGをブラウザーに直接出力してクライアントで直接変更を行うか、サーバーを使用して必要に応じてPNGとして出力することができます。

この配置により、最初に一緒にハックしようとしていたものよりも柔軟性と堅牢なソリューションが提供されると思います。

お時間をいただきありがとうございます!

于 2010-07-14T12:34:02.900 に答える