Использование glReadPixels
Как уже упоминалось это должно быть реализовано непосредственно в целевом приложении, чтобы вы должны иметь его исходный код или вводить код в нужное место/время. Я использую для снятия изображения этого кода:
void OpenGLscreen::screenshot(Graphics::TBitmap *bmp)
{
if (bmp==NULL) return;
int *dat=new int[xs*ys],x,y,a,*p;
if (dat==NULL) return;
bmp->HandleType=bmDIB;
bmp->PixelFormat=pf32bit;
if ((bmp->Width!=xs)||(bmp->Height!=ys)) bmp->SetSize(xs,ys);
if ((bmp->Width==xs)&&(bmp->Height==ys))
{
glReadPixels(0,0,xs,ys,GL_BGRA,GL_UNSIGNED_BYTE,dat);
glFinish();
for (a=0,y=ys-1;y>=0;y--)
for (p=(int*)bmp->ScanLine[y],x=0;x<xs;x++,a++)
p[x]=dat[a];
}
delete[] dat;
}
где xs,ys
является OpenGL разрешения окна, вы можете игнорировать весь bmp
материал (это VCL растровый я использую скриншот магазина), а также могу игнорировать for
это просто скопировать изображение от буфера до растрового изображения. Таким образом, важный материал просто так:
int *dat=new int[xs*ys]; // each pixel is 32bit int
glReadPixels(0,0,xs,ys,GL_BGRA,GL_UNSIGNED_BYTE,dat);
glFinish();
Вы должны выполнить этот код после того, как визуализация производится в противном случае вы получите незавершенные или пустой буфер. Я использую его после перерисовывания/перерисовки событий. Как уже упоминалось ранее, будет получен только материал, обработанный GL, поэтому, если ваше приложение объединяет GDI + OpenGL, лучше использовать следующий подход.
WinAPI подход
Для получения холста изображения любого окна я написал этот класс:
//---------------------------------------------------------------------------
//--- screen capture ver: 1.00 ----------------------------------------------
//---------------------------------------------------------------------------
class scrcap
{
public:
HWND hnd,hnda;
TCanvas *scr;
Graphics::TBitmap *bmp;
int x0,y0,xs,ys;
scrcap()
{
hnd=NULL;
hnda=NULL;
scr=new TCanvas();
bmp=new Graphics::TBitmap;
#ifdef _mmap_h
mmap_new('scrc',scr,sizeof(TCanvas() ));
mmap_new('scrc',bmp,sizeof(Graphics::TBitmap));
#endif
if (bmp)
{
bmp->HandleType=bmDIB;
bmp->PixelFormat=pf32bit;
}
x0=0; y0=0; xs=1; ys=1;
hnd=GetDesktopWindow();
}
~scrcap()
{
#ifdef _mmap_h
mmap_del('scrc',scr);
mmap_del('scrc',bmp);
#endif
if (scr) delete scr; scr=NULL;
if (bmp) delete bmp; bmp=NULL;
}
void init(HWND _hnd=NULL)
{
RECT r;
if (scr==NULL) return;
if (bmp==NULL) return;
bmp->SetSize(1,1);
if (!IsWindow(_hnd)) _hnd=hnd;
scr->Handle=GetDC(_hnd);
hnda=_hnd;
resize();
}
void resize()
{
if (!IsWindow(hnda)) return;
RECT r;
// GetWindowRect(hnda,&r);
GetClientRect(hnda,&r);
x0=r.left; xs=r.right-x0;
y0=r.top; ys=r.bottom-y0;
bmp->SetSize(xs,ys);
xs=bmp->Width;
ys=bmp->Height;
}
void capture()
{
if (scr==NULL) return;
if (bmp==NULL) return;
bmp->Canvas->CopyRect(Rect(0,0,xs,ys),scr,TRect(x0,y0,x0+xs,y0+ys));
}
};
//---------------------------------------------------------------------------
//---------------------------------------------------------------------------
//---------------------------------------------------------------------------
Опять он использует VCL так переписать растровый bmp
и холст scr
к вашему стилю окружающего ПРОГРАММИРОВАНИЯ , Также проигнорируйте фрагменты кода _mmap_h
, они предназначены только для отладки/трассировки указателей на память, связанных с некоторой неприятной ошибкой компилятора, с которой я столкнулся в то время, когда я это написал.
Использование прост:
// globals
scrcap cap;
// init
cap.init();
// on screenshot
cap.capture();
// here use cap.bmp
Если вы звоните cap.init()
он зафиксирует на всем рабочем столе окна. Если вы вызываете cap.init(window_handle)
, он будет блокировать определенное визуальное окно/компонент. Чтобы получить дескриптор окна с 3-го на стороне приложения смотрите:
К сожалению это на SE/RE вместо здесь на SE/SO, но мой ответ здесь охватывающий эту тему был удален. Я использую это для захвата видео ... все анимированные GIF-файлы в моих ответах, когда они созданы этим кодом. Другой пример можно увидеть на день этого ответа шахты:
Как вы можете видеть, что это работает и для DirectX накладки с Media Player Classic (даже функцией Windows, PrintScreen не может сделать это правильно). Как я уже писал, у меня пока нет проблем с этим.
Осторожно визуального материала WinAPI вызовов должны вызываться из приложения основного потока (WndProc) в противном случае серьезные проблемы могут возникнуть приводят к случайной несвязанной WinAPI вызывает исключения в любом месте в App.
Как вы считаете, «выход» видеокарты? Вероятно, вы ошибаетесь. – stark
Рамка. Букет пикселей. В основном я хочу, чтобы Windows и его драйверы обрабатывали весь рендеринг, и я хочу получить доступ к выходу. – Hassan
Выход идет по кабелю к монитору. Кто говорит, что он существует где угодно в памяти? – stark