Untitled
unknown
csharp
8 months ago
3.1 kB
4
Indexable
Never
using System; using System.Drawing; // Requires System.Drawing.Common package using System.Drawing.Imaging; public static Bitmap ResizeImageWithLanczos(Bitmap source, int targetWidth, int targetHeight, int a) { Bitmap target = new Bitmap(targetWidth, targetHeight, PixelFormat.Format32bppArgb); BitmapData sourceData = source.LockBits(new Rectangle(0, 0, source.Width, source.Height), ImageLockMode.ReadOnly, PixelFormat.Format32bppArgb); BitmapData targetData = target.LockBits(new Rectangle(0, 0, targetWidth, targetHeight), ImageLockMode.WriteOnly, PixelFormat.Format32bppArgb); int bytesPerPixel = 4; // For Format32bppArgb byte[] sourceBuffer = new byte[sourceData.Stride * sourceData.Height]; byte[] targetBuffer = new byte[targetData.Stride * targetHeight]; System.Runtime.InteropServices.Marshal.Copy(sourceData.Scan0, sourceBuffer, 0, sourceBuffer.Length); double scaleX = (double)source.Width / targetWidth; double scaleY = (double)source.Height / targetHeight; Parallel.For(0, targetHeight, y => { int targetYOffset = y * targetData.Stride; for (int x = 0; x < targetWidth; x++) { double sourceX = x * scaleX; double sourceY = y * scaleY; double sumR = 0, sumG = 0, sumB = 0, sumA = 0, sumWeight = 0; int xFrom = (int)Math.Max(Math.Floor(sourceX - a), 0); int xTo = (int)Math.Min(Math.Ceiling(sourceX + a), source.Width - 1); int yFrom = (int)Math.Max(Math.Floor(sourceY - a), 0); int yTo = (int)Math.Min(Math.Ceiling(sourceY + a), source.Height - 1); for (int sy = yFrom; sy <= yTo; sy++) { int sourceYOffset = sy * sourceData.Stride; double dy = LanczosKernel(sourceY - sy, a); for (int sx = xFrom; sx <= xTo; sx++) { double dx = LanczosKernel(sourceX - sx, a); double weight = dx * dy; int sourceIndex = sourceYOffset + sx * bytesPerPixel; sumB += sourceBuffer[sourceIndex] * weight; sumG += sourceBuffer[sourceIndex + 1] * weight; sumR += sourceBuffer[sourceIndex + 2] * weight; sumA += sourceBuffer[sourceIndex + 3] * weight; sumWeight += weight; } } int targetIndex = targetYOffset + x * bytesPerPixel; targetBuffer[targetIndex] = ClipToByte(sumB / sumWeight); targetBuffer[targetIndex + 1] = ClipToByte(sumG / sumWeight); targetBuffer[targetIndex + 2] = ClipToByte(sumR / sumWeight); targetBuffer[targetIndex + 3] = ClipToByte(sumA / sumWeight); } }); System.Runtime.InteropServices.Marshal.Copy(targetBuffer, 0, targetData.Scan0, targetBuffer.Length); source.UnlockBits(sourceData); target.UnlockBits(targetData); return target; } private static byte ClipToByte(double value) { return (byte)(Math.Max(Math.Min(value, 255), 0)); }
Leave a Comment