Bilinear interpolation, something is wrong with my implementation

I am trying to implement a bilinear interpolation function, but for some reason I am getting a bad result. I can’t understand what happened, any help received on the right path will be appreciated.

double lerp(double c1, double c2, double v1, double v2, double x)
{
if( (v1==v2) ) return c1;
double inc = ((c2-c1)/(v2 - v1)) * (x - v1);
double val = c1 + inc;
return val;
};

void bilinearInterpolate(int width, int height)
{
// if the current size is the same, do nothing
if(width == GetWidth() && height == GetHeight())
    return;

//Create a new image
std::unique_ptr<Image2D> image(new Image2D(width, height));

// x and y ratios
double rx = (double)(GetWidth()) / (double)(image->GetWidth()); // oldWidth / newWidth
double ry = (double)(GetHeight()) / (double)(image->GetHeight());   // oldWidth / newWidth


// loop through destination image
for(int y=0; y<height; ++y)
{
    for(int x=0; x<width; ++x)
    {
        double sx = x * rx;
        double sy = y * ry;

        uint xl = std::floor(sx);
        uint xr = std::floor(sx + 1);
        uint yt = std::floor(sy);
        uint yb = std::floor(sy + 1);

        for (uint d = 0; d < image->GetDepth(); ++d)
        {
            uchar tl    = GetData(xl, yt, d);
            uchar tr    = GetData(xr, yt, d);
            uchar bl    = GetData(xl, yb, d);
            uchar br    = GetData(xr, yb, d);
            double t    = lerp(tl, tr, xl, xr, sx);
            double b    = lerp(bl, br, xl, xr, sx);
            double m    = lerp(t, b, yt, yb, sy);
            uchar val   = std::floor(m + 0.5);
            image->SetData(x,y,d,val);
        }
    }
}

//Cleanup
mWidth = width; mHeight = height;
std::swap(image->mData, mData);
}

Input Image (4 pixels wide and high)

Input image (4 pixels wide and high)

My output

My conclusion

Expected Output (Photoshop's Bilinear Interpolation)

Expected Result (Photoshop Bilinear Interpolation)

+3
source share
1 answer

The Photoshop algorithm assumes that each pixel color of the source is in the center of the pixel, while your algorithm assumes that the color is in its stream. This results in a shift of the results by half a pixel up and to the left compared to Photoshop.

, x (0, srcWidth) (0, dstWidth), Photoshop - (-0.5, srcWidth-0.5) (-0.5, dstWidth-0.5) y.

:

double sx = x * rx;
double sy = y * ry;

:

double sx = (x + 0.5) * rx - 0.5;
double sy = (y + 0.5) * ry - 0.5;

. , sx sy.

+8

All Articles