c# - 如何正确划分编辑位图的任务以进行过滤器的并行处理
问题描述
我目前正处于光电转换器程序的开发阶段,并且正在开发模糊滤镜。在对该功能进行原型设计的初始阶段,我设计了一种算法,在该算法中,我为每个颜色通道设置了一个累加器,并将所有像素添加到目标像素的半径中。之后,程序会将累积值除以读取的像素数量(不包括屏幕外的像素)。起初我认为这会很好,但当它开始工作时,我遇到了这个过滤器需要一个小时才能渲染的问题,这是最低设置的结果。所以我选择在 C# 中使用并行处理来使这个过程更容易和更快地运行。随着速度的提高,图像的成本变得非常错误。这是之前的图, 这是之后的图像
这是我为过滤器编写的代码
public static DirectBitmap NewBlur (DirectBitmap image, int radius)
{
int sectorDiam = 128;
DirectBitmap newimage = image;
List<Rectangle> renderSectors = new List<Rectangle>();
Rectangle rect;
for (int x = 0; x < (image.Width / sectorDiam); x++)
{
int xwidth = sectorDiam;
for (int y = 0; y < (image.Height / sectorDiam); y++)
{
int yheight = sectorDiam;
rect = new Rectangle(x * sectorDiam, y * sectorDiam, xwidth, yheight);
renderSectors.Add(rect);
}
}
var Picrect = new Rectangle(0, 0, image.Width, image.Height);
var data = image.Bitmap.LockBits(Picrect, ImageLockMode.ReadWrite, image.Bitmap.PixelFormat);
var depth = Bitmap.GetPixelFormatSize(data.PixelFormat) / 8; //bytes per pixel
var buffer = new byte[data.Width * data.Height * depth];
Marshal.Copy(data.Scan0, buffer, 0, buffer.Length);
Parallel.ForEach(renderSectors, sector =>
{
BlurSection(buffer, sector, Picrect, radius, image.Width, image.Height, depth);
}
);
Marshal.Copy(buffer, 0, data.Scan0, buffer.Length);
image.Bitmap.UnlockBits(data);
return image;
}
下面是对图像的每个部分进行模糊处理的方法。
public static void BlurSection(byte[] buffer, Rectangle blurSector, Rectangle bitmaprect, int radius, int width, int height, int depth)
{
int[] Accum = new int[4];
for (int x = blurSector.X; x < blurSector.Width+ blurSector.X; x++)
{
for (int y = blurSector.Y; y < blurSector.Height + blurSector.Y; y++)
{
Accum[0] = 0;
Accum[1] = 0;
Accum[2] = 0;
Accum[3] = 0;
for (int i = -radius; i <= radius; i++)
{
for (int j = -radius; j <= radius; j++)
{
var offset = 0;
offset = (((y+j) * width) + (x+i)) * depth;
if (bitmaprect.Contains(new Point(x + i, y + j))){
Accum[0] += buffer[offset + 0];
Accum[1] += buffer[offset + 1];
Accum[2] += buffer[offset + 2];
Accum[3]++;
}
}
}
Accum[0] = Accum[0] / Accum[3];
if (Accum[0] > 255)
{
Accum[0] = 255;
}
Accum[1] = Accum[1] / Accum[3];
if (Accum[1] > 255)
{
Accum[1] = 255;
}
Accum[2] = Accum[2] / Accum[3];
if (Accum[2] > 255)
{
Accum[2] = 255;
}
var newoffset = ((y * width) + (x * depth*2));
buffer[newoffset + 0] = (byte)Accum[0];
buffer[newoffset + 1] = (byte)Accum[1];
buffer[newoffset + 2] = (byte)Accum[2];
}
}
}
还值得注意的是,我正在使用 Bitmap 类来更轻松地访问像素数据,您可以在此处找到“DirectBitmap”:https ://stackoverflow.com/a/34801225/15473435 。有什么我遗漏或不知道导致该算法无法运行的东西吗?
解决方案
推荐阅读
- angular - 为什么没有返回我的 Edge HTTP 响应标头?
- node.js - Ghost - 无法连接到引导套接字 (localhost 8000) ECONNREFUSED
- scala - 在运行时从自定义位置加载 HOCON 格式的类型安全配置
- javascript - “这个”属于它的主人——
- java - 使用 spring-boot 休息:内容协商失败!未找到类型返回值的转换器
- php - ERR_SSL_VERSION_OR_CIPHER_MISMATCH- 在我的网站 RiteOnPolish.com
- sql - 额外的 XML 数据键值对到 SQL
- python - 将列表项拆分为单独的列 - 熊猫数据框
- java - 是否可以从坐标生成对 JButton 的引用?
- java - 如何在包含 magisk 应用程序的根设备中限制我的 android 应用程序?