3

トラックバーをスライドするときに画像の色合いをスムーズに変更するためのより良い方法はありますか? 私がやっていることは、ピクセルごとの RGB 値を取得し、彩度と明るさを計算してから値を入れることです。画像のサイズは、色相が更新される速度に影響します。Photoshop の画像の色相機能は、色相を 0 から 360 まで滑らかに変化させます。

data = editImage.LockBits(new Rectangle(0, 0, editWidth, editHeight), 
ImageLockMode.ReadWrite, PixelFormat.Format24bppRgb);
byte* dataPtr = (byte*)data.Scan0;
h = trackBar1.Value / 60.0;
D = 1 - Math.Abs((h % 2) - 1);

if (h >= 0 && h < 1)
{
    for (int i = 0; i < editHeight; i++)
    {
        offsetStride = i * data.Stride;
        for (int j = 0; j < editWidth; j++)
        {
            blue = dataPtr[(j * 3) + offsetStride];
            green = dataPtr[(j * 3) + offsetStride + 1];
            red = dataPtr[(j * 3) + offsetStride + 2];

            if (green > blue) max = green;
            else max = blue;
            if (red > max) max = red;

            if (green < blue) min = green;
            else min = blue;
            if (red < min) min = red;

            s = (max == 0) ? 0 : 1d - (1d * min / max);
            v = max / 255d;

            C = v * s;
            X = C * D;
            E = v - C;

            dataPtr[(j * 3) + offsetStride] = (byte)(min);
            dataPtr[(j * 3) + offsetStride + 1] = (byte)((X + E) * 255);
            dataPtr[(j * 3) + offsetStride + 2] = (byte)(max);
        }
    }
}
4

2 に答える 2

4

色相が変化するモノクロ画像が必要な場合、最も効率的な方法は、赤、黄、緑、シアン、青、マゼンタの画像を生成し、必要に応じてそれらの間を補間することです。

したがって、10% の回転で画像を生成するには、50/60 * 赤 + 10/60 * 黄色を追加して表示します。

実際、6 つのイメージすべてを生成する必要はありません。赤と黄色の画像を生成するだけで十分です。たとえば、青の画像は赤の画像にすぎませんが、赤と青のピクセルが入れ替わっているため、オンザフライで生成できるその他のものがあります (赤から黄色を派生させることもできます)。しかし、おそらく最も簡単なのは、6 つの画像から始めて、後でその最適化を追加することです。

初期のカラー画像の 1 つを生成するコードは、(一見すると) 上記のものと似ていますが、HSV から RGB への最終ステップは少し疑わしいように見えます - ウィキペディアのページはこれを説明するのに適しています (C# には含まれている可能性があります)。この変換を行うためのライブラリ関数)。

[あなたの明確化を考えると、以下はあなたがしていることとは関係ありません]

色相をピクセルごとにシフトする場合 (緑がシアンに移動すると赤が黄色に移動するため)、最初に画像全体を HSV に変換してから作業することで、時間を節約できます。

複数の画像を生成し (たとえば、色相を 10 度ずつ回転させて)、それらの間を補間することで、(色相をシフトするとき) より多くの時間を節約できます。ただし、一部のピクセル (補間中に色相が 60 度の倍数を移動するピクセル) は特別な処理が必要なため、モノクロの場合よりも複雑です。したがって、それらを事前に検出し、その場で計算する必要もあります。中間画像が多いほど、特別なケースに必要なピクセルが少なくなるというトレードオフがあります。実際には、個別のイメージを遅延して (オンデマンドで) 生成すると、通常は小さな変更しか加えないため、起動が速くなります。

于 2011-08-06T02:22:26.213 に答える
2

最小値と最大値の範囲は 0 から 255 までしかないため、ルックアップ テーブルを使用して「s」の計算を取り除くことができますs = getS(min, max)。C と E の値も、おそらくこのテーブルに保持される可能性があります (しかし、遅れており、それほど詳しくは調べていません)。

getS テーブルの各要素は、次のように事前に計算されます。

for (int min = 0; min < 255; min++)
{
    for (int max = 0; max < 255; max++)
    {
        tableS[min, max] = (max == 0) ? 0 : 1d - (1d * min / max);
    }
}

Photoshop のコードは、最大のパフォーマンスを得るためにおそらくアセンブラーでも記述されています。

これが大きな効果をもたらすかどうかを確認するために、すべての色相計算コードをコメントアウトし、偽のデータをコピーするだけでどのように機能するかを確認できます。Photoshop のように高速である場合、これらの計算がボトルネックであることがわかります。

于 2011-08-06T02:07:41.443 に答える