kein Pointer auf Bitmap zu bekommen



  • 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ösung

    Den 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

    CPicture

    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



  • @hustbaer

    na ja das bei SetBitmap die daten wirklich kopiert werden das bezweifel ich jetzt mal, genau so wie wenn man von einem CString eine Kopie macht, die Daten nicht wirklich kopiert werden solange sich einer von beiden strings nicht ändert, also solange beide strings gleich sind gibt es auch nur einen Puffer, oder kannst du da was anderes beweisen?



  • @CTecS:
    Freund. Bezweifel was du willst, ich muss dir gar nix beweisen.

    Vermutlich bezweifelst du auch dass memcpy die Daten wirklich kopiert, weil das könnte es ja auch wie CString machen.


  • Mod

    CTecS schrieb:

    na ja das bei SetBitmap die daten wirklich kopiert werden das bezweifel ich jetzt mal

    SetBitmapBits koopiert die Daten. Da hat hustbaer recht. Was soll es auch anderes tun? Du hast ja kein verwaltetes Objekt, sondern einen Zeiger auf die Bits...

    CreateDIBSection führt dagegen so etwas wie ein Speichermapping durch... Es ist wirklich entscheidend schneller, besonders bei großen Bitmaps.

    Der Vergleich mit CString hinkt kräftig. Ein CString Objekt wurde durch die CString Klasse selbst erzeugt. Nur deshalb ist ein COW möglich. Der Zeiger den Du an SetBitmapBits übergibst darfst Du sofort danach wegschmeißen oder überschreiben... Würdest Du so etwas wie ein Objekt erzeugen (GDI-Handle) oder gäbe es so etwas wie GDI-Speicher, wäre das ja evtl. denkbar, aber so was kennt GDI nicht.



  • Man kann jedenfalls zwischen dem Übergeben des Arrays an SetBitmapBits und der Blit-Operation, ohne den Umweg über irgendwelche Klassenbibliotheken/Makros usw. zu gehen, mit *(pBilddaten+i)=... wild in das array schreiben, ohne dass das Konsequenzen für die Anzeige hat. Spricht eher dafür, dass wirklich kopiert wird, wovon ich jetzt erstmal ausgehe. Das Bitmap ist im 32BPP-Format ohne die momentane 2:1 Verkleinerung 5MB groß. Denke schon, dass das sinnvoll ist den Kopierschritt zu sparen.
    Ich hänge aber irgendwie fest.

    Ich fasse mal die SetBitmapBits-Version (die funktioniert) in Stichpunkten zusammen:
    in der ::OnDraw-Methode der View-Klasse eines SDI mach ich der Reihe nach folgendes
    1. memory DC erzeugen mit speichDC.CreateCompatibleDC(NULL)
    2. ein BITMAP str_bitmap deklarieren und mit Werten "ausfüllen"
    3. CBitmap deklarieren und Cvbitmap->CreateBitmapIndirect(&str_bitmap);
    4. speichDC.SelectObject(Cvbitmap)
    5. Daten in pKopierArray (32BPP BYTE-array) schreiben.
    6. Cvbitmap->SetBitmapBits(4*640*512,pKopierArray);
    7. pDC->SelectObject(Cvbitmap);
    8. pDC->BitBlt(30, 30, 640, 512, &speichDC, 0, 0, SRCCOPY);
    9. Zurückselektieren, array deleten usw.

    Das will ich jetzt umstellen.
    Also erst CreateDIBSection(.....,&pBitmapDaten,.....), dann in obigem Ablauf bei 5. pKopierArray durch pBitmapDaten ersetzen und dann?

    Wenn ich irgendwas verstanden habe, dann fällt Punkt 6 weg.
    1. wird weiter benötigt und speichDC.m_hDC wird später an CreateDIBSection übergeben.
    aus 2 wird dann ein entsprechender Punkt mit BITMAPINFO-struct. Da wird's schon problematisch. Ich will keine Paletten benutzen und 32BPP. Laut der onlinehilfe zu BITMAPINFOHEADER, Abschnitt biBitCount soll der bmiColors-member von BITMAPINFO dann NULL sein. Das ist aber ein array und das macht sich irgendwie nicht gut auf der linken Seite eines Zuweisungsoperators. Kann man das dann einfach uninitialisiert lassen?
    3. sollte eigentlich auch rausfallen, da CreateDIBSection das DIB so erzeugt "that applications can write to directly."
    Bei 4. kommt dann CreateDIBSection
    5. dann das schreiben der Daten. (hab schon im Debugger reingeschaut, Daten sind drin)
    6. und 7. fallen weg
    bei 8. kommt dann
    nSetDIBitsRueck = SetDIBitsToDevice(pDC->m_hDC,30, 30, 640, 512, 0,511,0,512, &pBitmapDaten, &str_bitmapinfo, DIB_RGB_COLORS);

    Rückgabewert ist immer 0 und es wird nichts gezeichnet.

    Vielleicht sieht ja einer den Denkfehler. An Sonsten lege ich das Thema Optimierung erstmal zu den Akten und mach mal mit den eigentlichen Messalgorithmen weiter.



  • sorry wenn ich jemanden auf die Füße getreten habe, dann führt eben CreateDIBSection sowas wie ein Speichermapping aus und SetBitmapBits kopiert, ist das halt so wieder was gelernt


Anmelden zum Antworten