问题描述
我想在 C# 中实现基本的 box blur,但在我的版本中改变了图片的颜色,就像一个红绿色过滤器。这有什么问题?为什么要这样做?行的索引和我想的一样好,所以我真的不知道为什么会发生这种情况。我只想要一个简单的框模糊,所以,平滑图像,而不是别的。
这是我的原始图片:https://ibb.co/pPsB2gT
private void Boxblur(object sender,EventArgs e)
{
Bitmap image = new Bitmap(pictureBox.Image);
BitmapData bitmapData = image.LockBits(new Rectangle(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,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;
}
这是经过上面的算法后的样子:https://ibb.co/dmrQB8F
如果我尝试没有并行性,那么它工作正常:
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,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,Color.FromArgb(newRValue,newGValue,newBValue));
}
}
}
pictureBox.Image = bitmap2;
}
这是没有并行算法之后的样子:https://ibb.co/dP9xrzT
我尝试执行 Gaussian blur,其工作方式也类似,但我遇到了同样的问题,但现在,使用另一种颜色过滤:
private void gaussianblur(object sender,EventArgs e)
{
Bitmap image = new Bitmap(pictureBox.Image);
BitmapData bitmapData = image.LockBits(new Rectangle(0,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,image.PixelFormat);
unsafe
{
byte* firstPixel = (byte*)bitmapData.Scan0;
Parallel.For(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,oldB));
}
idx++;
}
});
image.UnlockBits(bitmapData);
}
pictureBox.Image = bitmap2;
}
解决方法
暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!
如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。
小编邮箱:dio#foxmail.com (将#修改为@)