使用C#在pictureBox中的图像中添加或减去颜色

我想学习如何在Visual Studio中编写一些非常基本的图像编辑。 我正在使用openFileDialog将图片加载到pictureBox中。 我在互联网上发现了一些设计用于逐个像素地转换颜色的循环,但由于各种原因(每个代码示例不同)都没有用。 添加到(或减去)的正确方法是什么,例如红色值,以更改pictureBox中图像的色调? 我正在使用C#。

谢谢

编辑:这是一个至少是一个起点的例子:

Bitmap bmp = (Bitmap)Bitmap.FromFile(pictureBox1.ImageLocation); for (int x = 0; x < bmp.Width; x++) { for (int y = 0; y < bmp.Height; y++) { bmp.GetPixel(x, y); bmp.SetPixel(x, y, Color.FromArgb(128, 0, 128)); } } pictureBox1.Image = bmp; MessageBox.Show("Done"); 

这允许我逐个像素地获取图像,并且在这种情况下将颜色改变为紫色。 当然,这不是我想要做的。 我想要做的是获取每个像素的原始RGB值,并增加或减少值。 换句话说,执行一些非常基本的颜色校正。

如何获取每个像素的当前RGB,并设置新像素的RGB?

我也看到过这个例子。 问题是,我没有看到如何使用ModifyHue:

  var bmp = new Bitmap(pictureBox1.ImageLocation); for (int x = 0; x < bmp.Width; x++) { for (int y = 0; y < bmp.Height; y++) { Color oldColor = bmp.GetPixel(x, y); Color newColor = ModifyHue(oldColor); bmp.SetPixel(x, y, newColor); } } pictureBox1.Image = bmp; 

我意识到我应该第一次发布代码示例。 谢谢

这是使用GetpixelSetPixel的示例。

对于(更多)更快的滤波器结果,可以查看Lockbits以及使用ColorMatrix

 private void button2_Click(object sender, EventArgs e) { // we pull the bitmap from the image Bitmap bmp = (Bitmap) pictureBox1.Image; // we change some picels for (int y = 100; y < bmp.Height; y++) for (int x = 100; x < bmp.Width; x++) { Color c = bmp.GetPixel(x, y); bmp.SetPixel(x, y, Color.FromArgb(255, 255, cG, cB)); } // we need to re-assign the changed bitmap pictureBox1.Image = (Bitmap) bmp; } 

在此处输入图像描述在此处输入图像描述

更新:

上面的代码是一个非常简单的介绍。 它很简单但也很慢,而且不是很灵活。

这是一个非常快速且更灵活的版本:

 private void button3_Click(object sender, EventArgs e) { // pick one of our filter methods ModifyHue hueChanger = new ModifyHue(MaxChannel); // we pull the bitmap from the image Bitmap bmp = (Bitmap)pictureBox1.Image; Size s = bmp.Size; PixelFormat fmt = bmp.PixelFormat; // we need the bit depth and we assume either 32bppArgb or 24bppRgb ! byte bpp = (byte)(fmt == PixelFormat.Format32bppArgb ? 4 : 3); // lock the bits and prepare the loop Rectangle rect = new Rectangle(Point.Empty, s); BitmapData bmpData = bmp.LockBits(rect, ImageLockMode.ReadOnly, fmt); int size1 = bmpData.Stride * bmpData.Height; byte[] data = new byte[size1]; System.Runtime.InteropServices.Marshal.Copy(bmpData.Scan0, data, 0, size1); // loops for (int y = 0; y < s.Height; y++) { for (int x = 0; x < s.Width; x++) { // calculate the index int index = y * bmpData.Stride + x * bpp; // get the color Color c = Color.FromArgb( bpp == 4 ?data[index + 3]: 255 , data[index + 2], data[index + 1], data[index]); // process it c = hueChanger(c, 2); // set the channels from the new color data[index + 0] = cB; data[index + 1] = cG; data[index + 2] = cR; if (bpp == 4) data[index + 3] = cA; } } System.Runtime.InteropServices.Marshal.Copy(data, 0, bmpData.Scan0, data.Length); bmp.UnlockBits(bmpData); // we need to re-assign the changed bitmap pictureBox1.Image = (Bitmap)bmp; } 

上面的代码调用一个delegate

 public delegate Color ModifyHue(Color c, int ch); 

并且delegate设置为调用简单的filter函数:

 public Color MaxChannel(Color c, int channel) { if (channel == 1) return Color.FromArgb(255, 255, cG, cB); if (channel == 2) return Color.FromArgb(255, cR, 255, cB); if (channel == 3) return Color.FromArgb(255, cR, cG, 255); else return c; } 

这是另一个将Color变为灰色的Color

 public Color ToGreyscale(Color c, int dummy) { byte val = (byte) ( (cR * 0.299f + cG * 0.587f + cB *0.114f) ) ; return Color.FromArgb(255, val, val,val); } 

请注意,我们要通过delegate调用的所有方法都需要具有相同的signature 。 因此ToGreyscale也会将integer作为第二个参数,即使它不使用它。

另请注意,您可以限制LockBits循环开始和结束值,就像之前的简单示例一样,以获取第二个屏幕截图。