Schnelles anzeigen von Bitmaps



  • @geeky
    hab grad mal DrawDib ausprobiert, nur wird mir nix angezeigt.
    Habs so probiert:

    HDRAWDIB hdd;
    hdd = DrawDibOpen();
    
    LPBITMAPINFOHEADER lpbi;
    
    DrawDibDraw(hdd, client_hWndDC, 0, 0, g_ClientSizeX, g_ClientSizeY, lpbi, imageBits, 0, 0, texSizeX, texSizeY, 0);
    

    Wo könnte der Fehler liegen?
    Vielen Dank
    stone.mk



  • Du füllst die BITMAPINFOHEADER Struktur nicht aus, sondern übergibst nicht nen nicht initialisierten Pointer.

    Übrigens aufpassen: Die Funktion zeichnet direkt auf den Screen, d.h. du übermalst möglicherweise Fenster.
    Außerdem sind die Dst-Angaben Screen-Koordinaten und beziehen sich nicht aufs DC!



  • Wie müßte diese LPBITMAPINFOHEADER Struktur denn aussehen?
    Was muss man denn da reinschreiben?



  • Bei SetDIBits() füllst du auch BITMAPINFO aus ?
    Darin ist soviel ich weiss die BITMAPINFOHEADER-Struktur enthalten (bmiHeader oder so).



  • Wenn du da noch Child-Fenster oder sowas drüber legen willst, würde ich die DrawDib-Methode lieber nicht verwenden.

    Wenn es nen Spiel oder sowas wird, wäre vermutlich günstiger gleich DirectX oder ähnliches zu verwenden.

    Ansonsten lässt sich BitBlt noch beschleunigen, wenn die Pixeldaten vorher in DDBs mit gleicher Farbtiefe wie der Display-DC vorbereitet werden.

    Hmm, du könntest auch die Performance von StretchDIBits() testen!!



  • habs jetzt so gemacht:

    LPBITMAPINFOHEADER lpbi;
    lpbi->biSize        = sizeof(BITMAPINFOHEADER);
    lpbi->biWidth       = texSizeX;
    lpbi->biHeight      = texSizeY;
    lpbi->biPlanes      = 1;
    lpbi->biBitCount    = channels * 8;
    lpbi->biCompression = BI_RGB;
    
    DrawDibDraw(hdd, client_hWndDC, 0, 0, g_ClientSizeX, g_ClientSizeY, lpbi, serverOGLBits, 0, 0, texSizeX, texSizeY, 0);
    

    Allerding wird immer noch nix angezeigt.
    Woran könnts liegen?



  • Child-Fenster weden nicht verwendet, nur das einen Hauptfenster. Wird auch kein Spiel werden. StretchDIBits() hab ich auch schon getestet, was auch nicht viel schneller lief.

    Unabhängig davon, wie könnte ich denn die Daten in DDBs mit gleicher Farbtiefe umwandeln?

    Danke
    stone.mk



  • LPBITMAPINFOHEADER ist ein Pointer!
    Zitat MSDN: "Most of the pointer-type names begin with a prefix of P or LP"

    LPBITMAPINFOHEADER ist demnach ein Pointer auf eine BITMAPINFOHEADER-Struktur.
    So nur zeigt ein nicht-intialisierter Pointer nach irgendwo im Ram!
    Du schreibst also quasi die Daten der Struktur einfach irgendwo in den RAM!
    Das könnte Zugriffsverletzungen geben!
    Wenn Du es so schreibst:

    BITMAPINFOHEADER bi;
    lpbi.biSize        = sizeof(BITMAPINFOHEADER);
    lpbi.biWidth       = texSizeX;
    lpbi.biHeight      = texSizeY;
    lpbi.biPlanes      = 1;
    lpbi.biBitCount    = channels * 8;
    lpbi.biCompression = BI_RGB;
    
    DrawDibDraw(hdd, client_hWndDC, 0, 0, g_ClientSizeX, g_ClientSizeY, &bi, serverOGLBits, 0, 0, texSizeX, texSizeY, 0);
    

    ..dengelt es der Compiler das Speicher für die Struktur reserviert wird und mittels & kriegst du den Pointer auf die BITMAPINFOHEADER-Struktur im Speicher.

    Was mir ansonsten noch einfallen könnte:
    Möglicherweise musst du noch biSizeImage ausfüllen.
    Wird FALSE zurückgegeben ?



  • stone.mk schrieb:

    Unabhängig davon, wie könnte ich denn die Daten in DDBs mit gleicher Farbtiefe umwandeln?

    Wieviele Bilder willst du denn darstellen ? Wird das ne Animation ?

    Ich würde es vermutlich so machen:
    Mit CreateCompatibleDC() nen temporären DC erzeugen.
    Mittels CreateCompatibleBitmap() ne DDB erzeugen.
    DDB in das temp. DC selektieren.
    Mittels StretchDIBits() die DIB in das temporäre DC und somit auf die DDB blitten.
    Fertig.

    Sowas hab ich zuletzt auf nem alten 400 mhz rechner gemacht, hat da noch bei ner 1024x768 Bitmap etwa 10ms später beim blitten der DDBs gegenüber der DIBs gebracht, ob das heutzutage wirklich noch was bringt glaube ich eigentlich auch nicht mehr wirklich.

    Nachteil natürlich: Es wird zwar später wenn du Glück hast (also nichtmal sicher) schnell, aber dafür dauert es natürlich vorher länger und frisst RAM.

    Wenn du die Daten zur Laufzeit irgendwoher beziehst und direkt anzeigen willst, bringt das rein gar nichts so.



  • Es sollen so ca. 20 Bilder pro Sekunde angezeigt werden (also ne Animation), die zur Laufzeit generiert werden.

    Also es funktioniert jetzt mit DrawDibDraw.
    Hab auch bleich mal die Performance im Vergleich zu StretchBlt getestet.

    mit StretchBlt braucht er für ein Bild 1024x1024 ca. 31-32 ms
    mit DrawDibDraw braucht er für ein Bild 1024x1024 ca. 15-16 ms

    was ja schon mal eine verbesserung ist. 🙂
    Werd demnächst mal testen, ob das mit SDL noch schneller geht.

    Vielen Dank erstmal für deine Hilfe und deine Zeit.
    Gruß stone.mk



  • Die BITMAPINFOSTRUKTUR kannste z.B. noch global machen bzw. aus der Zeichen-Funktion raushauen und einmal ausfüllen, dann frisst die Speicherreservierung dafür schonmal keine Zeit mehr, falls du das nicht sowieso schon machst.
    Vermutlich lässt sich am meisten Performance gewinnen, wenn du irgendwie den Zeichenbereich verkleinern kannst. Wenn sich das Bild z.B. nur oben rechts irgendwo ändert, sollte auch nur der geänderte Bereich neu gezeichnet werden und nicht gleich alles...



  • Die Bitmapinfostruktur mach ich nur einmal am Anfang.
    Leider ändert sich das Bild immer komplett, so das man da nix kleiner machen könnte.

    Hab jetzt noch bissel rumgetestet. Läuft ganz prima. Ist auch ein ganzes stück schneller geworden.

    Besten Dank für die Tips



  • Wenn du etwas Zeitkritisches vor hast, würde ich nicht die GDI benutzen. Zwar unterstützt dein Prozessor das Blitting sogar Hardwaremäßig, allerdings ist es trotzdem alles etwas langsam, da die Berechnungen hauptsächlich über den Prozessor laufen.
    Benutze am Besten eine Schnittstelle die die Grafikbeschleunigung deiner Grafikkarte nutzt wie z.B. DirectX. Der vorteil ist, dass während die Grafikkarte rechnet, der Prozessor bereits andere Dinge erledigen kann.

    DirectDraw gibt es nichtmehr, da es mit Direct3D zusammengelegt worden ist. Man kann aber nach wievor auf dessen Funktionen zugreifen. Ich denke mal wenn du nur 2 Dimensionale Bitmaps darstellen willst und das auch noch möglichst schnell, solltest du damit gut bedient werden.



  • Btw: Wie sieht die Performance im Vergleich zu BitBlit() aus?

    Ich habe eben mal damit rumgespielt, aber keine Verbesserung zwischen DrawDib und BitBlit feststellen können ..
    (Ich kannte die Möglichkeit bisher gar nicht.)


Anmelden zum Antworten