¿Cómo manipulo imágenes a nivel de píxel en C#?Cómo manipular imágenes a nivel de píxel en C#
Necesito poder leer/modificar cada píxel de mapa de bits valores RGB por separado.
Se apreciará una muestra de código.
¿Cómo manipulo imágenes a nivel de píxel en C#?Cómo manipular imágenes a nivel de píxel en C#
Necesito poder leer/modificar cada píxel de mapa de bits valores RGB por separado.
Se apreciará una muestra de código.
System.Drawing.Bitmap tiene un método público GetPixel (int x, int y) que devuelve una estructura System.Drawing.Color. Esa estructura tiene miembros de byte R, G, B y A, que puedes modificar directamente, y luego volver a llamar a SetPixel (Color) en tu Bitmap.
Desafortunadamente, va a ser relativamente lento, pero es por la forma más fácil de hacerlo en C#. Si trabajas mucho con píxeles individuales y encuentras que el rendimiento es deficiente, y necesitas algo más rápido, puedes usar LockBits ... Sin embargo, es mucho más complicado, ya que necesitas entender la estructura de bits para esa profundidad y tipo de color. , y trabaje con la zancada del mapa de bits y lo que no ... así que si encuentra que es necesario, ¡asegúrese de encontrar un buen tutorial! Hay varios por ahí en la web, googlear "C# LockBits" le dará media docena que vale la pena leer.
Rutina de código de muestra (la utilizo para una funcionalidad simple de fusión y comparación. Toma dos imágenes y produce una tercera escala de grises que muestra las diferencias entre las dos imágenes como un nivel de tono de escala de grises. diff):.
public static Bitmap Diff(Bitmap src1, Bitmap src2, int x1, int y1, int x2, int y2, int width, int height)
{
Bitmap diffBM = new Bitmap(width, height, PixelFormat.Format24bppRgb);
for (int y = 0; y < height; y++)
{
for (int x = 0; x < width; x++)
{
//Get Both Colours at the pixel point
Color col1 = src1.GetPixel(x1 + x, y1 + y);
Color col2 = src2.GetPixel(x2 + x, y2 + y);
// Get the difference RGB
int r = 0, g = 0, b = 0;
r = Math.Abs(col1.R - col2.R);
g = Math.Abs(col1.G - col2.G);
b = Math.Abs(col1.B - col2.B);
// Invert the difference average
int dif = 255 - ((r+g+b)/3);
// Create new grayscale RGB colour
Color newcol = Color.FromArgb(dif, dif, dif);
diffBM.SetPixel(x, y, newcol);
}
}
return diffBM;
}
Marc's post notas LockBits y utilizarlo para modificar la imagen directamente en la memoria. Sugeriría mirar eso en lugar de lo que he publicado si el rendimiento es una preocupación. Gracias Marc!
necesita más votos !! – geekido
Como probablemente ya se ha mencionado varias veces, 'GetPixel' y' SetPixel' son notoriamente lentos. 'Bitmap.LockBits' en combinación con' Marshal.Copy' puede lograr lo mismo, pero obtiene los datos a granel en lugar de píxeles por píxel, lo que hace que se cargue más rápido. – Nyerguds
Si el rendimiento es crítico, se administra DirectX otra alternativa a LockBits.
Consulte la pregunta anterior sobre desbordamiento de pila Rendering graphics in C# para obtener más información.
Al igual que Lockbits, necesitará utilizar el modificador de palabra clave/compilador inseguro, pero obtendrá acceso de nivel de píxel de alto rendimiento.
También obtiene una representación de pantalla de mayor rendimiento a través de la función Backbuffering de DirectX, en comparación con la utilización de la clase de mapa de bits y el control PictureBox normales.
Managed DirectX ahora está en desuso. –
nice. Nunca me había molestado en buscar más allá de set/get pixel. Gracias por los enlaces. – mattlant
Lo que Bob Powell no le dice es que en realidad no necesita lidiar con punteros en C#. Eche un vistazo a LockBits en la biblioteca de MSDN, hay una muestra que copia la memoria en una matriz administrada donde el método no está marcado como inseguro y, por lo tanto, la aplicación no tiene que ser insegura :) – OregonGhost
Los usuarios de XNA deben tener cuidado, XBox360. NET CF no admite la biblioteca System.Drawing, que es donde reside LockBits. Así que DirectX manejado es probablemente tu única opción (gracias Ash). –