Reputation: 2615
I'm using WinForms. I have a picture-box in my form. When I open a picture in the picture-box I am able to invert the colors back and forth on a click of a button, but my code is extremely slow. How can I increase the performance.
private void Button1_Click(object sender, System.EventArgs e)
{
Bitmap pic = new Bitmap(PictureBox1.Image);
for (int y = 0; (y
<= (pic.Height - 1)); y++) {
for (int x = 0; (x
<= (pic.Width - 1)); x++) {
Color inv = pic.GetPixel(x, y);
inv = Color.FromArgb(255, (255 - inv.R), (255 - inv.G), (255 - inv.B));
pic.SetPixel(x, y, inv);
PictureBox1.Image = pic;
}
}
}
Upvotes: 6
Views: 18487
Reputation: 332
I've just searched for the same DOTNET to use in powershell. If you value speed use this colormatrix DOTNET example to invert in a single step: https://www.codeguru.com/dotnet/inverting-image-colors-in-net/ It uses https://learn.microsoft.com/en-us/dotnet/api/system.drawing.imaging.imageattributes , https://learn.microsoft.com/en-us/dotnet/api/system.drawing.imaging.colormatrix and https://learn.microsoft.com/de-de/dotnet/api/system.drawing.graphicsunit . I just applied these methods in Powershell to speed up the inversion a lot instead of doing it pixel by pixel. It should speed up the C# variant too.
Upvotes: 0
Reputation: 152624
You are setting the control's picture each time you change a pixel, which causes the control to redraw itself. Wait until you've finished the image:
Bitmap pic = new Bitmap(PictureBox1.Image);
for (int y = 0; (y <= (pic.Height - 1)); y++) {
for (int x = 0; (x <= (pic.Width - 1)); x++) {
Color inv = pic.GetPixel(x, y);
inv = Color.FromArgb(inv.A, (255 - inv.R), (255 - inv.G), (255 - inv.B));
pic.SetPixel(x, y, inv);
}
}
PictureBox1.Image = pic;
Upvotes: 17
Reputation: 29
Improving on D Stanley's suggestion and avoiding the memory and processing overload of converting the image to a Bitmap and then re-assigning it, you can actually directly Get and Set pixels on the .Image of the PictureBox by simply casing it and calling the associated Bitmap manipulation functions:
private void Button1_Click(object sender, System.EventArgs e)
{
for (int y = 0; (y
<= (PictureBox1.Image.Height - 1)); y++) {
for (int x = 0; (x
<= (PictureBox1.Image.Width - 1)); x++) {
Color inv = ((Bitmap)PictureBox1.Image).GetPixel(x, y);
inv = Color.FromArgb(255, (255 - inv.R), (255 - inv.G), (255 - inv.B));
((Bitmap)PictureBox1.Image).SetPixel(x, y, inv);
}
}
}
Upvotes: 0
Reputation: 697
In case someone need the similar code in VB.NET.
Also note the variable inv.A instead of the value 255. In case your picturebox has transparency you need this.
Public Function InvertImageColors(ByVal p As Image) As Image
Dim pic As New Bitmap(p)
For y As Integer = 0 To pic.Height - 1
For x As Integer = 0 To pic.Width - 1
Dim inv As Color = pic.GetPixel(x, y)
inv = Color.FromArgb(inv.A, 255 - inv.R, 255 - inv.G, 255 - inv.B)
pic.SetPixel(x, y, inv)
Next x
Next y
Return pic
End Function
Usage:
pic.image = InvertImageColors(pic.image)
Upvotes: 0