给定2个RGB颜色存储为32位整数(8位alpha可以忽略或设置为0xff
)。
使用0-255之间的第3个整数来混合它们的最快方法。
这是一个简单的实现,它只是将值插入为int:
int32_t rgb_blend(uint32_t src, uint32_t dst, uint32_t blend) {
const uint32_t iblend = 255 - blend;
union {
uint32_t u32;
struct { uint8_t
#if defined(__LITTLE_ENDIAN__)
a, b, g, r;
#else
r, g, b, a;
#endif
} u8;
} out, *s = (const void *)&src, *d = (const void *)&dst;
out.u8.r = (uint8_t)((((uint32_t)s->u8.r * iblend) + ((uint32_t)d->u8.r * blend)) / 255);
out.u8.g = (uint8_t)((((uint32_t)s->u8.g * iblend) + ((uint32_t)d->u8.g * blend)) / 255);
out.u8.b = (uint8_t)((((uint32_t)s->u8.b * iblend) + ((uint32_t)d->u8.b * blend)) / 255);
out.u8.a = 0xff;
return out.u32;
}
这不是必须完全准确,一些舍入偏差以获得一些额外的性能是好的。 (i / 256)
向下舍入为例如但可以用(((i * 2) + 255) / (2 * 255)
替换为0.5
,而仅使用整数运算。
注意:
答案 0 :(得分:1)
只使用加,减,乘和位移(无分支或类型转换)可以混合颜色:
uint32_t rgb_interp(uint32_t src, uint32_t dst, uint32_t t) {
assert(t <= 255);
const uint32_t s = 255 - t;
#if defined(__LITTLE_ENDIAN__)
return (
(((((src >> 0) & 0xff) * s +
((dst >> 0) & 0xff) * t) >> 8)) |
(((((src >> 8) & 0xff) * s +
((dst >> 8) & 0xff) * t) ) & ~0xff) |
(((((src >> 16) & 0xff) * s +
((dst >> 16) & 0xff) * t) << 8) & ~0xffff) |
0xff000000
);
#else
return (
(((((src >> 24) & 0xff) * s +
((dst >> 24) & 0xff) * t) << 16) & ~0xffffff) |
(((((src >> 16) & 0xff) * s +
((dst >> 16) & 0xff) * t) << 8) & ~0xffff) |
(((((src >> 8) & 0xff) * s +
((dst >> 8) & 0xff) * t) ) & ~0xff) |
0xff
);
#endif
}
RGBA版本供参考:
uint32_t rgba_interp(uint32_t src, uint32_t dst, uint32_t t) {
assert(t <= 255);
const uint32_t s = 255 - t;
return (
(((((src >> 0) & 0xff) * s +
((dst >> 0) & 0xff) * t) >> 8)) |
(((((src >> 8) & 0xff) * s +
((dst >> 8) & 0xff) * t) ) & ~0xff) |
(((((src >> 16) & 0xff) * s +
((dst >> 16) & 0xff) * t) << 8) & ~0xffff) |
(((((src >> 24) & 0xff) * s +
((dst >> 24) & 0xff) * t) << 16) & ~0xffffff)
);
}