I want to implement basic box blur in C#, but in my version change the color of the picture, like a red-green filter. What is the problem with this? Why is doing this? The indexes of rows are good as I think, so I really don't know why to happens this. I want only a simple box blur, so, smooth the image, and nothing else.
this is my original image: https://ibb.co/pPsB2gT
private void boxblur(object sender, EventArgs e)
{
Bitmap image = new Bitmap(pictureBox.Image);
BitmapData bitmapData = image.LockBits(new Rectangle(0, 0, image.Width, image.Height), ImageLockMode.ReadWrite, image.PixelFormat);
int height = bitmapData.Height;
int bPP = System.Drawing.Bitmap.GetPixelFormatSize(image.PixelFormat) / 8;
int width = bitmapData.Width * bPP;
Bitmap bitmap2 = image.Clone(new Rectangle(0, 0, image.Width, image.Height), image.PixelFormat);
unsafe
{
byte* firstPixel = (byte*)bitmapData.Scan0;
Parallel.For(1, height - 1, j =>
{
byte* line1 = firstPixel + ((j - 1) * bitmapData.Stride); //fst row
byte* line2 = firstPixel + (j * bitmapData.Stride); //snd row
byte* line3 = firstPixel + ((j + 1) * bitmapData.Stride); //thrd row
int idx = 0;
for (int i = 1; i < width-1; i = i + bPP)//one pixel in three elements of a row
{
int oldB = line1[i-1] + line1[i+2] + line1[i+5] +
line2[i-1] + line2[i+2] + line2[i+5] +
line3[i-1] + line3[i+2] + line3[i+5];
int oldG = line1[i] + line1[i + 3] + line1[i + 6] +
line2[i] + line2[i + 3] + line2[i + 6] +
line3[i] + line3[i + 3] + line3[i + 6];
int oldR = line1[i+1] + line1[i + 4] + line1[i + 7] +
line2[i+1] + line2[i + 4] + line2[i + 7] +
line3[i+1] + line3[i + 4] + line3[i + 7]; ;
oldB = oldB/9;
oldG = oldG/9;
oldR = oldR/9;
lock (bitmap2)
{
bitmap2.SetPixel(idx, j, Color.FromArgb(oldR, oldG, oldB));
}
idx++;
}
});
image.UnlockBits(bitmapData);
}
pictureBox.Image = bitmap2;
}
this is how it looks like after algo above: https://ibb.co/dmrQB8F
If I try without parallelism then it works fine:
private void boxblur(object sender, EventArgs e)
{
Bitmap bitmap = new Bitmap(pictureBox.Image);
int width = bitmap.Width;
int height = bitmap.Height;
Bitmap bitmap2 = bitmap.Clone(new Rectangle(0, 0, bitmap.Width, bitmap.Height), bitmap.PixelFormat);
for (int i = 0; i < width; i++)
{
for (int j = 0; j < height; j++)
{
if (i > 1 && j > 1 && i + 1 != width && j + 1 != height)
{
int newRValue = bitmap.GetPixel(i, j + 1).R +
bitmap.GetPixel(i + 1, j + 1).R +
bitmap.GetPixel(i - 1, j).R +
bitmap.GetPixel(i, j).R +
bitmap.GetPixel(i + 1, j).R +
bitmap.GetPixel(i - 1, j - 1).R +
bitmap.GetPixel(i, j - 1).R +
bitmap.GetPixel(i + 1, j - 1).R;
newRValue = Convert.ToInt32(newRValue / 9);
int newGValue = bitmap.GetPixel(i, j + 1).G +
bitmap.GetPixel(i + 1, j + 1).G +
bitmap.GetPixel(i - 1, j).G +
bitmap.GetPixel(i, j).G +
bitmap.GetPixel(i + 1, j).G +
bitmap.GetPixel(i - 1, j - 1).G +
bitmap.GetPixel(i, j - 1).G +
bitmap.GetPixel(i + 1, j - 1).G;
newGValue = Convert.ToInt32(newGValue / 9);
int newBValue = bitmap.GetPixel(i, j + 1).B +
bitmap.GetPixel(i + 1, j + 1).B +
bitmap.GetPixel(i - 1, j).B +
bitmap.GetPixel(i, j).B +
bitmap.GetPixel(i + 1, j).B +
bitmap.GetPixel(i - 1, j - 1).B +
bitmap.GetPixel(i, j - 1).B +
bitmap.GetPixel(i + 1, j - 1).B;
newBValue = Convert.ToInt32(newBValue / 9);
bitmap2.SetPixel(i, j, Color.FromArgb(newRValue, newGValue, newBValue));
}
}
}
pictureBox.Image = bitmap2;
}
This is how it look like after algo without parallelism: https://ibb.co/dP9xrzT
I tried to do the Gaussian blur, which works similar as well, but I got the same problem, but now, with another color filtering:
private void gaussianblur(object sender, EventArgs e)
{
Bitmap image = new Bitmap(pictureBox.Image);
BitmapData bitmapData = image.LockBits(new Rectangle(0, 0, image.Width, image.Height), ImageLockMode.ReadWrite, image.PixelFormat);
int height = bitmapData.Height;
int bPP = System.Drawing.Bitmap.GetPixelFormatSize(image.PixelFormat) / 8;
int width = bitmapData.Width * bPP;
Bitmap bitmap2 = image.Clone(new Rectangle(0, 0, image.Width, image.Height), image.PixelFormat);
unsafe
{
byte* firstPixel = (byte*)bitmapData.Scan0;
Parallel.For(1, height - 1, j =>
{
byte* line1 = firstPixel + ((j - 1) * bitmapData.Stride);
byte* line2 = firstPixel + (j * bitmapData.Stride);
byte* line3 = firstPixel + ((j + 1) * bitmapData.Stride);
int idx = 0;
for (int i = 1; i < width - 1; i = i + bPP)
{
int oldB = line1[i - 1] + line1[i + 2] * 2 + line1[i + 5] +
line2[i - 1] *2 + line2[i + 2] *4 + line2[i + 5] * 2 +
line3[i - 1] + line3[i + 2] *2+ line3[i + 5];
int oldG = line1[i] + line1[i + 3] *2 + line1[i + 6] +
line2[i] *2+ line2[i + 3] *4+ line2[i + 6] *2+
line3[i] + line3[i + 3] *2+ line3[i + 6];
int oldR = line1[i + 1] + line1[i + 4] *2 + line1[i + 7] +
line2[i + 1] *2 + line2[i + 4] *4 + line2[i + 7] *2+
line3[i + 1] + line3[i + 4] *2+ line3[i + 7];
oldB = oldB / 16;
oldG = oldG / 16;
oldR = oldR / 16;
lock (bitmap2)
{
bitmap2.SetPixel(idx, j, Color.FromArgb(oldR, oldG, oldB));
}
idx++;
}
});
image.UnlockBits(bitmapData);
}
pictureBox.Image = bitmap2;
}