public static unsafe void ApplyConvolution(ImageChannel <TPixel> img, ConvolutionKernel k)
        {
            if (img.Width < 2 || img.Height < 2)
            {
                return;
            }

            int widthTypeScaled = img.Width * img.Step;

            int kernelHeight = k.Width;
            int kernelWidth  = k.Height;
            int scale        = k.Scale;

            int[,] kernel = k.Kernel;
            int extend = Math.Max(kernelWidth, kernelHeight) / 2;
            ImageChannel <TPixel> maskImage = new ImageChannel <TPixel>(img.Width + extend * 2, img.Height + extend * 2);

            FillImage(maskImage, (TPixel)0); //这里效率不高。原本只需要填充四周扩大的部分即可
            CopyChannel(img, maskImage, new System.Drawing.Point(0, 0), new System.Drawing.Rectangle(0, 0, img.Width, img.Height), new System.Drawing.Point(extend, extend));

            int step     = img.Step;
            int maskStep = maskImage.Step;

            int     width     = img.Width;
            int     height    = img.Height;
            TPixel *start     = (TPixel *)img.StartIntPtr;
            TPixel *maskStart = (TPixel *)maskImage.StartIntPtr;

            // 复制边界像素
            TPixel *dstStart        = maskStart + extend;
            int     maskWidth       = img.Width + extend * 2;
            int     maskHeight      = img.Height + extend * 2;
            TPixel *dstContentStart = maskStart + extend + maskWidth * extend;

            // 复制上方的像素
            for (int y = 0; y < extend; y++)
            {
                TPixel *lineStart = dstStart + y * maskWidth;
                TPixel *lineEnd   = lineStart + width;
                TPixel *copyStart = dstContentStart;
                while (lineStart != lineEnd)
                {
                    *lineStart = *copyStart;
                    lineStart++;
                    copyStart++;
                }
            }

            // 复制下方的像素
            for (int y = height + extend; y < maskHeight; y++)
            {
                TPixel *lineStart = dstStart + y * maskWidth;
                TPixel *lineEnd   = lineStart + width;
                TPixel *copyStart = dstContentStart + height * maskWidth - maskWidth;
                while (lineStart != lineEnd)
                {
                    *lineStart = *copyStart;
                    lineStart++;
                    copyStart++;
                }
            }

            // 复制左右两侧的像素
            TPixel *dstLine = maskStart + maskWidth * extend;
            TPixel  p       = default(TPixel);

            for (int y = extend; y < height + extend; y++)
            {
                p = dstLine[extend];
                for (int x = 0; x < extend; x++)
                {
                    dstLine[x] = p;
                }

                p = dstLine[extend + width - 1];
                for (int x = width + extend; x < maskWidth; x++)
                {
                    dstLine[x] = p;
                }
                dstLine += maskWidth;
            }

            // 复制四个角落的像素

            // 左上
            p = dstContentStart[0];
            for (int y = 0; y < extend; y++)
            {
                for (int x = 0; x < extend; x++)
                {
                    maskStart[y * maskWidth + x] = p;
                }
            }

            // 右上
            p = dstContentStart[width - 1];
            for (int y = 0; y < extend; y++)
            {
                for (int x = width + extend; x < maskWidth; x++)
                {
                    maskStart[y * maskWidth + x] = p;
                }
            }

            // 左下
            p = dstContentStart[(height - 1) * maskWidth];
            for (int y = height + extend; y < maskHeight; y++)
            {
                for (int x = 0; x < extend; x++)
                {
                    maskStart[y * maskWidth + x] = p;
                }
            }

            // 右下
            p = dstContentStart[(height - 1) * maskWidth + width - 1];
            for (int y = height + extend; y < maskHeight; y++)
            {
                for (int x = width + extend; x < maskWidth; x++)
                {
                    maskStart[y * maskWidth + x] = p;
                }
            }

            if (scale == 1)
            {
                for (int h = 0; h < height; h++)
                {
                    for (int w = 0; w < width; w++)
                    {
                        TValue val = 0;
                        for (int kw = 0; kw < kernelWidth; kw++)
                        {
                            for (int kh = 0; kh < kernelHeight; kh++)
                            {
                                val += maskStart[(h + kh) * maskWidth + (w + kw)] * kernel[kh, kw];
                            }
                        }
                        start[h * widthTypeScaled + w] = (TPixel)val;
                    }
                }
            }
            else
            {
                double factor = 1.0 / scale;
                for (int h = 0; h < height; h++)
                {
                    for (int w = 0; w < width; w++)
                    {
                        TValue val = 0;
                        for (int kw = 0; kw < kernelWidth; kw++)
                        {
                            for (int kh = 0; kh < kernelHeight; kh++)
                            {
                                val += maskStart[(h + kh) * maskWidth + (w + kw)] * kernel[kh, kw];
                            }
                        }
                        start[h * widthTypeScaled + w] = (TPixel)(val * factor);
                    }
                }
            }
            maskImage.Dispose();
        }
 public void ApplyConvolution(ConvolutionKernel k)
 {
     ApplyConvolution(this, k);
 }
        public unsafe void ApplyConvolution(ConvolutionKernel k)
        {
            int kernelHeight = k.Width;
            int kernelWidth  = k.Height;
            int scale        = k.Scale;

            int[,] kernel = k.Kernel;
            int    extend    = Math.Max(kernelWidth, kernelHeight) / 2;
            TImage maskImage = new TImage(Width + extend * 2, Height + extend * 2);

            maskImage.Fill(0);//这里效率不高。原本只需要填充四周扩大的部分即可

            maskImage.Copy(this, new System.Drawing.Point(0, 0), new System.Drawing.Rectangle(0, 0, this.Width, this.Height), new System.Drawing.Point(extend, extend));

            int     width  = this.Width;
            int     height = this.Height;
            TPixel *start  = (TPixel *)this.StartIntPtr;

            // 复制边界像素
            TPixel *dstStart     = maskImage.Start + extend;
            int     extendWidth  = this.Width + extend * 2;
            int     extendHeight = this.Height + extend * 2;

            // 复制上方的像素
            for (int y = 0; y < extend; y++)
            {
                TPixel *dstP     = dstStart + y * extendWidth;
                TPixel *srcStart = start;
                TPixel *srcEnd   = srcStart + width;

                while (srcStart != srcEnd)
                {
                    *dstP = *srcStart;
                    srcStart++;
                    dstP++;
                }
            }

            // 复制下方的像素
            for (int y = height + extend; y < extendHeight; y++)
            {
                TPixel *dstP     = dstStart + y * extendWidth;
                TPixel *srcStart = start + (height - 1) * width;
                TPixel *srcEnd   = srcStart + width;

                while (srcStart != srcEnd)
                {
                    *dstP = *srcStart;
                    srcStart++;
                    dstP++;
                }
            }

            // 复制左右两侧的像素
            TPixel *dstLine = maskImage.Start + extendWidth * extend;
            TPixel *srcLine = start;
            TPixel  p       = default(TPixel);

            for (int y = extend; y < height + extend; y++)
            {
                for (int x = 0; x < extend; x++)
                {
                    p          = srcLine[0];
                    dstLine[x] = p;
                }

                p = srcLine[width - 1];
                for (int x = width + extend; x < extendWidth; x++)
                {
                    dstLine[x] = p;
                }
                dstLine += extendWidth;
                srcLine += width;
            }

            // 复制四个角落的像素

            // 左上
            p = start[0];
            for (int y = 0; y < extend; y++)
            {
                for (int x = 0; x < extend; x++)
                {
                    maskImage[y, x] = p;
                }
            }

            // 右上
            p = start[width - 1];
            for (int y = 0; y < extend; y++)
            {
                for (int x = width + extend; x < extendWidth; x++)
                {
                    maskImage[y, x] = p;
                }
            }

            // 左下
            p = start[(height - 1) * width];
            for (int y = height + extend; y < extendHeight; y++)
            {
                for (int x = 0; x < extend; x++)
                {
                    maskImage[y, x] = p;
                }
            }

            // 右下
            p = start[height * width - 1];
            for (int y = height + extend; y < extendHeight; y++)
            {
                for (int x = width + extend; x < extendWidth; x++)
                {
                    maskImage[y, x] = p;
                }
            }

            if (scale == 1)
            {
                for (int h = 0; h < height; h++)
                {
                    for (int w = 0; w < width; w++)
                    {
                        int val = 0;
                        for (int kw = 0; kw < kernelWidth; kw++)
                        {
                            for (int kh = 0; kh < kernelHeight; kh++)
                            {
                                val += maskImage[h + kh, w + kw] * kernel[kh, kw];
                            }
                        }
                        start[h * width + w] = (TPixel)val;
                    }
                }
            }
            else
            {
                double factor = 1.0 / scale;
                for (int h = 0; h < height; h++)
                {
                    for (int w = 0; w < width; w++)
                    {
                        int val = 0;
                        for (int kw = 0; kw < kernelWidth; kw++)
                        {
                            for (int kh = 0; kh < kernelHeight; kh++)
                            {
                                val += maskImage[h + kh, w + kw] * kernel[kh, kw];
                            }
                        }
                        start[h * width + w] = (TPixel)(val * factor);
                    }
                }
            }
            maskImage.Dispose();
        }
        public unsafe void ApplyConvolution(ConvolutionKernel  k)
        {
            int kernelHeight = k.Width;
            int kernelWidth = k.Height;
            int scale = k.Scale;
            int[,] kernel = k.Kernel;
            int extend = Math.Max(kernelWidth, kernelHeight) / 2;
            TImage maskImage = new TImage(Width + extend * 2, Height + extend * 2);
            maskImage.Fill(0);//这里效率不高。原本只需要填充四周扩大的部分即可

            maskImage.Copy(this, new System.Drawing.Point(0, 0), new System.Drawing.Rectangle(0, 0, this.Width, this.Height), new System.Drawing.Point(extend, extend));

            int width = this.Width;
            int height = this.Height;
            TPixel* start = (TPixel*)this.StartIntPtr;

            // 复制边界像素
            TPixel* dstStart = maskImage.Start + extend;
            int extendWidth = this.Width + extend * 2;
            int extendHeight = this.Height + extend * 2;

            // 复制上方的像素
            for (int y = 0; y < extend; y++)
            {
                TPixel* dstP = dstStart + y * extendWidth;
                TPixel* srcStart = start;
                TPixel* srcEnd = srcStart + width;

                while (srcStart != srcEnd)
                {
                    *dstP = *srcStart;
                    srcStart++;
                    dstP++;
                }
            }

            // 复制下方的像素
            for (int y = height + extend; y < extendHeight; y++)
            {
                TPixel* dstP = dstStart + y * extendWidth;
                TPixel* srcStart = start + (height - 1)*width;
                TPixel* srcEnd = srcStart + width;

                while (srcStart != srcEnd)
                {
                    *dstP = *srcStart;
                    srcStart++;
                    dstP++;
                }
            }

            // 复制左右两侧的像素
            TPixel* dstLine = maskImage.Start + extendWidth * extend;
            TPixel* srcLine = start;
            TPixel p = default(TPixel);
            for (int y = extend; y < height + extend; y++)
            {
                for(int x = 0; x < extend; x ++)
                {
                    p = srcLine[0];
                    dstLine[x] = p;
                }

                p = srcLine[width-1];
                for(int x = width + extend; x < extendWidth; x++)
                {
                   dstLine[x] = p;
                }
                dstLine += extendWidth;
                srcLine += width;
            }

            // 复制四个角落的像素

            // 左上
            p = start[0];
            for (int y = 0; y < extend; y++)
            {
                for (int x = 0; x < extend; x++)
                {
                    maskImage[y, x] = p;
                }
            }

            // 右上
            p = start[width - 1];
            for (int y = 0; y < extend; y++)
            {
                for (int x = width + extend; x < extendWidth; x++)
                {
                    maskImage[y, x] = p;
                }
            }

            // 左下
            p = start[(height - 1) * width];
            for (int y = height + extend; y < extendHeight; y++)
            {
                for (int x = 0; x < extend; x++)
                {
                    maskImage[y, x] = p;
                }
            }

            // 右下
            p = start[height * width - 1];
            for (int y = height + extend; y < extendHeight; y++)
            {
                for (int x = width + extend; x < extendWidth; x++)
                {
                    maskImage[y, x] = p;
                }
            }

            if (scale == 1)
            {
                for (int h = 0; h < height; h++)
                {
                    for (int w = 0; w < width; w++)
                    {
                        int val = 0;
                        for (int kw = 0; kw < kernelWidth; kw++)
                        {
                            for (int kh = 0; kh < kernelHeight; kh++)
                            {
                                val += maskImage[h + kh, w + kw] * kernel[kh, kw];
                            }
                        }
                        start[h * width + w] = (TPixel)val;
                    }
                }
            }
            else
            {
                double factor = 1.0 / scale;
                for (int h = 0; h < height; h++)
                {
                    for (int w = 0; w < width; w++)
                    {
                        int val = 0;
                        for (int kw = 0; kw < kernelWidth; kw++)
                        {
                            for (int kh = 0; kh < kernelHeight; kh++)
                            {
                                val += maskImage[h + kh, w + kw] * kernel[kh, kw];
                            }
                        }
                        start[h * width + w] = (TPixel)(val * factor);
                    }
                }
            }
            maskImage.Dispose();
        }
Example #5
0
        public void ApplyGaussianBlur(double sigma = 1.4, int size = 5)
        {
            ConvolutionKernel kernel = ConvolutionKernel.CreateGaussianKernel(sigma, size);

            this.ApplyConvolution(kernel);
        }