Bitmap erstellen und speichern?



  • So nach 2 Stunden Google versuch ich es mal hier. Ich versuche ein neues Bitmap zu erstellen, Text reinzuschreiben und anschließend zu speichern. Code bisher:

    //create new bitmap
    HBITMAP hbitmap = CreateBitmap (48,48,4,8,NULL);
    
    BITMAP bm;
    GetObject (hbitmap, sizeof(BITMAP), &bm );
    long width=bm.bmWidth;
    long height=bm.bmHeight;
    
    //prepare the bitmap attributes
    BITMAPINFO bmInfo;
    memset(&bmInfo.bmiHeader,0,sizeof(BITMAPINFOHEADER));
    bmInfo.bmiHeader.biSize=sizeof(BITMAPINFOHEADER);
    bmInfo.bmiHeader.biWidth=width;
    bmInfo.bmiHeader.biHeight=height;
    bmInfo.bmiHeader.biPlanes=1;
    bmInfo.bmiHeader.biBitCount=24;
    //create a temporary dc in memory.
    HDC pDC = ::GetDC(0);
    HDC TmpDC=CreateCompatibleDC(pDC);
    //create a new bitmap and select it in the memory dc
    BYTE *pbase;
    HBITMAP TmpBmp=CreateDIBSection(pDC,
    	&bmInfo,DIB_RGB_COLORS,(void**)&pbase,0,0);
    HGDIOBJ TmpObj=SelectObject(TmpDC,TmpBmp);
    
    //draw the background
    HDC dcBmp=CreateCompatibleDC(TmpDC);
    HGDIOBJ TmpObj2 = SelectObject(dcBmp,hbitmap);
    BitBlt(TmpDC,0,0,width,height,dcBmp,0,0,SRCCOPY);
    SelectObject(TmpDC,TmpObj2);
    DeleteDC(dcBmp);
    
    //choose the font
    CFont m_Font;
    LOGFONT* m_pLF;
    m_pLF=(LOGFONT*)calloc(1,sizeof(LOGFONT));
    strncpy(m_pLF->lfFaceName,"Times New Roman",31);
    m_pLF->lfHeight=64;
    m_pLF->lfWeight=600;
    m_pLF->lfItalic=1;
    m_pLF->lfUnderline=0;
    m_Font.CreateFontIndirect(m_pLF);
    
    //select the font in the dc
    CDC dc;
    dc.Attach(TmpDC);
    CFont* pOldFont=NULL;
    if (m_Font.m_hObject) 
    	pOldFont = dc.SelectObject(&m_Font);
    else 
    	dc.SelectObject(GetStockObject(DEFAULT_GUI_FONT));
    
    //Set text color
    dc.SetTextColor(RGB(60,120,240));
    //Set text position;
    RECT pos = {40,40,0,0};
    //draw the text
    dc.SetBkMode(TRANSPARENT);
    dc.DrawText("Test",4,&pos,DT_CALCRECT);
    dc.DrawText("Test",4,&pos,0);
    
    //cleanup 
    if (pOldFont) dc.SelectObject(pOldFont);
    m_Font.DeleteObject();
    dc.Detach();
    free(m_pLF);
    
    DeleteObject(hbitmap);
    hbitmap=TmpBmp;
    
    //final cleanup
    SelectObject(TmpDC,TmpObj);
    DeleteDC(TmpDC);
    

    So weit so gut nur weiß ich nicht wie man das ganze jetzt als bmp-Datei abspeichert. Ich finde weder in der MSDN, noch bei Google oder hier im Forum eine halbwegs verständliche Lösung. Muss man dazu eine externe Bibliothek verwenden? Entwicklungsumgebung ist Visual Studio .NET 2003





  • Danke erstmal für die Hilfe.
    So viel zum Thema das gäbe es nicht *hust*

    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;
    }
    

    Wenn ich dem irgendeinen Pfad, TmpDC und hbitmap übergebe krieg ich zwar ein Bild, das ist aber einfach nur schwarz. Was mach ich falsch?



  • Hmm, vielleicht übergibst du das falsche HDC, versuchs mal mit pDC vom Typ HDC...

    Gruß
    :: NoName ::



  • Nö gibt das gleiche Verhalten. Ich poste einfach mal den gesamten Code:

    // Paar Standard-Header und uninteressante defines
    // Function prototypes
    void GenerateBitmap ();
    BOOL WriteBitmap (LPTSTR szFile, HBITMAP hbitmap, HDC memdc);
    
    int _tmain(int argc, TCHAR* argv[], TCHAR* envp[])
    {
    	int nRetCode = 0;
    
    	// MFC initialisieren und drucken. Bei Fehlschlag Fehlermeldung aufrufen.
    	if (!AfxWinInit(::GetModuleHandle(NULL), NULL, ::GetCommandLine(), 0))
    	{
    		// TODO: Passen Sie den Fehlercode an Ihre Anforderungen an
    		_tprintf(_T("Schwerwiegender Fehler: MFC-Initialisierung fehlgeschlagen\n"));
    		nRetCode = 1;
    	}
    	else
    	{
    		GenerateBitmap();
    	}
    
    	return nRetCode;
    }
    
    void GenerateBitmap ()
    {
    	//create new bitmap
    	HBITMAP hbitmap = CreateBitmap (48,48,4,8,NULL);
    
    	BITMAP bm;
    	GetObject (hbitmap, sizeof(BITMAP), &bm );
    	long width=bm.bmWidth;
    	long height=bm.bmHeight;
    
    	//prepare the bitmap attributes
    	BITMAPINFO bmInfo;
    	memset(&bmInfo.bmiHeader,0,sizeof(BITMAPINFOHEADER));
    	bmInfo.bmiHeader.biSize=sizeof(BITMAPINFOHEADER);
    	bmInfo.bmiHeader.biWidth=width;
    	bmInfo.bmiHeader.biHeight=height;
    	bmInfo.bmiHeader.biPlanes=1;
    	bmInfo.bmiHeader.biBitCount=24;
    
    	//create a temporary dc in memory.
    	HDC pDC = ::GetDC(0);
    	HDC TmpDC=CreateCompatibleDC(pDC);
    
    	//create a new bitmap and select it in the memory dc
    	BYTE *pbase;
    	HBITMAP TmpBmp=CreateDIBSection(pDC,
    	&bmInfo,DIB_RGB_COLORS,(void**)&pbase,0,0);
    	HGDIOBJ TmpObj=SelectObject(TmpDC,TmpBmp);
    
    	//draw the background
    	HDC dcBmp=CreateCompatibleDC(TmpDC);
    	HGDIOBJ TmpObj2 = SelectObject(dcBmp,hbitmap);
    	BitBlt(TmpDC,0,0,width,height,dcBmp,0,0,SRCCOPY);
    	SelectObject(TmpDC,TmpObj2);
    	DeleteDC(dcBmp);
    
    	//choose the font
    	CFont m_Font;
    	LOGFONT* m_pLF;
    	m_pLF=(LOGFONT*)calloc(1,sizeof(LOGFONT));
    	strncpy(m_pLF->lfFaceName,"Times New Roman",31);
    	m_pLF->lfHeight=64;
    	m_pLF->lfWeight=600;
    	m_pLF->lfItalic=1;
    	m_pLF->lfUnderline=0;
    	m_Font.CreateFontIndirect(m_pLF);
    	//select the font in the dc
    	CDC dc;
    	dc.Attach(TmpDC);
    	CFont* pOldFont=NULL;
    	if (m_Font.m_hObject) 
    		pOldFont = dc.SelectObject(&m_Font);
    	else 
    		dc.SelectObject(GetStockObject(DEFAULT_GUI_FONT));
    	//Set text color
    	dc.SetTextColor(RGB(60,120,240));
    	//Set text position
    	RECT pos = {40,40,0,0};
    	//draw the text
    	dc.SetBkMode(TRANSPARENT);
    	dc.DrawText("Test",4,&pos,DT_CALCRECT);
    	dc.DrawText("Test",4,&pos,0);
    
    	//cleanup 
    	if (pOldFont) dc.SelectObject(pOldFont);
    	m_Font.DeleteObject();
    	dc.Detach();
    	free(m_pLF);
    
    	WriteBitmap ("Tmp.bmp", hbitmap, pDC);
    
    	DeleteObject(hbitmap);
    	hbitmap=TmpBmp;
    
    	//final cleanup
    	SelectObject(TmpDC,TmpObj);
    	DeleteDC(TmpDC);
    }
    
    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;
    }
    

    Vielleicht ist es auch einfach schon zu sehr Freitag und ich bin blind 😃



  • Keiner eine Idee? Bin mittlerweile schon etwas verzweifelt.



  • Versuch es mal mit allen DC die du hast, irgendeiner muss doch gehen...(TmpDC)



  • Nein ich glaub ich mach grundsätzlich was falsch. Hab jetzt mal die DC2Bitmap Funktion hergenommen und ähnliche Ergebnisse. Anscheinend komm ich nicht drum herum dieses ganze GDI Zeug zu lernen bevor ich es gebacken kriege.

    Wenn jemand helfen will: Ich brauch Code der mir ein neues Bitmap erstellt (irgendein kleines Ding) und mit einem Standardfont Text reinschreibt. Anschließend das ganze als Bmp-Datei (monochrom) speichern. Nichts mit Transparenz, Kompresssion oder sonst was nur stupides 48x48 bmp mit Text drin.



  • Kurze Auflösung für alle Interessierten:
    Bibliothek runterladen:
    http://www.codeproject.com/bitmap/cximage.asp

    Alternativer Code:

    void GenerateBitmap ()
    {
    	//Create a new image
    	CxImage image;
    	image.Create(640,480,24,CXIMAGE_FORMAT_BMP);
    
    	if (image.IsValid())
    	{
    		//Preparing 
    		long width = image.GetWidth();
    		long height = image.GetHeight();
    		BITMAPINFO bmInfo;
    		memset(&bmInfo.bmiHeader,0,sizeof(BITMAPINFOHEADER));
    		bmInfo.bmiHeader.biSize =sizeof(BITMAPINFOHEADER);
    		bmInfo.bmiHeader.biWidth = width;
    		bmInfo.bmiHeader.biHeight = height;
    		bmInfo.bmiHeader.biPlanes = 1;
    		bmInfo.bmiHeader.biBitCount = 24;
    
    		BYTE *pbase; //points to the final dib
    		//get the background
    		HDC pDC = ::GetDC(0);
    		HDC TmpDC = CreateCompatibleDC(pDC);
    		HBITMAP TmpBmp = CreateDIBSection(pDC,&bmInfo,DIB_RGB_COLORS,(void**)&pbase,0,0);
    		HGDIOBJ TmpObj = SelectObject(TmpDC,TmpBmp);
    		//draw the background
    		image.Draw(TmpDC);
    		//choose the font
    		CFont m_Font;
    		LOGFONT* m_pLF;
    		m_pLF=(LOGFONT*)calloc(1,sizeof(LOGFONT));
    		strncpy(m_pLF->lfFaceName,"Times New Roman",31);
    		m_pLF->lfHeight=64;
    		m_pLF->lfWeight=600;
    		m_pLF->lfItalic=1;
    		m_pLF->lfUnderline=0;
    		m_Font.CreateFontIndirect(m_pLF);
    
    		//select the font in the dc
    		CDC dc;
    		dc.Attach(TmpDC);
    		CFont* pOldFont=NULL;
    		if (m_Font.m_hObject) pOldFont = dc.SelectObject(&m_Font);
    		else dc.SelectObject(GetStockObject(DEFAULT_GUI_FONT));
    
    		//Set text color
    		dc.SetTextColor(RGB(60,120,240));
    		//Set text position;
    		RECT pos = {40,40,0,0};
    		//draw the text
    		dc.SetBkMode(TRANSPARENT);
    		dc.DrawText("Test",4,&pos,DT_CALCRECT);
    		dc.DrawText("Test",4,&pos,0);
    
    		//cleanup 
    		if (pOldFont) dc.SelectObject(pOldFont);
    		m_Font.DeleteObject();
    		dc.Detach();
    		free(m_pLF);
    
    		//transfer the result in the image
    		CxImage tmpimage;
    		tmpimage.CreateFromHBITMAP(TmpBmp);
    		tmpimage.DecreaseBpp(image.GetBpp(),0,image.GetPalette());
    		image.Transfer(tmpimage);
    		image.Save("tmp.bmp", CXIMAGE_FORMAT_BMP); 
    
    		//cleanup
    		DeleteObject(SelectObject(TmpDC,TmpObj));
    		DeleteDC(TmpDC);
    	}
    }
    

Anmelden zum Antworten