C 语言标准库中并没有一个叫做 drawpixel 的原生函数。

(图片来源网络,侵删)
drawpixel 是一个在图形编程领域非常常见的概念性名称或自定义函数名,它的意思是“绘制一个像素点”(Draw a Pixel),不同的图形库(如 Windows GDI, SDL, Allegro, OpenGL 等)都有自己的方法来实现这个功能。
要使用 drawpixel,你必须:
- 选择一个图形库。
- 了解该库提供的、用于绘制像素点的具体函数。
- 你可以自己封装一个名为
drawpixel的函数来方便使用。
下面我将介绍几种主流 C/C++ 图形库中如何实现像素绘制,并给出封装成 drawpixel 函数的示例。
在 Windows GDI (图形设备接口) 中
这是 Windows 平台原生但较老的图形方式,它不直接操作像素缓冲区,而是通过设备上下文来绘制。

(图片来源网络,侵删)
核心概念:
- 设备上下文: 你可以把它理解为一块画布。
SetPixel函数: GDI 提供的、最直接的设置像素点颜色的函数。
示例代码:
#include <windows.h> // 包含 Windows 头文件
// 自定义的 drawpixel 函数,封装了 GDI 的 SetPixel
void drawpixel(HDC hdc, int x, int y, COLORREF color) {
SetPixel(hdc, x, y, color);
}
// 一个简单的窗口程序来演示
LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) {
switch (uMsg) {
case WM_PAINT: {
PAINTSTRUCT ps;
HDC hdc = BeginPaint(hwnd, &ps);
// 调用我们的 drawpixel 函数在 (50, 50) 位置画一个红点
drawpixel(hdc, 50, 50, RGB(255, 0, 0)); // RGB(红, 绿, 蓝)
// 再画一个绿点
drawpixel(hdc, 100, 100, RGB(0, 255, 0));
EndPaint(hwnd, &ps);
}
return 0;
case WM_DESTROY:
PostQuitMessage(0);
return 0;
}
return DefWindowProc(hwnd, uMsg, wParam, lParam);
}
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) {
const char* CLASS_NAME = "My Window Class";
WNDCLASS wc = { };
wc.lpfnWndProc = WindowProc;
wc.hInstance = hInstance;
wc.lpszClassName = CLASS_NAME;
RegisterClass(&wc);
HWND hwnd = CreateWindowEx(
0, CLASS_NAME, "GDI DrawPixel Example",
WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, CW_USEDEFAULT, 500, 400,
NULL, NULL, hInstance, NULL
);
if (hwnd == NULL) {
return 0;
}
ShowWindow(hwnd, nCmdShow);
MSG msg = { };
while (GetMessage(&msg, NULL, 0, 0)) {
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return 0;
}
说明:
HDC hdc是设备上下文句柄,是进行所有绘图操作的前提。SetPixel函数虽然简单,但效率不高,因为它需要频繁地与图形驱动交互,在需要高性能绘制的场景(如游戏、动画)中,不推荐逐个像素地调用它。
在 SDL (Simple DirectMedia Layer) 中
SDL 是一个跨平台的多媒体库,非常适合游戏开发和图形应用,它提供直接访问像素缓冲区的能力,效率很高。

(图片来源网络,侵删)
核心概念:
SDL_Surface: 一个像素数据块,可以看作是一张内存中的图片。- *`Uint32
**: 指向SDL_Surface` 像素数据的指针,我们可以直接操作它来修改像素颜色。 SDL_PixelFormat: 描述像素格式(如 RGBA 每个通道占多少位)。
示例代码:
#include <SDL2/SDL.h>
#include <stdio.h>
// 自定义的 drawpixel 函数,直接操作像素缓冲区
void drawpixel(SDL_Surface* surface, int x, int y, Uint32 color) {
// 检查坐标是否在表面范围内
if (x < 0 || y < 0 || x >= surface->w || y >= surface->h) {
return;
}
// 计算目标像素在像素数组中的位置
Uint32* pixels = (Uint32*)surface->pixels;
int pitch = surface->pitch / sizeof(Uint32); // 每行的像素数
pixels[(y * pitch) + x] = color;
}
int main(int argc, char* argv[]) {
if (SDL_Init(SDL_INIT_VIDEO) < 0) {
printf("SDL could not initialize! SDL_Error: %s\n", SDL_GetError());
return 1;
}
SDL_Window* window = SDL_CreateWindow("SDL DrawPixel Example",
SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED,
640, 480,
SDL_WINDOW_SHOWN);
if (window == NULL) {
printf("Window could not be created! SDL_Error: %s\n", SDL_GetError());
return 1;
}
SDL_Surface* screenSurface = SDL_GetWindowSurface(window);
// 将整个屏幕填充为白色
SDL_FillRect(screenSurface, NULL, SDL_MapRGB(screenSurface->format, 0xFF, 0xFF, 0xFF));
// 定义几个颜色
Uint32 red = SDL_MapRGB(screenSurface->format, 0xFF, 0x00, 0x00);
Uint32 green = SDL_MapRGB(screenSurface->format, 0x00, 0xFF, 0x00);
Uint32 blue = SDL_MapRGB(screenSurface->format, 0x00, 0x00, 0xFF);
// 调用我们的 drawpixel 函数
drawpixel(screenSurface, 100, 100, red);
drawpixel(screenSurface, 150, 150, green);
drawpixel(screenSurface, 200, 200, blue);
// 更新窗口表面,将修改后的像素显示到屏幕上
SDL_UpdateWindowSurface(window);
// 等待3秒
SDL_Delay(3000);
SDL_DestroyWindow(window);
SDL_Quit();
return 0;
}
说明:
SDL_MapRGB: 将 RGB 颜色值转换成SDL_Surface所需的Uint32格式的颜色值。pixels[(y * pitch) + x] = color;是核心操作,它通过指针直接内存写入来修改像素,速度极快,这是现代图形编程的基础。SDL_UpdateWindowSurface: 将内存中的surface数据同步到屏幕上。
在 Allegro 5 中
Allegro 是一个专门为游戏设计的跨平台库,API 设计得非常直观。
核心概念:
ALLEGRO_BITMAP: Allegro 中的位图对象,等同于 SDL 的SDL_Surface。al_put_pixel: Allegro 提供的、直接向位图写入像素的函数。
示例代码:
#include <allegro5/allegro.h>
#include <allegro5/allegro_primitives.h> // 需要这个头文件
#include <stdio.h>
int main(int argc, char* argv[]) {
if (!al_init()) {
fprintf(stderr, "Failed to initialize allegro!\n");
return -1;
}
if (!al_init_primitives_addon()) {
fprintf(stderr, "Failed to initialize primitives addon!\n");
return -1;
}
ALLEGRO_DISPLAY* display = al_create_display(640, 480);
if (!display) {
fprintf(stderr, "Failed to create display!\n");
return -1;
}
// 获取屏幕位图
ALLEGRO_BITMAP* screen = al_get_backbuffer(display);
// 使用 al_put_pixel 函数(这本身就是 drawpixel)
al_put_pixel(screen, 100, 100, al_map_rgb(255, 0, 0)); // 红色
al_put_pixel(screen, 150, 150, al_map_rgb(0, 255, 0)); // 绿色
al_put_pixel(screen, 200, 200, al_map_rgb(0, 0, 255)); // 蓝色
al_flip_display(); // 翻转缓冲区,显示内容
al_rest(3.0); // 暂停3秒
al_destroy_display(display);
return 0;
}
说明:
al_put_pixel函数非常直接,Allegro 版本的drawpixel。al_map_rgb: 将 RGB 值转换成 Allegro 的颜色格式。al_flip_display: 切换前后缓冲区,实现无闪烁的图形显示。
总结与对比
| 特性 | Windows GDI | SDL | Allegro 5 |
|---|---|---|---|
| 函数名 | SetPixel |
pixels[y * pitch + x] = color |
al_put_pixel |
| 直接操作内存 | 否,效率较低 | 是,效率最高 | 是,效率高 |
| 跨平台 | 仅 Windows | 是 | 是 |
| 适用场景 | 简单的 Windows 桌面应用 | 游戏、高性能图形、多媒体应用 | 游戏、多媒体应用 |
| 学习曲线 | 较简单 | 中等 | 较简单 |
如何选择?
- 如果你只是想在 Windows 上快速画点东西,不关心性能:可以使用 GDI 的
SetPixel并封装成drawpixel。 - 如果你想学习现代图形编程,或者开发游戏、高性能应用:强烈推荐 SDL,它让你直接操作像素缓冲区,这是理解图形渲染原理的关键一步。
- 如果你想专注于游戏开发,喜欢更“游戏化”的 API:Allegro 5 是一个很好的选择。
希望这个详细的解释能帮助你理解 drawpixel 在 C 语言中的实际应用!
