Сохранение пикселей с экрана HDC - PullRequest
0 голосов
/ 03 апреля 2019

Многие форумы дают следующий код относительно того, как получить в массив копию пикселей экрана:

char* Pixels = NULL;
HDC MemDC = CreateCompatibleDC(Context);
HBITMAP Section = CreateDIBSection(Context, &Info, DIB_RGB_COLORS, (void**)&Pixels, 0, 0);
DeleteObject(SelectObject(MemDC, Section));
BitBlt(MemDC, 0, 0, Width, Height, Context, Area.left, Area.top, SRCCOPY);
DeleteDC(MemDC);
std::fstream hFile(FilePath, std::ios::out | std::ios::binary);
if (hFile.is_open())
{
    hFile.write((char*)&Header, sizeof(Header));
    hFile.write((char*)&Info.bmiHeader, sizeof(Info.bmiHeader));
    hFile.write(Pixels, (((BitsPerPixel * Width + 31) & ~31) / 8) * Height);
    hFile.close();
    DeleteObject(Section);
    return true;
}

( Ссылка )

Но это включает в себя фактическое копирование области «памяти» пикселей с экрана HDC в область памяти. Почему бы не это:

char* Pixels = NULL;
HBITMAP Section = CreateDIBSection(Context, &Info, DIB_RGB_COLORS, (void**)&Pixels, 0, 0);
SelectObject(Context, Section);

Context HDC уже содержит все данные. Почему я не могу просто прочитать это?

И я подумал, что растровое изображение должно быть должно быть выбрано в HDC, и что HDC на самом деле переносит данные. Тогда почему CreateDIBSection возвращает указатель, хотя растровое изображение еще не было выбрано ни в одном HDC? (Если он дает указатель на память HDC, переданную в качестве аргумента, тогда массив уже содержит значения пикселей экрана, но это не так, потому что BitBlt все еще требуется.)

Я пришел к такому выводу, потому что BitBlt принимает аргумент HDC, а не растровое изображение. Это, вероятно, означает, что он копирует данные в связанный HDC.

1 Ответ

0 голосов
/ 04 апреля 2019

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

Видеоданные, хранящиеся на аппаратном обеспечении, возможно, потребуется перевести в другой формат перед передачей в ваше приложение. И это оборудование может использовать другие методы для копирования данных, которые напрямую не связаны с процессором (например, прямой доступ к памяти или DMA). Поскольку копирование занимает небольшое время, требуемый раздел может быть скопирован в другой раздел видеопамяти на видеоадаптере (что может быть очень быстрым процессом) перед копированием в основную память (намного более медленный процесс).

Отображение видео также является общим ресурсом: для доступа ко всем процессам в системе может потребоваться доступ к нему. Если у вас был указатель на видеопамять, то, что вы читаете, может не совпадать с тем, что видно (если оно было обновлено до другого содержимого), или вы можете повредить экран, если написали в него.

...