【问题标题】:Convert RGBA color to RGB将 RGBA 颜色转换为 RGB
【发布时间】:2011-01-04 04:31:21
【问题描述】:

如何将一个 RGBA 颜色元组,例如 (96, 96, 96, 202) 转换为对应的 RGB 颜色元组?

编辑:

我想要的是在白色背景上获得一个与 RGBA 元组视觉上最相似的 RGB 值。

【问题讨论】:

  • 不就是(96,96,96)吗?
  • 这取决于背景像素的颜色。
  • 您只想删除 Alpha 通道吗?还是您想要将 RGBA 叠加在(例如)白色背景上的 RGB 结果?
  • 您可能想阅读著名论文“合成数字图像”(Porter 和 Duff 撰写)以了解有关 alpha 合成的完整详细信息:keithp.com/~keithp/porterduff
  • Andras Zoltan 和 hkurabko 的答案对于计算相反也很有用,我的意思是,如果您有各种 alpha 混合颜色并具有其原始背景(遮罩),那么您可以计算原始 RGBA 颜色,即我一直在寻找的东西;)

标签: image colors rgb


【解决方案1】:

我赞成 Johannes 的回答,因为他是对的。

* 有人提出我的原始答案不正确。如果 alpha 值与正常值相反,它会起作用。但是,根据定义,这在大多数情况下都行不通。因此,我更新了下面的公式,使其适用于正常情况。这最终等于@hkurabko 在下面的答案 *

然而,更具体的答案是将 alpha 值合并到基于不透明背景颜色(或称为“哑光”)的实际颜色结果中。

对此有一个算法(来自this维基百科链接):

  • 标准化 RGBA 值,使它们都在 0 和 1 之间 - 只需将每个值除以 255 即可。我们将调用结果Source
  • 也将哑光颜色(黑色、白色等)标准化。我们将调用结果BGColor 注意 - 如果背景颜色也是透明的,那么您必须首先递归该过程(再次选择遮罩)以获得源 RGB用于此操作。
  • 现在,转换被定义为(这里是完整的伪代码!):

    Source => Target = (BGColor + Source) =
    Target.R = ((1 - Source.A) * BGColor.R) + (Source.A * Source.R)
    Target.G = ((1 - Source.A) * BGColor.G) + (Source.A * Source.G)
    Target.B = ((1 - Source.A) * BGColor.B) + (Source.A * Source.B)
    

要获得Target 的最终 0-255 值,您只需将所有归一化值乘以 255,如果任何组合值超过 1.0,请确保上限为 255(这是过度曝光并且有处理这个问题的更复杂的算法,涉及整个图像处理等)。

编辑:在您的问题中,您说您想要白色背景 - 在这种情况下,只需将 BGColor 修复为 255,255,255。

【讨论】:

  • 根据问题编辑,这是一个非常准确和好的答案。我删除了我的,希望你冒泡,因为你解释得更好:)
  • 我认为这个答案假定背景颜色是 rgb,而不是 rgba。
  • 考虑到 RGBA(0,0,0,1) 是完全不透明的黑色,这很不寻常。但是使用给定的算法,它将是完全透明的黑色。我认为重新安排算法以反映这一点将使其成为更有用的资源并更好地回答问题。
  • @BryanRayner 为我的回答添加了一些编辑。我定期获得对这个答案的支持,有些人可能会发现它,不得不自己反转算法。要是能完整点就更好了谢谢。
  • 如果有人仍然感兴趣,这个 JSBin 允许观察正在转换的颜色。它也可以用作 javacript 函数。我将 BGColor 用作白色,因为我只是不了解遮罩的概念(对不起!)。链接如下:jsbin.com/qocixeh/edit?html,js,console,output 以及要点:gist.github.com/vladimirbrasil/bd139851ff757a1c8cb46fac93e733eb 希望它也有帮助。非常感谢您的回答!
【解决方案2】:

嗯...关于

http://en.wikipedia.org/wiki/Alpha_compositing#Alpha_blending

Andras Zoltan 提供的解决方案应稍微更改为:

Source => Target = (BGColor + Source) =
Target.R = ((1 - Source.A) * BGColor.R) + (Source.A * Source.R)
Target.G = ((1 - Source.A) * BGColor.G) + (Source.A * Source.G)
Target.B = ((1 - Source.A) * BGColor.B) + (Source.A * Source.B)

这个更改后的版本对我来说很好用,因为在 prev.带有哑光 rgb(ff,ff,ff) 的版本 rgba(0,0,0,0) 将更改为 rgb(0,0,0)。

【讨论】:

  • 我相信你是对的。维基百科和 Andras Zoltan 的回答有点不同。
  • 我同意,使用这个版本,而不是@Andras Zoltan 的。对于测试场景,使用两个公式在背景 rgb(255,255,255) 上转换 rgba(0,0,0,.7); hkurabko 的论坛显然给出了正确的答案。
  • Andras 将 0 alpha 定义为不透明,将 255 定义为透明,而 CSS 以相反的方式定义它。这个答案适用于 CSS 对 alpha 的定义。
  • +1 这适用于最常见的 alpha 定义(0 = 透明),例如 OpenGL、SDL、图形编辑器。
  • +1 - 我已经更新了我的答案,以使用 alpha 作为“正确的方式”,同样如此。具有讽刺意味的是,刚刚尝试使用我的解决方案来执行此操作,我同意我最初的答案,虽然它有其自身的意义,但并没有真正适用于大多数应用程序。
【解决方案3】:

在我的例子中,我想将一个 RGBA 图像转换为 RGB,并且下面的工作正如预期的那样:

rgbImage = cv2.cvtColor(npimage, cv2.COLOR_RGBA2RGB)

【讨论】:

    【解决方案4】:

    这取决于您使用的色彩空间。如果 RGBA 在预乘颜色空间中并且是半透明的,则需要除掉 alpha 以获得正确的 RGB 颜色。如果颜色在非预乘颜色空间中,则可以丢弃 Alpha 通道。

    【讨论】:

      【解决方案5】:

      这是一些 java 代码(适用于 Android API 24):

              //int rgb_background = Color.parseColor("#ffffff"); //white background
              //int rgba_color = Color.parseColor("#8a000000"); //textViewColor 
      
              int defaultTextViewColor = textView.getTextColors().getDefaultColor();
      
              int argb = defaultTextViewColor;
              int alpha = 0xFF & (argb >> 24);
              int red = 0xFF & (argb >> 16);
              int green = 0xFF & (argb >> 8);
              int blue = 0xFF & (argb >> 0);
              float alphaFloat = (float)alpha / 255;
      
              String colorStr = rgbaToRGB(255, 255, 255, red, green, blue, alphaFloat);
      

      功能:

      protected String rgbaToRGB(int rgb_background_red, int rgb_background_green, int rgb_background_blue,
                              int rgba_color_red, int rgba_color_green, int rgba_color_blue, float alpha) {
      
          float red = (1 - alpha) * rgb_background_red + alpha * rgba_color_red;
          float green = (1 - alpha) * rgb_background_green + alpha * rgba_color_green;
          float blue = (1 - alpha) * rgb_background_blue + alpha * rgba_color_blue;
      
          String redStr = Integer.toHexString((int) red);
          String greenStr = Integer.toHexString((int) green);
          String blueStr = Integer.toHexString((int) blue);
      
          String colorHex = "#" + redStr + greenStr + blueStr;
      
          //return Color.parseColor(colorHex);
          return colorHex;
      }
      

      【讨论】:

        【解决方案6】:

        根据 Andras 和 hkurabko 的回答,这是一个方便的 SASS 函数。

        @function rgba_blend($fore, $back) {
          $ored: ((1 - alpha($fore)) * red($back) ) + (alpha($fore) * red($fore));
          $ogreen: ((1 - alpha($fore)) * green($back) ) + (alpha($fore) * green($fore));
          $oblue: ((1 - alpha($fore)) * blue($back) ) + (alpha($fore) * blue($fore));
          @return rgb($ored, $ogreen, $oblue);
        }
        

        用法:

        $my_color: rgba(red, 0.5); // build a color with alpha for below
        
        #a_div {
          background-color: rgba_blend($my_color, white);
        }
        

        【讨论】:

        • 在 sass 中,我们可以使用:mix($color, white, $alpha*100)
        【解决方案7】:

        根据hkurabko的回答的Python函数。

        def rgba2rgb(rgba: tuple[int, int, int, float], background: tuple[int, int, int] = (255, 255, 255)):
            return (
                round(((1 - rgba[3]) * background[0]) + (rgba[3] * rgba[0])),
                round(((1 - rgba[3]) * background[1]) + (rgba[3] * rgba[1])),
                round(((1 - rgba[3]) * background[2]) + (rgba[3] * rgba[2])),
            )
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2011-09-23
          • 2012-03-05
          • 1970-01-01
          • 2011-10-04
          • 2012-04-11
          • 1970-01-01
          • 2019-02-08
          相关资源
          最近更新 更多