2

ビットマップ イメージをフィルタリングして、色相、彩度、および明度の値を増減させようとしています。

私のコードは完全に機能していますが、遅いです。

元のソースと現在の宛先の 2 つのビットマップをメモリにロックしています。ユーザーは、さまざまなトラックバーコントロールを移動して、HSL 値に変換される各値を変更できます。たとえば、トラックバーの値は -1.0 ~ 1.0 の範囲に対応します。

トラックバーの値が変更されたというイベントがスローされるたびに、宛先ビットマップをロックし、HSL 値をソース ビットマップに適用して、結果を宛先ビットマップに格納する関数を実行します。完了したら、宛先ビットマップのロックを解除し、画面にイメージをペイントします。

以前は、バイトごとの操作を行っていたため、他のフィルターにルックアップ テーブルを使用していました。ただし、代わりに HSL を使用してそれを適用する方法がわかりません。私が使用しているコードは次のとおりです。

byte red, green, blue;

for (int i = 0; i < sourceBytes.Length; i += 3)
{
    blue = sourceBytes[i];
    green = sourceBytes[i + 1];
    red = sourceBytes[i + 2];

    Color newColor = Color.FromArgb(red, green, blue);

    if (ModifyHue)
        newColor = HSL.ModifyHue(newColor, Hue);

    if (ModifySaturation)
        newColor = HSL.ModifySaturation(newColor, Saturation);

    if (ModifyLightness)
        newColor = HSL.ModifyBrightness(newColor, Lightness);

    destBytes[i] = newColor.B;
    destBytes[i + 1] = newColor.G;
    destBytes[i + 2] = newColor.R;
}

そして、ここに私のModifyBrightness関数があります:

public static Color ModifyBrightness(Color color, double brightness)
{
    HSL hsl = FromRGB(color);
    hsl.L *= brightness;
    return hsl.ToRGB();
}

したがって、基本的に明るさスライダーが真ん中にある場合、その値は 0 になり、関数に渡すときに「1.0」に変換されるため、明るさが 1.0 倍されます。つまり、変化しません。スライダーを右端までドラッグすると、値が 100 になり、モディファイアが 2.0 になるので、明るさの値を 2.0 倍して 2 倍にします。

4

2 に答える 2

5

最終的に ImageAttributes と ColorMatrix を調査したところ、パフォーマンスが優れていることがわかりました。

彩度と明るさのフィルターを実装する方法は次のとおりです。

// Luminance vector for linear RGB
const float rwgt = 0.3086f;
const float gwgt = 0.6094f;
const float bwgt = 0.0820f;

private ImageAttributes imageAttributes = new ImageAttributes();
private ColorMatrix colorMatrix = new ColorMatrix();
private float saturation = 1.0f;
private float brightness = 1.0f;

protected override void OnPaint(object sender, PaintEventArgs e)
{
    base.OnPaint(sender, e);

    e.Graphics.DrawImage(_bitmap, BitmapRect, BitmapRect.X, BitmapRect.Y, BitmapRect.Width, BitmapRect.Height, GraphicsUnit.Pixel, imageAttributes);
}

private void saturationTrackBar_ValueChanged(object sender, EventArgs e)
{
    saturation = 1f - (saturationTrackBar.Value / 100f);

    float baseSat = 1.0f - saturation;

    colorMatrix[0, 0] = baseSat * rwgt + saturation;
    colorMatrix[0, 1] = baseSat * rwgt;
    colorMatrix[0, 2] = baseSat * rwgt;
    colorMatrix[1, 0] = baseSat * gwgt;
    colorMatrix[1, 1] = baseSat * gwgt + saturation;
    colorMatrix[1, 2] = baseSat * gwgt;
    colorMatrix[2, 0] = baseSat * bwgt;
    colorMatrix[2, 1] = baseSat * bwgt;
    colorMatrix[2, 2] = baseSat * bwgt + saturation;

    imageAttributes.SetColorMatrix(colorMatrix, ColorMatrixFlag.Default, ColorAdjustType.Bitmap);

    Invalidate();
}

private void brightnessTrackBar_ValueChanged(object sender, EventArgs e)
{
    brightness = 1f + (brightnessTrackBar.Value / 100f);

    float adjustedBrightness = brightness - 1f;

    colorMatrix[4, 0] = adjustedBrightness;
    colorMatrix[4, 1] = adjustedBrightness;
    colorMatrix[4, 2] = adjustedBrightness;

    imageAttributes.SetColorMatrix(colorMatrix, ColorMatrixFlag.Default, ColorAdjustType.Bitmap);

    Invalidate();
}
于 2013-01-17T17:14:12.843 に答える
1

アプリのプロファイルを作成し、問題がどこにあるかを確認する必要があります。

ランダムな提案:

  • 位置合わせされていない読み取りを回避するために、32ビット/ピクセル形式を使用してください。(そして32全体を単一の操作として読み取る)
  • 複数のRGB<->HSL変換を避ける
于 2013-01-16T18:11:04.903 に答える