图层混合算法(一)

常见混合结果展示

 图层混合后变暗

正常模式(normal)

混合色*不透明度+(100%-混合色不透明度)

void layerblend_normal(Mat &base,Mat &blend,Mat &dst,float opacity)
{
    if (base.rows != blend.rows ||
        base.cols != blend.cols ||
        base.type() != blend.type())
        return;

    dst = Mat::zeros(base.rows,base.cols,base.type());

    for (int h = 0;h < base.rows;h ++)
    {
        uchar *d1 = base.ptr<uchar>(h);
        uchar *d2 = blend.ptr<uchar>(h);
        uchar *d3 = dst.ptr<uchar>(h);
        for (int w = 0;w < base.cols;w ++)
        {
            int cw = w * base.channels();
            for (int c = 0;c < base.channels();c ++)
                d3[cw + c] = opacity * d1[cw + c] + (1.0f - opacity) * d2[cw + c];
        }
    }
}

溶解模式(dissolve)

        溶解模式下混合色的不透明度及填充都是100%的话,我们就看不到基色图层。降低混合色图层的不透明度后,我们就会发现结果色中出现了很多细小的颗粒。这些颗粒会随着混合色的不透明度变化。不透明度越低混合色图层就被溶解的越多。剩下的部分就越少。不透明度越高混合色图层被溶解的部分就越少,剩下的部分就越多,结果色就越接近混合色。

变暗模式(darkness)

        变暗混合模式下,它会把混合色与基色进行对比,分别选择R,G,B三组数值中最小的数值,也就是最暗的颜色作为结果色的数值。这样整个画面会变得更暗,如果是彩色图像,颜色也会发生很大的改变。(位置互换不发生变化)

void layerblend_darkness(Mat &base,Mat &blend,Mat &dst)
{
    if (base.rows != blend.rows ||
        base.cols != blend.cols ||
        base.type() != blend.type())
        return;

    dst = Mat::zeros(base.rows,base.cols,base.type());

    for (int h = 0;h < base.rows;h ++)
    {
        uchar *d1 = base.ptr<uchar>(h);
        uchar *d2 = blend.ptr<uchar>(h);
        uchar *d3 = dst.ptr<uchar>(h);
        for (int w = 0;w < base.cols;w ++)
        {
            int cw = w * base.channels();
            for (int c = 0;c < base.channels();c ++)
                d3[cw + c] = d1[cw + c] < d2[cw + c] ? d1[cw + c] : d2[cw + c];
        }
    }
}

正片叠底(multiply)

        正片叠底混合原理:它是按照混合色与基色中的各R,G,B值计算,计算公式:结果色R=混合色R * 基色R / 255,G值与B值同样的方法计算。最后得到的R,G,B值就是结果色的颜色。由于各通道的最大值是255,因此结果色的数值比混合色及基色的数值都要小,也就是结果色要暗。(位置互换不发生变化)

void layerblend_multiply(Mat &base,Mat &blend,Mat &dst)
{
    if (base.rows != blend.rows ||
        base.cols != blend.cols ||
        base.type() != blend.type())
        return;

    dst = Mat::zeros(base.rows,base.cols,base.type());

    for (int h = 0;h < base.rows;h ++)
    {
        uchar *d1 = base.ptr<uchar>(h);
        uchar *d2 = blend.ptr<uchar>(h);
        uchar *d3 = dst.ptr<uchar>(h);
        for (int w = 0;w < base.cols;w ++)
        {
            int cw = w * base.channels();
            for (int c = 0;c < base.channels();c ++)
                d3[cw + c] = 1.0f * d1[cw + c] * d2[cw + c] / 255;
        }
    }
}

颜色加深(color dark)

        颜色加深可以快速增加图片的暗部。它的计算公式:结果色 = (基色 + 混合色 - 255)* 255 / 混合色。其中(基色 + 混合色 - 255)如果出现负数就直接归0。因此在基色与混合色都较暗的时候都是直接变成黑色的。这样结果色的暗部就会增加。整体效果看上去对比较为强烈.

void layerblend_color_dark(Mat &base,Mat &blend,Mat &dst)
{
    if (base.rows != blend.rows ||
        base.cols != blend.cols ||
        base.type() != blend.type())
        return;

    dst = Mat::zeros(base.rows,base.cols,base.type());

    for (int h = 0;h < base.rows;h ++)
    {
        uchar *d1 = base.ptr<uchar>(h);
        uchar *d2 = blend.ptr<uchar>(h);
        uchar *d3 = dst.ptr<uchar>(h);
        for (int w = 0;w < base.cols;w ++)
        {
            int cw = w * base.channels();
            for (int c = 0;c < base.channels();c ++){
                d3[cw + c] = 1.0f * d1[cw + c] * d2[cw + c] / 255;

                 int temp = d1[cw + c] + d2[cw + c] - 255;

                 temp = temp < 0 ? 0 : temp;

                 int res = 0;
                 if (d2[cw + c] == 0)
                     res = d1[cw + c];
                 else
                     res = temp * 255.0f / d2[cw + c];

                 d3[cw + c] = saturate_cast<uchar>(res);
            }
        }
    }
}

 深色模式(dark)

        深色混合模式比较好理解。它是通过计算混合色与基色的所有通道的数值,然后选择数值较小的作为结果色。因此结果色只跟混合色或基色相同,不会产生出另外的颜色。白色与基色混合色得到基色,黑色与基色混合得到黑色。深色模式中,混合色与基色的数值是固定的,我们颠倒位置后,混合色出来的结果色是没有变化的,此模式与变暗模式类同。

猜你喜欢

转载自blog.csdn.net/hulinhulin/article/details/133252870