# 三十分鐘理解：線性插值，雙線性插值Bilinear Interpolation演算法

## 線性插值

y−y0x−x0=y1−y0x1−x0

\frac{y – y_0}{x – x_0} = \frac{y_1 – y_0}{x_1 – x_0}

y=x1−xx1−x0y0 x−x0x1−x0y1

y = \frac{x_1 – x}{x_1 – x_0}y_0 \frac{x – x_0}{x_1 – x_0}y_1

## 雙線性插值

SrcX=(dstX 0.5)* (srcWidth/dstWidth) -0.5
SrcY=(dstY 0.5) * (srcHeight/dstHeight)-0.5

cv::Mat matSrc, matDst1, matDst2;
matSrc = cv::imread("lena.jpg", 2 | 4);
matDst1 = cv::Mat(cv::Size(800, 1000), matSrc.type(), cv::Scalar::all(0));
matDst2 = cv::Mat(matDst1.size(), matSrc.type(), cv::Scalar::all(0));
double scale_x = (double)matSrc.cols / matDst1.cols;
double scale_y = (double)matSrc.rows / matDst1.rows;
int stepDst = matDst1.step;
uchar* dataSrc = matSrc.data;
int stepSrc = matSrc.step;
int iWidthSrc = matSrc.cols;
int iHiehgtSrc = matSrc.rows;
for (int j = 0; j < matDst1.rows;   j)
{
float fy = (float)((j   0.5) * scale_y - 0.5);
int sy = cvFloor(fy);
fy -= sy;
sy = std::min(sy, iHiehgtSrc - 2);
sy = std::max(0, sy);
short cbufy[2];
cbufy[0] = cv::saturate_cast<short>((1.f - fy) * 2048);
cbufy[1] = 2048 - cbufy[0];
for (int i = 0; i < matDst1.cols;   i)
{
float fx = (float)((i   0.5) * scale_x - 0.5);
int sx = cvFloor(fx);
fx -= sx;
if (sx < 0) {
fx = 0, sx = 0;
}
if (sx >= iWidthSrc - 1) {
fx = 0, sx = iWidthSrc - 2;
}
short cbufx[2];
cbufx[0] = cv::saturate_cast<short>((1.f - fx) * 2048);
cbufx[1] = 2048 - cbufx[0];
for (int k = 0; k < matSrc.channels();   k)
{
*(dataDst  j*stepDst   3*i   k) = (*(dataSrc   sy*stepSrc   3*sx   k) * cbufx[0] * cbufy[0]
*(dataSrc   (sy 1)*stepSrc   3*sx   k) * cbufx[0] * cbufy[1]
*(dataSrc   sy*stepSrc   3*(sx 1)   k) * cbufx[1] * cbufy[0]
*(dataSrc   (sy 1)*stepSrc   3*(sx 1)   k) * cbufx[1] * cbufy[1]) >> 22;
}
}
}
cv::imwrite("linear_1.jpg", matDst1);
cv::resize(matSrc, matDst2, matDst1.size(), 0, 0, 1);
cv::imwrite("linear_2.jpg", matDst2);