2014-09-23 25 views
8

Uwielbiam tworzyć "animacje" w języku C++, takie jak symulator MandelBrot Set, Game of Life itp., Ustawiając piksele bezpośrednio na ekranie klatka po klatce. Polecenie SetPixel() sprawia, że ​​jest to niezwykle proste, chociaż niestety jest ono również bardzo powolne. Oto rodzaj konfiguracji używam dla każdej klatki, jeśli chciałem malować cały ekran z zawartością tablicy R:Jak wyświetlać piksele na ekranie bezpośrednio z surowej tablicy wartości RGB szybciej niż SetPixel()?

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

Na moim komputerze to trwa prawie 5 sekund, aby wykonać za oczywiste powód, dla którego SetPixel() jest wywoływany ponad milion razy. Najlepszy scenariusz, mógłbym uruchomić to 100 razy szybciej i uzyskać płynną animację 20 klatek na sekundę.

Słyszałem, że konwersja R do pliku bitmapowego w jakiś sposób, a następnie użycie BitBlt do wyświetlania klatki w jednym czystym poleceniu jest drogą do zrobienia, ale nie mam pojęcia, jak to zaimplementować dla mojej konfiguracji i byłbym bardzo wdzięczny jakaś pomoc.

Jeśli jest to istotne, używam systemu Windows 7 i używam Code :: Blocks jako mojego IDE.

+0

Twoje przeczucie jest poprawne: interakcja pomiędzy Windows i ustawianie poszczególnych pikseli jest wąskim gardłem, a preferowanym sposobem jest stworzenie mapy bitowej w pamięci. Nie powinno być trudno znaleźć samouczek. Po jego wdrożeniu możesz być * zaskoczony * wzrostem prędkości. (Inną opcją może być zmiana na SDL, która również może być przyspieszana w ten sam sposób, ale minimalizuje część specyficzną dla systemu Windows.) – usr2564301

+0

Użyj 'CreateDIBitmap()', aby utworzyć mapę bitową z dostarczonych danych pikseli. Powstała bitmapa będzie kompatybilna z oknem HDC, które chcesz narysować, możesz więc użyć 'CreateCompatibleDC()' i 'SelectObject()' aby przygotować bitmapę do rysowania, a następnie 'BitBlt()' aby narysować mapa bitowa w oknie. –

+1

Zobacz także CreateDIBSection –

Odpowiedz

7

Poniższe porady Remy skończyło się z tego sposobu pokazując tablicę pikseli (dla facetów, którzy potrzebują trochę kodu jako przykład):

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 
+1

https://www.gamedev.net/topic/563156-what-is-a-color-plane/ –

+1

Nie zapomnij również wywołać 'DeleteObject (map)' before 'DeleteDC (src) 'na końcu. Zobacz [tutaj] (https://stackoverflow.com/questions/25829796/repeated-calls-to-createcompatiblebitmap-eventually-failure-with-getlasterror). – pmaxim98