网站首页 > 技术文章 正文
有时候,我们需要在画面上显示一张角色的图像,而这张图片是有自己的背景的,要是直接贴到了游戏的画面中,就会出项覆盖游戏画面。显示出的效果特别不好,这里我们可以用到透明效果来处理。
其中,原理就是用BitBlt() 的Raster值运算去掉原图片的背影。但是只适用于原图背景为黑色,才会看到效果。
如图,左边部分为前景图,右边部分为屏蔽图
以下为显示的背景图
为了得到透明效果,我们需要运用到BitBlt()贴图函数以及其参数Raster的值来将图片中不必要的部分去掉(又称去背),使得图中的主题可以与背景完美融合。
制作透明效果有很多种方法,但是基本上都是利用贴图时不同的Raster运算,通过转换而产生相同的透明效果。在这里先来介绍一种透明运算的方法。
我们以图中的恐龙为例子,首先准备一张位图,如下图。
图中的左边的图是要去背并贴到背景上的前景图。右边的黑白图称为“屏蔽图”,在透明的过程中会用到它。要把去背的位图与屏蔽图合并成同一张图,透明的时候再按照需要来进行裁切。可以把它分成两张图,但是这样程序必须运行两次图文件加载的操作。
有了屏蔽图就可以利用贴图函数来产生透明效果了,所需的贴图步骤如下:
<1>将屏蔽图与背景图做"AND"运算,Raster值为SRCAND,贴到目的地DC中。
<2>将前景图与背景图做"OR"运算,Raster值为SRCPAINT,贴到目的地DC中。
为什么经过上面两个操作就能产生透明的效果呢?看下图就理解了:
下面具体说明上面两个步骤所产生的图点色彩的变化。
1.屏蔽图与背景图做"AND"运算
<1>屏蔽图中的黑色部分与背景图做"AND"运算:
我们怎么样使用则会图来处理透明呢?其实就是Raster运算。
将屏蔽图和背景图做“AND”运算,贴到目的DC; 再将前景图和背景图做“OR”运算,贴到目的DC;
<2>屏蔽图中的白色部分与背景图做"AND"运算:
2.前景图与背景图做"OR"运算
<1>前景图中的彩色部分与图第一步得到的“黑色恐龙”图做"OR"运算:
<2>前景图中的黑色部分与第一步得到的“黑色恐龙”图做"OR"运算:
经过这一运算后所显示的画面就是所需的透明图了,如下图所示:
现在开始编写程序:
在VS2008中新建Win32程序,使用VC默认的框架。
#include "stdafx.h"
//全局变量声明
HINSTANCE hInst;
HBITMAP bg,dra; //声明两个位图对象,分别存储背景图与前景恐龙图
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中
dra = (HBITMAP)LoadImage(NULL,"dra.bmp",IMAGE_BITMAP,170,99,LR_LOADFROMFILE);
//加载恐龙图到dra中
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,dra); //选用恐龙图到"mdc"中
BitBlt(hdc,280,320,85,99,mdc,85,0,SRCAND);//进行制作贴图的第一步骤,即将屏蔽图与背景图做"AND"运算,屏蔽图在整张恐龙图中,最左上角起始位置点得坐标为(85,0),BitBlt()函数中最后一个Raster参数值设置为SRCAND。
BitBlt(hdc,280,320,85,99,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(dra);
PostQuitMessage(0);
break;
default: //其他消息
return DefWindowProc(hWnd, message, wParam, lParam);
}
return 0;
}
- 上一篇: Lazarus 打印 raz打印方法
- 下一篇: 惊!部分日志为何不打印?排查过程大揭秘
猜你喜欢
- 2024-12-28 Lazarus 打印 raz打印方法
- 2024-12-28 Android 性能优化工具篇:如何使用 DDMS 中的 TraceView 工具
- 2024-12-28 「3D效果图」法线贴图的正确使用方法和技巧
- 2024-12-28 TF Lite Model Maker: 构建安卓图片分类器
- 2024-12-28 用户界面控件Xtreme Calendar发布v17.0.0
- 2024-12-28 UG各版本安装时出现报警问题及解决方法
- 2024-12-28 记本人使用人工智能辅助编程的实践
- 2024-12-28 6.1 用Bitmap实现精确去重 bitmap字符串去重
- 2024-12-28 MFC常用函数与指令 mfcformat函数
- 2024-12-28 MFC中双缓冲技术 双缓冲技术java
- 02-21走进git时代, 你该怎么玩?_gits
- 02-21GitHub是什么?它可不仅仅是云中的Git版本控制器
- 02-21Git常用操作总结_git基本用法
- 02-21为什么互联网巨头使用Git而放弃SVN?(含核心命令与原理)
- 02-21Git 高级用法,喜欢就拿去用_git基本用法
- 02-21Git常用命令和Git团队使用规范指南
- 02-21总结几个常用的Git命令的使用方法
- 02-21Git工作原理和常用指令_git原理详解
- 最近发表
- 标签列表
-
- cmd/c (57)
- c++中::是什么意思 (57)
- sqlset (59)
- ps可以打开pdf格式吗 (58)
- phprequire_once (61)
- localstorage.removeitem (74)
- routermode (59)
- vector线程安全吗 (70)
- & (66)
- java (73)
- org.redisson (64)
- log.warn (60)
- cannotinstantiatethetype (62)
- js数组插入 (83)
- resttemplateokhttp (59)
- gormwherein (64)
- linux删除一个文件夹 (65)
- mac安装java (72)
- reader.onload (61)
- outofmemoryerror是什么意思 (64)
- flask文件上传 (63)
- eacces (67)
- 查看mysql是否启动 (70)
- java是值传递还是引用传递 (58)
- 无效的列索引 (74)