Correct bicubic oversampling

I experimented with the image resampling algorithm introduced by AForge with the idea of ​​introducing something similar into my image processing solution. See. The original algorithm is here , and the interpolation kernel here

Sorry, I hit the wall. It seems to me that I somehow incorrectly calculate the position of the sample location, possibly due to the algorithm that is designed for images Format24bppRgb, where, when I use the format Format32bppPArgb.

Here is my code:

public Bitmap Resize(Bitmap source, int width, int height)
{
    int sourceWidth = source.Width;
    int sourceHeight = source.Height;

    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))
        {
            double heightFactor = sourceWidth / (double)width;
            double widthFactor = sourceHeight / (double)height;

            // Coordinates of source points
            double ox, oy, dx, dy, k1, k2;
            int ox1, oy1, ox2, oy2;

            // Width and height decreased by 1
            int maxHeight = height - 1;
            int maxWidth = width - 1;

            for (int y = 0; y < height; y++)
            {
                // Y coordinates
                oy = (y * widthFactor) - 0.5;

                oy1 = (int)oy;
                dy = oy - oy1;

                for (int x = 0; x < width; x++)
                {
                    // X coordinates
                    ox = (x * heightFactor) - 0.5f;
                    ox1 = (int)ox;
                    dx = ox - ox1;

                    // Destination color components
                    double r = 0;
                    double g = 0;
                    double b = 0;
                    double a = 0;

                    for (int n = -1; n < 3; n++)
                    {
                        // Get Y cooefficient
                        k1 = Interpolation.BiCubicKernel(dy - n);

                        oy2 = oy1 + n;
                        if (oy2 < 0)
                        {
                            oy2 = 0;
                        }

                        if (oy2 > maxHeight)
                        {
                            oy2 = maxHeight;
                        }

                        for (int m = -1; m < 3; m++)
                        {
                            // Get X cooefficient
                            k2 = k1 * Interpolation.BiCubicKernel(m - dx);

                            ox2 = ox1 + m;
                            if (ox2 < 0)
                            {
                                ox2 = 0;
                            }

                            if (ox2 > maxWidth)
                            {
                                ox2 = maxWidth;
                            }

                            Color color = sourceBitmap.GetPixel(ox2, oy2);

                            r += k2 * color.R;
                            g += k2 * color.G;
                            b += k2 * color.B;
                            a += k2 * color.A;
                        }
                    }

                    destinationBitmap.SetPixel(
                        x, 
                        y, 
                        Color.FromArgb(a.ToByte(), r.ToByte(), g.ToByte(), b.ToByte()));
                }
            }

        }
    }

    source.Dispose();
    return destination;
}

And the core that this equation should represent on Wikipedia

public static double BiCubicKernel(double x)
{
    if (x < 0)
    {
        x = -x;
    }

    double bicubicCoef = 0;

    if (x <= 1)
    {
        bicubicCoef = (1.5 * x - 2.5) * x * x + 1;
    }
    else if (x < 2)
    {
        bicubicCoef = ((-0.5 * x + 2.5) * x - 4) * x + 2;
    }

    return bicubicCoef;
}

Here's the original image at 500px x 667px.

tree picture

And the image has changed to 400px x 543px.

tree using bicubic algorithm

, , , .

- , ?

FastBitmap - Bitmap, LockBits . .

Edit

ToByte

public static byte ToByte(this double value)
{
    return Convert.ToByte(ImageMaths.Clamp(value, 0, 255));
}

public static T Clamp<T>(T value, T min, T max) where T : IComparable<T>
{
    if (value.CompareTo(min) < 0)
    {
        return min;
    }

    if (value.CompareTo(max) > 0)
    {
        return max;
    }

    return value;
}
+2
2

ox2 oy2 , .

:

// Width and height decreased by 1
int maxHeight = height - 1;
int maxWidth = width - 1;

:

// Width and height decreased by 1
int maxHeight = sourceHeight - 1;
int maxWidth = sourceWidth - 1;
+2

, , . . 4x4 . :

 var source = Bitmap.FromFile(@"C:\Users\Public\Pictures\Sample Pictures\.png");
 using (FastBitmap sourceBitmap = new FastBitmap(source))
        {
            for (int TY = 0; TY < 4; TY++)
            {
                for (int TX = 0; TX < 4; TX++)
                {
                    Color color = sourceBitmap.GetPixel(TX, TY);
                    Console.Write(color.B.ToString().PadLeft(5));
                }
                Console.WriteLine();
            }
        }

Exit

, .

, , , , . : DPI?

, , :

, .

+1

All Articles