You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

像素混合(Blend Pixel):如何正确计算混合后Alpha值(无浮点方案)

问题原因

现有代码的核心错误有两处:

  • 前景有效透明度的计算逻辑错误,原逻辑Alpha2 = 前景Alpha -255 + 全局Alpha不符合alpha缩放规则,实际应该是前景自带透明度和全局调整透明度相乘后归一化到0-255范围
  • Alpha通道的混合公式错误,直接套用了RGB通道的混合系数,不符合标准的Alpha Over混合规则,导致输出的alpha值偏低,和背景叠加时整体变暗

修正后的代码

struct PIXEL
{
    unsigned char Blue;
    unsigned char Green;
    unsigned char Red;
    unsigned char Alpha;
};

// 辅助宏:整数运算四舍五入,避免除法精度损失,不需要可直接替换为普通除法
#define INT_DIV_ROUND(x, div) ((x + (div)/2) / (div))

void RenderAlphaPixel(PIXEL* pDestination, U32 Color, unsigned char Alpha)
{
    unsigned int fg_alpha_raw, fg_alpha_eff, bg_alpha, out_alpha;
    unsigned int Red, Green, Blue;

    // 提取前景各通道原始值
    fg_alpha_raw = (Color >> (8 * offsetof(PIXEL, Alpha))) & 0xFF;
    Red = (Color >> (8 * offsetof(PIXEL, Red))) & 0xFF;
    Green = (Color >> (8 * offsetof(PIXEL, Green))) & 0xFF;
    Blue = (Color >> (8 * offsetof(PIXEL, Blue))) & 0xFF;
    bg_alpha = pDestination->Alpha;

    // 计算前景实际有效透明度:前景自带alpha * 全局调整alpha,归一化到0-255
    fg_alpha_eff = INT_DIV_ROUND(fg_alpha_raw * Alpha, 255);
    // 边界判断优化性能
    if (fg_alpha_eff == 0) return;
    if (fg_alpha_eff == 255) {
        pDestination->Red = (unsigned char)Red;
        pDestination->Green = (unsigned char)Green;
        pDestination->Blue = (unsigned char)Blue;
        pDestination->Alpha = 0xFF;
        return;
    }

    // 修正:使用标准Over操作计算输出Alpha,公式为 out_a = a_fg + a_bg * (1 - a_fg)
    out_alpha = fg_alpha_eff + INT_DIV_ROUND(bg_alpha * (255 - fg_alpha_eff), 255);

    // 以下RGB计算适配非预乘Alpha格式的PIXEL结构
    unsigned int fg_rgb_factor = fg_alpha_eff * 255;
    unsigned int bg_rgb_factor = bg_alpha * (255 - fg_alpha_eff);
    pDestination->Red = (unsigned char)INT_DIV_ROUND(Red * fg_rgb_factor + pDestination->Red * bg_rgb_factor, out_alpha * 255);
    pDestination->Green = (unsigned char)INT_DIV_ROUND(Green * fg_rgb_factor + pDestination->Green * bg_rgb_factor, out_alpha * 255);
    pDestination->Blue = (unsigned char)INT_DIV_ROUND(Blue * fg_rgb_factor + pDestination->Blue * bg_rgb_factor, out_alpha * 255);
    pDestination->Alpha = (unsigned char)out_alpha;
}

格式适配说明

如果你使用的PIXEL是预乘Alpha格式(即RGB值已提前乘以对应Alpha值),只需要将RGB计算部分替换为以下代码即可:

pDestination->Red = (unsigned char)INT_DIV_ROUND(Red * fg_alpha_eff + pDestination->Red * (255 - fg_alpha_eff), 255);
pDestination->Green = (unsigned char)INT_DIV_ROUND(Green * fg_alpha_eff + pDestination->Green * (255 - fg_alpha_eff), 255);
pDestination->Blue = (unsigned char)INT_DIV_ROUND(Blue * fg_alpha_eff + pDestination->Blue * (255 - fg_alpha_eff), 255);

所有运算均为整数运算,未使用任何float/double类型,符合要求。

内容的提问来源于stack exchange,提问作者b.sullender

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.06 08:06:04