C++ Framebuffer auslesen mit OpenGL

Zhen

Lt. Junior Grade
Registriert
Aug. 2009
Beiträge
299
Hallo Leute,

also ich habe zwar schon gegoogelt, aber irgendwie ist meine Frage immernoch offen geblieben... :(

Ich hab mich nämlich gefragt ob es möglichst ist in C++ und OpenGL den Framebuffer auszulesen und das ganze - z.B. - in eine Bitmap speichern?
Und ich meine jetzt nicht irgendwie die Pixel/Inhalte von einem Fenster sondern gesamten Desktop. So wie ich den z.B. jetzt sehe, durch auslesen des Framebuffers in eine Bitmap speichern?

Ist sowas mit OpenGL möglicht? Hat da jemand gute Tutorials? In Sachen OpenGL bin ich nämlich ein absoluter Neuling :rolleyes:

EDIT: Ein anderer Weg wie z.B. über WinAPI, DirectX, etc. wäre aber auch willkommen.

Hoffe ihr könnt mir da weiterhelfen ;)
 
Zuletzt bearbeitet:
glReadPixels mit OpenGL. Aber das ist nur der OpenGL Framebuffer den du da holst ;)
Du kannst den Windows Desktop mit hDC/hRC auslesen, Google hilft da ungemein. ;-)
 
Vielen vielen Dank :)

Immerhin hab ich jetzt paar Stichwörter und kann fröhlich weitergooglen :D :D :D
 
Ja das sind aber einfach nur WinAPI-/.NET-Funktionen zum Screenshot erstellen.
Mir gehts aber wirklich um den Framebuffer... ;)
 
Der Framebuffer enthält doch die Pixel, die hinterher im Screenshot landen :o
 
Ja nur, dass ich z.B. keine Screenshots aus einem Service her erstellen kann.
Unter Win7 ist ja die Station für Dienste und Desktop komplett von einander getrennt so zu sagen ;)

Deswegen ja auch meine Hoffnung, dass irgendwie Zugriff auf den Framebuffer bekomme :D

Außerdem brauch ich die Screenshots ja nicht als Bitmap oder so (das oben war nur ein Beispiel), ich will sie auslesen und anschließend zu einem Remote-PC versenden. Da kosten die Screenshots zu viel Performance und sind somit etwas zu langsam ;)
 
Hat den wirklich keiner eine Ahnung wie ich auf den Framebuffer zugreifen könnte?

Völlig egal ob in C# oder C++, ob mit OpenGL, DirectX, SDL oder ner anderen API... brauch dringend einen Weg um den Framebuffer auszulesen... :(
 
Nach meinem Verständnis wird der OpenGL-Framebuffer nur gefüllt wenn per OpenGL-Befehle geschrieben werden. Ob das stimmt weiß ich jetzt nicht aber ich bezweifel, dass der Desktop hier drin zu finden ist.

Auch wenn ich jetzt nicht weiß wie, aber es müsste schon irgendeinen Weg geben sich von der Grafikkarte das aktuelle Bild geben zu lassen. Vielleicht kann man mit OpenCL da irgendwas machen? Das ist aber leider auch nur eine Idee und ich weiß nicht ob das möglich ist.
 
Ja das mit dem OpenGL Buffer hab ich auch gelesen gehabt... allem Anschein nach kann man mit dem wirklich den Desktop nicht herbekommen... :(

Wegen OpenCL werd ich mich gleich mal erkundigen und die weiten des Internets durchforsten :D
Danke für den Tipp :)

Wenn jemandem noch eine Möglichkeit einfällt, dann immer her damit ;)
Ergänzung ()

Also wie es mir scheint, ist auch OpenCL die falsche Lösung gewesen... :(
 
Sicher, dass glReadPixels nicht DEN Framebuffer ausliest? Zumindest steht in der SDK "read a block of pixels from the frame buffer", also nix von OpenGL Framebuffer. Kann es gerade nicht testen, aber probier es doch einfach selbst aus. ;)

Unter Linux kannst du übrigens direkt via /dev/fbX auf den Framebuffer zugreifen(X = Nummer des Monitors).
 
Danke für den Tipp, werds ausprobieren, aber ich glaub die Funktion liest den OpenGL Framebuffer :P (werds dennoch mal testen, nicht dass die Lösung direkt vor der Nase liegt und ich ignorier die :D :D )

Ja Linux hats wohl einfacher... leider brauch ich das ganze aber unter Windows :(
 
Code:
GdiplusStartupInput gdiplusStartupInput=GdiplusStartupInput(); 
	GdiplusStartup(&gdiplus, &gdiplusStartupInput, NULL);
	{
		wchar_t path[4096]={};
		UINT  num = 0;// number of image encoders
		UINT  size = 0;// size of the image encoder array in bytes
		OPENFILENAME f={sizeof(OPENFILENAME),0,0,L"",0,0,1,path,4096,0,0,0,0,
			OFN_EXPLORER ,0,0,L"png",0,0,0,0,};
		HDC bitmap=0;
HWND window=GetDesktopWindow();
		HDC screen=GetDC(window);
		RECT dim={};
		GetClientRect(window,&dim);
		int width=dim.right,height=dim.bottom;
		Graphics g(screen);
		Bitmap b(width,height,&g);
		Graphics d(&b);
		bitmap=d.GetHDC();
		BitBlt(bitmap,0,0,width,height,screen,0,0,SRCCOPY);
		d.ReleaseHDC(bitmap);
		ReleaseDC(0,screen);


		GetImageEncodersSize(&num, &size);
		ImageCodecInfo* pImageCodecInfo = new ImageCodecInfo[size/sizeof(ImageCodecInfo)+1];
		GetImageEncoders(num, size, pImageCodecInfo);
		std::wstring ext;
		for(size_t i=0;i<num;++i){
			ext+=wstring(pImageCodecInfo[i].MimeType)+L" mit "+pImageCodecInfo[i].CodecName+wstring(L"\0",1);
			ext+=wstring(pImageCodecInfo[i].FilenameExtension)+wstring(L"\0",1);
		}
		f.lpstrFilter=ext.c_str();
		if(GetSaveFileName(&f)){
			wstring p(f.lpstrFile);
			CLSID cid={};
			b.Save(f.lpstrFile,&pImageCodecInfo[f.nFilterIndex-1].Clsid);
		}
		delete[]pImageCodecInfo;
		DeleteDC(screen);
	}
	GdiplusShutdown(gdiplus);
Das ist ne Funktion, die ich mal für nen Screenshotprogramm geschrieben hab.
Kern ist der BitBlt und GetDC(GetDesktopWindow()).
 
Danke dir Hancock, aber BitBlt benutzt ja soweit ich weiß GDI und hat nichts mit dem Framebuffer zu tun oder?!

Das hilft mir deswegen nicht weiter, vor allem weil ich alle GDI Screenshot Funktionen in einem Windows-Dienst unter Win Vista/7 nicht verwenden kann.

Wie oben schon erwähnt haben die verschiedene Win Stations, die fast gänzlich von einander getrennt sind. Kann also daher keine GDI Funktionen verwenden um den Windows Desktop zu bekommen.
 
Kleines Update... :D

Ich habs soweit geschafft mir einen Screenshot mit Hilfe von DirectX zu erstellen in dem ich den Frontbuffer auslese... es ist schnell, man kann es zur Analyse einzelner Pixel oder eventuell ja sogar Abgleich von zwei Screenshots verwenden.

Doch leider bin ich immernoch nicht da angekommen wo ich hin wollte :D :D :D

Ich habe nämlich die Befürchtung, dass diese Methode nicht in einem Windows-Service funktionieren wird... :(

Grund dafür ist, dass man beim Erstellen eines Devices ein Handle auf ein Windows-Fenster übergeben muss damit man überhaupt später auf den Frontbuffer zugreifen kann... was beim Windows Service ja schlecht geht :D


Langsam befürchte ich, dass ich hier ohne eigenen Treiber nicht wirklich weiterkomme... :freak:


EDIT: Wen die Sache mit dem Frontbuffer interessiert, der kann hier mal das Tutorial lesen. Hat mir auch weitergeholfen ;-)

DirectX Framebuffer auslesen
 
Zuletzt bearbeitet:
Den Weg kann ich leider auch nicht gehen... die Exe würde sich nicht starten lassen, wenn ich im Logon-Desktop bin :P

Sprich wenn sich mein PC hochfährt und der Dienst (der eigentlich die Screenshots machen sollte) startet, kann er die Exe nicht ausführen damit sie die Screens macht und diese an den Dienst weiterleitet.

Das ganze soll ne anständige Fernwartung werden übrigens (hab eh schon zig Threads zu dem Thema hier eröffnet gehabt :D ). Wenn du dich wunderst wieso ich in einem Service "Screenshots" machen will ;)
 
Warum, der LogonDesktop gehört auch einem Nutzer (SYSTEM?). Daher solltest du es auch öffnen können. Aber wahrscheinlich wird es an den Zugriffsrechten scheitern, da dieser Anmeldebildschirm ja recht "wichtig" ist und daher auch gut geschützt sein wird.

Zur Fernwartung: Was gefällt dir an RDP/Teamviewer nicht?
 
Will was eigenes auf die Beine stellen + ich will paar Features drin haben die die beiden halt nicht bieten :D

Außerdem soll die Fernwartung nur ein Teil eines größeren Ganzen sein ;)
 
Zurück
Oben