慢羊羊的空间

无为,无我,无欲,居下,清虚,自然

通过直接操作显示缓冲区实现高速绘图和特殊效果(如逐渐变亮) 铜牌收录

概述

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;
}

希望此文能起到抛砖引玉的作用,相信大家可以做出更绚丽的效果。

添加评论