繁体   English   中英

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 位空间(有更多的大小)。 生成的灰度值应为 5 位,这样,我将适合 R G 和 B。但是,完成的计算提供了 6 位灰度,因此我没有得到正确的灰度图像。

谁能帮我将 rgb565 转换为灰度并将其存储为 16 位。

Green分量有 6 位,不是因为它需要更高的值,而是因为它需要更高的分辨率(请参阅RGB 565 - 为什么绿色使用 6 位)。

因此,要使值范围等于RedBlue的值范围,只需将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 的答案中仍然存在一些移位/掩码错误,并且它使用浮点数,根据您的环境,可能会非常慢甚至不可能。 前段时间我自己做了这个,所以这是我写的:

我想要的第一件事是单色取景器模式......我想在 16 位 integer 空间中工作,为了速度,所以我需要使用标准定点缩放数学。 https://en.wikipedia.org/wiki/Grayscale#Luma_coding_in_video_systems开始,它使用与伽马校正值一起使用的系数:

Y = 0.2126×R + 0.7152×G + 0.0722×B

给定 R MAX = G MAX = B MAX = 63,比例因子 1000 将避免 U16 溢出。 所以,我们必须失去给定四位数系数的 LSD。 为了避免求和后除以 1000,我们可以将所有因子按比例放大 1024/1000,然后我们的除法变为右移 10 位。 因此,对于我们的系数:(2126×1024)÷10000 = 217.7,四舍五入为 218。等等。给定这些计算出的系数和 RGB565 源格式,Y MAX = 64,220,不会溢出 U16; 查看。 除以 1024 最大结果为 62.7,可四舍五入为 63; 完美的。 (四舍五入只是简单地加回移位中丢失的最高有效位,这在汇编语言中通常几乎微不足道[带进位加 0] 但在 C 中有点混乱。)这给了我们一个 0..63 6 位 integer易于打包回 RGB565 的亮度值。 最终的脱色代码变为:

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 的查找表,用类似于上面的代码初始化,RGB565 像素可以直接通过数组查找转换,这在大多数处理器上都非常快。 除非您使用 GPU 或矢量处理器,否则我认为您无法在速度上击败它。 LUT 是我最终实际使用此代码的方式。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM