C# 如何使用滑块控件调整位图的亮度?
在我的图像处理器项目中,我试图调整RGB值,使图片变暗或变亮。这将是很好的结合暗和轻在一个轨迹控制,中性,不变的图像是当滑块设置为0在中间。 然而,我目前仍在试图找出如何在一个轨迹栏上只做一个功能,例如变暗 在我的项目中放置轨迹栏控件(C# 如何使用滑块控件调整位图的亮度?,c#,winforms,graphics,colormatrix,C#,Winforms,Graphics,Colormatrix,在我的图像处理器项目中,我试图调整RGB值,使图片变暗或变亮。这将是很好的结合暗和轻在一个轨迹控制,中性,不变的图像是当滑块设置为0在中间。 然而,我目前仍在试图找出如何在一个轨迹栏上只做一个功能,例如变暗 在我的项目中放置轨迹栏控件(min0,Max 10)后,我使用TrackBar\u scroll事件来检测何时滚动轨迹栏。 我还对其进行了编码,通过从图像每个像素的RGB中减去某个字节值,使图像变暗。 当您将滚动条向右滑动时,滚动条成功地使图像变暗,但是当您将轨迹条向左滑动回到其原始位置时,
min0,Max 10
)后,我使用TrackBar\u scroll
事件来检测何时滚动轨迹栏。我还对其进行了编码,通过从图像每个像素的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;
您只需保持原始位图的安全,并在调整值时对原始位图应用一个值。
当然,您不会调整已经调整的内容,否则,您将永远无法恢复到源位图的原始亮度/对比度值。
将新值设置为原始位图,然后仅显示结果,保留原始位图 对比度分量可以设置为
-1.00f
到2.00f
的范围当对比度值低于
0
时,您正在反转颜色以生成负片图像。您需要决定是否允许这种行为。否则,您可以将对比度限制为最小值0.00f
:应用于所有颜色组件,生成灰色斑点(完全没有对比度)
亮度分量的值可以设置为-1.00f
到+1.00f
的范围。在上面和下面,你有全白和全黑的结果
使用单位矩阵作为参考:
C=对比度=1
:B=亮度=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
(如果您习惯于矩阵的数学定义或其他平台定义它的方式,您可能会认为这是错误的。这正是在.Net/GDI方言中定义ColorMatrix的方式)
一个调整位图亮度和对比度所需的代码示例,使用颜色矩阵和标准PictureBox控件显示结果
样本结果:
Bitmap adjustBitmap = null;
程序:将图像分配给PictureBox控件,然后将相同的图像分配给位图对象,这里有一个名为
adjustBitmap
的字段:
Bitmap adjustBitmap = null;
在某处(Form.Load()
,可能),将图像分配给PicureBox,并将相同图像的副本分配给adjustBitmap
字段,该字段将保留原始图像颜色值。注意:
adjustBitmap
对象在窗体关闭(Form.FormClosed
)事件时的Dispose()
添加两个轨迹栏控件,一个用于调整亮度,另一个用于对比度(此处命名为trkContrast
和trkBrightness
)
亮度轨迹栏将有:最小值=-100,最大值=100,值=0
对比度轨迹栏将有:
最小值=-100,最大值=200,值=100
为滚动事件订阅并分配给两个相同的事件处理程序。
处理程序代码使用2个轨迹栏控件的当前值和原始位图的引用调用负责调整位图亮度和对比度的方法:
// 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);
}
主要方法是将轨迹栏的int
值转换为前面描述的范围内的浮点值,然后再转换为矩阵数组:
新的
被分配给ImageAttribute
类,该类用作接受ImageAttribute
的方法重载中的参数
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;
}
}
您将按百分比减少,因此撤消更改将需要更大的数字。如果你有100个苹果,损失了20%,你就剩下80个了。如果你增加20%,你就有96。您的80个苹果需要增加25%才能恢复到原始值。@MakeStackOverflowGood再次说明这是有道理的,但我应该把它放在哪里?我们只希望在滑块的值减小时才进行添加,因此如何检测不使用图像属性,而是使用绘制事件。使用e.Graphics.DrawImage()绘制位图,使用颜色矩阵实现亮度调整。当滚动条值更改时调用其Invalidate()方法,以便再次启动绘制。除了大大提高的效率之外,关键的区别在于始终保留原始位图。感谢您提供的解决方案。我在执行此操作时遇到内存泄漏。每次进行调整时,尽管使用了using语句,我的内存使用量还是会增加。你也看到了吗?@user2188329你说得很对!我直接在这里调整了代码。严重的错误。谢谢你的注意。我添加了一些注释并更正了代码。