RGB565 转灰度
RGB565 to Grayscale
我正在尝试将 RGB565 图像转换为灰度图像。
我使用下面的代码进行转换。我有一个 rgb565 像素。我正在获取 R、G 和 B 值并进行转换操作。获得灰度后,我将重建一个 16 位像素值,其中 R、G 和 B 将具有相同的灰度值。
int16_t pixel = *buffer;
int16_t red = ((pixel & 0xF800)>>11);
int16_t green = ((pixel & 0x07E0)>>5);
int16_t blue = (pixel & 0x001F);
int16_t grayscale = (0.2126 * red) + (0.7152 * green) + (0.0722 * blue);
*buffer=(grayscale<<11)+(grayscale<<5)+grayscale;
在这里,我期待一张灰度图像。然而,发生的事情是 ->
绿色有 6 位 space(具有更大的幅度)。生成的灰度值应为 5 位,这样,我将适合 R G 和 B。但是,完成的计算提供了 6 位灰度,因此我没有得到正确的灰度图像。
谁能帮我将 rgb565 转换为灰度并将其存储为 16 位。
Green
组件有 6 位,不是因为它需要更高的值,而是因为它需要更高的分辨率(参见 RGB 565 - Why 6 Bits for Green Color)。
因此,要使值范围等于 Red
和 Blue
,只需将 Green
值除以 2:
int16_t pixel = *buffer;
int16_t red = ((pixel & 0xF800)>>11);
int16_t green = ((pixel & 0x07E0)>>5);
int16_t blue = (pixel & 0x001F);
int16_t grayscale = (0.2126 * red) + (0.7152 * green / 2.0) + (0.0722 * blue);
// ^^^^^
*buffer=(grayscale<<11)+(grayscale<<6)+grayscale;
我认为 Pibben 的回答仍然有一些 shift/mask 错误,并且它使用浮点数,根据您的环境,可能会非常慢甚至不可能。前段时间我自己做了这个,所以这是我写的:
我首先想要的是单色取景器模式...我想使用 16 位整数 space,为了速度,
所以我需要使用标准 fixed-point 比例数学。从 https://en.wikipedia.org/wiki/Grayscale#Luma_coding_in_video_systems 开始,它使用的系数与
gamma-corrected 值:
Y = 0.2126×R + 0.7152×G + 0.0722×B
给定 RMAX = GMAX = BMAX = 63,一个尺度
1000 的系数将避免溢出 U16。所以,我们必须失去
给定 four-digit 系数的 LSD。避免被 1000 除
求和后我们可以将所有因子放大 1024/1000,然后我们的
除法变成 right-shift 10 位。所以对于我们的系数:
(2126×1024)÷10000 = 217.7,四舍五入为 218。等等。给定
这些计算出的系数和 RGB565 源格式,
YMAX = 64,220,这不
溢出一个U16;查看。除以 1024 最大结果为 62.7,
可以四舍五入为 63;完美的。 (四舍五入只是加回去
most-significant 位在移位中丢失,这通常是
在汇编语言中几乎是微不足道的[带进位加0]但有点
C 中的 messier。)这给了我们一个 0..63 6 位整数亮度值
这很容易打包回 RGB565。最后的 de-colorization 代码
变成:
void
decolorize(U16 *usp, int count)
{
U16 us, rc, gc, bc, luma;
while (--count) {
us = *usp;
rc = (us >> 10) & 0x3E; /* 6-bit Red Component. */
gc = (us >> 5) & 0x3F; /* 6-bit Green Component. */
bc = (us << 1) & 0x3E; /* 6-bit Blue Component. */
luma = (rc * 218) + (gc * 732) + (bc * 74); /* Wx*1024/10000. */
luma = (luma >> 10) + ((luma >> 9) & 1); /* 6-bit Luminance value. */
*usp++ = ((luma & 0x3E) << 10) | (luma << 5) | (luma >> 1); /* RGB565 */
}
}
此外,如果您能负担得起 128kB 的查找 table,通过类似于上面的代码初始化,RGB565 像素可以通过数组查找直接转换,这在大多数处理器上都非常快。除非您使用 GPU 或矢量处理器,否则我认为您无法在速度上击败它。 LUT 是我最终实际使用此代码的方式。
我正在尝试将 RGB565 图像转换为灰度图像。
我使用下面的代码进行转换。我有一个 rgb565 像素。我正在获取 R、G 和 B 值并进行转换操作。获得灰度后,我将重建一个 16 位像素值,其中 R、G 和 B 将具有相同的灰度值。
int16_t pixel = *buffer;
int16_t red = ((pixel & 0xF800)>>11);
int16_t green = ((pixel & 0x07E0)>>5);
int16_t blue = (pixel & 0x001F);
int16_t grayscale = (0.2126 * red) + (0.7152 * green) + (0.0722 * blue);
*buffer=(grayscale<<11)+(grayscale<<5)+grayscale;
在这里,我期待一张灰度图像。然而,发生的事情是 ->
绿色有 6 位 space(具有更大的幅度)。生成的灰度值应为 5 位,这样,我将适合 R G 和 B。但是,完成的计算提供了 6 位灰度,因此我没有得到正确的灰度图像。
谁能帮我将 rgb565 转换为灰度并将其存储为 16 位。
Green
组件有 6 位,不是因为它需要更高的值,而是因为它需要更高的分辨率(参见 RGB 565 - Why 6 Bits for Green Color)。
因此,要使值范围等于 Red
和 Blue
,只需将 Green
值除以 2:
int16_t pixel = *buffer;
int16_t red = ((pixel & 0xF800)>>11);
int16_t green = ((pixel & 0x07E0)>>5);
int16_t blue = (pixel & 0x001F);
int16_t grayscale = (0.2126 * red) + (0.7152 * green / 2.0) + (0.0722 * blue);
// ^^^^^
*buffer=(grayscale<<11)+(grayscale<<6)+grayscale;
我认为 Pibben 的回答仍然有一些 shift/mask 错误,并且它使用浮点数,根据您的环境,可能会非常慢甚至不可能。前段时间我自己做了这个,所以这是我写的:
我首先想要的是单色取景器模式...我想使用 16 位整数 space,为了速度, 所以我需要使用标准 fixed-point 比例数学。从 https://en.wikipedia.org/wiki/Grayscale#Luma_coding_in_video_systems 开始,它使用的系数与 gamma-corrected 值:
Y = 0.2126×R + 0.7152×G + 0.0722×B
给定 RMAX = GMAX = BMAX = 63,一个尺度 1000 的系数将避免溢出 U16。所以,我们必须失去 给定 four-digit 系数的 LSD。避免被 1000 除 求和后我们可以将所有因子放大 1024/1000,然后我们的 除法变成 right-shift 10 位。所以对于我们的系数: (2126×1024)÷10000 = 217.7,四舍五入为 218。等等。给定 这些计算出的系数和 RGB565 源格式, YMAX = 64,220,这不 溢出一个U16;查看。除以 1024 最大结果为 62.7, 可以四舍五入为 63;完美的。 (四舍五入只是加回去 most-significant 位在移位中丢失,这通常是 在汇编语言中几乎是微不足道的[带进位加0]但有点 C 中的 messier。)这给了我们一个 0..63 6 位整数亮度值 这很容易打包回 RGB565。最后的 de-colorization 代码 变成:
void
decolorize(U16 *usp, int count)
{
U16 us, rc, gc, bc, luma;
while (--count) {
us = *usp;
rc = (us >> 10) & 0x3E; /* 6-bit Red Component. */
gc = (us >> 5) & 0x3F; /* 6-bit Green Component. */
bc = (us << 1) & 0x3E; /* 6-bit Blue Component. */
luma = (rc * 218) + (gc * 732) + (bc * 74); /* Wx*1024/10000. */
luma = (luma >> 10) + ((luma >> 9) & 1); /* 6-bit Luminance value. */
*usp++ = ((luma & 0x3E) << 10) | (luma << 5) | (luma >> 1); /* RGB565 */
}
}
此外,如果您能负担得起 128kB 的查找 table,通过类似于上面的代码初始化,RGB565 像素可以通过数组查找直接转换,这在大多数处理器上都非常快。除非您使用 GPU 或矢量处理器,否则我认为您无法在速度上击败它。 LUT 是我最终实际使用此代码的方式。