/// <summary> /// Apply convolution to given image /// </summary> /// <param name="invert">Whether to invert the resulting convolution</param> /// <param name="intensity">Value by which to multiply inversion strength</param> internal Bitmap ApplyTo(Bitmap imageSource, bool invert, float intensity) { ColorMatrix source = new ColorMatrix(imageSource); ColorMatrix target = ColorMatrix.Blank(source.Width, source.Height); float a, r, g, b; float factor = 0.0f; int offsetX, offsetY; int sourceY, sourceX, matrixY, matrixX; int width = source.Width, height = source.Height; int startX = 0, startY = 0; if (!_includeEdges) { height -= _radius; width -= _radius; startX = startY = _radius; } for (sourceY = startY; sourceY < height; sourceY++) { for (sourceX = startX; sourceX < width; sourceX++) { a = r = g = b = 0.0f; if (!(_preserveTransparency && source.IsTransparent(sourceX, sourceY))) { // do not convolve alpha channel a = source.Color[sourceX, sourceY, ColorMatrix.Channel.Alpha]; for (matrixY = -_radius; matrixY <= _radius; matrixY++) { // now analyze pixels under matrix offsetY = Idaho.Utility.Constrain(sourceY + matrixY, 0, height - 1); for (matrixX = -_radius; matrixX <= _radius; matrixX++) { factor = _matrix[matrixY + _radius, matrixX + _radius]; offsetX = Idaho.Utility.Constrain(sourceX + matrixX, 0, width - 1); // track sum of all color values separately in area // covered by matrix r += factor * source.Color[offsetX, offsetY, ColorMatrix.Channel.Red]; g += factor * source.Color[offsetX, offsetY, ColorMatrix.Channel.Green]; b += factor * source.Color[offsetX, offsetY, ColorMatrix.Channel.Blue]; } } r /= _total; g /= _total; b /= _total; } // apply convolved color to single pixel under consideration target.SetPixel(sourceX, sourceY, a, r, g, b); } } if (invert) { source.CombineWith(target, new ColorMatrix.CombineDelegate(Invert), intensity); return(source.ToBitmap()); } else { return(target.ToBitmap()); } }