SetPixel() grausam langsam - gehts schneller?



  • Hallo zusammen,
    folgende Ausgangssituation:

    Ich habe ein Bild, in dem die Pixelinformation umkomprimiert vorliegen (KEIN Bitmap, sondern ein selbst gebautes Format).

    Diese Bildinformationen will ich in einer MFC Anwendung in einem Dialogfenster auf den Schirm schmeißen.

    Mein erster (naiver) Ansatz hierfür ist SetPixel über CClientDC und zwei for-Schleifen zu benutzen.
    Das ist aber grausam langsam - man kann quasi den Pixeln beim gemalt werden zugucken.

    Meine Frage ist daher, geht es irgendwie schneller, reine Pixelinformationen, die in einer Matrix vorliegen, auf dem Schirm darzustellen.

    Grüße und schon mal Danke für eventuelle Tips!



  • Das schnellste ist immer noch:
    GetDIBits



  • wenn ich das richtig sehe, braucht man für GetDIBits doch auch ein Bitmap, das ich nicht habe...

    int GetDIBits(
    HDC hdc, // handle to DC
    HBITMAP hbmp, // handle to bitmap
    UINT uStartScan, // first scan line to set
    UINT cScanLines, // number of scan lines to copy
    LPVOID lpvBits, // array for bitmap bits
    LPBITMAPINFO lpbi, // bitmap data buffer
    UINT uUsage // RGB or palette index
    );

    Mein Ausgangspunkt ist ja eben, daß ich die Pixelinformationen nur einer Matrix vorliegen habe und nicht als Bitmap.

    Mein Format sieht so aus:

    PIC MyPic[x][y];

    Kann ich das vorher in ein Bitmap umwandeln?
    Beim Bitmap liegen die Pixelinformationen ja auch unkomprimiert in einer Matrix vor...



  • Um eine Bitmap wirst du nicht drum rum kommen. Der CDC braucht nun mal ein Zeichenobjekt mit einer Reference auf das Pixelarray, außer du machst es mit SetPixel das geht langsam, aber du brauchst kein Zeichenobjekt dafür.

    Schau mal unter: http://atlc.sourceforge.net/bmp.html
    wegen des Bitmap-Daten-Formates.
    Ist warscheindlich am schnellsten wenn du es in eine Bitmap wandelst und mit dem Blit auf den Desktop, etc. donnerst.



  • mostrich schrieb:

    PIC MyPic[x][y];

    Was soll den PIC sein? Und warum verwendest Du jetzt SetPixel?
    Du solltest ein Bitmap mit der passenden grö0e und Farbtiefe anlegen und dann die Bits dort manipulieren. In den DC kannst Du das ganze mit BitBlt zeichnen...



  • Jochen Kalmbach schrieb:

    Was soll den PIC sein? Und warum verwendest Du jetzt SetPixel?

    Das ist wie schon erwähnt ein eigenes Format erstellt vom Lehrstuhl an der Uni!
    SetPixel verwende ich, da ich im Moment nichts besseres weiß...

    Wie kann ich denn aus den Pixelinformationen ein Bitmap anlegen?
    Wenn ich das schaffen würde, hätte ich ja gewonnen.



  • CreateBitmapIndirect ?



  • Hier mal ein Ansatz wie man das machen könnte.

    CBitmap *CreateBitmap(PCI ???)
    {
        CBitmap *Bitmap = new CBitmap();
        if(Bitmap)
        {
            Bitmap->CreateBitmap(nWidth,nHeight,1,32,NULL); //Breite und höhe stetzen
            	BITMAP     bm;
    	Bitmap->GetObject(sizeof(BITMAP), (LPSTR)&bm);
    
    	DWORD *pPixels = (DWORD*)new BYTE[ bm.bmWidthBytes*bm.bmHeight ];//allocate memory for image 
                                                  //byte buffer
            for(/*y*/)
    	{
    		for(/*x*/)
    		{
                        //Hier Pixel setzen
    		}
    	}
            dwValue = Bitmap->SetBitmapBits(bm.bmWidthBytes*bm.bmHeight,bmpBuffer);
    	delete[] pPixels ;
            return Bitmap;
        }
        return NULL;
    }
    

    Muß man natürlich noch anpassen! Das Bitmap kannste dann mit SelectObject in den DC selecten und blitten

    Gruß Matthias



  • Wow - danke!
    CreateBitmap und CreateBitmapIndirect hören sich schon sehr gut an!

    Geschenke shoppen kann aber ganz schön anstrengend sein - daher werde ich das Ganze erst morgen ausprobieren...



  • Oder CreateDIBSection. Wenn man Glück hat (hängt vom Treiber und Speicherstand ab), schreibt man da direkt in den Grafikspeicher.



  • Hallo,

    Ich habe ein Bild, in dem die Pixelinformation umkomprimiert vorliegen (KEIN >Bitmap, sondern ein selbst gebautes Format).
    Diese Bildinformationen will ich in einer MFC Anwendung in einem Dialogfenster >auf den Schirm schmeißen.
    Mein erster (naiver) Ansatz hierfür ist SetPixel über CClientDC und zwei >for-Schleifen zu benutzen.

    <vbg> ja, das habe ich auch mal vor langer Zeit so probiert.
    Wenn Du aber mal Terabyte großen Daten zu tun hast ist
    das etwas langsam ;-).

    Die GDI-Funktionen kannst Du alle vergessen. Die Einzig vernünftige
    Möglichkeit, solche Daten anzuzeigen ist als DIB (Device Independent
    Bitmap). Wenn dein PIC-Format halwebgs vernünftig ist, kannst Du vielleicht
    eine Klasse ableiten, die nur den PIC UND BITMAPV4HEADER Header hat und
    die Daten entsprechend mappt.

    Du musst dich allerdings fragen lassen, warum du das Rad bzw. das Bild
    neu erfinden willst? Gibt es wirklich GUTE GRÜNDE dafür? Jetzt wäre
    ein guter Teitpunkt dein Design nochmal kritisch zu überdenken!

    Ansonsten bleibt dir nur, ein DIB zu erstellen, dein PIC dort geeignet reinzukopieren und das anzuzeigen! Bitte nur 1:1 (BitBlt). Habe mich mal
    umn ein Pixel verrechnet und hatte einen Performanceeinbruch von
    über faktor 100!


Anmelden zum Antworten