Screen capture
Народ, как правильно захватить экран? Я его собираюсь отсылать по сети, поэтому мне необходимо получить биты изображения. Любое обращение к DC экрана вызывает торможение курсора. Пытался эмулировать нажатие ПринтСкрин, но даже обращение к битмапу экрана из буфера обмена все равно тормозит! Что делать?
Использовать Библиотеку DirectX Начиная с н-ых виндов она включена по умолчанию...
Народ, как правильно захватить экран? Я его собираюсь отсылать по сети, поэтому мне необходимо получить биты изображения. Любое обращение к DC экрана вызывает торможение курсора. Пытался эмулировать нажатие ПринтСкрин, но даже обращение к битмапу экрана из буфера обмена все равно тормозит! Что делать?
Ну в принципе, ты на правильном пути, только надо сначала снять (capture) информацию с экрана в память, а потом её уже обрабатывать.
Порядок действий:
1) получаешь DC GetDC(hwnd). Для рабочего стола hwnd=0;
2) создаешь соотв. битмап в памяти CreateCompatibleBitmap;
3) копируешь BitBlt;
4) освобождаешь DC ReleaseDC.
А-хаю... А потом GetBitmapBits тормозит так, что мама не горюй. Даже если все это загнать в CImage, все равно тормозит.
Ну не используй раз тормозит. В общем все надо свести к операциям с ОП, а не каждый раз вызывать GetBitmapBits. Адрес битов у битмапа с течением времени не меняется. По поводу DirectX - не уверен, что это вызовет прирост производительности. Тут же ничего не рендерится. А BitBlt он везде BitBlt.
В общем все надо свести к операциям с ОП,
Pavor, не объяснишь, в кач-ве братской помощи народам севера, что такое "ОП"?
Pavor, не объяснишь, в кач-ве братской помощи народам севера, что такое "ОП"?
Иде учишься? У нас один тоже сдавал микроэлектронику и не мог преподу сказать как расшифровывается ПЗУ, а мы проектировали RISC микропроцессор с микропрограммым ПЗУ.
ОП = Оперативная память
То есть по возможности свести операцию к копированию памяти и затем ее пересылке, возможно с каким-либо сжатием на лету если есть ресурсы у компа, но нет у сети.
Иде учишься? У нас один тоже сдавал микроэлектронику и не мог преподу сказать как расшифровывается ПЗУ...
Ниче, зато у нас олежки водятся, однако...
надо свести к операциям с ОП, а не каждый раз вызывать GetBitmapBits
Но вот опять не пойму, с чем же, тогда по-вашему,
GetBitmapBits "оперирует"?
А то у нас вот каждая собака, по наивности, наверное, думает, что с той же самой "ОП"...
И как добраться, до этой самой "ОП", в смысле
данных о цвете, не используя GetBitmapBits,
или GetDiBits, или CreateDIBitmap (c к-рой
BitBlt тормозит так же, как GetBitmapBits)??
bmBits у BITMAP, если её получить из
GetObject - 0...
Ниче, зато у нас олежки водятся, однако...
надо свести к операциям с ОП, а не каждый раз вызывать GetBitmapBits
Но вот опять не пойму, с чем же, тогда по-вашему,
GetBitmapBits "оперирует"?
А то у нас вот каждая собака, по наивности, наверное, думает, что с той же самой "ОП"...
И как добраться, до этой самой "ОП", в смысле
данных о цвете, не используя GetBitmapBits,
или GetDiBits, или CreateDIBitmap (c к-рой
BitBlt тормозит так же, как GetBitmapBits)??
bmBits у BITMAP, если её получить из
GetObject - 0...
Постарайся узнать, на каком именно этапе тормозит, подумаем как оптимизировать. Используй какой-нибудь Perfomance Analyser.
Ну не используй раз тормозит. В общем все надо свести к операциям с ОП, а не каждый раз вызывать GetBitmapBits
Все-таки :
какой способ доступа к данным о цвете ты имел ввиду, когда это писал?
про этап: "bitblock transfer" вызывает задержку,
что вобщем-то не мудрено, ~3-5 Mb все-таки
но в этом snippet'е:
int w=GetDeviceCaps(hdcCompatible, HORZRES);
int h=GetDeviceCaps(hdcCompatible, VERTRES);
HBITMAP hbmScreen = CreateCompatibleBitmap(hdcCompatible,w,h);
HBITMAP hbmOld=(HBITMAP)SelectObject(hdcCompatible,hbmScreen);
HDC hdcScreen = GetDC(0);
BitBlt(hdcCompatible, 0,0,w,h,
hdcScreen,0,0,SRCCOPY);
ReleaseDC(0,hdcScreen);
BitBlt работает значительно быстрее, чем если бы
было, например
memset(&binfo,0,sizeof(BITMAPINFO));
binfo.bmiHeader.biSize=sizeof(BITMAPINFOHEADER);
binfo.bmiHeader.biHeight=h;
binfo.bmiHeader.biWidth=w;
binfo.bmiHeader.biBitCount=24; //не надо про DeviceCaps
binfo.bmiHeader.biPlanes=1;
binfo.bmiHeader.biCompression=BI_RGB;
binfo.bmiHeader.biSizeImage=((((w * 24) + 31) & ~31) >> 3) * h;
void* pdt;
HBITMAP hbmScreen=CreateDIBSection(hdcCompatible,&binfo,DIB_RGB_COLORS,&pdt,0,0);
//далее SelectObject,BitBlt и т.д...
то же с другими перечисленными мной функциями,
поэтому еще раз спрашиваю, что ты имел ввиду...
пока мне кажется, что для оптимизации прийдется или лезьть в режим ядра, или шаманить
с DeviceIOControl (что может быть и не поможет)...
хотя странно, что Enygma, не хочет мириться имнно с этой задержкой, ведь сжатие и пересылка, вероятно, займут больше времени...
то же с другими перечисленными мной функциями,
поэтому еще раз спрашиваю, что ты имел ввиду...
пока мне кажется, что для оптимизации прийдется или лезьть в режим ядра, или шаманить
с DeviceIOControl (что может быть и не поможет)...
хотя странно, что Enygma, не хочет мириться имнно с этой задержкой, ведь сжатие и пересылка, вероятно, займут больше времени...
Не лезь в ядрень, потом будет программа плохо совместима.
Ты протестил прогу, где тормозит.
По поводу трафика - надо посмотреть быстрые алгоритмы сжатия на лету. Надо сжимать и слать в параллельных потоках.
int w=GetDeviceCaps(hdcCompatible, HORZRES);
int h=GetDeviceCaps(hdcCompatible, VERTRES);
Надеюсь ты hdc создаешь не каждый раз? GetDeviceCaps тоже достаточно один раз.
Конечно GetDIBits будет медленнее, там какое-то преобразование. BitBlt будет работать быстрее всего, что можно придумать.
HBITMAP hbmScreen = CreateCompatibleBitmap(hdcCompatible,w,h);
Так вообще-то не должно работать, так как в HDC при создании CreateCompatibleDC селектается монохромная битмапа 1x1, и твоя Compatible будет тоже monochrome.
hOldBitmap один раз запомни и вспомни только при выходе из проги. Т.е. SelectBitmap лучше один раз.
Посмотри sample на MMX инструкции в VS по-моему mmxswarm называется. Там по-моему получается hdc толко один раз, а потом не мучается API.
Именно так и называется:
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/vcsample/html/vcsamMMXSwarmSampleDemonstratesCImageVisualCsMMXSupport.asp
спасибо, это уже ближе к теме :)
И не работает, что интересно:).
Конечно CreateCompatibleBitmap(hdcScreen,w,h);
HBITMAP hbmOld=(HBITMAP)SelectObject(hdcCompatible,hbmScreen);
HDC hdcScreen = GetDC(0);
BitBlt(hdcCompatible, 0,0,w,h,
hdcScreen,0,0,SRCCOPY);
ReleaseDC(0,hdcScreen);
Здесь BitBlt работает с той же скоростью,
что и GetDIBits.
Это к Enygm'е
пример пока не смотрел
http://www.codeproject.com/dialog/screencap.asp
здесь экран захватывается 3-мя способами:
GDI, DirectX и Windows Media API...
ваще сайтик симпатичный
Сайт по DirectX:
есть tutorials с нуля по 7 и 8 (Mr. Snow's columns), ваще куча всего по-русски и человеческим языком