首页 > 解决方案 > 如何正确划分编辑位图的任务以进行过滤器的并行处理

问题描述

我目前正处于光电转换器程序的开发阶段,并且正在开发模糊滤镜。在对该功能进行原型设计的初始阶段,我设计了一种算法,在该算法中,我为每个颜色通道设置了一个累加器,并将所有像素添加到目标像素的半径中。之后,程序会将累积值除以读取的像素数量(不包括屏幕外的像素)。起初我认为这会很好,但当它开始工作时,我遇到了这个过滤器需要一个小时才能渲染的问题,这是最低设置的结果。所以我选择在 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 。有什么我遗漏或不知道导致该算法无法运行的东西吗?

标签: c#bitmapbitmapdata

解决方案


推荐阅读