// See also: http://matlabtricks.com/post-5/3x3-convolution-kernels-with-online-demo#demo

        public static ImageBuffer Convolution(this ImageBuffer buffer, double[,] kernel, double factor = 1, int bias = 0)
        {
            byte[] source = buffer.Bytes;

            ImageBuffer output = buffer.Fill(Color.Black);

            byte[] target = output.Bytes;

            double blue, green, red;

            int width = kernel.GetLength(0);
            //int height = kernel.GetLength(1);  // ?? wordt (nog?) niet gebruikt (20150101 FH)

            int matrixOffset = (width - 1) / 2;

            int calcOffset, byteOffset;

            for (int offsetY = matrixOffset; offsetY < buffer.Height - matrixOffset; offsetY++)
            {
                for (int offsetX = matrixOffset; offsetX < buffer.Width - matrixOffset; offsetX++)
                {
                    blue  = 0;
                    green = 0;
                    red   = 0;

                    byteOffset = offsetY * buffer.Stride + offsetX * 4;

                    for (int filterY = -matrixOffset; filterY <= matrixOffset; filterY++)
                    {
                        for (int filterX = -matrixOffset; filterX <= matrixOffset; filterX++)
                        {
                            calcOffset = byteOffset + (filterX * 4) + (filterY * buffer.Stride);

                            blue  += (double)(source[calcOffset + 0]) * kernel[filterY + matrixOffset, filterX + matrixOffset];
                            green += (double)(source[calcOffset + 1]) * kernel[filterY + matrixOffset, filterX + matrixOffset];
                            red   += (double)(source[calcOffset + 2]) * kernel[filterY + matrixOffset, filterX + matrixOffset];
                        }
                    }

                    blue  = factor * blue + bias;
                    green = factor * green + bias;
                    red   = factor * red + bias;

                    target[byteOffset + 0] = ByteConversion.Bounded(blue);
                    target[byteOffset + 1] = ByteConversion.Bounded(green);
                    target[byteOffset + 2] = ByteConversion.Bounded(red);
                    target[byteOffset + 3] = 255;
                }
            }

            return(output);
        }