Сохранение пикселей с экрана HDC
Многие форумы дают следующий код относительно того, как получить в массив копию пикселей экрана:
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 ответ
Видеопамять может храниться в нескольких местах, включая основную системную память (RAM), выделенную память на видеокарте, на внешнем устройстве отображения или даже некоторую их комбинацию. Доступ к этой памяти может быть медленным, и память может быть недоступна для процесса (по крайней мере, его необходимо отобразить в адресное пространство процесса).
Видеоданные, хранящиеся на аппаратном обеспечении, возможно, потребуется перевести в другой формат перед передачей в ваше приложение. И это оборудование может использовать другие методы для копирования данных, которые напрямую не связаны с процессором (например, прямой доступ к памяти или DMA). Поскольку копирование занимает небольшое время, требуемый раздел может быть скопирован в другой раздел видеопамяти на видеоадаптере (что может быть очень быстрым процессом) перед копированием в основную память (намного более медленный процесс).
Видеодисплей также является общим ресурсом: все процессы в системе могут нуждаться в доступе к нему. Если у вас был указатель на видеопамять, то, что вы читаете, может не совпадать с тем, что видно (если оно было обновлено до другого содержимого), или вы можете испортить экран, если будете писать в него.