码迷,mamicode.com
首页 > 其他好文 > 详细

Alpha叠加

时间:2016-03-03 10:17:22      阅读:512      评论:0      收藏:0      [点我收藏+]

标签:

学习过程中的记录,供参考。

foruok原创,转载请保留出处。欢迎关注微信订阅号“程序视界”。

Alpha值的含义

对于 RGBA(或 BGRA )数据, Alpha 通道中存储的 Alpha 值,实际上应该是 Opaque 值,即不透明度。当 Alpha 值为 255 时,表示不透明; Alpha 值为 0 时,表示全透明。

Alpha 值也经常用 0 ~ 1 这个区间的数字来表示。 0 表示全透明, 1 表示不透明。详见这里:https://en.wikipedia.org/wiki/Alpha_compositing

直接 Alpha 和预乘 Alpha 的区别

Alpha 模式有两种,直接 Alpha 和预乘 Alpha 。

使用直接 Alpha 描述 RGBA 颜色时,颜色的 Alpha 值会存储在 Alpha 通道中。例如,若要描述具有 60% 不透明度的绿色,请使用以下值:(0 , 255 , 0 , 255 * 0.6) = (0 , 255 , 0 , 153)。值 255 指示全绿, 153(255 的 60%)指示颜色应具有 60% 的不透明度。

使用预乘 Alpha 描述 RGBA 颜色时,每种颜色都会与 Alpha 值相乘:(0 * 0.6, 255 * 0.6 , 0 * 0.6 , 255 * 0.6) = (0 , 153 , 0 , 153)。同时 Alpha 值也会存储在 Alpha 通道中。

RGBA图像数据叠加

我只考虑一幅带 Alpha 效果的图像叠加在背景上的情况。

假设背景图像是 B ,无透明效果,带透明效果的图像是 A ,那么透过 A 去看 B ,看上去的图象 C 就是 A 和 B 的混合图象。

假设 A 图像的透明度为 alpha ,则图像 C 的混合公式如下:

R(C) = alpha * R(A) + (1 - alpha) * R(B)
G(C) = alpha * G(A) + (1 - alpha) * G(B)
B(C) = alpha * B(A) + (1 - alpha) * B(B)
A(C) = 1

混合后的图像 C 的Alpha值为 1 ,所以后面的代码里,直接将结果的 Alpha 值设置为 0xFF 。

基于于 Skia 和 PPAPI 的图像叠加代码

我的一个 PPAPI+Skia 示例,使用 Skia 的 SkBitmap 作为后端来绘图,然后再把 SkBitmap 的数据叠加到 PPAPI 的图像数据上。下面是部分代码:

static void blendFromBgraToRgba(void *srcData, void *destData, struct PP_ImageDataDesc &desc)
{
    unsigned char *src = (unsigned char*)srcData;
    unsigned char *dst = (unsigned char*)destData;
    int len = desc.size.height * desc.stride;
    for (int i = 0; i < len; i += 4, src += 4, dst += 4)
    {
        switch(src[3])
        {
        case 0:
            //do nothing
            break;
        case 255:
            dst[0] = src[2]; //Red
            dst[1] = src[1]; //Green
            dst[2] = src[0]; //Blue
            break;
        default:
            dst[0] = (((int)dst[0]) * (255 - src[3])) / 255 + src[2]; //Red
            dst[1] = (((int)dst[1]) * (255 - src[3])) / 255 + src[1]; //Green
            dst[2] = (((int)dst[2]) * (255 - src[3])) / 255 + src[0]; //Blue
            break;
        }
        dst[3] = 0xFF;
    }
}

void XXX::init()
{
    ...
    PPB_ImageData * d;
    d->Describe(m_image, &m_image_desc);
    m_pixels = d->Map(m_image);
    ...
    SkImageInfo ii = SkImageInfo::Make(m_image_desc.size.width, 
            m_image_desc.size.height,
            kBGRA_8888_SkColorType,
            kPremul_SkAlphaType,
            kLinear_SkColorProfileType);
    m_bitmap = new SkBitmap();
    m_bitmap->allocPixels(ii, m_image_desc.stride);
    ...
}

void XXX::paint()
{
    ....
    void *skiaPixels = m_bitmap->getPixels();
    blendFromBgraToRgba(skiaPixels, m_pixels, m_image_desc);
    ...
}

代码有很多可以优化的地方。

参考链接


就这样吧。

其他参考文章详见我的专栏:【CEF与PPAPI开发】。

Alpha叠加

标签:

原文地址:http://blog.csdn.net/foruok/article/details/50785841

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!