Provides interpolation routines for resampling algorithms.
예제 #1
0
        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);
        }
예제 #2
0
        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);
        }