如何将 RGBA 格式的两个 32 位颜色相乘
How to multiply two 32 bit colours in RGBA format
我正在使用 raylib and it uses the 32 bit RGBA colours. I searched in a cheatsheet,但找不到任何合适的例程。我想要做的是将两种颜色相乘,就好像它们是 opengl 中的 vec4
s(每个通道的范围从 0 到 1)。我其实已经成功了
执行了乘法运算,但它是相当慢的运算,涉及很多如此简单的浮点运算:
uint8_t multiplyBytes(uint8_t a, uint8_t b) {
const float invertedByte = 1/255.0;
return (uint8_t)(((a * invertedByte) * (b * invertedByte)) * 255.0);
}
我的问题是是否有更好的方法来做到这一点?或者我应该坚持使用这个解决方案?
经过一番搜索我意识到,我可以将其升级为:
uint8_t multiplyBytes(uint8_t a, uint8_t b) {
return (uint8_t)(((unsigned short)a * (unsigned short)b + 255) >> 8);
}
不确定这是否是最佳解决方案。
I actually already successfully performed the multiplication but it is rather slow operation involving lot of floating point arithmetic for something so simple:
改进 FP 数学的一个步骤是避免使用 float
和 double
类型。
// double to float
const float invertedByte = 1/255.0;
// uint8_t to float (twice)
// float to double
// double to uint8_t
return (uint8_t)(((a * invertedByte) * (b * invertedByte)) * 255.0);
// ^---- float product ------------------^ double
更好的 FP 解决方案将使用
const float invertedByte = 1.0f/255.0f;
// unsigned to float (once)
// float to uint8_t
return (uint8_t)( ((unsigned)a * (unsigned)b) * invertedByte);
然而,一个全整数解决方案 - 类似于 。
return (uint8_t) (((unsigned)a * (unsigned)b + 255u) >> 8);
或按照
的建议
return (uint8_t) ((unsigned)a * (unsigned)b + 127u) / 255u;
另见好主意
return ((uint_fast32_t)a * (uint_fast32_t)b * 0x10101u + 0x800000u) >> 24;
我正在使用 raylib and it uses the 32 bit RGBA colours. I searched in a cheatsheet,但找不到任何合适的例程。我想要做的是将两种颜色相乘,就好像它们是 opengl 中的 vec4
s(每个通道的范围从 0 到 1)。我其实已经成功了
执行了乘法运算,但它是相当慢的运算,涉及很多如此简单的浮点运算:
uint8_t multiplyBytes(uint8_t a, uint8_t b) {
const float invertedByte = 1/255.0;
return (uint8_t)(((a * invertedByte) * (b * invertedByte)) * 255.0);
}
我的问题是是否有更好的方法来做到这一点?或者我应该坚持使用这个解决方案?
经过一番搜索我意识到,我可以将其升级为:
uint8_t multiplyBytes(uint8_t a, uint8_t b) {
return (uint8_t)(((unsigned short)a * (unsigned short)b + 255) >> 8);
}
不确定这是否是最佳解决方案。
I actually already successfully performed the multiplication but it is rather slow operation involving lot of floating point arithmetic for something so simple:
改进 FP 数学的一个步骤是避免使用 float
和 double
类型。
// double to float
const float invertedByte = 1/255.0;
// uint8_t to float (twice)
// float to double
// double to uint8_t
return (uint8_t)(((a * invertedByte) * (b * invertedByte)) * 255.0);
// ^---- float product ------------------^ double
更好的 FP 解决方案将使用
const float invertedByte = 1.0f/255.0f;
// unsigned to float (once)
// float to uint8_t
return (uint8_t)( ((unsigned)a * (unsigned)b) * invertedByte);
然而,一个全整数解决方案 - 类似于
return (uint8_t) (((unsigned)a * (unsigned)b + 255u) >> 8);
或按照
return (uint8_t) ((unsigned)a * (unsigned)b + 127u) / 255u;
另见
return ((uint_fast32_t)a * (uint_fast32_t)b * 0x10101u + 0x800000u) >> 24;