VC编程之VC++图片透明技术原理
小标 2018-08-28 来源 : 阅读 1467 评论 0

摘要:本文主要向大家介绍了VC编程之VC++图片透明技术原理,通过具体的内容向大家展示,希望对大家学习VC编程有所帮助。

本文主要向大家介绍了VC编程之VC++图片透明技术原理,通过具体的内容向大家展示,希望对大家学习VC编程有所帮助。

透明效果


由于所有的图文件都是以矩形来储存的,我们也许会需要把一张易拉罐图片贴到窗口的背景图上,而这种情况下如果直接进行贴图,结果如下图:


这似乎不是我们想要的结果。


为了得到透明效果,我们需要运用到BitBlt()贴图函数以及其参数Raster的值来将图片中不必要的部分去掉(又称去背),使得图中的主题可以与背景完美融合。


制作透明效果有很多种方法,但是基本上都是利用贴图时不同的Raster运算,通过转换而产生相同的透明效果。在这里先来介绍一种透明运算的方法。


我们以图中的易拉罐为例子,首先准备一张位图,如下图。


图中的左边的图是要去背并贴到背景上的前景图。右边的黑白图称为“屏蔽图”,在透明的过程中会用到它。要把去背的位图与屏蔽图合并成同一张图,透明的时候再按照需要来进行裁切。可以把它分成两张图,但是这样程序必须运行两次图文件加载的操作。


有了屏蔽图就可以利用贴图函数来产生透明效果了,所需的贴图步骤如下:

<1>将屏蔽图与背景图做"AND"运算,Raster值为SRCAND,贴到目的地DC中。

<2>将前景图与背景图做"OR"运算,Raster值为SRCPAINT,贴到目的地DC中。


为什么经过上面两个操作就能产生透明的效果呢?看下图就理解了:





下面具体说明上面两个步骤所产生的图点色彩的变化。


1.屏蔽图与背景图做"AND"运算

<1>屏蔽图中的黑色部分与背景图做"AND"运算:


<2>屏蔽图中的白色部分与背景图做"AND"运算:


进过这一运算所产生的结果如下图




2.前景图与背景图做"OR"运算


<1>前景图中的彩色部分与图第一步得到的“黑色易拉罐”图做"OR"运算:


<2>前景图中的黑色部分与第一步得到的“黑色易拉罐”图做"OR"运算:


经过这一运算后所显示的画面就是所需的透明图了,如下图所示:




下面我们来看看实现上述透明贴图效果的源代码


[cpp] view plaincopy

#include "stdafx.h"  

//全局变量声明  

HINSTANCE hInst;  

HBITMAP bg,sprite;        //声明两个位图对象,分别存储背景图与前景易拉罐  

HDC  mdc;       //声明一个内存DC"mdc",用来暂存位图  

//全局函数声明  

ATOM     MyRegisterClass(HINSTANCE hInstance);  

BOOL     InitInstance(HINSTANCE, int);  

LRESULT CALLBACK    WndProc(HWND, UINT, WPARAM, LPARAM);  

void     MyPaint(HDC hdc);  

////****Winmain函数,程序入口点函数**************************************  

int APIENTRY WinMain(HINSTANCE hInstance,  

                     HINSTANCE hPrevInstance,  

                     LPSTR     lpCmdLine,  

                     int       nCmdShow)  

{  

MSG msg;  

MyRegisterClass(hInstance);  

if (!InitInstance (hInstance, nCmdShow))   

{  

return FALSE;  

}  

//消息循环  

while (GetMessage(&msg, NULL, 0, 0))   

{  

TranslateMessage(&msg);  

DispatchMessage(&msg);  

}  

return msg.wParam;  

}  

//****设计一个窗口类,类似填空题,使用窗口结构体*************************  

ATOM MyRegisterClass(HINSTANCE hInstance)  

{  

WNDCLASSEX wcex;  

wcex.cbSize = sizeof(WNDCLASSEX);   

wcex.style   = CS_HREDRAW | CS_VREDRAW;  

wcex.lpfnWndProc    = (WNDPROC)WndProc;  

wcex.cbClsExtra  = 0;  

wcex.cbWndExtra  = 0;  

wcex.hInstance   = hInstance;  

wcex.hIcon   = NULL;  

wcex.hCursor     = NULL;  

wcex.hCursor     = LoadCursor(NULL, IDC_ARROW);  

wcex.hbrBackground  = (HBRUSH)(COLOR_WINDOW+1);  

wcex.lpszMenuName   = NULL;  

wcex.lpszClassName  = "canvas";  

wcex.hIconSm     = NULL;  

return RegisterClassEx(&wcex);  

}  

//****初始化函数*************************************  

// 1.建立与窗口DC兼容的内存DC  

// 2.从文件加载背景图与恐龙图  

BOOL InitInstance(HINSTANCE hInstance, int nCmdShow)  

{  

HWND hWnd;  

HDC hdc;  

hInst = hInstance;  

hWnd = CreateWindow("canvas", "绘图窗口" , WS_OVERLAPPEDWINDOW,  

CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, NULL, NULL, hInstance, NULL);  

if (!hWnd)  

{  

return FALSE;  

}  

MoveWindow(hWnd,10,10,600,450,true);  

ShowWindow(hWnd, nCmdShow);  

UpdateWindow(hWnd);  

hdc = GetDC(hWnd);                     //获得窗口DC  

mdc = CreateCompatibleDC(hdc);           //创建与窗口兼容的内存DC(mdc)  

bg = (HBITMAP)LoadImage(NULL,"bg.bmp",IMAGE_BITMAP,600,450,LR_LOADFROMFILE);   

//J加载背景图到bg中  

sprite = (HBITMAP)LoadImage(NULL,"sprite.bmp",IMAGE_BITMAP,170,99,LR_LOADFROMFILE);   

//加载易拉罐图到sprite中  

MyPaint(hdc);  

ReleaseDC(hWnd,hdc);  

return TRUE;  

}  

//****自定义绘图函数*********************************  

//透明贴图  

void MyPaint(HDC hdc)  

{  

SelectObject(mdc,bg);  

BitBlt(hdc,0,0,600,450,mdc,0,0,SRCCOPY);    //先将背景图贴到显示窗口中  

SelectObject(mdc,sprite);                      //选用易拉罐图到"mdc"中  

BitBlt(hdc,50,50,225,225,mdc,225,0,SRCAND);//进行制作贴图的第一步骤,即将屏蔽图与背景图做"AND"运算,屏蔽图在整张易拉罐图中,最左上角起始位置点得坐标为(225,0),BitBlt()函数中最后一个Raster参数值设置为SRCAND。  

BitBlt(hdc,50,50,225,225,mdc,0,0,SRCPAINT);//进行制作透明贴图的第二步骤,即将前景图与背景图做"OR"运算,前景图在整张易拉罐图中,最左上角起始位置的坐标为(0,0),BitBlt()函数最后一个参数值设置为SRCPAINT。  

}  

//****消息处理函数**********************************  

LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)  

{  

PAINTSTRUCT ps;  

HDC hdc;  

switch (message)  

{  

case WM_PAINT:   //窗口重绘消息  

hdc = BeginPaint(hWnd, &ps);  

MyPaint(hdc);  

EndPaint(hWnd, &ps);  

break;  

case WM_DESTROY:     //窗口结束消息  

DeleteDC(mdc);  

DeleteObject(bg);  

DeleteObject(sprite);  

PostQuitMessage(0);  

break;  

default:     //其他消息  

return DefWindowProc(hWnd, message, wParam, lParam);  

   }  

   return 0;  

}  





最后程序的运行结果为:


通过BitBlt()贴图函数及Raster运算值的设定,很简单地就做出了想要的透明效果,这种方法在设计2D游戏的一些画面内容时使用相当频繁。


本文由职坐标整理并发布,希望对同学们有所帮助。了解更多详情请关注职坐标编程语言VC/MFC频道!

本文由 @小标 发布于职坐标。未经许可,禁止转载。
喜欢 | 1 不喜欢 | 0
看完这篇文章有何感觉?已经有1人表态,100%的人喜欢 快给朋友分享吧~
评论(0)
后参与评论

您输入的评论内容中包含违禁敏感词

我知道了

助您圆梦职场 匹配合适岗位
验证码手机号,获得海同独家IT培训资料
选择就业方向:
人工智能物联网
大数据开发/分析
人工智能Python
Java全栈开发
WEB前端+H5

请输入正确的手机号码

请输入正确的验证码

获取验证码

您今天的短信下发次数太多了,明天再试试吧!

提交

我们会在第一时间安排职业规划师联系您!

您也可以联系我们的职业规划师咨询:

小职老师的微信号:z_zhizuobiao
小职老师的微信号:z_zhizuobiao

版权所有 职坐标-一站式AI+学习就业服务平台 沪ICP备13042190号-4
上海海同信息科技有限公司 Copyright ©2015 www.zhizuobiao.com,All Rights Reserved.
 沪公网安备 31011502005948号    

©2015 www.zhizuobiao.com All Rights Reserved