如何比 SetPixel() 更快地从原始 RGB 值数组直接在屏幕上显示像素?
我喜欢用 C++ 制作动画",例如 MandelBrot Set 缩放器、生命游戏模拟器等,方法是将像素直接逐帧设置到屏幕上.SetPixel() 命令使这变得非常简单,尽管不幸的是它也非常缓慢.如果我想用数组 R 的内容绘制整个屏幕,这是我为每一帧使用的那种设置:
I enjoy making "animations" in c++ such as a MandelBrot Set zoomer, Game of Life simulator etc. by setting pixels directly to the screen frame-by-frame. The SetPixel() command makes this incredibly easy, although unfortunately it's also painfully slow. Here is the sort of set-up I use for each frame, if I wanted to paint the entire screen with the contents of the array R:
#include <windows.h>
using namespace std;
int main()
{
int xres = 1366;
int yres = 768;
char *R = new char [xres*yres*3];
/*
R is a char array containing the RGB value of each pixel sequentially
Arithmetic operations done to each element of R here
*/
HWND window; HDC dc; window = GetActiveWindow(); dc = GetDC(window);
for (int j=0 ; j<yres ; j++)
for (int i=0 ; i<xres ; i++)
SetPixel(dc,i,j,RGB(R[j*xres+3*i],R[j*xres+3*i+1],R[j*xres+3*i+2]));
delete [] R;
return 0;
}
在我的机器上,由于 SetPixel() 被调用超过一百万次的明显原因,这需要将近 5 秒的时间来执行.最好的情况是我可以让它运行速度提高 100 倍并获得流畅的 20fps 动画.
On my machine this takes almost 5 seconds to execute for the obvious reason that SetPixel() is being called over a million times. Best case scenario I could get this to run 100x faster and get a smooth 20fps animation.
我听说以某种方式将 R 转换为位图文件,然后使用 BitBlt 在一个干净的命令中显示帧是要走的路,但我不知道如何为我的设置实现这一点,非常感谢任何帮助.
I hear that converting R into a bitmap file in some way and then using BitBlt to display the frame in one clean command is the way to go, but I have no idea how to implement this for my setup and would greatly appreciate any help.
如果相关,我在 Windows 7 上运行并使用 Code::Blocks 作为我的 IDE.
If it is relevant, I am running on Windows 7 and using Code::Blocks as my IDE.
推荐答案
按照 Remy 的建议,我最终采用了这种显示像素数组的方式(对于需要一些代码的人来说):
Following Remy's advices I ended up with this way of showing pixel array (for guys, who needs some code as an example):
COLORREF *arr = (COLORREF*) calloc(512*512, sizeof(COLORREF));
/* Filling array here */
/* ... */
// Creating temp bitmap
HBITMAP map = CreateBitmap(512 // width. 512 in my case
512, // height
1, // Color Planes, unfortanutelly don't know what is it actually. Let it be 1
8*4, // Size of memory for one pixel in bits (in win32 4 bytes = 4*8 bits)
(void*) arr); // pointer to array
// Temp HDC to copy picture
HDC src = CreateCompatibleDC(hdc); // hdc - Device context for window, I've got earlier with GetDC(hWnd) or GetDC(NULL);
SelectObject(src, map); // Inserting picture into our temp HDC
// Copy image from temp HDC to window
BitBlt(hdc, // Destination
10, // x and
10, // y - upper-left corner of place, where we'd like to copy
512, // width of the region
512, // height
src, // source
0, // x and
0, // y of upper left corner of part of the source, from where we'd like to copy
SRCCOPY); // Defined DWORD to juct copy pixels. Watch more on msdn;
DeleteDC(src); // Deleting temp HDC
相关文章