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

时间:2019-04-12 23:48:52

标签: c# winforms graphics colormatrix

我正在尝试调整RGB值,以使图像处理器项目中的图片实质上变暗或变亮。最好在一个TrackBar控件上同时添加变暗和变亮,并且在中间将滑块设置为0时使用中性不变的图像。
但是,我目前仍在尝试找出如何仅在一个TrackBar上执行一项功能,例如变暗。

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

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;

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

有没有一种方法可以检测滑块的值何时增加,并在滑块值减小时进行检测?
我假设我必须以某种方式存储旧的轨迹栏值,以便可以将其与新的轨迹栏值进行比较?


我在哪里可以得到:

if (trackbar value is increasing) 
{

} 
else if (trackbar value is decreasing)
{

}

1 个答案:

答案 0 :(得分:1)

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

“对比度”组件可以设置为-1.00f2.00f的范围。
当“对比度”值低于0时,您将反转“负”图像的颜色。您需要确定是否允许这种行为。否则,您可以将对比度限制为0.00f的最小值:应用于所有颜色分量,生成灰色的 blob (完全没有对比度)。

“亮度”组件的值可以设置为-1.00f+1.00f的范围。在下方的上方,您会看到全白色和全黑色的结果。

使用身份矩阵作为参考:

C = Contrast = 1B = 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

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

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

抽样结果

Bitmap Brightness Contrast Adjustment

过程
将图片分配给PictureBox控件,然后将相同的图片分配给Bitmap对象,这里是名为 adjustBitmap 的字段:

Bitmap adjustBitmap = null; 

在某个地方(可能是Form.Load()),将一个图像分配给PicureBox,将相同的图像分配给adjustBitmap,这将保留原始图像的颜色值。
注意 Dispose() 对象中的adjustBitmap,当表单关闭(Form.FormClosed)事件时。

添加2个TrackBar控件,一个用于调整亮度,另一个用于对比度(此处分别命名为 trkContrast trkBrightness )。

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

Scroll 事件订阅并分配给这两个事件处理程序。
处理程序代码使用2个TrackBar控件的当前值和原始Bitmap的引用调用负责调整Bitmap的Brigthness和Contrast的方法:

private void trackBar_Scroll(object sender, EventArgs e)
{
    pictureBox1.Image = AdjustBrightnessContrast(adjustBitmap, trkContrast.Value, trkBrightness.Value);
}

main方法将TrackBars的int值转换为先前描述的范围内的float,然后将其转换为Matrix数组:
新的 ColorMatrix 被分配给一个 ImageAttribute 类,该类在Graphics.DrawImage方法重载中用作接受参数的参数。 ImageAttribute

public Bitmap AdjustBrightnessContrast(Image image, int contrastValue, int brightnessValue)
{
    float brightness = -(brightnessValue / 100.0f);
    float contrast = contrastValue / 100.0f;
    using (Bitmap bitmap = new Bitmap(image.Width, image.Height, PixelFormat.Format32bppArgb))
    using (Graphics g = Graphics.FromImage(bitmap))
    using (ImageAttributes 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)bitmap.Clone();
    }
}