C
C#3mo ago
Array

Blurring an Image in C#, working slowly

Small glitch but my algorithm for making this image blur is running super slow, going from the top of the picture to the bottom. I attached a video showing this, any help
private void mnuProcessBlur_Click(object sender, EventArgs e)
{
//code to Blur
this.Refresh();

if (transformedPic != null)
{
//get height and width of transformed picture
int Height = transformedPic.GetLength(0);
int Width = transformedPic.GetLength(1);
//create temp array to store original transformed pic
Color[,] Temp = transformedPic;
transformedPic = new Color[Height, Width];
for (int row = 0; row < Height; row++)
{
for (int col = 0; col < Width; col++)
{
int TotalRed = 0, TotalGreen = 0, TotalBlue = 0;
int Counter = 0;

for (int i = -1; i <= 1; i++)
{

for (int j = -1; j <= 1; j++)
{
int row2 = row + i;
int col2 = col + j;
if (row2 >= 0 && row2 < Height && col2 >= 0 && col2 < Width)
{
//add colours
TotalRed += transformedPic[row2, col2].R;
TotalBlue += transformedPic[row2, col2].B;
TotalGreen += transformedPic[row2, col2].G;
Counter++;

}
}

}

//Averaging
int AverageR = TotalRed / Counter;
int AverageG = TotalGreen / Counter;
int AverageB = TotalBlue / Counter;
//add to temp
Temp[row, col] = Color.FromArgb(AverageR, AverageG, AverageB);
}
transformedPic = Temp;
this.Refresh();


}



}



}
private void mnuProcessBlur_Click(object sender, EventArgs e)
{
//code to Blur
this.Refresh();

if (transformedPic != null)
{
//get height and width of transformed picture
int Height = transformedPic.GetLength(0);
int Width = transformedPic.GetLength(1);
//create temp array to store original transformed pic
Color[,] Temp = transformedPic;
transformedPic = new Color[Height, Width];
for (int row = 0; row < Height; row++)
{
for (int col = 0; col < Width; col++)
{
int TotalRed = 0, TotalGreen = 0, TotalBlue = 0;
int Counter = 0;

for (int i = -1; i <= 1; i++)
{

for (int j = -1; j <= 1; j++)
{
int row2 = row + i;
int col2 = col + j;
if (row2 >= 0 && row2 < Height && col2 >= 0 && col2 < Width)
{
//add colours
TotalRed += transformedPic[row2, col2].R;
TotalBlue += transformedPic[row2, col2].B;
TotalGreen += transformedPic[row2, col2].G;
Counter++;

}
}

}

//Averaging
int AverageR = TotalRed / Counter;
int AverageG = TotalGreen / Counter;
int AverageB = TotalBlue / Counter;
//add to temp
Temp[row, col] = Color.FromArgb(AverageR, AverageG, AverageB);
}
transformedPic = Temp;
this.Refresh();


}



}



}
12 Replies
ffmpeg -i me -f null -
you have 4 nested loops on thousands of pixels, think of the number of operations that are going on to speed this up while running on the cpu you have to find a way to probably remove at least the inner two loops
Array
Array3mo ago
Any ideas how I cam do it without ruining the code?
Joreyk ( IXLLEGACYIXL )
first try your algorithm without GUI is the algorithm really the problem? probably the rendering is the problem so i would first try it without GUI to see the bottleneck ( or you can use a performance analysis of VS depends how you approach such stuff
Array
Array3mo ago
Hey sorry if this is dumb bc Im beginner but what is gui?
Joreyk ( IXLLEGACYIXL )
"graphical user interface" make a new console project, load in it the picture, run your algorithm without displaying it in wpf measure the time with stopwatch.. should be sufficient if the algorithm takes only a few milli seconds then the algorithm isnt the problem then drawing the GUI ( the wpf picture ) is the problem
Array
Array3mo ago
Wpf = winform app? Wdym by wpf
Joreyk ( IXLLEGACYIXL )
oke you have winforms then thats your gui library wpf is just another gui library thought you had wpf then run your algorithm once without winforms
Array
Array3mo ago
Ye I can show sorry if I sound super inexperienced I’m a beginner lmao
Joreyk ( IXLLEGACYIXL )
maybe you draw your image wrong and your algorithm is fine first find the cause
Array
Array3mo ago
It’s a file you read in
Joreyk ( IXLLEGACYIXL )
then a solution read the file, run the algorithm output the time it needed if its fast, you know the problem is the gui
ffmpeg -i me -f null -
if the code is not directly reading and writing pixels from a picturebox/gdi surface then yes it's mostly fine, probably Refresh method contains a sort of bitblt (although it's weird it's called two times) still even this code seems a bit slow for the image size, but i don't know what machine is this running on; also i guess it's a debug build there are many many ways you can start by doing more math and less loops in the inner part, since you are averaging the color there is no need to sum and average when you can do it in place then there is the Color type: it's a struct which i believe has more than just a/r/g/b inside of it, so it's more memory to manage using a less expensive type (like an int with 8 bit for color) could improve speed (but make it less readable) third is that even if you are using a matrix for the colors remember that memory is still linear so to speed things up you can try to use it more linearly possible; you can search for "loop tiling" remember that by convention names with cap first letter are public fields; i would advice to not capitalize variables names alaso i would change the first if to an early exit
if (transformedPic == null) return;
if (transformedPic == null) return;
to shave an indentation level on the whole method