internal static Bitmap ResizeLanczos(Bitmap source, int width, int height, Rectangle destinationRectangle, bool fixGamma = true) { int sourceWidth = source.Width; int sourceHeight = source.Height; int startX = destinationRectangle.X; int startY = destinationRectangle.Y; int endX = destinationRectangle.Width + startX; int endY = destinationRectangle.Height + startY; Bitmap destination = new Bitmap(width, height, PixelFormat.Format32bppPArgb); destination.SetResolution(source.HorizontalResolution, source.VerticalResolution); using (FastBitmap sourceBitmap = new FastBitmap(source)) { using (FastBitmap destinationBitmap = new FastBitmap(destination)) { // Scaling factors double widthFactor = sourceWidth / (double)destinationRectangle.Width; double heightFactor = sourceHeight / (double)destinationRectangle.Height; // Width and height decreased by 1 int maxHeight = sourceHeight - 1; int maxWidth = sourceWidth - 1; // For each column Parallel.For( startY, endY, y => { if (y >= 0 && y < height) { // Y coordinates of source points. double originY = ((y - startY) * heightFactor) - 0.5; int originY1 = (int)originY; double dy = originY - originY1; // For each row. for (int x = startX; x < endX; x++) { if (x >= 0 && x < width) { // X coordinates of source points. double originX = ((x - startX) * widthFactor) - 0.5f; int originX1 = (int)originX; double dx = originX - originX1; // Destination color components double r = 0; double g = 0; double b = 0; double a = 0; for (int n = -3; n < 6; n++) { // Get Y cooefficient double k1 = Interpolation.LanczosKernel3(dy - n); int originY2 = originY1 + n; if (originY2 < 0) { originY2 = 0; } if (originY2 > maxHeight) { originY2 = maxHeight; } for (int m = -3; m < 6; m++) { // Get X cooefficient double k2 = k1 * Interpolation.LanczosKernel3(m - dx); int originX2 = originX1 + m; if (originX2 < 0) { originX2 = 0; } if (originX2 > maxWidth) { originX2 = maxWidth; } // ReSharper disable once AccessToDisposedClosure Color sourceColor = sourceBitmap.GetPixel(originX2, originY2); if (fixGamma) { sourceColor = PixelOperations.ToLinear(sourceColor); } r += k2 * sourceColor.R; g += k2 * sourceColor.G; b += k2 * sourceColor.B; a += k2 * sourceColor.A; } } Color destinationColor = Color.FromArgb( a.ToByte(), r.ToByte(), g.ToByte(), b.ToByte()); if (fixGamma) { destinationColor = PixelOperations.ToSRGB(destinationColor); } // ReSharper disable once AccessToDisposedClosure destinationBitmap.SetPixel(x, y, destinationColor); } } } }); } } source.Dispose(); return(destination); }
public static Bitmap ResizeBicubicHighQuality(Bitmap source, int width, int height, Rectangle destinationRectangle, bool fixGamma) { int sourceWidth = source.Width; int sourceHeight = source.Height; int startX = destinationRectangle.X; int startY = destinationRectangle.Y; int endX = destinationRectangle.Width + startX; int endY = destinationRectangle.Height + startY; // Scaling factors double widthFactor = sourceWidth / (double)destinationRectangle.Width; double heightFactor = sourceHeight / (double)destinationRectangle.Height; // Width and height decreased by 1 int maxHeight = sourceHeight - 1; int maxWidth = sourceWidth - 1; Bitmap destination = new Bitmap(width, height, PixelFormat.Format32bppPArgb); destination.SetResolution(source.HorizontalResolution, source.VerticalResolution); // The radius for pre blurring the images. // We only apply this for very small images. int radius = 0; if (width <= 150 && height <= 150) { radius = 4; } using (FastBitmap sourceBitmap = new FastBitmap(source)) { using (FastBitmap destinationBitmap = new FastBitmap(destination)) { // For each column Parallel.For( startY, endY, y => { if (y >= 0 && y < height) { // Y coordinates of source points. double originY = ((y - startY) * heightFactor) - 0.5; int originY1 = (int)originY; double dy = originY - originY1; // Houses colors for blurring. Color[,] sourceColors = new Color[4, 4]; // For each row. for (int x = startX; x < endX; x++) { if (x >= 0 && x < width) { // X coordinates of source points. double originX = ((x - startX) * widthFactor) - 0.5f; int originX1 = (int)originX; double dx = originX - originX1; // Destination color components double r = 0; double g = 0; double b = 0; double a = 0; for (int yy = -1; yy < 3; yy++) { int originY2 = originY1 + yy; if (originY2 < 0) { originY2 = 0; } if (originY2 > maxHeight) { originY2 = maxHeight; } for (int xx = -1; xx < 3; xx++) { int originX2 = originX1 + xx; if (originX2 < 0) { originX2 = 0; } if (originX2 > maxWidth) { originX2 = maxWidth; } Color sourceColor = sourceBitmap.GetPixel(originX2, originY2); sourceColors[xx + 1, yy + 1] = sourceColor; } } // Blur the colors. if (radius > 0) { sourceColors = BoxBlur(sourceColors, radius, fixGamma); } // Do the resize. for (int yy = -1; yy < 3; yy++) { // Get Y cooefficient double kernel1 = Interpolation.BiCubicBSplineKernel(dy - yy); for (int xx = -1; xx < 3; xx++) { // Get X cooefficient double kernel2 = kernel1 * Interpolation.BiCubicBSplineKernel(xx - dx); Color sourceColor = sourceColors[xx + 1, yy + 1]; if (fixGamma) { sourceColor = PixelOperations.ToLinear(sourceColor); } r += kernel2 * sourceColor.R; g += kernel2 * sourceColor.G; b += kernel2 * sourceColor.B; a += kernel2 * sourceColor.A; } } Color destinationColor = Color.FromArgb( a.ToByte(), r.ToByte(), g.ToByte(), b.ToByte()); if (fixGamma) { destinationColor = PixelOperations.ToSRGB(destinationColor); } destinationBitmap.SetPixel(x, y, destinationColor); } } } }); } } source.Dispose(); return(destination); }