Bitmap erstellen und füllen...



  • hallo!

    ich hab schon das forum durchforstet aber keinen konkreten ansatz gefunden...

    folgendes problem:
    in einem bestehenden programm werden messergebnisse in einem 32x32 pixel grossen feld dargestellt. dieses feld möchte ich nun in eine bitmap datei schreiben. an die einzelnen pixelfarben komme ich dran, darum geht es mir nicht.

    am besten wäre, wenn jemand nen konkreten kurzen code posten könnte, der:
    - ein bitmap mit dem dateinamen "Dateiname" und 8bit farbtiefe erstellt
    - und dazu einfach den simplen befehl um ein pixel mit rgb-farbe hineinzuschreiben

    besten dank!



  • Schau mal bei Google nach BITMAPINFOHEADER, BITMAPFILEHEADER

    da müßtest du einiges Finden was dir auch Codebespiele gibt.

    Im Grunde ist eine Bitmapdatei wie folgt aufgebaut:
    - BITMAPFILEHEADER
    - BITMAPINFOHEADER
    - evtl Farbpalette
    - RGB Bildpunkte

    Du musst halt schauen was für Variablen die Strukturen BITMAPINFOHEADER usw haben und diese dann entsprechend anpassen bevor du sie in eine Datei schreibst.



  • Hallo,
    schau dir mal die Klassen CPaintDC/ CDC und CBitmap an. Du erstellst einen DC
    malst in ihn und verbindest ihn dann mit dem Bitmap.
    Turbobrain



  • 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.


Anmelden zum Antworten