kein Pointer auf Bitmap zu bekommen
-
Hallo,
ich möchte gerne in einem MFC-Progrämmchen Bilder aus einer SW-Kamera auslesen, Berechnungen anstellen, die Bilddaten manipulieren und die dann darstellen.
Auslesen in ein unsigned char array geht schonmal. Die Darstellung über GDI per zweier for-Schleifen um ein pDC->SetPixelV funktioniert erstmal ist aber natürlich zäh wie Sirup.
Deswegen möchte ich einen memory device context mit 'nem Bitmap drin erzeugen, einen Pointer auf die Bilddaten erhalten, um diesen dann in die MFC-Ansicht zu blit-en. Ich steh aber offenbar gerad auf der Leitung. Nach meinem Verständnis und auch dem eines Kollegen müsste nachfogender Code aus pDiePixel einen Pointer auf die Bitmapdaten machen. pDiePixel zeigt leider immer auf 0x00000000.CDC speichDC; speichDC.CreateCompatibleDC(NULL); //Versuche mit Bitmap Objekt int nGetBitmapFehler, nCreateBitmapFehler; CBitmap* Cvbitmap; BITMAP str_bitmap; short int* testarray; unsigned char* pDiePixel; Cvbitmap = new CBitmap(); testarray = new short int[1024*1280*4]; nCreateBitmapFehler = Cvbitmap->CreateBitmap(1280,1024,1,speichDC.GetDeviceCaps(BITSPIXEL),NULL /*testarray*/); speichDC.SelectObject(Cvbitmap); nGetBitmapFehler = Cvbitmap->GetBitmap(&str_bitmap); //jetzt sollte nach meinem Verstaendnis str_bitmap.bmBits ein Pointer auf die Bilddaten sein. pDiePixel =(unsigned char*)str_bitmap.bmBits; // ist es aber nicht
Ist mit Visual Studio 2010 und Windows 7 erstellt. Die Codezeilen sind in einem MFC-SDI in der Ansichtklasse in ::OnDraw.
Ein Denkanstoss würde schon erstmal helfen.
-
So kann man meines Wissens nicht einen Poiter auf die Bitmap-Bits holen. mit GetBitmapBits() kannst Du Bits holen. bm.bmBits ist nur für die Funktion CreateBitmapIndirect() gültig, d.h. damit werden die Bits gesetzt, ansonsten ist er immer NULL.
-
So kann man meines Wissens nicht einen Poiter auf die Bitmap-Bits holen. mit GetBitmapBits() kannst Du Bits holen. bm.bmBits ist nur für die Funktion CreateBitmapIndirect() gültig, d.h. damit werden die Bits gesetzt, ansonsten ist er immer NULL.
Warum wurden jetzt schon zwei Antworten von mir doppelt angezeigt
Is doch nicht soooo tolle ...
-
Danke für die Antwort. Ich werde mir morgen mal SetBitmapBits etwas genauer ansehen. Das könnte ungefähr das tun was ich vorhabe (momentan kein Visual Studio in Griffweite).
Aber kann es sein, dass du mich etwas falsch verstanden hast.
Ich habe nicht die function GetBitmapBits sondern die member function CBitmap::GetBitmap benutzt.
-
wenn ich mich nicht irre bekommst Du so ein DDB (Device Dependent Bitmap). Wenn Du aber an die Bits direkt ran willst, musst Du ein DIB mit CreateBitmapIndirect erzeugen.
PS:
bmWidthBytes = ((WidthPixel * BitCount + 31) & ~31) / 8;
-
GetBitmapBits() sollte der Tipp sein, wie Du an die Bits 'rankommst. NochX: Das .bmBits ist nur für das setzen der Bits für die Funktion CreateBitmapIndirect() von Bedeutung. Für GetBitmap() ist es immer NULL. Durch GetBitmapBits() kannst Du doch an diese herankommen.
-
GetBitmapBits() sollte der Tipp sein, wie Du an die Bits 'rankommst. NochX: Das .bmBits ist nur für das Setzen der Bits für die Funktion CreateBitmapIndirect() von Bedeutung. Für GetBitmap() ist es immer NULL. Durch GetBitmapBits() kannst Du doch an diese herankommen.
Man...schon wieder
Was mache ich falsch, daß das passiert
-
Sorry, ich hab's immernoch nicht.
Nur um Missverständnisse zu vermeiden. Du redest von CBitmap::GetBitmapBits.
Mangels Verständnis hab' ich mal mit entsprechenden Breakpoints im Debugger geschaut was da überhaupt passiert und nochmal http://msdn.microsoft.com bemüht.Was mich stutzig macht ist folgendes:
aus http://msdn.microsoft.comCBitmap::GetBitmapBits
Visual Studio 2010Copies the bit pattern of the attached bitmap into the specified buffer.
Ich möchte aber in eine später darzustellende Bitmap rein schreiben. Was nützt mir das dann, wenn die Methode den Inhalt in das vorher aufgespannte array kopiert?
Müsste ich da nicht entweder einen Pointer auf die tatsächlichen Daten bekommen oder eben mein array in die Bitmap kopieren?
-
Wenn man mit GetBitmapBits die Daten bekommt, dann sollte man doch mit SetBitmapBits diese Setzen können, is doch irgendwie logisch wenn man mal danach schaut. also wenn du das Bitmap richtig erzeugst kannst du bei Create gleich deine Daten anhängen uind alles ist prima.
-
Die Experimente einen Pointer auf das Bitmap zu bekommen habe ich vorerst eingestellt. Ich präpariere das array jetzt erst im 32bpp Format im Speicher kopiere es mit SetBitmapbits in einen memoryDC und blit-e es dann in die Ansicht.
Das funktioniert, scheint mir aber irgendwie noch nicht die optimale Lösung zu sein. Die schwarz-weiß-Rohdaten, was ja immerhin 1,3MB sind und das GDI-Objekt in der Ansicht (5MB) liegen so oder so im Speicher. Um das eine ins andere in zu kopieren muss ich jetzt nebenbei noch das 32Bit/Pixel-array und den memDC im Speicher aufspannen, womit nochmal 10MB verbraten werden.
Mehr ist ohne Detailkenntnisse der WinAPI nur von den MFC aus vermutlich nicht machbar.
Als jemandem der mal auf 'nem C128 programmiert hat kommt mir das komisch vor.
-
Auch mit mehr Detailkenntnissen der Windows-API wirst Du nicht mehr erreichen. Die MFC kapselt die API-Funktionen in verschiedenen Klassen. Du hast die selben Möglichkeiten wie mit der API. Die Ressourcen-Verschwendung mußt Du als gegeben hinnehmen. Vielleicht kannst Du mit DirectX Lösungen finden...
-
Bitmap mit CreateDIBSection erstellen, Daten reinschreiben und auf den Bildschirm blitten.
http://msdn.microsoft.com/en-us/library/dd183494(VS.85).aspx
Direkter geht's mit GDI nicht, da dir GDI keinen direkten Zugriff auf den Videospeicher ermöglicht. Ist normalerweise aber auch nicht nötig.
Achja: mit Direct3D sollte das schön gehen. Da müsstest du nur die Helligkeitswerte in eine Textur kopieren, die "Umrechnung" in RGB würde dann die Grafikkarte machen. Die Frage ist aber ob das den Aufwand wert ist.
-
hier mal ein Beispiel, bei dem es geht:
BITMAP bmp_data; HBITMAP hBitmap = getMyBitmapHandle(); if(GetObject(hBitmap, sizeof(bmp_data), &bmp_data)) { if(bmp_data.bmBits) { // direkter Zugriff auf "orginal" Daten } else { // kein DIB } }
By The way:
The GetBitmapBits function copies the bitmap bits of a specified device-dependent bitmap into a buffer.**Note: This function is provided only for compatibility with 16-bit versions of Windows. Applications should use the GetDIBits function.
**
-
schau mal die Funktionen
kamera->GetDibBits
view->SetDibBits
-
Da es mit dem Zwischenspeichern in einem array und SetBitmapBits funktioniert, habe ich das nicht mehr so intensiv weiterverfolgt. Interessieren würde es mich allerdings schon, da ich die Lösung für wenig Speichereffizient halte.
Das Codebeispiel von Matze555 habe ich getestet. Möglicherweise habe ich da noch ein Verständnisproblem oder das ist auch nicht LösungDen Funktionsaufruf getMyBitmapHandle() im Besipiel muss ich ja noch irgendwie umsetzen?
Ich habe vorher ein CBitmap-Object namens Cvbitmap erzeugt und mit CreateBitmapIndirect initialisiert. Das Objekt hat aber keinen Member vom Typ HBITMAP sondern nur einen vom Typ HGDIOBJ.
Also hab ich es zum Testen erstmal so versucht und mit Breakpoints vorher und nacher geschaut was passiert:handleA=(HBITMAP)(*Cvbitmap); handleB=Cvbitmap->operator HBITMAP(); GetObject(handleA,sizeof(testbitmapA),&testbitmapA); GetObject(handleB,sizeof(testbitmapB),&testbitmapB);
Die beiden Testbitmaps werden durch GetObject mit sinnvollen Daten gefüllt, aber testbitmapA.bmBits und testbitmapB.bmBits sind Nullpointer.
-
vielleicht versuchst du mal die Klasse, könnte dich weiter bringen, geht aber nicht als 64 bit code weil assembler drin ist
ob dir das weiter hilft weis ich aber nicht.
-
Nochmal, du musst CreateDIBSection verwenden wenn du direkt auf die Bits zugreifen willst:
http://msdn.microsoft.com/en-us/library/dd183494(VS.85).aspx
-
Hi,
habe mich nochmal mit dem CreateDIBSection befasst.
Die structures mit dem man das füttern muss sind doch etwas umfangreich.
Da werde ich wohl noch ein paar Tage brauchen, bis ich weiß wie ich den device context zu präparieren habe, was ich mit der Farbpalette mache usw..Danke auf jeden Fall schonmal. Das geht jedenfalls von der Beschreibung her schonmal definitiv in die Richtung in die ich will.
-
hustbaer schrieb:
Nochmal, du musst CreateDIBSection verwenden wenn du direkt auf die Bits zugreifen willst:
http://msdn.microsoft.com/en-us/library/dd183494(VS.85).aspx
wieso kann ich dann mit GetBitmapBits von jeder CBitmap die Daten geben lassen und mit SetBitmapBits die Daten setzen wenn das doch alles nur über CreateDIBSection gehen soll?
-
@CTecS:
Klar geht es auch mit GetBitmapBits/SetBitmapBits, bloss dann musst du die Daten 1x mehr kopieren.
BTW: ich habe ja auch "direkt auf die Bits zugreifen" geschrieben. Und erst in einen Puffer schreiben und diesen dann nochmals mit SetBitmapBits auf die Bitmap kopieren ist für micht alles andere als direkt.Mit SetBitmapBits:
for each frame write data to my_buffer SetBitmapBits from my_buffer to my_bitmap BitBlt from my_bitmap to screen
= 1x schreiben + 2x kopieren (SetBitmapBits & BitBlt)
Mit CreateDIBSection & SetDIBitsToDevice:
for each frame write data to my_buffer (which belongs to my_bitmap) SetDIBitsToDevice from my_bitmap (=my_buffer) to screen
= 1x schreiben + 1x kopieren (SetDIBitsToDevice)
= schneller