图层混合算法(二)

混合后图像变亮

变亮模式(lighten)

        变亮模式跟变暗模式是相对的,它是通过混合色与基色的相关数值进行比较,选择较大的数值作为结果色。因此结果色会更亮,同时颜色也会变化。(位置互换不发生变化)

void layerblend_lightness(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];
        }
    }
}

滤色模式(screen)

        滤色模式与正片叠底模式相对。它的计算公式是:255 - 混合色的补色 * 基色补色 / 255。得到的数据会比混合及基色更大,因此结果色会更亮。从计算公式也可以看出基色或混合色任何一项为255也就是白色,结果色数值就是255为白色。任何一项数值为0,也就是为黑色的话,结果色就跟数值不为0的一致。

void layerblend_screen(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] = 255 - (255.0f - d1[cw + c]) * (255.0f - d2[cw + c]) / 255;
        }
    }
}

颜色减淡(color light)

        颜色减淡是通过混合色及基色的各通道颜色值进行对比,减少二者的对比度使基色的变亮来反映混合色。它的计算公式:结果色 = 基色 + (混合色 * 基色) / (255 - 混合色)。混合色为黑色,结果色就等于基色,混合色为白色结果色就为白色。基色为黑色结果色就为黑色.

void layerblend_color_light(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 ++){
                 int res = 0;
                 if (d2[cw + c] == 0)
                     res = 255;
                 else
                     res = d1[cw + c] + (1.0f * d1[cw + c] * d2[cw + c]) / (255.0f - d2[cw + c]);

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

颜色线性减淡(color linear light)

        颜色线性减淡是通过查看每个通道的颜色信息,并通过增加亮度使基色变亮以反映混合色。它的计算公式:结果色 = 基色 + 混合色,其中基色与混合色的数值大于255,系统就默认为最大值也就是255。由公式可以分析出混合色为黑色结果色就等于基色,混合色为白色结果色就为白色。基色也一样。我们颠倒混合色及基色的位置,结果色也不会变化。(位置互换不发生变化)

void layerblend_color_linear_light(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] = saturate_cast<uchar>(d1[cw + c] + d2[cw + c]);
            }
        }
    }
}

浅色模式

        浅色模式比较好理解:它是通过计算混合色与基色所有通道的数值总和,哪个数值大就选为结果色。因此结果色只能在混合色与基色中选择,不会产生第三种颜色。与深色模式刚好相反。

叠加模式(overlay)

        叠加模式比较特别,它是通过分析基色个通道的数值,对颜色进行正片叠加或滤色混合,结果色保留基色的明暗对比,因此结果色以基色为主导。
计算公式:
基色 < = 128:结果色 = 混合色 * 基色 / 128;基色 > 128:结果色 = 255 - (255 - 混合色)* (255 - 基色) / 128。

void layerblend_overlay(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 ++){
                 int res = 0;
                 res = ((d1[cw + c]  <= 128) ? (1.0f * d2[cw + c] * d1[cw + c]  / 128):(255 - (255.0f - d2[cw + c]) * (255.0f - d1[cw + c]) / 128));
                 d3[cw + c] = saturate_cast<uchar>(res);
            }
        }
    }
}

柔光模式(soft light)

        柔光模式是较为常用的模式,它是根据混合色的通道数值选择不同的公式计算混合色。数值大于128的时候,结果色就比基色稍亮;数值小于或等于128,结果色就比基色稍暗。柔光模式是以基色为主导,混合色只相应改变局部明暗。其中混合色为黑色,结果色不会为黑色,只比结果色稍暗,混合色为中性色,结果色跟基色一样。
计算公式:
混合色 <=128:结果色 = 基色 + (2 * 混合色 - 255) * (基色 - 基色 * 基色 / 255) / 255;
混合色 >128: 结果色 = 基色 + (2 * 混合色 - 255) * (Sqrt(基色/255)*255 - 基色)/255。

如果基色=混合色,则可优化为256的表smoothlight,公式变形如下:

res = x + (2x-255)*(x-x*x/255)/255;

res = x+(2x-255)*(255*sqrt(x/255)-x)/255;

void layerblend_soft_light(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 ++){
                int res = 0,temp1,temp2;
                temp1 = ((int)((float)d1[cw + c]+((float)d2[cw + c]+(float)d2[cw + c]-255.0f)*((sqrt((float)d1[cw + c]/255.0f))*255.0f-(float)d1[cw + c])/255.0f));
                temp2 = ((int)((float)d1[cw + c]+((float)d2[cw + c]+(float)d2[cw + c]-255.0f)*((float)d1[cw + c]-(float)d1[cw + c]*(float)d1[cw + c]/255.0f)/255.0f));
                res = d2[cw + c] > 128 ? temp1 : temp2;
                d3[cw + c] = saturate_cast<uchar>(res);
            }
        }
    }
}

强光模式(strong light)

        强光模式跟叠加模式十分类似,只是在计算的时候需要通过混合色来控制,混合色的数值小于或等于128的时候,颜色会变暗;混合色的数值大于128的时候,颜色会变亮。混合色为白色,结果色就为白色;混合色为黑色,结果为黑色。混合色起到主导作用。
计算公式:
混合色 <= 128:结果色 = 混合色 * 基色 / 128;
混合色 > 128 :结果色 = 255 - (255 - 混合色) * (255 - 基色) / 128.

void layerblend_strong_light(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 ++){
                int res = 0;

                res = d2[cw + c] <= 128.0f ? ((float)d2[cw + c] * d1[cw + c] / 128.0f):(255.0f - (255.0f - d2[cw + c]) * (255.0f - d1[cw + c]) / 128.0f);

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

亮光模式(hight light)

        亮光模式是通过增加或减少对比度是颜色变暗或变亮,具体取决于混合色的数值。混合色比中性灰色暗,结果色就相应的变暗,混合色比中性灰色亮,结果色就相应的变亮。有点类似颜色加深或颜色减淡。
计算公式:

A---基色;B—混合色

C=A-(255-A)*(255-2B)/2B 当混合色>128时 

C=A+[A*(2B-255)]/[255-(2B-255)

void layerblend_hight_light(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 ++){
                int res = 0;

                if (d2[cw + c] <= 128)
                    res = d2[cw + c] == 0 ? d1[cw + c] : (d1[cw + c] - (255.0f - d1[cw + c])*(255.0f -2.0f * d2[cw + c]) / (2.0f * d2[cw + c]));
                else
                    res = d2[cw + c] == 255 ? d1[cw + c] : d1[cw + c]+ (d1[cw + c]*(2.0f * d2[cw + c]-255.0f))/(255.0f - (2.0f * d2[cw + c] - 255.0f));

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

线性光(linear light)

        线性光:通过减少或增加亮度,来使颜色加深或减淡。具体取决于混合色的数值。混合色数值比中性灰色暗的时候进行相应的加深混合;混合色的数值比中性灰色亮的时候进行减淡混合。这里的加深及减淡时线性加深或线性减淡。
计算公式:结果色 = 2 * 混合色 + 基色 -255。数值大于255取255。

void layerblend_linear_light(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 ++){
                int res = 2 * d2[cw + c] + d1[cw + c] - 255;
                d3[cw + c] = saturate_cast<uchar>(res);
            }
        }
    }
}

点光(point light)

        点光模式:它会根据混合色的颜色数值替换相应的颜色。如果混合色数值小于中性灰色,那么就替换比混合色亮的像素;相反混合色的数值大于中性灰色,则替换比混合色暗的像素,因此混合出来的颜色对比较大。
计算公式:
基色 < 2 * 混合色 - 255:结果色 = 2 * 混合色 - 255;
2 * 混合色 - 255 < 基色 < 2 * 混合色 :结果色 = 基色;
基色 > 2 * 混合色:结果色 = 2 * 混合色。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

视图猿人

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值