c# image-processing picturebox openfiledialog

Sumar o restar color de una imagen en un cuadro de imagen usando C#



image-processing picturebox (1)

Me gustaría aprender a codificar algunas ediciones de imágenes muy básicas en Visual Studio. Estoy usando openFileDialog para cargar una imagen en un cuadro de imagen. He encontrado algunos bucles en Internet que están diseñados para convertir el color píxel por píxel, pero por varias razones (que difieren con cada muestra de código) ninguno funciona. ¿Cuál es la forma correcta de sumar (o restar), por ejemplo, el valor rojo, para cambiar el tinte de una imagen en una PictureBox? Estoy usando C #.

Gracias

EDITAR: Aquí hay un ejemplo de algo que es al menos un punto de partida:

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");

Esto me permite obtener la imagen píxel por píxel y cambiar el color, en este caso, a púrpura. Por supuesto, eso no es lo que quiero hacer. Lo que quiero hacer es obtener el valor RGB original de cada píxel y aumentar o disminuir los valores. En otras palabras, realice una corrección de color muy básica.

¿Cómo obtengo el RGB actual de cada píxel y establezco el RGB del nuevo píxel?

También he visto esto publicado como un ejemplo. El problema es que no veo cómo usar 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;

Me doy cuenta de que debería haber publicado muestras de código la primera vez. Gracias


Este es un ejemplo del uso de Getpixel y SetPixel .

Para obtener resultados de filtro (mucho, mucho más rápidos), busque Lockbits y también use un 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, c.G, c.B)); } // we need to re-assign the changed bitmap pictureBox1.Image = (Bitmap) bmp; }

Actualizar:

El código anterior es una introducción muy simple. Es simple pero también muy lento y no es muy flexible.

Aquí hay una versión que es muy rápida y mucho más flexible:

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] = c.B; data[index + 1] = c.G; data[index + 2] = c.R; if (bpp == 4) data[index + 3] = c.A; } } 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; }

El código anterior llama a un delegate :

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

Y el delegate está configurado para llamar a una función de filtro simple:

public Color MaxChannel(Color c, int channel) { if (channel == 1) return Color.FromArgb(255, 255, c.G, c.B); if (channel == 2) return Color.FromArgb(255, c.R, 255, c.B); if (channel == 3) return Color.FromArgb(255, c.R, c.G, 255); else return c; }

Y aquí hay otro que cambia un Color a gris

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

Tenga en cuenta que todos los métodos que queremos llamar a través de un delegate deben tener la misma signature . Por ToGreyscale tanto, ToGreyscale también toma un integer como segundo parámetro, aunque no lo use.

También tenga en cuenta que puede limitar los LockBits inicio y finalización del bucle LockBits al igual que en el ejemplo simple anterior para obtener la segunda captura de pantalla.