一、基本思路

1.半透明的原理

一张位图由许多像素组成,而每一像素包含R、G、B三原色,三原色的值决定了像素的色彩,要实现半透明效果,需要把前景图    和背景图彼此对应的像素颜色按某一比例进行调配,称为 ‘不透明度’,直接贴图,则前景图不透明度为100%,背景图为0%;

公式:半透明图色彩=前景图色彩 * 不透明度 + 背景图色彩 * (1-不透明度)

2.半透明操作步骤

(1)取得位图结构,需要使用GetObject函数,介绍如下:

函数原型:int GetObject(HGDIOBJ hgdiobj, int cbBuffer, LPVOID lpvObject);

函数功能:表示获取位图的信息

参数一   : 要获取的位图句柄

参数二   : 指定将要写到缓冲区的信息的字节数目,在这里是位图类型的字节数

参数三   : 在这里是指向位图结构变量的地址,该变量当作缓冲区

关于位图结构BITMAP介绍如下:

(2)建立暂存数组,目的是为了存储位图中所有像素的颜色值

unsigned char * px1 = new unsigned char [bm1.bmHeight * bm1.bmWidthBytes];

其中数组的大小即为整个位图所有像素占的字节数,若一个像素24bits,则占3个字节,也就是3个数组元素

(3)取得位图中所有的颜色值,并存储到暂存数组中,函数介绍如下:

函数原型:LONG GetBitmapBits(HBITMAP hbmp, LONG cbBuffer, LPVOID lpvBits);

函数功能:把位图的色彩值存储到暂存数组中

参数一   :位图句柄

参数二   :要取得的字节数

参数三   :指向暂存数组

(4)合成像素颜色值,这里介绍基本思想:

假设每个像素24bit,则每个像素占3字节,关于背景图,首先要取得整张图像素各原色值所在的索引值,即:

 for(y=ystart;y<yend;y++)  {for(x=xstart;x<xend;x++) //对背景图贴图部分做颜色处理{rgb_b = y * bm1.bmWidthBytes + x * PxBytes ;//像素各原色值存储的元素索引值px1[rgb_b] = px1[rgb_b] * 0.7;               //PxBytes为每个像素所占的字节数px1[rgb_b+1] = px1[rgb_b+1] * 0.7;           //bmWidthBytes为每一列像素占的字节数px1[rgb_b+2] = px1[rgb_b+2] * 0.7;  }}

举个简单的例子,假设从(xstart,ystary)~(xend,yend) 为 (0,0)~(1,1),则有如下情况:

[0][1][2]   [3][4][5]

[6][7][8]   [9][10][11]

注释:每个像素占3个字节;每一列像素占6字节,书里都把行称为列,也不知道为啥

同理:处理前景图时,直接进行颜色合成:前景图30%的不透明度+背景图70%的不透明度,存放到px2

for(y=0;y<(bm2.bmHeight); y++)     {for(x=0;x<bm2.bmWidth; x++) {rgb_b = y * bm2.bmWidthBytes + x * PxBytes ;i = (ystart+y) * bm1.bmWidthBytes + (xstart+x) * PxBytes;px2[rgb_b]   = px2[rgb_b]  *0.3 + px1[i];  //半透明色彩合成px2[rgb_b+1] = px2[rgb_b+1] *0.3 + px1[i+1];  px2[rgb_b+2] = px2[rgb_b+2] *0.3 + px1[i+2];}}

(5)重设位图颜色,根据暂存数组中的内容重设位图颜色

函数原型:LONG SetBitmapBits(HBITMAP hmbp, DWORD cBytes, CONST VOID (lpBits));

函数功能:重设位图颜色

参数一    :要设置的位图句柄

参数二    :暂存数组的字节数

参数三    :指向暂存数组

二、结合前面所学的实现透明半透明效果,代码如下:


#include "stdafx.h"
#include <stdio.h>HINSTANCE hInst;
HBITMAP bg,girl;
HDC     mdc;const int xstart = 222;
const int ystart = 50;ATOM             MyRegisterClass(HINSTANCE hInstance);
BOOL                InitInstance(HINSTANCE, int);
LRESULT CALLBACK    WndProc(HWND, UINT, WPARAM, LPARAM);
void                MyPaint(HDC hdc);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);
}BOOL InitInstance(HINSTANCE hInstance, int nCmdShow)
{HWND hWnd;HDC hdc,bufdc;HBITMAP bmp;BITMAP bm1,bm2;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,445,true);ShowWindow(hWnd, nCmdShow);UpdateWindow(hWnd);bg = (HBITMAP)LoadImage(NULL,"bg.bmp",IMAGE_BITMAP,600,400,LR_LOADFROMFILE); //背景图句柄bmp = (HBITMAP)LoadImage(NULL,"girlmask.bmp",IMAGE_BITMAP,766,345,LR_LOADFROMFILE);//前景图句柄GetObject(bg,sizeof(BITMAP),&bm1);     //get the message of image to bm1if(bm1.bmBitsPixel != 32 && bm1.bmBitsPixel != 24) //bit of pixe     l{MessageBox(NULL,"此程序只能在32 bit 或 24 bit 显示模式中运行","警告",0);return FALSE;}hdc = GetDC(hWnd);mdc = CreateCompatibleDC(hdc);//建立与窗口DC兼容的内存DC "mdc"bufdc = CreateCompatibleDC(hdc);//建立与窗口DC兼容的内存DC "bufdc",选择前景图或背景图,贴到mdc作透明处理girl = CreateCompatibleBitmap(hdc,383,345);//建立一个与窗口相兼容的空位图"girl",298*329像素,处理后就是要贴到窗口的透明半透明图案SelectObject(mdc,girl);//girl 存到 mdc,在mdc上进行透明处理SelectObject(bufdc,bg);//bg replace bufdc,背景图bg存入bufdcBitBlt(mdc,0,0,383,345,bufdc,xstart,ystart,SRCCOPY);//将透明区域的背景图贴到mdc中SelectObject(bufdc,bmp);//将包含屏蔽图的前景图存入bufdcBitBlt(mdc,0,0,383,345,bufdc,383,0,SRCAND);//屏蔽图在整张图中,左上角坐标(298,0),屏蔽图与背景图and运算BitBlt(mdc,0,0,383,345,bufdc,0,0,SRCPAINT);//前景图与背景图or运算,得到透明后的前景图,接下来进行半透明处理unsigned char *px1,*px2;px1 = new unsigned char [bm1.bmHeight * bm1.bmWidthBytes];GetBitmapBits(bg,bm1.bmHeight * bm1.bmWidthBytes,px1);//px1储存位图颜色值GetObject(girl,sizeof(BITMAP),&bm2);//bme得到girl的全部信息px2 = new unsigned char [bm2.bmHeight * bm2.bmWidthBytes];GetBitmapBits(girl,bm2.bmHeight * bm2.bmWidthBytes,px2);//px2储存位图bm2的颜色值int x,y,xend,yend;int i;int rgb_b;int PxBytes = bm1.bmBitsPixel / 8 ;xend = xstart + 383;yend = ystart + 345;for(y=ystart;y<yend;y++)     {for(x=xstart;x<xend;x++) {rgb_b = y * bm1.bmWidthBytes + x * PxBytes ;px1[rgb_b] = px1[rgb_b] * 0.7;      px1[rgb_b+1] = px1[rgb_b+1] * 0.7;       px1[rgb_b+2] = px1[rgb_b+2] * 0.7;       }}for(y=0;y<(bm2.bmHeight); y++)  {for(x=0;x<bm2.bmWidth; x++) {rgb_b = y * bm2.bmWidthBytes + x * PxBytes ;i = (ystart+y) * bm1.bmWidthBytes + (xstart+x) * PxBytes;px2[rgb_b]    = px2[rgb_b] *0.3 + px1[i];  px2[rgb_b+1] = px2[rgb_b+1] *0.3 + px1[i+1];   px2[rgb_b+2] = px2[rgb_b+2] *0.3 + px1[i+2];   }}SetBitmapBits(girl,bm2.bmHeight*bm2.bmWidthBytes,px2);MyPaint(hdc);ReleaseDC(hWnd,hdc);DeleteDC(bufdc);DeleteObject(bmp);delete [] px1;delete [] px2;return TRUE;
}void MyPaint(HDC hdc)
{SelectObject(mdc,bg);//bg replace mdc,bg存入到mdc中BitBlt(hdc,0,0,600,400,mdc,0,0,SRCCOPY);//将mdc贴到hdcSelectObject(mdc,girl);BitBlt(hdc,xstart,ystart,383,345,mdc,0,0,SRCCOPY);
}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(girl);PostQuitMessage(0);break;default:                     return DefWindowProc(hWnd, message, wParam, lParam);}return 0;
}

四、效果

Visual C++游戏编程基础之透明半透明效果相关推荐

  1. Visual C++游戏编程基础之多背景循环动画

    一.基本思路 1.现在有三张背景图:天空和草地.山峦.房屋: 2.天空在最远处,其次是草地和山峦(因为山峦在草地上),最后是房屋: 3.背景的循环速度是天空最慢.然后是山峦.最后是草地和房屋: 4.恐 ...

  2. Visual C++游戏编程基础之景物贴图

    一.基本思路 1.首实现斜角贴图,需要显示菱形图块,使用矩形图块贴图,但是要将它的周围进行透明处理,只显示菱形部分 2.计算图块索引值的公式: 列编号 = 索引值 / 每一列的图块个数: 行编号 =  ...

  3. Visual C++游戏编程基础之键盘消息

    一.键盘 1.虚拟键码:Windows系统下所有的按键被视为虚拟键(包含鼠标在内),每一个虚拟键都有其对应的虚拟键码: 2.键盘消息 (1)VM_KEWDOWN:按下按键消息: (2)VM_KEYUP ...

  4. Visual C++游戏编程基础之摩擦力、加速度、重力

    一.基本思路 1.假设小球在空中只受到重力作用,一开始给它一个水平的速度,就像是平抛运动一样: 2.当小球碰到地面时,受到摩擦力作用,分为x方向和y方向: 3.在摩擦力作用下,1.减少水平方向的速度, ...

  5. Visual C++游戏编程基础之利用鼠标消息实现贴图

    一.鼠标键入消息 1.WM_LBUTTONDBLCLK       双击鼠标左键: 2.WM_LBUTTONDOWN         单击鼠标左键: 3.WM_LBUTTONUP            ...

  6. Visual C++游戏编程基础之追逐移动

    一.基本思路 1.追逐移动的实现与飞机追随鼠标光标原理类似: 2.现在小鸟作为追逐者,设定其贴图坐标为(nowX-25,nowY-16),其中(nowX,nowY)是飞机的贴图坐标: 3.通过判断小鸟 ...

  7. VC++游戏编程基础无法找到“d3d9.h”问题

    经反复查阅是缺少Direct X SDK导致的,我用的是VC++6.0,支持Direct X SDK 9.0b及之前的版本,最新版DX SDK(JUNE)VC6驾驭不了...下面是我解决问题的思路(只 ...

  8. 游戏编程基础(五)背景地图滚动显示

    在游戏过程中,背景地图需要跟着人物的移动而动态的滚动变换.C++游戏编程基础中介绍了2D游戏中常用的3种动态背景表现手法.其原理和实现技巧分析如下: 方法一:单一背景滚动         原理是:利用 ...

  9. 小学生python游戏编程arcade----动画图片实现爆炸效果

    小学生python游戏编程arcade----动画图片实现爆炸效果 前言 动画图片实现爆炸效果 1.爆炸类的的实现 1.1爆炸图片 1.2 类的定义 1.3 爆炸类的引用 1.4 爆炸类的更新 1.5 ...

最新文章

  1. JForum 的 SSO集成
  2. Python图像处理:图像腐蚀与图像膨胀
  3. 全国成人计算机考试题,成人计算机考试试题.docx
  4. 名片去噪识别-aip
  5. Python : 什么是*args和**kwargs[转载]
  6. 物料单位转换的两个函数
  7. #pragma 详解
  8. 各种锁的介绍、锁之间的区别
  9. python内存分配失败_关于python:如何避免[Errno 12]无法分配使用子进程模块导致的内存错误...
  10. react中创建组件
  11. javaMail发送邮件设置发件人中文昵称
  12. 用java怎么做微信公众号,用Java搭建微信公众号(一)构建基础请求框架
  13. ​在Windows 10 下安装 Vmware 时遇到的问题和解决​方法
  14. 详解17000tps的以太坊snark侧链方案
  15. 提问 未来计算机的发展趋势是什么,计算机今后的发展趋势是什么?
  16. 电脑如何剪辑视频?自学视频剪辑的朋友看过来
  17. “海底数据中心”被打捞出水,故障率仅为陆地1/8;京东超大规模联邦学习平台开源...
  18. 腾讯提供的TBS调试小程序页面
  19. 如何设置Windows XP自动登录
  20. 佳顺通用进销存系统去广告_母婴收银系统应该如何选择?

热门文章

  1. Android studio 导出安卓APP软件方法
  2. Unity 打包IOS平台错误
  3. h5 php 拍照上传图片,H5拍照、选择图片上传组件核心
  4. Android读取M1卡数据
  5. 【USACO题库】3.2.4 Feed Ratios饲料调配
  6. 怎么从扫描的PDF文档/图片里提取文字
  7. 2019年6款最佳的wordpress主机推荐(优缺点分析)
  8. python永久配置pip下载镜像源方法(window版本)
  9. dPCA 二面角主成分分析
  10. android开发流程