Рисовать на DeviceContext от COLORREF [] - PullRequest
1 голос
/ 28 августа 2010

У меня есть указатель на буфер COLORREF, что-то вроде: COLORREF* buf = new COLORREF[x*y];

Подпрограмма заполняет этот буфер информацией о цвете.Каждый COLORREF представляет один пиксель.

Теперь я хочу нарисовать этот буфер в контексте устройства. Мой текущий подход работает, но довольно медленный (== ~ 200 мс на рисунок, в зависимости от размера изображения):

for (size_t i = 0; i < pixelpos; ++i) 
{
    // Get X and Y coordinates from 1-dimensional buffer.
    size_t y = i / wnd_size.cx;
    size_t x = i % wnd_size.cx;
    ::SetPixelV(hDC, x, y, buf[i]);
}

Есть ли способ сделать это быстрее;все сразу, не один пиксель за другим?
Я не очень знаком с GDI.Я слышал о многих API, таких как CreateDIBitmap (), BitBlt (), HBITMAP, CImage и обо всем этом, но понятия не имею, как его применить.Кажется, все довольно сложно ...
MFC также приветствуется.

Есть идеи?

Заранее спасибо.

(Справочная информация: упомянутая выше подпрограмма является ядром OpenCL - графический процессор вычисляет изображение Мандельброта и сохраняет его в буфере COLORREF.)

EDIT:
Спасибо всем за ваши предложения.Ответы (и ссылки) дали мне некоторое представление о графическом программировании Windows.Производительность теперь приемлема (работает полу-в реальном времени прокрутка Мандельброта:)
Я получил следующее решение (MFC):

...
CDC dcMemory;
dcMemory.CreateCompatibleDC(pDC);

CBitmap mandelbrotBmp;
mandelbrotBmp.CreateBitmap(clientRect.Width(), clientRect.Height(), 1, 32, buf);

CBitmap* oldBmp = dcMemory.SelectObject(&mandelbrotBmp);
pDC->BitBlt(0, 0, clientRect.Width(), clientRect.Height(), &dcMemory, 0, 0, SRCCOPY);

dcMemory.SelectObject(oldBmp);
mandelbrotBmp.DeleteObject();

Так что в основном CBitmap :: CreateBitmap () спас меняот использования сырого API (который я до сих пор не до конца понимаю).Пример из документации CDC :: CreateCompatibleDC также был полезен.
Мой Мандельброт теперь синий - с помощью SetPixelV () он был красным.Но я предполагаю, что это как-то связано с CBitmap :: CreateBitmap (), интерпретирующим мой буфер, не очень важно.

Я мог бы попробовать предложение OpenGL, потому что это был бы гораздо более логичный выбор, и я все равно хотел попробовать OpenCL под Linux.

Ответы [ 3 ]

2 голосов
/ 29 августа 2010

Поскольку у вас уже есть массив пикселей, вы можете напрямую использовать BitBlt для передачи его в DC окна. Смотрите эту ссылку для частичного примера: http://msdn.microsoft.com/en-us/library/aa928058.aspx

2 голосов
/ 29 августа 2010

В этих условиях я бы, вероятно, использовал раздел DIB (который вы создаете с помощью CreateDIBSection).Раздел DIB - это растровое изображение, которое позволяет вам обращаться к содержимому напрямую в виде массива, но при этом использовать его со всеми обычными функциями GDI.

Я думаю, что это даст вам наилучшую производительность из всего, что основано на GDI,Если вам нужно лучше, тогда @Kornel в основном верен - вам нужно переключиться на что-то, что имеет более прямую поддержку аппаратного ускорения (DirectX или OpenGL - хотя для IMO OpenGL - гораздо лучший выбордля работы, отличной от DirectX).

Учитывая, что вы в настоящее время выполняете вычисления в OpenCL и помещаете выходные данные в цветовой буфер, OpenGL был бы действительно очевидным выбором.В частности, вы можете сделать так, чтобы OpenCL поместил выходные данные в текстуру OpenGL, а затем вы должны нарисовать OpenGL с помощью этой текстуры.В качестве альтернативы, поскольку вы все равно просто выводите вывод на экран, вы можете просто выполнить вычисление в фрагментном шейдере OpenGL (или, конечно, в пиксельном шейдере DirectX), чтобы вы не помещали вывод в память вне экрана.просто так вы можете скопировать результат на экран.Если память не изменяет, в книге Оранжевого шейдера Мандельброта есть один из примеров.

2 голосов
/ 28 августа 2010

Да, конечно, это медленно. Вы совершаете обход по ядру и драйверу видеоустройства для каждого отдельного пикселя. Вы делаете это быстро, сначала рисуя в памяти, а затем обновляете экран одним махом. Это займет, скажем, CreateDIBitmap, CreateCompatibleDc () и BitBlt ().

Это не подходящее время и место для обширного учебника по графическому программированию. Это хорошо описано в любом вводном тексте по программированию GDI и / или Windows API. Все, что вам нужно знать, вы можете найти в оригинальной Windows от Petzold Programming Windows.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...