Bitmap erstellen und füllen...



  • Hi

    Dieses feld möchte ich nun in eine bitmap datei schreiben.

    Sobald du das Bitmap in einem DC hast, kannst du es mit folgender Funktion in eine .bmp Datei schreiben:

    BOOL WriteBitmap( LPTSTR szFile, HBITMAP hbitmap, HDC memdc)
    {
      	BITMAP  bmp;
      	if(GetObject(hbitmap, sizeof(BITMAP), &bmp))
      	{
        	BITMAPINFOHEADER BmpInfoHdr;
     	BITMAPFILEHEADER BmpFileHdr;
             BmpInfoHdr.biSize = sizeof(BITMAPINFOHEADER);
        	BmpInfoHdr.biWidth = bmp.bmWidth;
    	BmpInfoHdr.biHeight = bmp.bmHeight;
        	BmpInfoHdr.biPlanes = bmp.bmPlanes;
    	BmpInfoHdr.biBitCount = 24;
        	BmpInfoHdr.biCompression    = BI_RGB;
             BmpInfoHdr.biSizeImage        = bmp.bmWidth*bmp.bmHeight*3;
             BmpFileHdr.bfType        = 0x4d42;
             BmpFileHdr.bfReserved1        = 0;
             BmpFileHdr.bfReserved2        = 0;
             BmpFileHdr.bfOffBits = sizeof(BITMAPFILEHEADER)+sizeof (BITMAPINFOHEADER);
            BmpFileHdr.bfSize = BmpFileHdr.bfOffBits+BmpInfoHdr.biSizeImage;
            bmp.bmBits = (void*)GlobalAlloc(GMEM_FIXED, BmpInfoHdr.biSizeImage);
            if(GetDIBits(memdc, hbitmap, 0, BmpInfoHdr.biHeight, bmp.bmBits, (BITMAPINFO*)&BmpInfoHdr, DIB_RGB_COLORS) == BmpInfoHdr.biHeight)
            {
                HANDLE hFile = CreateFile(szFile, GENERIC_READ | GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL,NULL);
                if(hFile != INVALID_HANDLE_VALUE)  {
                DWORD dwTmp;
                WriteFile(hFile, &BmpFileHdr, sizeof(BITMAPFILEHEADER), &dwTmp, NULL);
                WriteFile(hFile, &BmpInfoHdr, sizeof(BITMAPINFOHEADER), &dwTmp, NULL);
                WriteFile(hFile, bmp.bmBits,  BmpInfoHdr.biSizeImage,   &dwTmp, NULL);
            }
        	CloseHandle(hFile);
        }
        GlobalFree(bmp.bmBits);
        return TRUE;
      }
      return FALSE;
    }
    

    Grüße Rapha



  • danke, so sollte das wohl klappen...

    wenn ich das bestehende dc als memdc übergebe, was übergebe ich dann als hbitmap?



  • Hi,

    Angenommen du hast ein CDC Objekt mit dem Inhalt den du speichern willst.
    Erstelle noch ein 2. CDC (mit CreateCompatible... auf dein 1. CDC) und ein CBitmap Objekt. Wähle jetzt als "Ziel" für dein 2. CDC das Bitmap (=>SelectObject). Kopiere (=>Blit) jetz den Inhalt des 1. CDCs in das 2.

    Jetzt hast du das Bitmap und das DC, das du für die Funktion brauchst.

    Grüße Rapha



  • problem: das programm stürzt an folgender stelle ab

    CPaintDC dc(this);  //bestehendes CPaintDC
    CDC memdc;
    CBitmap hbitmap;
    
    memdc.CreateCompatibleDC(&dc);   // hier stürzt es ab!
    


  • weiß denn niemand rat? es eilt doch... 😞



  • Hast du es mal mit 2 CDC's versucht?



  • die funktion die in das CPaintDC zeichnet existiert halt schon. wie würde ich denn dann dieses in ein CDC umwandeln?



  • Es müsste so was sein wie:

    CDC* pDC = CDC::CreateDC(dc.m_hDC);
    

    Birgt aber gewisse Risiken, weil pDC dann nur noch temporär ist (laut MSDN).
    Ich bin immer noch am rätseln, ob dass, was ich weiter oben vorgeschlagen habe eigentlich Sinn macht, weil man doch eigentlich ein CPaintDC übergeben können müsste, auch wenn ein CDC gefragt ist, denn schließlich ist doch CPaintDC von CDC abgeleitet. Meistens geht das so auf jeden Fall. Nur manchmal nicht 😕 . Versuchs doch mal.



  • es ist jetzt folgendermassen:

    CPaintDC dc(this);
    CBitmap hbitmap;
    dc.SelectObject(&hbitmap);
    
    //das dc wird gefüllt
    
    WriteBitmap("test.bmp",hbitmap,dc); //obige funktion
    

    und es läuft net... GetObject liefert immer FALSE!



  • Ich muss mich korrigieren. Es muss natürlich FromHandle sein und nicht CreateDC. Was mir noch so aufgefallen ist, ist, dass du ein CBitmap an WriteBitmap übergibst, obwohl nen HBITMAP gefragt ist. Schreib doch mal:

    (HBITMAP) hbitmap
    

    (siehe MSDN).



  • ne also irgendwie liefert GetObject immer 0 😡



  • Du könntest dir mit GetLastError() ne brauchbare Fehlermeldung holen.



  • ich versteh dieses GetObject nicht...

    CPaintDC dc(this); // device context for painting
    CDC memdc;
    memdc.CreateCompatibleDC(&dc);
    CBitmap bitmap;
    memdc.SelectObject(&bitmap);
    
    dc.BitBlt(0,0,180,180,&memdc,0,0,SRCCOPY);
    BITMAP bmp;
    if (GetObject((HBITMAP)bitmap, sizeof(BITMAP), &bmp)==0) AfxMessageBox("nuuuuuuull");
    

    es gibt immer 0 aus obwohl doch alles wunderbar sein sollte? GetLastError gibt auch nur nen Zahlenwust aus.



  • Das GetObject packt den Inhalt von bitmap in bmp. Geh mal mit der Zahl von GetLastError in die MSDN-Suchfunktion oder -Inhaltsfunktion, dort gibt es eine Tabelle, da steht mehr drin.



  • ne, unter 1240568 findet er da nix...



  • Hab den Code grad ausprobiert, weil ich ein ähnliches Problem hab. Bei mir liefert GetObject auch immer 0.



  • Ich mach dass immer so:

    ......
    .......
    .......
    int error=GetLastError();
    CString str;
    str.Format("%d",error);
    MessageBox(str);

    Mit der Zahl findet man auch was.



  • Die Tabelle findet man unter Win32 API unter Error Codes im MSDN Inhalt. Geht allerdings nur bis 11031, wohl wahr.



  • Vielleicht mach ich auch was komplett falsch. So ruf ich übrignes die Funktion auf:

    CDC pDC;
    pDC.CreateCompatibleDC(m_Graph.GetDC());
    CBitmap CBmp;
    pDC.SelectObject(&CBmp);
    CRect rect;
    m_Graph.GetWindowRect(&rect);
    pDC.BitBlt(0,0,rect.right,rect.bottom,m_Graph.GetDC(),0,0,0);
    WriteBitmap(FileName,(HBITMAP)CBmp,pDC);
    

    Vielleicht liegt ja da schon der Fehler.
    Mit GetLastError bekomm ich übrigens 0 raus, also eigentlich kein Fehler. Aber trotzdem gibt GetObject 0. hmmmm....

    Phips!



  • ich hab jetzt

    CBitmap bitmap;
    

    durch

    HBITMAP bitmap=CreateCompatibleBitmap(dc, 32, 32);
    

    ersetzt und es scheint besser. allerdings ist mein bitmap komplett schwarz...


Anmelden zum Antworten