通过直接操作显示缓冲区实现高速绘图和特殊效果(如逐渐变亮)
2011-2-27 ~ 2020-11-15
(0)
概述
EasyX 从 2011-2-24 开始,支持了直接操作显示缓冲区的功能。本文介绍一下在 EasyX 中怎样使用“显示缓冲区”。
比如画点,传统的画点函数会受坐标系、缩放、裁剪区等因素影响,导致性能较差。为了实现高速绘图,需要更直接的方法,这就是直接操作显示缓冲区的目的。
理论知识
在 EasyX 中,每个点用 4 个字节表示。对于 640 x 480 的绘图窗口,显示缓冲区的大小为 640 x 480 x 4 = 307,200 x 4 = 1,228,800 字节。
一个 DWORD 类型为四个字节,如果是 DWORD 类型的指针指向显示缓冲区,那么用数组的形式,数组的下标范围是 0~307,199。
关于颜色需要注意:平时用 COLORREF 表示颜色,但是显示缓冲区中的颜色是 RGBTRIPLE 结构体格式(该结构体的定义请参考 MSDN)。RGBTRIPLE 在内存中的表示形式为:0xrrggbb (bb=蓝,gg=绿,rr=红),而 COLORREF 在内存中的表示形式为:0xbbggrr。所以,直接操作显示缓冲区时,需要交换红色和蓝色。
以上内容为理论部分,在进行 Windows 编程的时是一样的。
使用方法
EasyX 中使用 GetImageBuffer(IMAGE* pImg) 函数获取绘图窗口或者 IMAGE 对象的显示缓冲区指针。如果 pImg 为 NULL,就获取绘图窗口的指针。
可以使用宏 BGR 交换红色和蓝色。
以下示例用一个 DWORD 指针指向显示缓冲区,并用蓝色填满显示缓冲区:
// 编译环境:Visual C++ 6.0/2010/2019,EasyX_20200902
//
#include <graphics.h>
#include <conio.h>
int main()
{
// 初始化绘图窗口
initgraph(640, 480);
// 获取绘图窗口的显示缓冲区指针
DWORD* p = GetImageBuffer();
// 对显示缓冲区中的每个点赋值
for (int i = 0; i < 640 * 480; i++)
p[i] = BGR(BLUE);
// 按任意键退出
_getch();
closegraph();
return 0;
}
下面这个例子,可以实现逐渐变亮的效果(注意,请确保 D:\test.jpg 的大小是 640x480):
// 编译环境:Visual C++ 6.0/2010/2019,EasyX_20200902
//
#include <graphics.h>
#include <conio.h>
int main()
{
// 初始化绘图窗口
initgraph(640, 480);
// 定义并加载图片
IMAGE img;
loadimage(&img, _T("R:\\test.jpg")); // 请确保该图片是 640x480 像素
// 获取绘图窗口和 img 对象的显示缓冲区指针
DWORD* pbWnd = GetImageBuffer();
DWORD* pbImg = GetImageBuffer(&img);
// 计算原图片每个点的颜色,实现逐渐变量的效果
int r, g, b;
for (int light = 1; light <= 64; light++)
{
for (int i = 0; i < 640 * 480; i++)
{
r = (GetRValue(pbImg[i]) * light) >> 6;
g = (GetGValue(pbImg[i]) * light) >> 6;
b = (GetBValue(pbImg[i]) * light) >> 6;
pbWnd[i] = RGB(r, g, b);
}
Sleep(20);
}
// 按任意键退出
_getch();
closegraph();
return 0;
}
希望此文能起到抛砖引玉的作用,相信大家可以做出更绚丽的效果。
添加评论
取消回复