欢迎来到尧图网

客户服务 关于我们

您的位置:首页 > 文旅 > 游戏 > 【学Rust写CAD】31 muldiv255函数(muldiv255.rs)

【学Rust写CAD】31 muldiv255函数(muldiv255.rs)

2025/4/9 15:34:04 来源:https://blog.csdn.net/weixin_43219667/article/details/147016178  浏览:    关键词:【学Rust写CAD】31 muldiv255函数(muldiv255.rs)

源码

// Calculates floor(a*b/255 + 0.5)
#[inline]
pub fn muldiv255(a: u32, b: u32) -> u32 {// The deriviation for this formula can be// found in "Three Wrongs Make a Right" by Jim Blinn.let tmp = a * b + 128;(tmp + (tmp >> 8)) >> 8
}

代码分析

这个 muldiv255 函数是一个高效的实现,用于计算 floor(a * b / 255 + 0.5),也就是将两个无符号整数 a 和 b 相乘,然后除以 255,并进行四舍五入。这种计算在图像处理中很常见,比如在 alpha 混合(alpha blending)或颜色空间转换时。

步骤分解:
  1. a * b + 128:
  • 首先计算 a * b,然后加上 128。这个 128 的作用是为了后续的四舍五入(因为 255 / 2 = 127.5,所以加 128 可以确保正确的舍入)。
  1. tmp + (tmp >> 8):
  • tmp >> 8 相当于 tmp / 256(右移 8 位相当于除以 2^8)。

  • 然后 tmp + (tmp >> 8) 相当于 tmp + tmp / 256。

  1. 8:

  • 最后右移 8 位,相当于除以 256。

为什么这个公式有效?

这个方法的数学原理来自 Jim Blinn 的文章 “Three Wrongs Make a Right”,它利用了近似计算来避免昂贵的除法运算(因为整数除法在 CPU 上通常比乘法和移位慢)。

  • 原本的计算是 (a * b + 127) / 255(四舍五入)。

  • 但 (a * b + 128) * 257 / 65536(即 (tmp + (tmp >> 8)) >> 8)是一个近似计算,可以高效地用移位和加法实现。

数学推导:

  1. 我们希望计算 (a * b + 127) / 255(四舍五入)。

  2. 可以近似为 (a * b + 128) * (256 + 1) / 65536(因为 255 ≈ 65536 / 257)。

展开后:

(a * b + 128) * (256 + 1) / 65536
= (256*(a*b + 128) + (a*b + 128)) / 65536
= ( (a*b + 128) << 8 + (a*b + 128) ) >> 16
= (tmp << 8 + tmp) >> 16
= (tmp + (tmp >> 8)) >> 8

最终得到 (tmp + (tmp >> 8)) >> 8。

示例

假设 a = 100, b = 200:

  1. tmp = 100 * 200 + 128 = 20000 + 128 = 20128

  2. tmp >> 8 = 20128 / 256 = 78

  3. tmp + (tmp >> 8) = 20128 + 78 = 20206

20206 >> 8 = 20206 / 256 = 78(实际 100 * 200 / 255 ≈ 78.431,四舍五入得 78)

为什么不用 (a * b + 127) / 255?

虽然 (a * b + 127) / 255 也能得到正确结果,但:

  • 除法 (/ 255) 在 CPU 上通常比移位和加法慢。

  • 这个优化方法避免了除法,改用移位和加法,性能更高。

适用场景

  • 图像处理(如 alpha 混合、颜色计算)。

  • 需要高效计算 (a * b) / 255 并四舍五入的情况。

总结

这个函数巧妙地利用移位和加法来近似计算 (a * b) / 255 并四舍五入,避免了昂贵的除法运算,是一种高效的位操作优化方法。

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com

热搜词