Untitled

mail@pastecode.io avatar
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