首页 > 解决方案 > 在YUV中调整Y分量的效果?

问题描述

我一直在对程序进行逆向工程,最近遇到了一个函数,该函数旨在创建一种用于文本选择的半透明颜色。它通过将 RGB 转换为 YUV,更改 Y(亮度?)分量,然后转换回 RGB 来实现这一点。

uint32_t CalcSelectionColor(uint32_t bgr)
{
  double r,g,b;
  double y,u,v;

  r = (bgr >>  0) & 0xFF;
  g = (bgr >>  8) & 0xFF;
  b = (bgr >> 16) & 0xFF;

  /* RGB to YUV */
  y = 0.299*r + 0.587*g + 0.114*b;
  u = (b-y) * 0.565 * 0.5;
  v = (r-y) * 0.713 * 0.5;

  /* lower brightness? */
  y = 255.0 - y;

  /* YUV to RGB */
  r = y + 1.403*v;
  g = y - 0.344*u - 0.714*v;
  b = y + 1.77*u;

  return ((uint8_t)(b) << 16) | ((uint8_t)(g) << 8) | ((uint8_t)(r));
}

作为对计算机图形学知识非常有限的人,我只想更详细地了解它在转换之间的作用以及更广泛意义上的实际预期效果。这是调整颜色亮度的常用方法还是什么?如果我传入 0x00FF00,我得到的结果是 0x1E9D1E

标签: ccolorsrgbyuv

解决方案


这不是很常见,但它是一个非常好的方法。像 HSL/HSV 这样的常用模型不能正确地表示强度,并且有一些奇怪的分段线性的东西,色调/颜色在变化。YUV 是一个非常好的色彩空间,表示沿一个轴的强度和垂直平面中的色度(色调/颜色)。

通常在不调整(至少钳制)U 和 V 的情况下修改 Y 有点可疑,因为在极端附近(Y = 0 黑色,Y = 全白)U 和 V 具有有限的范围(在端点处根本没有范围)。否则,应用它们会将您带出 RGB 立方体,并在您返回 RGB 时导致虚假剪辑结果。但是这里的技巧非常聪明。代码在保持色度固定的同时反转Y,因此接近黑色的 U 和 V 的输入范围限制将自动确保它们在输出中大致正确,反之亦然。

正如 Alex 所指出的,这里的代码也将色度值减半,从而降低了色彩饱和度。这可能是为了避免上面提到的剪辑问题,但这不是必需的。但也许它也是预期视觉效果的一部分。

所以,TL;DR:效果是反转强度/亮度并将饱和度减半。


推荐阅读