快速画点的原理简述,以及写一个自己的快速画点函数
2011-3-4 ~ 2021-5-31
(2)
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);
}
// 主函数
int main()
{
// 初始化绘图窗口
initgraph(WIDTH, HEIGHT);
// 获取绘图窗口的显示缓冲区指针并保存为全局变量
g_pBuf = GetImageBuffer();
// 随机画 100 个点
for(int i = 0; i< 100; i++)
fast_putpixel(rand() % WIDTH, rand() % HEIGHT, RED);
// 扫描每一个点,如果是红色,就以该点为圆心画一个圆:
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();
return 0;
}
COLORREF c =0;
if(x<WIDTH )c= g_pBuf[y * WIDTH + x];
即可解决。