Bitmap laden, aber transparente farbe ??



  • Öhm, also entweder ich steh voll daneben oder keiner hat bisher in den MFC-FAQ danach gesucht.



  • Zu CrazyOwl:
    Entweder bin ich wirklich blind, oder das Thema existiert nicht in der FAQ. Daher werde ich die Frage von Red Skall beantworten.

    Zu turbobrain:
    Dein Vorschlag ist zwar sehr gut, entspricht aber nicht dem Präfix deines Benutzernamens - besonders nicht wenn große Bilder transparent gestaltet werden sollen.

    Beantwortung der Urprungs-Frage:
    Wenn du Bilder transparent anzeigen lassen willst, empfehlen sich dazu oft nur Bitmaps (*.bmp), da GIFs oder JPGs häufig einen mehrfarbigen Hintergrund enthalten, der aufgrund der Kompression entsteht. Daher lässt sich der Hintergrund nur schwer transparent zeichnen. Bitmaps läd man schnell wie gefolgt:

    CString szFileName = "C:\\MyBitmapFile.bmp";
    HBITMAP hBmp = (HBITMAP)::LoadImage(AfxGetInstanceHandle(), szFileName, IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE | LR_CREATEDIBSECTION);
    

    Wenn du das Bitmap-Handle hast, rufst du die unten stehende Funktion auf. Erklärung der Parameter:
    pDC: Gerätekontext, auf den du das Bild zeichnen willst
    hBmp: Handle deines Bitmaps
    x,y: Obere linke Ecke des "neuen" Bildes
    crColour: Transparente Farbe, z.B. RGB(0, 0, 255) für blau

    Die Funktion:

    void DrawTransparent(CDC * pDC, HBITMAP hBmp, int x, int y, COLORREF crColour)
    {
     COLORREF crOldBack = pDC->SetBkColor(m_crWhite);
     COLORREF crOldText = pDC->SetTextColor(m_crBlack);
     CBitmap pMyBitmap;
     CDC dcImage, dcTrans;
    
     // Attach bitmap
     pBitmap.Attach(hBmp);
    
     // Create two memory dcs for the image and the mask
     dcImage.CreateCompatibleDC(pDC);
     dcTrans.CreateCompatibleDC(pDC);
    
     // Select the image into the appropriate dc
     CBitmap* pOldBitmapImage = dcImage.SelectObject(this);
    
     // Create the mask bitmap
     CBitmap bitmapTrans;
     int nWidth = Width();
     int nHeight = Height();
     bitmapTrans.CreateBitmap(nWidth, nHeight, 1, 1, NULL);
    
     // Select the mask bitmap into the appropriate dc
     CBitmap* pOldBitmapTrans = dcTrans.SelectObject(&bitmapTrans);
    
     // Build mask based on transparent colour
     dcImage.SetBkColor(crColour);
     dcTrans.BitBlt(0, 0, nWidth, nHeight, &dcImage, 0, 0, SRCCOPY);
    
     // Do the work - True Mask method - cool if not actual display
     pDC->BitBlt(x, y, nWidth, nHeight, &dcImage, 0, 0, SRCINVERT);
     pDC->BitBlt(x, y, nWidth, nHeight, &dcTrans, 0, 0, SRCAND);
     pDC->BitBlt(x, y, nWidth, nHeight, &dcImage, 0, 0, SRCINVERT);
    
     // Restore settings
     dcImage.SelectObject(pOldBitmapImage);
     dcTrans.SelectObject(pOldBitmapTrans);
     pMyBitmap.Detach();
     pDC->SetBkColor(crOldBack);
     pDC->SetTextColor(crOldText);
    }
    

    ____________________________________________________
    PS: Sollte das Thema transparente Bilder tatsächlich nicht in der FAQ stehen, empfehle ich dieses Thema dort hineinzustellen.



  • Zwei kleine Fehler im 2. Code!

    FALSCH: pBitmap.Attach(hBmp);
    RICHTIG: pMyBitmap.Attach(hBmp);

    FALSCH: CBitmap* pOldBitmapImage = dcImage.SelectObject(this);
    RICHTIG: CBitmap* pOldBitmapImage = dcImage.SelectObject(&pMyBitmap);

    ____________________________________________________
    Ich bitte um Verständnis!



  • Hab ich das Problem etwa völlig falsch verstanden, naja jedenfalls das ist das was ich gemeint hab:
    http://www.c-plusplus.net/forum/viewtopic.php?t=39066



  • 1000 dank, das hilft bestimmt. ich probiers gleich mal aus 😃 😉 :p 🕶 😋

    habs gerade ausprobiert, es läuft ^^



  • Hallo!

    Wollte gerade mal die Funktion nachvollziehen, aber es hagelt insgesamt fünf Fehlermeldungen:
    error C2065: 'm_crWhite' : nichtdeklarierter Bezeichner
    error C2065: 'm_crBlack' : nichtdeklarierter Bezeichner
    error C2065: 'Width' : nichtdeklarierter Bezeichner
    error C2065: 'Height' : nichtdeklarierter Bezeichner
    error C2664: 'DrawTransparent' : Konvertierung des Parameters 1 von 'class CPaintDC' in 'class CDC *' nicht moeglich
    Kein benutzerdefinierter Konvertierungsoperator verfuegbar, der diese Konvertierung durchfuehren kann, oder der Operator kann nicht aufgerufen werden
    Fehler beim Ausführen von cl.exe.

    Ich hab das ganze im OnPaint-Ereignis aufegerufen:

    CPaintDC dc(this); // device context for painting
    
    	// TODO: Code für die Behandlungsroutine für Nachrichten hier einfügen
    	// Transparentes Bitmap erzeugen
    	HBITMAP hbitmap = ::LoadBitmap(m_hInstance,MAKEINTRESOURCE(IDB_BOSCH));
    	DrawTransparent(dc,hbitmap,20,20,RGB(0,0,255));
    


  • habs so gemacht:

    void CProgramm::DrawTransparent(CDC * pDC, HBITMAP hBmp)
    {
    int x = 110; // standart parameter
    int y = 110; // standart parameter
    COLORREF crColour; // standart parameter
    CRect rc;

    GetClientRect(rc);

    crColour = crTransparent;

    COLORREF crOldBack = pDC->SetBkColor(RGB(255, 255, 255));
    COLORREF crOldText = pDC->SetTextColor(RGB(0, 0, 0));
    CBitmap pMyBitmap;
    CDC dcImage, dcTrans;

    // Attach bitmap
    pMyBitmap.Attach(hBmp);

    // Create two memory dcs for the image and the mask
    dcImage.CreateCompatibleDC(pDC);
    dcTrans.CreateCompatibleDC(pDC);

    // Select the image into the appropriate dc
    CBitmap* pOldBitmapImage = dcImage.SelectObject(&pMyBitmap);

    // Create the mask bitmap
    CBitmap bitmapTrans;
    int nWidth = rc.Width();
    int nHeight = rc.Height();
    bitmapTrans.CreateBitmap(nWidth, nHeight, 1, 1, NULL);

    // Select the mask bitmap into the appropriate dc
    CBitmap* pOldBitmapTrans = dcTrans.SelectObject(&bitmapTrans);

    // Build mask based on transparent colour
    dcImage.SetBkColor(crColour);
    dcTrans.BitBlt(0, 0, nWidth, nHeight, &dcImage, 0, 0, SRCCOPY);

    // Do the work - True Mask method - cool if not actual display
    pDC->BitBlt(x, y, nWidth, nHeight, &dcImage, 0, 0, SRCINVERT);
    pDC->BitBlt(x, y, nWidth, nHeight, &dcTrans, 0, 0, SRCAND);
    pDC->BitBlt(x, y, nWidth, nHeight, &dcImage, 0, 0, SRCINVERT);

    // Restore settings
    dcImage.SelectObject(pOldBitmapImage);
    dcTrans.SelectObject(pOldBitmapTrans);
    pMyBitmap.Detach();
    pDC->SetBkColor(crOldBack);
    pDC->SetTextColor(crOldText);
    }

    und so hab ich das programm aufgerufen:

    CDC *MPdc = GetDC();

    ((CWhiteEvalDlg*)GetParent())->DrawTransparent(MPdc, hBmp);

    die werte für transparenz uns x, y mußte ändern, ist ja klar
    und das mit 'CRect rc' hab ich erstmal so gemacht zum testen. aber die größe vom bitmap hab ich noch nicht raus



  • Red Skall schrieb:

    habs so gemacht:

    void CProgramm::DrawTransparent(CDC * pDC, HBITMAP hBmp)
    {
    int x = 110; // stan**** parameter
    int y = 110; // stan**** parameter
    COLORREF crColour; // stan**** parameter
    CRect rc;

    GetClientRect(rc);

    crColour = RGB(10, 10, 10); // das ist jetzt die transparente farbe

    COLORREF crOldBack = pDC->SetBkColor(RGB(255, 255, 255));
    COLORREF crOldText = pDC->SetTextColor(RGB(0, 0, 0));
    CBitmap pMyBitmap;
    CDC dcImage, dcTrans;

    // Attach bitmap
    pMyBitmap.Attach(hBmp);

    // Create two memory dcs for the image and the mask
    dcImage.CreateCompatibleDC(pDC);
    dcTrans.CreateCompatibleDC(pDC);

    // Select the image into the appropriate dc
    CBitmap* pOldBitmapImage = dcImage.SelectObject(&pMyBitmap);

    // Create the mask bitmap
    CBitmap bitmapTrans;
    int nWidth = rc.Width();
    int nHeight = rc.Height();
    bitmapTrans.CreateBitmap(nWidth, nHeight, 1, 1, NULL);

    // Select the mask bitmap into the appropriate dc
    CBitmap* pOldBitmapTrans = dcTrans.SelectObject(&bitmapTrans);

    // Build mask based on transparent colour
    dcImage.SetBkColor(crColour);
    dcTrans.BitBlt(0, 0, nWidth, nHeight, &dcImage, 0, 0, SRCCOPY);

    // Do the work - True Mask method - cool if not actual display
    pDC->BitBlt(x, y, nWidth, nHeight, &dcImage, 0, 0, SRCINVERT);
    pDC->BitBlt(x, y, nWidth, nHeight, &dcTrans, 0, 0, SRCAND);
    pDC->BitBlt(x, y, nWidth, nHeight, &dcImage, 0, 0, SRCINVERT);

    // Restore settings
    dcImage.SelectObject(pOldBitmapImage);
    dcTrans.SelectObject(pOldBitmapTrans);
    pMyBitmap.Detach();
    pDC->SetBkColor(crOldBack);
    pDC->SetTextColor(crOldText);
    }

    und so hab ich das programm aufgerufen:

    CDC *MPdc = GetDC();

    ((CWhiteEvalDlg*)GetParent())->DrawTransparent(MPdc, hBmp);

    die werte für transparenz uns x, y mußte ändern, ist ja klar
    und das mit 'CRect rc' hab ich erstmal so gemacht zum testen. aber die größe vom bitmap hab ich noch nicht raus



  • Hallo, ich bin's noch mal.

    Erstmal: Entschuldigung für die 5 Fehler, Phips!. Den Quelltext hatte ich aus einer eigenen Klasse kopiert, ohne an die Ausdrücke zu denken, die dort zwar definiert sind, 'global' aber ungültig sind. Zwar sind die Fehler von den Kollegen fast behoben worden, aber trotzdem möchte ich sie dir noch mal der Reihe nach verbessern:

    1. Ersetze m_crWhite durch RGB(255, 255, 255)
    2. Ersetze m_crBlack durch RGB(0, 0, 0)
    3. Ersetze Width() durch die Breite des Bildes
    4. Ersetze Height() durch die Höhe des Bildes
    5. Ändere deinen Code um in:
    CPaintDC dc(this); // device context for painting 
    
    // Transparentes Bitmap erzeugen 
     HBITMAP hbitmap = ::LoadBitmap(m_hInstance,MAKEINTRESOURCE(IDB_BOSCH)); 
     DrawTransparent(&dc, hbitmap, 20, 20, RGB(0,0,255));
    

    zu 3) und 4): Du kannst auch einfach zwei neue Parameter zur Funktion geben, die Breite und Höhe des Bildes erwarten.

    ________________________________________________________________
    Ich bitte erneut um Verständnis und hoffe, dass nun alles läuft!



  • Danke!
    Jetzt klappts auch bei mir! 🙂



  • jetzt hab ich wieder was neues:
    ich habe jetzt alle bilder auf mein dialogfeld gezeichnet. wenn ich jetzt aber irgend ein neues bild zeichnen will, kommt einfach ein scharzes feld !?
    ich hab erstmal ein buschen rumprobiert, aber auch wenn ich ein bild nehme, was noch nicht geöffnet ist, kommt ein schwarzes feld !?

    ich hab keine ahnung was das ist 😕



  • Hallo,
    ich habe die Unteraltung verfolgt und dann ausprobiert, ob es auch bei mir klappt. Ich habe ein Dialogfeldbasierende Anwendung erstellt. Sie lässt sich ohne Fehler kompilieren. Aber wenn ich das Bild anzeigen will (beim Klicken auf einen Button) zeigt er nichts. Woran kann das liegen?
    Turbobrain



  • @ turbobrain: zeigt er ne fehlermeldung an oder macht er einfach nichts ?? vielleicht haste kein ereignis auf dein button hinzugefügt 😃 . Scherz, aber beschreib bitte etwas genauer. könnte mir nähmlich vorstellen das du einfach einen total dummen fehler gemacht hast oder was übersehen hast, so ist es bei mir ziemlich oft !!

    (hat auch einer ne antwort auf meine frage nur so nebenbei ??)



  • ich habe keine ahnung was ich an meinen code gemacht habem aber auf einmal geht es ^^ *freu* 🙂 😃 😉 👍 💡
    jetzt kommt das bitmap was ich haben will !!

    jetzt brauchen wir nur noch ne antwort für turbobrain 😃



  • Hallo Red Skall,
    du wolltest eine Beschreibung meines Problems.
    Also ich habe den Code der hier im Beitrag geschrieben wurde übernommen und die Variablen angepasst. Dann habe ich das Bitmap mit LoadBitmap geladen, und dann DrawTransparence aufgerufen wie du, nur mit allen Parametern.
    Wenn ich das Programm ausführe wird kein Fehler angezeigt, doch wenn ich dann auf den Button drücke um das Bild anzuzeigen, passiert nichts.
    Bitte um Hilfe.
    Turbobrain 😃



  • probiers mal mit

    HBITMAP hBmp;
    // erst noch das bitmap laden ...
    DrawTransparent(GetDC(), hBmp);
    

    oder falls du das getan hast ruf das mal in OnPaint() auf und nimm den schon in OnPaint() erzeugten DC (CDC dc).

    vielleicht klappts. könnte mir nichts anderes vorstellen
    ich machs ja auch so. und wenn er nichts macht, dann kann es eigentlich nur heißen das er nicht auf dem DC malst auf dem du malen willst *vermut*



  • Hallo Red Skall,
    ich habe mir die Funktion DrawTransparent noch einmal eingehend zu Gemüte geführt und dann implementiert. Auf einmal hat es funktioniert, obwohl ich soweit ich weiß nichts anders gemacht habe als vorher.
    Na ja Danke für deine Hilfe.
    Übrigens hab ich in der MSDN einen Beitrag zu genau zu diesem Transparentzeichnen gefunden. Falls es dich interessiert, versuch es mal mit dem STichwort transparent.
    Turbobrain 😃



  • ach so. verstehe. in der funktion werden in schreitt 2 die bilder ohne transparenz dargestellt (maske). kann mann vielleicht versuchen so die "wirklichen" maße rauszukriegen

    danke 😃


Anmelden zum Antworten