скрин с 3д приложения

Тема в разделе "WASM.SOFTWARE", создана пользователем spa, 9 май 2010.

  1. spa

    spa Active Member

    Публикаций:
    0
    Регистрация:
    9 мар 2005
    Сообщения:
    2.240
    Мне для оптимизации некоторой рутины, надо программу которая может делать скриншоты, даже если работают 3д приложения. Еще из требований работа из консоли. Может подскажет кто?
     
  2. Com[e]r

    Com[e]r Com[e]r

    Публикаций:
    0
    Регистрация:
    20 апр 2007
    Сообщения:
    2.624
    Адрес:
    ого..
    так а какая разница же? обычный метод работает во всех случаях,
    а если речь об оверлейном выводе (как в AVP 2o1o), то тут уж делу ничем не помочь, ящитаю.
     
  3. spa

    spa Active Member

    Публикаций:
    0
    Регистрация:
    9 мар 2005
    Сообщения:
    2.240
    Comer_
    что же за обычный метод? я перепробовал кучу, и если запущенно 3д приложение кторое работает на весь экран, но скрин получается, как будто нету вовсе этого приложения
     
  4. slavanap

    slavanap Вячеслав

    Публикаций:
    0
    Регистрация:
    10 сен 2008
    Сообщения:
    300
    Адрес:
    Смоленск, Россия
    Насколько мне известно, приложения, использующие OpenGL спокойно фоткаются через PrtSc. Вот только как его заставить работать через OpenGL - более сложный вопрос.
     
  5. Booster

    Booster New Member

    Публикаций:
    0
    Регистрация:
    26 ноя 2004
    Сообщения:
    4.860
    spa
    Юзай плату видеозахвата.
     
  6. Com[e]r

    Com[e]r Com[e]r

    Публикаций:
    0
    Регистрация:
    20 апр 2007
    Сообщения:
    2.624
    Адрес:
    ого..
    spa
    Код (Text):
    1. SLV, 24.06.2009 3:20:52:
    2. /*
    3.  
    4.     получить снимок экрана
    5.  
    6. */
    7.  
    8. BOOL PrintScreen(char *file)
    9. {
    10.     HDC hdc, memdc, hdcScreen;
    11.     BITMAPINFO bmpinfo;
    12.     BITMAPFILEHEADER finfo;
    13.     BITMAPINFOHEADER *info;
    14.     HBITMAP hBitmap;
    15.     void* pBits;
    16.     HWND hwndScreen;
    17.     int i;
    18.     BYTE *bits;
    19.     HANDLE fp;
    20.     long ctsize, imgsize, pixels;
    21.     char *ptr;
    22.     BOOL ret_val = FALSE;
    23.  
    24.     hdc = GetWindowDC(GetDesktopWindow());
    25.     if (hdc == 0)
    26.         return FALSE;
    27.  
    28.     memdc = CreateCompatibleDC(hdc);
    29.     if (memdc == 0)
    30.         return FALSE;
    31.  
    32.     bmpinfo.bmiHeader.biWidth=  GetDeviceCaps(hdc,HORZRES);
    33.     bmpinfo.bmiHeader.biHeight= GetDeviceCaps(hdc,VERTRES);
    34.     bmpinfo.bmiHeader.biPlanes=1;
    35.     bmpinfo.bmiHeader.biBitCount=24;
    36.     bmpinfo.bmiHeader.biCompression=BI_RGB;
    37.     bmpinfo.bmiHeader.biSizeImage=0;
    38.     bmpinfo.bmiHeader.biXPelsPerMeter=2834;
    39.     bmpinfo.bmiHeader.biYPelsPerMeter=2834;
    40.     bmpinfo.bmiHeader.biClrUsed=0;
    41.     bmpinfo.bmiHeader.biClrImportant=0;
    42.     bmpinfo.bmiHeader.biSize=sizeof(bmpinfo.bmiHeader);
    43.  
    44.     hBitmap = CreateDIBSection(hdc, &bmpinfo, DIB_PAL_COLORS, &pBits, 0, 0);
    45.     SelectObject(memdc, hBitmap);
    46.     BitBlt(memdc, 0, 0, bmpinfo.bmiHeader.biWidth, bmpinfo.bmiHeader.biHeight, hdc, 0, 0, SRCCOPY);
    47.  
    48.     hwndScreen = GetDesktopWindow();
    49.     hdcScreen = GetDC(hwndScreen);
    50.     if (hdcScreen == 0)
    51.         return FALSE;
    52.  
    53.     info = (BITMAPINFOHEADER*)malloc(sizeof(BITMAPFILEHEADER)+(1024*sizeof(RGBQUAD)));
    54.     if (info == 0)
    55.         return FALSE;
    56.  
    57.     info->biSize = sizeof(BITMAPINFOHEADER);
    58.     info->biBitCount = 0;
    59.  
    60.     i = GetDIBits(hdcScreen, hBitmap, 0, 0, NULL, (BITMAPINFO*)info, DIB_RGB_COLORS);
    61.     info->biBitCount=8;
    62.     info->biCompression=BI_RGB;
    63.     pixels=info->biWidth*info->biHeight;
    64.     switch(info->biBitCount)
    65.     {
    66.         case 4:     ctsize=16;  imgsize=pixels/2;   break;
    67.         case 8:     ctsize=256; imgsize=pixels;     break;
    68.         case 16:    ctsize=0;   imgsize=pixels*2;   break;
    69.         case 24:    ctsize=0;   imgsize=pixels*3;   break;
    70.         case 32:    ctsize=0;   imgsize=pixels*4;   break;
    71.         default:
    72.             {
    73.                 ReleaseDC( hwndScreen,hdcScreen );
    74.                 return FALSE;
    75.             }
    76.     }
    77.  
    78.     bits = (unsigned char*)malloc(imgsize);
    79.     if (bits == 0)
    80.     {
    81.         free(info);
    82.         return FALSE;
    83.     }
    84.  
    85.     i = GetDIBits(hdcScreen, hBitmap, 0, info->biHeight, bits, (BITMAPINFO*)info, DIB_RGB_COLORS);
    86.  
    87.     ptr = (char *)&finfo.bfType;
    88.     ptr[0]='B';
    89.     ptr[1]='M';
    90.     finfo.bfOffBits=sizeof(BITMAPFILEHEADER)+sizeof(BITMAPINFOHEADER)+(sizeof(RGBQUAD)*ctsize);
    91.     finfo.bfSize=finfo.bfOffBits+imgsize;
    92.     finfo.bfReserved1=0;
    93.     finfo.bfReserved2=0;
    94.  
    95.     fp = _fcreate(file);
    96.     if (fp != INVALID_HANDLE_VALUE)
    97.     {
    98.         _fwrite(fp, &finfo, sizeof(BITMAPFILEHEADER));
    99.         _fwrite(fp, info, sizeof(BITMAPINFOHEADER)+sizeof(RGBQUAD)*ctsize);
    100.         _fwrite(fp, bits, imgsize);
    101.         _fclose(fp);
    102.         ret_val = TRUE;
    103.     }
    104.  
    105.     free(info);
    106.     free(bits);
    107.     ReleaseDC(hwndScreen,hdcScreen);
    108.     return ret_val;
    109. }
     
  7. spa

    spa Active Member

    Публикаций:
    0
    Регистрация:
    9 мар 2005
    Сообщения:
    2.240
    Ну, собственной как я и говорил, получается скрин как будто нету приложения, а показывает то что под ним. Может это из-за windows7?
     
  8. spa

    spa Active Member

    Публикаций:
    0
    Регистрация:
    9 мар 2005
    Сообщения:
    2.240
    Booster
    для оптимизации рутины? да мне скрин, ну раз в 5 минут и то хорошо если надо будет )
     
  9. Z3N

    Z3N New Member

    Публикаций:
    0
    Регистрация:
    10 фев 2009
    Сообщения:
    812
    Думаю, что тут без DX не обойтись, нужно получить рабочую в данный момент поверхность экрана и сохранить её. Как-то можно, давно уже дела имел с дикс. Я писАл поверх окон, а вот пройдёт ли такое в 3д - не знаю, для 3д юзал оверлей.

    Или можно повторить действия fraps.
     
  10. spa

    spa Active Member

    Публикаций:
    0
    Регистрация:
    9 мар 2005
    Сообщения:
    2.240
    Z3N
    да мне не обязательно писать, но надо чтобы из консоли можно было щелкнуть.
     
  11. Booster

    Booster New Member

    Публикаций:
    0
    Регистрация:
    26 ноя 2004
    Сообщения:
    4.860
    spa
    Действительно, чем fraps не устраивает? По хоткею делает шоты.
     
  12. spa

    spa Active Member

    Публикаций:
    0
    Регистрация:
    9 мар 2005
    Сообщения:
    2.240
    Booster
    у меня доступ, к удаленной консоли и все. У меня есть и граф удаленный доступ, но мне нужен лишь скришот.
     
  13. G13

    G13 New Member

    Публикаций:
    0
    Регистрация:
    24 мар 2006
    Сообщения:
    499
    spa
    Возьмите Taksi (taksi.sourceforge.net) и доточите напильником под вашу конкретную задачу. Работает по тому же принципу, что и Fraps (сиречь хукает вывод DirectX).
     
  14. Z3N

    Z3N New Member

    Публикаций:
    0
    Регистрация:
    10 фев 2009
    Сообщения:
    812
    Понимаю, но между писать и прочитать не такая уж и большая разница.

    Код (Text):
    1. DDCAPS                                      caps;
    2. DDSCAPS2                                    capsovbb;/*for overlay back buffer*/
    3. extern  HWND                            hWnd;
    4. LPDIRECTDRAW7                       lpDDraw;
    5. DDSURFACEDESC2                  ddsd;
    6. DDSURFACEDESC2                  ddsdo;/*for overlay*/
    7. DDOVERLAYFX                         ddofx;
    8. LPDIRECTDRAWSURFACE7    lpPrimarySurface;
    9. LPDIRECTDRAWSURFACE7    lpOverlaySurface;
    10. LPDIRECTDRAWSURFACE7    lpOverlaySurfaceBB;
    11. #define OVERLAY_WIDTH       256;
    12. #define     OVERLAY_HEIGHT  64;
    13. bool    OverlaysSupported(void);
    14. bool    OverlayUpdate(void);
    15. void    DDrawDone(void);
    16. bool    OverlayInit(void);
    17. bool    DDrawInit(void);
    18.  
    19. bool    DDrawInit(void)
    20. {
    21.     if (DirectDrawCreateEx(NULL,(void**)&lpDDraw,IID_IDirectDraw7,NULL)!=DD_OK)
    22.         return FALSE;
    23.     ZeroMemory(&caps, sizeof(caps));
    24.     caps.dwSize=sizeof(caps);
    25.     if (lpDDraw->GetCaps(&caps, 0)!=DD_OK)
    26.         return FALSE;
    27.     if (lpDDraw->SetCooperativeLevel(hWnd,DDSCL_NORMAL)!=DD_OK)
    28.         return FALSE;
    29.     ZeroMemory(&ddsd,sizeof(ddsd));
    30.     ddsd.dwSize=sizeof(ddsd);
    31.     ddsd.ddsCaps.dwCaps=DDSCAPS_PRIMARYSURFACE;
    32.     ddsd.dwFlags=DDSD_CAPS;
    33.     if (lpDDraw->CreateSurface(&ddsd,&lpPrimarySurface,NULL)!=DD_OK)
    34.         return FALSE;
    35.     return TRUE;
    36. }
    ^тут есть немного лишнего кода :)
    дальше
    Код (Text):
    1. lpPrimarySurface->Lock(NULL,&ddsd,DDLOCK_WAIT,NULL);
    2. //длинну можно получить из ddsd.dwWidth
    3. //ширину из <аналогично>
    4. ..
    5. тут, наверно, лучше побыстрому скопировать куда-нибудь буфер
    6. (int*)ddsd.lpSurface //- указатель на буфер
    7. ..
    8. //и обязательно
    9. lpPrimarySurface->Unlock(NULL);
    При копирвании нужно учитывать округление, насколько я помню. Читал про него на этом сайте.
    Но когда я эксперементировал - я забивал на всё это и просто копировал raw изображение в файл.

    Когда вы скопируете ddsd.lpSurface, то там у вас будет raw data, возможно стоит поискать какую-нибудь граф либу, которая поддерживает рав инпут.

    Посмотрел как это делат taxi - (искать MakeScreenShot) какие-то замарочки с ави а в MakeScreenShotGDIP, соответсвенно, гдиплюс. Бр-р-р-р.
     
  15. spa

    spa Active Member

    Публикаций:
    0
    Регистрация:
    9 мар 2005
    Сообщения:
    2.240
    Z3N
    спасибо за код, мб потом гляну. Просто дхсдк нету, нече нету. Я вообще софт готовый искал ), но все равно спасибо ,как смогу обязательно проверю работоспособность.
     
  16. Booster

    Booster New Member

    Публикаций:
    0
    Регистрация:
    26 ноя 2004
    Сообщения:
    4.860
    spa
    Напиши скрипт и будет по команде из консоли.
     
  17. Z3N

    Z3N New Member

    Публикаций:
    0
    Регистрация:
    10 фев 2009
    Сообщения:
    812
    Как я и предполагал мой метод не работает при полноэкранном DX приложении, извините.
    ДДРАУ не хочет создавать нужную поверхность. Хотя при огл всё работает.

    Во время написания тестовой проги я выяснил, что гдиплюс может работать с ддрав7 поверхностями и сохраниение скриншота не представляет трудности, просто image->Save(...) %).

    Интересно, как винде удаётся делать скрины и в dx 3д приложениях?

    Может кто-нибудь знает, что там подвешено на клавишу PrintScreen???

    У мена принтскрин снимает и с dx приложений.
     
  18. T800

    T800 Member

    Публикаций:
    0
    Регистрация:
    7 дек 2006
    Сообщения:
    293
    Адрес:
    Moscow
    Z3N
    Было бы конечно интересно знать алгоритм работы PrintScreen (если кто то видел инфу - поделитесь).

    А метод который ты предложил я тоже пробовал (давно). Да и метод этот очень уж тормозной (как мне помнится).

    Я сейчаз вообще разбираюсь вот с этим делом http://www.wasm.ru/forum/viewtopic.php?id=30224 (вообще занятное это дело - стрелять по воробьям из пушки).
    Пока получаю скрины только на WinXP. В d3d ещё не пробовал ...