[置顶] 使用easyx中的putimage函数实现无背景贴图

1,待解决的问题

如果我们要在背景图片贴上小图片玫瑰花会出现什么样的效果

背景图片
[置顶] 使用easyx中的putimage函数实现无背景贴图_第1张图片

玫瑰花

贴图之后的图片(玫瑰花图片我有意缩小,为了与背景看起来融洽些)
[置顶] 使用easyx中的putimage函数实现无背景贴图_第2张图片
直接上代码:

 #include<graphics.h>
#include <stdio.h>

int main(void)
{
    IMAGE backgroundimg;//存储背景图片
    IMAGE flower;       //存储贴图
    loadimage(&backgroundimg,_T("E:\\学习\\工程项目\\easyx\\Mipmap\\background.jpg"));//加载背景图片
    loadimage(&flower,_T("E:\\学习\\工程项目\\easyx\\Mipmap\\flower.jpg"),80,80,true);//加载背景图片,按指定大小存储
    int width = backgroundimg.getwidth();
    int height = backgroundimg.getheight();//获取长和宽
    initgraph(width,height);//根据背景图片的长和宽初始化窗口,使之铺满窗
    BeginBatchDraw();
     putimage(0,0,&backgroundimg);//在窗口上绘制背景图片
     putimage(190,200,&flower);
     FlushBatchDraw();
     EndBatchDraw();
    system("pause");
    return 0;
}

玫瑰花的黑色部分与背景图片显得很不和谐,怎么去掉黑色部分呢?

解决方法1(掩码图法)

方法步骤

    第一步:把玫瑰图片的掩码图(黑白图)1与背景图片做与运算。

第二步:把玫瑰图片(彩色)与第一步运算生成的图片做或运算(当然彩色玫瑰图片要与其掩码图重叠,
也就是说要贴在背景图片上的同一个位置)。
这样就得到了上面贴有瑰花的背景图

实现原理

颜色在内存中表示形式
    EasyX使用24Bit真色彩,用16进制的颜色表示,形式为0xbbggrr (bb=蓝,gg=绿,rr=红)
    例如,在EasyX中预定义的颜色常量BLACK用十六进制表示就是0x000000,BLUE:0xAA0000,WHITE:0xFFFFFF,但一个像素在内存中占4字节,也就是占用32位,蓝色在内存中存储形式是0x00AA0000,我们没有必要讨论最高位的一个字节,因为它在任何情况下都是0,只起占位的作用。我们讨论颜色的24位表示形式就够了。
讨论
    第一步:把玫瑰图片的掩码图(黑白图与背景图片做与运算.
    与运算想必大家都懂,0^0=0;0^1=0;1^1=1;
    一个像素在内存中是以二进制数存储的,所以当一个白色像素与任意颜色做与运算后得到的是那个任意颜色,任意颜色与黑色做与运算得到的是黑色,想想为什么。
    所以当一个掩码图与背景图做与运算后会出现什么效果,就是在背景图上画了一个黑色的内容空洞
    第二步:把玫瑰图片(彩色)与第一步运算生成的图片做或运算
    或运算:1|1=1,1|0=1,0|0=0;
        彩色玫瑰图片与背景图片做或运算时,黑色部分都变成了彩色,也就是,背景图片的彩色部分替换了玫瑰图片的黑色部分,玫瑰图片的彩色部分替换了背景图片的黑色部分,也就是说,两张图片摞在一起,只保留各自的彩色部分。于是就把玫瑰花抠出来贴到背景图片上了。

详细步骤

现在我就按照步骤一步一步来实现
我们需要三张图片,一张背景图,一张彩色玫瑰花图,还有一张玫瑰花掩码图,我们缺一张掩码图。我猜测有制作掩码图的工具,大家有兴趣可以找一下,现在我就介绍一下如何用EasyX制作掩码图。
原理很简单,先取玫瑰图片背景(在这张图片上是黑色)上任意一点,保存其色值,然后遍历整章图片,是此色值的像素点更改为白色,否则更改为黑色。先说明一点,采取此种方法只适用于需要抠出来的内容里面没有或者少量包含与背景色值相同的像素。否则抠出来的图片会出现各种漏洞。这是此种方法的局限性。
下面是制作掩码图的代码:
DWORD *pmemflower = GetImageBuffer(&flower);
    DWORD *pmemmaskbitmap = GetImageBuffer(&maskbitmap);
    COLORREF maskbk = pmemflower[0];//我确定此点肯定是玫瑰花背景色
    for (int i = 0;i<80*80;i++)
    {
        if (pmemflower[i] <=0x555555&&pmemflower[i] >=0)//0x55555555是深灰色
        {
            pmemmaskbitmap[i]= WHITE;
        }
        else
        pmemmaskbitmap[i]=BLACK;
    }
下面是掩码图


完整代码:

#include<graphics.h>
#include <stdio.h>

int main(void)
{

    IMAGE backgroundimg;//存储背景图片
    IMAGE flower;       //存储贴图
    IMAGE maskbitmap(80,80); //存储掩码
    loadimage(&backgroundimg,_T("E:\\学习\\工程项目\\easyx\\Mipmap\\background.jpg"));//加载背景图片
    loadimage(&flower,_T("E:\\学习\\工程项目\\easyx\\Mipmap\\flower.jpg"),80,80,true);//加载背景图片,按指定大小存储
    int width = backgroundimg.getwidth();
    int height = backgroundimg.getheight();//获取长和宽
    initgraph(width,height);//根据背景图片的长和宽初始化窗口,使之铺满窗
    DWORD *pmemflower = GetImageBuffer(&flower);
    DWORD *pmemmaskbitmap = GetImageBuffer(&maskbitmap);
    COLORREF maskbk = pmemflower[0];//我确定此点肯定是玫瑰花背景色
    for (int i = 0;i<80*80;i++)
    {
        if (pmemflower[i] <=0x555555&&pmemflower[i] >=0)//0x55555555是深灰色
        {
            pmemmaskbitmap[i]= WHITE;
        }
        else
        pmemmaskbitmap[i]=BLACK;
    }
    BeginBatchDraw();
    putimage(0,0,&backgroundimg);//在窗口上绘制背景图片
    //putimage(190,200,&maskbitmap);
    putimage(190,200,&maskbitmap,SRCAND);
    putimage(190,200,&flower,SRCPAINT);
     FlushBatchDraw();
     EndBatchDraw();
    system("pause");
    return 0;
}

  1. 掩码位图就是一个黑白位图,黑色部分就是要显示的部分,白色部分就是要透明的部分经过掩码运算后,即可将一个位图的背景色去掉而只保留内容部分 。 ↩

你可能感兴趣的:(背景图片,Easyx)