BitBlt kann nur schwarzweiss



  • Hallo, ich versuche verzweifelt an schnelle Windows API - Graphik zu kommen. Aus irgendeinem Grunde kann er keine
    Farbe mit dem BitBlt Befehl machen. Es funktioniert nur mit einem nBitCount von 1 im Erzeuger
    der Bitmap-Datenstruktur mit CreateBitmap. Jeder anderer Parameter hat zur Folge, daß gar kein
    Bild kommt. Der direkte SetPixel - Befehl kann Farbe, nur der ist zu langsam. Ich habs unter MinGW/bin
    compiliert, aber auch mit Dev C++ probiert, es ist immer der gleiche Mist. Ich habe Windows 10. Weiss Jemand, woran es liegen könnte ?

      HWND    wnd = GetConsoleWindow();
       HDC     hdc = GetDC( wnd );
    
       char ImagAry[300000];
    
       for(int i=0; i<300000; i++) {  ImagAry[i] = 5;  };
    
       HBITMAP Imag = 
       CreateBitmap(
                300,     //  [in] int        nWidth,
                300,     //  [in] int        nHeight,
                  1,     //  [in] UINT       nPlanes,
                  1,     //  [in] UINT       nBitCount,
                 ImagAry //  [in] const VOID *lpBits
                  );
    
         HDC memDC = CreateCompatibleDC( hdc );
    
    
    
    	              //	HBITMAP hbmp = ske_CreateDIB32(mWidth, mHeight);
    
     HBITMAP holdbmp = (HBITMAP) SelectObject(memDC, Imag);            // hbmp);
    
     GetObject( (HGDIOBJ) Imag, sizeof( Imag ) , &Imag);
    for(int j=0; j<255; j+=26) 
      for(int i=0; i<255; i++) 
          SetPixel( memDC, i, j, RGB(200,i, 0) );
    
        if ( BitBlt( hdc, 4,4, 300, 300, memDC, 1, 1,  SRCCOPY)
           )    Kz('S');  // Selbstgemachter Konsolenoutput.
           else Kz('F');
    
      DeleteDC( memDC );
      DeleteObject( Imag );
    
       ReleaseDC( wnd , hdc);


  • Überprüfe mal den Rückgabewert (sowie Fehlerwert mittels GetLastError) von BitBlt.



  • @Th69 Der boolesche Rückgabewert von BitBlt war immer true, obwohl er gar nichts
    angezeigt hat.



  • Der GetLastError-Wert nach dem Aufruf von BitBlt war immer 0, egal ob er
    was angezeigt hat, oder nicht.



  • @rsobe sagte in BitBlt kann nur schwarzweiss:

    for(int i=0; i<300000; i++) { ImagAry[i] = 5; };

    Probiere doch mal bitte nBitCount auf 24 zu setzen und in ImagAry Zufallswerte zwischen 0 und 255 zu setzen.



  • @rsobe Du hast mein Beispiel von neulich noch?

    Wie @Quiche-Lorraine vorgeschlagen hat, sollte nBitCount schon 24 oder 32 sein. Letzteres macht die Adressierung etwas simpler und hat auch einen Alpha-Kanal für Transparenz (4. Byte jedes Pixels auf 0xff setzen für volle Deckraft/Sichtbarkeit).

    Bei 24 Bits auch die Dokumentation von CreateBitmap beachten:

    Each scan line in the rectangle must be word aligned (scan lines that are not word aligned must be padded with zeros)

    Ich bin mir nicht ganz sicher ob hier ein Windows-WORD (2 Bytes) oder ein CPU-Word (4 oder 8 Bytes) gemeint ist. Ich denke es ist ein Windows-WORD. In jedem Fall werden mit 24 Bit mindestens bei einer ungeraden width zusätzliche Padding-Bytes benötigt. Bei 32 Bits braucht man das nicht, die haben immer ein 4-Byte-Alignment.

    Und um einer eventuellen Folgefrage vorzubeugen: Windows-Bitmaps stehen im Speicher auf dem Kopf. In meinem Beispiel konnte ich in BITMAPINFO einfach eine negative Höhe angeben, damit das richtig herum angezeigt wird. Ich weiss nicht, ob das mit CreateBitmap auch funktioniert, aber das kannst du ja mal versuchen, wenn deine Pixel kopfüber angezeigt werden.



  • @Quiche-Lorraine sagte in BitBlt kann nur schwarzweiss:

    @rsobe sagte in BitBlt kann nur schwarzweiss:

    for(int i=0; i<300000; i++) { ImagAry[i] = 5; };

    Probiere doch mal bitte nBitCount auf 24 zu setzen und in ImagAry Zufallswerte zwischen 0 und 255 zu setzen.

    Hab ich gemacht, bringt nichts, es kommt nur schwarz weiss mit nBitCount == 1 oder
    gar keine Bildausgabe, bei jeder anderen Parameter-Einstellung. Das Farbdaten-Alignment habe ich natürlich erstmal ignoriert, für den Test. Dann
    greift er sich halt irgendwelche Daten. Aber es sollte wengistens erstmal schnell bunt werden.
    Macht er nicht, vielleicht hat die Bibliothek MinGW/lib/gdi32.a eine Macke ??

    Ich checke mal, was es mit BITMAPINFO auf sich hat.



  • @rsobe In meinem Beispiel damals habe ich auch das Bitmap mit CreateDIBSection erzeugt. Vor allem wegen

    The CreateDIBSection function creates a DIB that applications can write to directly.

    Die Pixeldaten, die man CreateBitmap übergibt, werden sehr wahrscheinlich nur für die einmalige Initialisierung verwendet. Nachträglich in ImagAry zu schreiben wird vermutlich das Bitmap nicht mehr verändern. ImagAry wird also bei CreateBitmap in das Bitmap kopiert, während ImagAry bei der CreateDIBSection-Variante zum Pixel-Speicher des Bitmaps gemacht wird.

    Das Pixelformat und die Dimensionen des Bitmap werden bei CreateDIBSection in der BITMAPINFO-Struktur definiert, die man der Funktion mit übergeben muss (als Pointer auf das struct).



  • @Finnegan sagte in BitBlt kann nur schwarzweiss:

    CreateDIBSection

    Danke das ist der Denkanstoß. In der HBITMAP -Struktur, die anscheinend gekapselt ist, steckt offensichtlich noch
    mehr drin, auch irgendwelche Farbinfos, das muss ich jetzt mal untersuchen.


Anmelden zum Antworten