如何使用滑块控件来调整位图的亮度?

4 .net c# graphics colormatrix winforms

我正在尝试调整 RGB 值,以基本上使图像处理器项目中的图片变暗或变亮。如果在一个 TrackBar 控件上同时包含变暗和变亮功能,并且当滑块在中间设置为 0 时,图像会呈现中性且未更改的图像,这将是一件好事。
然而,我目前仍在尝试弄清楚如何在一个 TrackBar 上只执行一项功能,例如变暗。

在我的项目中放置 TrackBar 控件 ( Min 0, Max 10) 后,我使用该trackbar_scroll事件来检测 TrackBar 何时滚动。
我还对其进行了编码,通过从图像每个像素的 RGB 中减去某个字节值来使图像变暗。
当您向右滑动滚动条时,滚动条成功地使图像变暗,但是当您将轨迹栏向左滑动回到其原始位置时,我也想取消它的变暗。

private void trbBrightness_Scroll(object sender, EventArgs e)
{
    if (bitmapImage == null) return; 

    Byte Red, Green, Blue;
    int iWidth = 320;
    int iHeight = 240;

    for (int i = 0; i < iWidth; i++)
    {
        for (int j = 0; j < iHeight; j++)
        {
            Color pixel = ImageArray[i, j];

            Red = pixel.R;
            Green = pixel.G;
            Blue = pixel.B;

            Color newColor = 
                Color.FromArgb(255, 
                               Red - Convert.ToByte(Red * (trbBrightness.Value * 0.1)), 
                               Green - Convert.ToByte(Green * (trbBrightness.Value * 0.1)), 
                               Blue - Convert.ToByte(Blue * (trbBrightness.Value * 0.1)));
            ImageArray[i, j] = newColor;
Run Code Online (Sandbox Code Playgroud)

现在它只是像我想要的那样使图像变暗,但是我期望当向左滑动时,滑块基本上会在向右滑动时取消变暗。

有没有办法检测滑块值何时增加,执行此操作,以及当滑块值减少时执行此操作?
我假设我必须以某种方式存储旧的轨迹栏值,以便我可以将它与新的进行比较?


我在哪里可以获得:

if (trackbar value is increasing) 
{

} 
else if (trackbar value is decreasing)
{

}
Run Code Online (Sandbox Code Playgroud)

Jim*_*imi 6

您只需保持原始位图的安全,并在调整值时将ColorMatrix应用于原始位图ImageAttributes即可。
当然,您不要调整已经调整过的内容,否则,您将永远不会回到源位图的原始亮度/对比度值。
将新值设置为原始位图,然后仅显示结果,保留原始值。

对比度分量可以设置为-1.00f到的范围2.00f
当对比度值低于 时0,您将反转颜色以形成图像。您需要决定是否允许这种行为。否则,您可以将对比度限制为最小值0.00f:应用于所有颜色分量,生成灰色斑点(根本没有对比度)。

亮度分量的值可以设置为-1.00f到的范围+1.00f。上面和下面有全白和全黑的结果。

使用单位矩阵作为参考:

C = Contrast = 1:B = Brightness = 0

    C, 0, 0, 0, 0        1, 0, 0, 0, 0
    0, C, 0, 0, 0        0, 1, 0, 0, 0
    0, 0, C, 0, 0        0, 0, 1, 0, 0
    0, 0, 0, 1, 0        0, 0, 0, 1, 0
    B, B, B, 1, 1        0, 0, 0, 1, 1
Run Code Online (Sandbox Code Playgroud)

(如果您习惯Matrix 的数学定义或其他平台定义它的方式,您可能会认为这是错误的。这只是在 .Net/GDI方言中定义 ColorMatrix 的方式)。

调整位图亮度和对比度所需的代码示例,使用 ColorMatrix 和标准 PictureBox 控件来呈现结果。

结果示例

位图亮度对比度调整

过程
将图像分配给 PictureBox 控件,然后将相同的图像分配给位图对象,此处为名为 的字段adjustBitmap

Bitmap adjustBitmap = null; 
Run Code Online (Sandbox Code Playgroud)

在某个地方(Form.Load()也许),将图像分配给 PicureBox,并将同一图像的副本分配给字段adjustBitmap,这将保留原始图像颜色值。
Dispose()adjustBitmap对象在Form关闭时发生( Form.FormClosed)事件。

添加 2 个 TrackBar 控件,一个用于调整亮度,一个用于对比度(已命名trkContrasttrkBrightness在此处)。

亮度跟踪栏将具有: 对比度跟踪将具有:Minimum = -100, Maximum = 100, Value = 0
Minimum = -100, Maximum = 200, Value = 100

订阅并分配给该Scroll事件的相同事件处理程序。
处理程序代码使用 2 个 TrackBar 控件的当前值和原始位图的引用来调用负责调整位图的亮度和对比度的方法:

// Somewhere... assign the Bitmap to be altered to the Field
adjustBitmap = [Some Bitmap];
// Use a copy of the above as the PictureBox image
pictureBox1.Image = [A copy of the above];

private void trackBar_Scroll(object sender, EventArgs e)
{
    pictureBox1.Image?.Dispose();
    pictureBox1.Image = AdjustBrightnessContrast(adjustBitmap, trkContrast.Value, trkBrightness.Value);
}
Run Code Online (Sandbox Code Playgroud)

main 方法将intTrackBar 的值转换为前面描述的范围内的浮点数,然后分配给 Matrix 数组:
新值ColorMatrix分配给一个ImageAttribute类,该类用作接受.DrawImageImageAttribute方法重载中的参数。

using System.Drawing;
using System.Drawing.Imaging;

public Bitmap AdjustBrightnessContrast(Image image, int contrastValue, int brightnessValue)
{
    float brightness = -(brightnessValue / 100.0f);
    float contrast = contrastValue / 100.0f;
    var bitmap = new Bitmap(image.Width, image.Height, PixelFormat.Format32bppArgb));

    using (var g = Graphics.FromImage(bitmap))
    using (var attributes = new ImageAttributes())
    {
        float[][] matrix = {
            new float[] { contrast, 0, 0, 0, 0},
            new float[] {0, contrast, 0, 0, 0},
            new float[] {0, 0, contrast, 0, 0},
            new float[] {0, 0, 0, 1, 0},
            new float[] {brightness, brightness, brightness, 1, 1}
        };

        ColorMatrix colorMatrix = new ColorMatrix(matrix);
        attributes.SetColorMatrix(colorMatrix);
        g.DrawImage(image, new Rectangle(0, 0, bitmap.Width, bitmap.Height),
            0, 0, bitmap.Width, bitmap.Height, GraphicsUnit.Pixel, attributes);
        return bitmap;
    }
}
Run Code Online (Sandbox Code Playgroud)