c – 开罗的阿尔法透明度

我使用GTK和Cairo显示alpha透明度时遇到问题.我尝试显示此图像1

如果我将alpha混合我的自我,一切正常.

Manual alpha blending

如果我将alpha值直接传递给Cairo,阴影似乎渲染得很好,但是发光效果已损坏.

Cairo alpha rendering

这是开罗1.14.2中的错误,还是我错过了什么?

//Need deprecated API to get background color
GdkColor color = gtk_widget_get_style(widget)->bg[GTK_STATE_NORMAL];
Pixel color_blend
    {
     uint8_t(255*color.red/65535.0f)
    ,uint8_t(255*color.green/65535.0f)
    ,uint8_t(255*color.blue/65535.0f)
    ,255
    };
while(ptr!=ptr_end)
    {
//  TODO: Interpolate
    auto row_src=size_t(row*factor);
    auto col_src=size_t(col*factor);

    auto alpha=ptr_src[row_src*width_in + col_src].v3/255.0f;
    *ptr=
        {
    //  Using manual alpha blend works  
        uint8_t(alpha*ptr_src[row_src*width_in + col_src].v2 + (1-alpha)*color_blend.v2)
        ,uint8_t(alpha*ptr_src[row_src*width_in + col_src].v1 + (1-alpha)*color_blend.v1)
        ,uint8_t(alpha*ptr_src[row_src*width_in + col_src].v0 + (1-alpha)*color_blend.v0)
        ,255
    /*  This appears to be broken 
        ptr_src[row_src*width_in + col_src].v2
        ,ptr_src[row_src*width_in + col_src].v1
        ,ptr_src[row_src*width_in + col_src].v0
        ,ptr_src[row_src*width_in + col_src].v3*/
        };

    ++col;
    if(col==width_out)
        {
        col=0;
        ++row;
        }
    ++ptr;
    }

我用像素推像素

auto surface=cairo_image_surface_create_for_data((uint8_t*)pixels.begin(),CAIRO_FORMAT_ARGB32,width_out,height_out,width_out*sizeof(Pixel));

cairo_set_source_surface(cr, surface, 0.5*(width-width_out), 0.0);
cairo_paint(cr);

cairo_surface_destroy(surface);

将操作符显式设置为CAIRO_OPERATOR_OVER没有帮助,结果仍然相同.

最佳答案
正如您在上面的评论中提到的,您的像素值是错误的.你需要使用预乘的alpha.从问题中回到我的例子(并忽略字节顺序),50%透明度的完全红色是0x7f<< 24 |开罗的0x7f.具有无效值的像素(某些颜色分量大于alpha值)会产生未定义的结果,并且您的0xff<< 24 | 0x7f属于这一类. 见http://www.cairographics.org/manual/cairo-Image-Surfaces.html#cairo-format-t

Pre-multiplied alpha is used. (That is, 50% transparent red is
0x80800000, not 0x80ff0000.)

P.S.:在我看来,访问像素数据的正确方法是通过uint32_t和移位,例如, uint32_t pixel =(r<< 24)| (g << 16)| (b << 8)|一个;.这样你根本不必担心字节序. P.P.S.:对于OVER和一个完全不透明的目标,Cairo使用的公式简化为source_color target_color *(1 – source_alpha),而您的代码使用source_color * source_alpha target_color *(1 – source_alpha).见http://www.cairographics.org/operators/.这两个公式显然不相同.

编辑:好的,也许它们在使用pre-multiplie alpha时是等效的.对不起那里的混乱.

转载注明原文:c – 开罗的阿尔法透明度 - 代码日志