【学Rust写CAD】27 双线性插值函数(bilinear_interpolation.rs)

时间:2025-04-04 16:20:36

源码

use super::constant::BILINEAR_INTERPOLATION_BITS;
// Inspired by Filter_32_opaque from Skia.
fn bilinear_interpolation(
    tl: u32,
    tr: u32,
    bl: u32,
    br: u32,
    mut distx: u32,
    mut disty: u32,
) -> u32 {
    let distxy;
    let distxiy;
    let distixy;
    let distixiy;
    let mut lo;
    let mut hi;

    distx <<= 4 - BILINEAR_INTERPOLATION_BITS;
    disty <<= 4 - BILINEAR_INTERPOLATION_BITS;

    distxy = distx * disty;
    distxiy = (distx << 4) - distxy; // distx * (16 - disty)
    distixy = (disty << 4) - distxy; // disty * (16 - distx)

    // (16 - distx) * (16 - disty)
    // The intermediate calculation can underflow so we use
    // wrapping arithmetic to let the compiler know that it's ok
    distixiy = (16u32 * 16)
        .wrapping_sub(disty << 4)
        .wrapping_sub(distx << 4)
        .wrapping_add(distxy);

    lo = (tl & 0xff00ff) * distixiy;
    hi = ((tl >> 8) & 0xff00ff) * distixiy;

    lo += (tr & 0xff00ff) * distxiy;
    hi += ((tr >> 8) & 0xff00ff) * distxiy;

    lo += (bl & 0xff00ff) * distixy;
    hi += ((bl >> 8) & 0xff00ff) * distixy;

    lo += (br & 0xff00ff) * distxy;
    hi += ((br >> 8) & 0xff00ff) * distxy;

    ((lo >> 8) & 0xff00ff) | (hi & !0xff00ff)
}

代码分析

这个函数实现了双线性插值算法,用于在四个已知像素点(tl, tr, bl, br)之间插值计算一个新的像素值。该代码参考Skia图形库中Filter_32_opaque函数。

参数说明

  • tl: 左上(top-left)像素值

  • tr: 右上(top-right)像素值

  • bl: 左下(bottom-left)像素值

  • br: 右下(bottom-right)像素值

  • distx: x方向的插值距离(0-15)

  • disty: y方向的插值距离(0-15)

算法步骤

1.距离调整:

distx <<= 4 - BILINEAR_INTERPOLATION_BITS;
disty <<= 4 - BILINEAR_INTERPOLATION_BITS;

将输入的distx和disty从BILINEAR_INTERPOLATION_BITS精度调整到4位精度(0-15)。

  1. 计算权重因子:
  • distxy: distx * disty

  • distxiy: distx * (16 - disty)

  • distixy: disty * (16 - distx)
  • distixiy: (16 - distx) * (16 - disty)
  1. 分离颜色通道计算:
    函数将32位颜色值分为两个16位部分处理:
  • lo: 处理蓝色(低8位)和红色(高8位)通道

  • hi: 处理绿色(低8位)和alpha(高8位)通道

4.加权求和:
对四个角的像素值按照计算出的权重进行加权求和。

  1. 合并结果:
((lo >> 8) & 0xff00ff) | (hi & !0xff00ff)

将计算结果重新组合成32位像素值。

技术细节

  • 使用wrapping_操作防止中间计算溢出

  • 使用位操作高效处理颜色通道

  • 假设输入像素是不透明的(alpha通道为0xff)

这个函数在图像缩放、旋转等变换中非常有用,可以平滑地计算出新位置的像素值,避免锯齿效果。