将 RGBA 颜色转换为 RGB

问题描述 投票:0回答:10

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

编辑:

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

image colors rgb
10个回答
104
投票

我对约翰内斯的回答投了赞成票,因为他是对的。

* 有人提出了一些评论,认为我原来的答案不正确。如果 alpha 值与正常值相反,它就会起作用。然而,根据定义,这在大多数情况下不起作用。因此,我更新了下面的公式,使其适合正常情况。这最终等于@hkurabko 下面的答案*

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

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

  • 标准化 RGBA 值,使它们都在 0 和 1 之间 - 只需将每个值除以 255 即可。我们将结果称为
    Source
  • 也将哑光颜色标准化(黑色、白色等)。我们将结果称为
    BGColor
    Note - 如果背景颜色也是透明的,那么您必须首先递归该过程(再次选择遮罩)以获得此操作的源 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。


46
投票

嗯...关于

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)

这个更改后的版本对我来说效果很好,因为在以前的版本中。带有遮罩 rgb(ff,ff,ff) 的 rgba(0,0,0,0) 版本将更改为 rgb(0,0,0)。


12
投票

就我而言,我想将 RGBA 图像转换为 RGB,并且以下内容按预期工作:

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

7
投票

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


3
投票

这里是一些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;
}

2
投票

Python函数按照hkurabko的答案。

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])),
    )

1
投票

这是根据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);
}

0
投票

Typescript 功能符合 hkurabko 的答案。

type RgbType = { red: number; green: number; blue: number; };
type RgbaType = { alpha: number; } & RgbType;

export const blendAlphaToBackground = (
  rgba: RgbaType,
  background: RgbaType = {red: 255, green: 255, blue: 255, alpha: 1},
): RgbaType => {
  const red = Math.round((1 - rgba.alpha) * background.red + rgba.alpha * rgba.red);
  const green = Math.round((1 - rgba.alpha) * background.green + rgba.alpha * rgba.green);
  const blue = Math.round((1 - rgba.alpha) * background.blue + rgba.alpha * rgba.blue);

  return {red, green, blue, alpha: 1};
};

0
投票

就我而言,我想让 RGB 图像看起来就像是白色背景上的 RGBA 图像。由于典型的转换方法只是删除 A 通道,这可能会导致 RGB 通道中的像素变得可见,而之前通过 alpha 通道使其透明的像素变得可见。

以下对我有用:

import numpy as np

def convert_RGBA_to_RGB(input_image): 
    # Takes an RGBA image as input
    
    # Based on the following chat with user Andras Deak
    ## https://chat.stackoverflow.com/transcript/message/55060299#55060299
   
    input_image_normed = input_image / 255  # shape (nx, ny, 4), dtype float
    alpha = input_image_normed[..., -1:]  # shape (nx, ny, 1) for broadcasting
    input_image_normed_rgb = input_image_normed[..., :-1]  # shape (nx, ny, 3)
    #bg_normed = np.zeros_like(red_normed_rgb)  # shape (nx, ny, 3) <-- black background
    bg_normed = np.ones_like(input_image_normed_rgb)  # shape (nx, ny, 3) <-- white background
    composite_normed = (1 - alpha) * bg_normed + alpha * input_image_normed_rgb
    composite = (composite_normed * 255).round().astype(np.uint8)
    return composite

0
投票

向所有辛勤工作的人们致以应有的敬意,但为什么不让画布为你做这些辛苦的工作呢? :)

function ReplaceAlpha(){

var Cx=C.getContext('2d');

Cx.imageSmoothingEnabled=true; 

Cx.imageSmoothingQuality='high';

var I=new Image();

I.crossOrigin='anonymous';

I.src=C.toDataURL('image/jpeg',1);

I.onload=function(){

 Cx.drawImage(this,0,0,C.width,C.height);

};

}

这里有很棒的测试图像...

https://www.pngmart.com/image/136052

© www.soinside.com 2019 - 2024. All rights reserved.