由于对于每种原色(一般意义上的原色,意味着颜色组合形成其他颜色),RGB 分量往往是从无色到全色的比例,我可能会先转换为 RGB,然后使用正常的灰度算法(您声明“适用于 24 位 RGB888”的任何算法)。
第一个位可能用(大写是 8 位值,小写是 5/6 位值):
R = r * 8 ; 256/32, 8-bit from 5-bit
B = b * 4 ; 256/64, 8-bit from 6-bit
G = g * 8 ; 256/32, 8-bit from 5-bit
只需确保在提取位时顺序正确,因为您将 RBG 转换为 RGB。
例如,这是一个完整的 C 程序(因为您没有提供语言标记),其中包含一个可以执行此操作的函数,只是它使用了稍微不同的缩放比例,它依赖于百分比而不是需要 0..255 的固定值输入:
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
uint16_t greyScale(uint16_t rbg565) {
// Get the values (32-bit to hold larger intermediate values).
uint32_t r = (rbg565 >> 11) & 31U; // XXXXX___________
uint32_t g = rbg565 & 31U; // ___________XXXXX
uint32_t b = (rbg565 >> 5) & 63U; // _____XXXXXX_____
// Scale each of them up to the range 0..500.
g = g * 500 / 31;
b = b * 500 / 63;
r = r * 500 / 31;
// Use example RGB weights of 299/587/114 (summing to 1,000).
// Range then 0..500,000 so divide by 500 to get grey 0..1,000.
uint32_t grey = (r * 299 + g * 587 + b * 114);
grey /= 500;
return (uint16_t)grey;
}
int main(int argc, char *argv[])
{
for (int i = 1; i < argc; i++) {
uint16_t rbg = atoi(argv[i]);
printf("%5d -> %d\n", rbg, greyScale(rbg));
}
return 0;
}
如果你用一些样本值运行它,你会看到灰度值出来(cmets 是我添加的):
pax:~> ./prog 0 65535 31 $((63*32)) $((31*2048)) $((16*2048+32*32+16))
0 -> 0 # No colour components.
65535 -> 1000 # Max RGB (white).
31 -> 587 # Max green, nothing else.
2016 -> 114 # Max blue, nothing else.
63488 -> 299 # Max red, nothing else.
33808 -> 514 # A little more than half of everything.
如果您想使用与我提供的权重不同的权重(29.9%、58.7% 和 11.4%),只需更改此行以匹配,确保它们的总和仍为一千:
uint32_t grey = (r * 299 + g * 587 + b * 114);