更快的算法来改变位图中的色调/饱和度/亮度

我正在尝试过滤位图图像以增加或减少色调,饱和度和亮度值。

我的代码工作得很好,但速度很慢

我在内存中锁定了两个位图,原始源和当前目标。 用户可以移动各种轨迹栏控件来修改每个值,然后将其转换为HSL值。 例如,轨迹栏上的值对应于-1.0到1.0的范围。

每次抛出轨道栏值发生变化的事件时,我都会运行一个锁定目标位图的函数,并将HSL值与源位图一起应用,然后将结果存储在目标位图中。 完成后,我解锁目标位图并在屏幕上绘制图像。

以前我使用查找表来处理其他filter,因为我正在进行每字节操作。 但是我不知道如何使用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以使其加倍。

我最终研究了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(); } 

您需要了解应用程序并查看问题所在。

随机建议:

  • 使用32位/像素格式以避免未对齐的读取。 (并将整个32作为单个操作读取)
  • 避免多次RGB < - > HSL转换