快速画点的原理简述,以及写一个自己的快速画点函数
作者:EasyX

EasyX 自带的 putpixel 函数源自 Windows GDI 函数 SetPixel,由于要考虑裁剪区、缩放、原点坐标、坐标方向等等诸多因素,所以性能很低,在一些只要求速度的场合很不实用。这篇文章就教你写一个自己的画点函数。

总的思想,是通过直接显存操作来避免系统做不需要的运算。

在 EasyX 绘图窗口的显存中,每个点占用 4 个字节,用 DWORD 指针指向显存就可以像一维数组一样访问了。然后就是将二维坐标 (x, y) 映射到一维数组中,很简单,y * 640 + x 就是。另外需要注意的是,显存中颜色的保存和 COLORREF 相比,蓝色和红色是相反的,需要用 BGR 宏转换一下(BGR 宏执行两次就会还原为原值)。

然后,我们整理出画点和读点的函数:
(记得要获取显存指针并保存为全局变量)

DWORD* g_pBuf;

// 在 main 函数中
g_pBuf = GetImageBuffer();

void fast_putpixel(int x, int y, COLORREF c)
{
	g_pBuf[y * 640 + x] = BGR(c);
}

COLORREF fast_getpixel(int x, int y)
{
	COLORREF c = g_pBuf[y * 640 + x];
	return BGR(c);
}

作为完善,大家还可以自己加上判断数组是否越界、屏幕分辨率自适应等多种功能,这里不再详述。

 

最后看一个完整的范例,该范例在屏幕上随机画 100 个红点,然后用 fast_getpixel 扫描屏幕上每一个点,如果是红色,就以该点为圆心画一个圆:

#include <graphics.h>
#include <conio.h>

#define	WIDTH	640
#define	HEIGHT	480

// 显存指针
DWORD* g_pBuf;

// 快速画点函数
void fast_putpixel(int x, int y, COLORREF c)
{
	g_pBuf[y * WIDTH + x] = BGR(c);
}

// 快速读点函数
COLORREF fast_getpixel(int x, int y)
{
	COLORREF c = g_pBuf[y * WIDTH + x];
	return BGR(c);
}

// 主函数
void main()
{
	// 初始化绘图窗口
	initgraph(WIDTH, HEIGHT);

	// 获取绘图窗口的显存指针并保存为全局变量
	g_pBuf = GetImageBuffer();

	// 随机画 100 个点
	for(int i = 0; i< 100; i++)
		fast_putpixel(rand() % WIDTH, rand() % HEIGHT, RED);

	// 使针对绘图窗口的显存操作生效
	FlushBatchDraw();

	// 扫描每一个点,如果是红色,就以该点为圆心画一个圆:
	for(int x = 0; x < WIDTH; x++)
		for(int y = 0; y < HEIGHT; y++)
			if (fast_getpixel(x, y) == RED)
				circle(x, y, 10);

	// 按任意键退出
	getch();
	closegraph();
}
更新时间:2011/3/4