verkleinertes bit mit StretchBlt(): transparente farbe zu sehen !?



  • ich zeiche ein bitmap auf einen DC mit der StretchBlt(), benutzte die "True Mask" methode, also kurzform:

    cDC->StretchBlt(iPosX, iPosY, iWidth, iHight, &dcImage, iSrcPosX, iSrcPosY, iSrcWidth, iSrcHight, SRCINVERT); 
    		cDC->StretchBlt(iPosX, iPosY, iWidth, iHight, &dcTrans, iSrcPosX, iSrcPosY, iSrcWidth, iSrcHight, SRCAND);
    		cDC->StretchBlt(iPosX, iPosY, iWidth, iHight, &dcImage, iSrcPosX, iSrcPosY, iSrcWidth, iSrcHight, SRCINVERT);
    

    wenn ich das bild vergrößere wird es ganz normnal abgebildet. wenn ich es aber verkleinere, dann wird am rechten und unteren rand die transparente farbe sichtbar (je kleiner das bild, desto größer die fläche der transparenten farbe).

    ich habe schon geprüft, das durch die verkleinerung in bild andere farbwerte entstehen, dann wärs klar das die transparente farbe abgebildet wird. ist aber nicht so.

    aber woran kann es dann liegen ?



  • Vielleicht kann man dir eher helfen, wenn du mal die True Mask Methode beschreibst oder nen Link hinzufügst. Google, Wiki kennen die bei mir nicht. 😉
    Sieht aber interessant aus.



  • oh osrry, ich dachte die währe ziemlich bekannt 😉

    also das hier ist die funktion die ich benutzte und etwas erweitert habe:

    void CXTGlobal::BltTransparentBitmap(CDC *cDC, CBitmap *bBitmap, int iPosX, int iPosY, int iWidth, int iHight, COLORREF cTransparent, UINT uFlags, int iBmpWidth, int iBmpHeight)
    {
    	COLORREF	crOldBack = cDC->SetBkColor(RGB(255, 255, 255)); 
    	COLORREF	crOldText = cDC->SetTextColor(RGB(0, 0, 0));
    	CDC			dcImage, dcTrans; 
    	CBitmap		*pOldBitmapImage, *pOldBitmapTrans, bitmapTrans;
    
    	// Create two memory dcs for the image and the mask 
    	dcImage.CreateCompatibleDC(cDC); 
    	dcTrans.CreateCompatibleDC(cDC); 
    
    	// Select the image into the appropriate dc 
    	pOldBitmapImage = dcImage.SelectObject(bBitmap);
    
    	// Create the mask bitmap 
    	bitmapTrans.CreateBitmap(iWidth, iHight, 1, 1, NULL); 
    
    	// Select the mask bitmap into the appropriate dc 
    	pOldBitmapTrans = dcTrans.SelectObject(&bitmapTrans); 
    
    	// Build mask based on transparent colour 
    	dcImage.SetBkColor(cTransparent); 
    	dcTrans.BitBlt(0, 0, iWidth, iHight, &dcImage, 0, 0, SRCCOPY); 
    
    	// Do the work - True Mask method - cool if not actual display 
    	if (uFlags & BTB_STRETCH)
    	{
    		CRect rPosition;
    
    		if ((iBmpWidth == -1) && (iBmpHeight == -1))
    		{
    			iBmpWidth	= iWidth;
    			iBmpHeight	= iHight;
    		}
    
    		rPosition.left		= (uFlags & BTB_FLIP_HORIZONTAL) ? (iBmpWidth - 1) : (0);
    		rPosition.right		= (uFlags & BTB_FLIP_HORIZONTAL) ? (-iBmpWidth) : (iBmpWidth);
    		rPosition.top		= (uFlags & BTB_FLIP_VERTICAL) ? (iBmpHeight - 1) : (0);
    		rPosition.bottom	= (uFlags & BTB_FLIP_VERTICAL) ? (-iBmpHeight) : (iBmpHeight);
    
    		cDC->StretchBlt(iPosX, iPosY, iWidth, iHight, &dcImage, rPosition.left, rPosition.top, rPosition.right, rPosition.bottom, SRCINVERT); 
    		cDC->StretchBlt(iPosX, iPosY, iWidth, iHight, &dcTrans, rPosition.left, rPosition.top, rPosition.right, rPosition.bottom, SRCAND);
    		cDC->StretchBlt(iPosX, iPosY, iWidth, iHight, &dcImage, rPosition.left, rPosition.top, rPosition.right, rPosition.bottom, SRCINVERT);
    	}
    	else
    	{
    		dcTrans.BitBlt(0, 0, iWidth, iHight, &dcImage, 0, 0, SRCCOPY); 
    
    		cDC->BitBlt(iPosX, iPosY, iWidth, iHight, &dcImage, 0, 0, SRCINVERT); 
    		cDC->BitBlt(iPosX, iPosY, iWidth, iHight, &dcTrans, 0, 0, SRCAND);
    		cDC->BitBlt(iPosX, iPosY, iWidth, iHight, &dcImage, 0, 0, SRCINVERT); 
    	}
    
    	// Restore settings 
    	dcImage.SelectObject(pOldBitmapImage); 
    	dcTrans.SelectObject(pOldBitmapTrans); 
    
    	cDC->SetBkColor(crOldBack); 
    	cDC->SetTextColor(crOldText);
    }
    

    erklärung:
    man kann die funktion benutzen um bitmaps "normal" auf einen DC zu malen indem man den parameter BTB_STRETCH für 'uFlags' nicht verwendet, das währe dann die normale funktion.

    int iPosX, int iPosY, int iWidth, int iHight sind die position und größe für das zu zeichnende bild.

    cTransparent ist die farbe im bitmap die nicht abgebildet werden soll, also die transparente farbe.

    wenn das bild gestrecht werden soll kann man die parameter int iBmpWidth, int iBmpHeight verwenden. die geben die originalmaße des bitmaps an. durch int iWidth, int iHight wird das bild dann vergrößert oder verkleinert.



  • Danke für deine Erklärung. Ich hatte das doch schon mal wo gesehen (aber nicht unter diesem Namen und ich hatte es auch nicht verstanden :)). In der CxSkinButton - Klasse von CodeProject.
    Hatte erst vermutet, dass es an den SCRINVERT, etc liegt.

    Da du aber geschrieben hast, dass am rechten und unteren Rand die Farbe sichtbar wird, vermute ich mal, dass du rposition.right und rposition.width nicht richtig berechnest.
    Du gibst ja an

    rposition.right =  (uFlags & BTB_FLIP_HORIZONTAL) ? (-iBmpWidth) : (iBmpWidth);
    

    Meiner Meinung nach darfst du nicht iBmpWidth nehmen, sondern
    (iBmpWidth-iBmpLeft).
    Bei rposition.bottom dann (iBmpHeight - iBmpTop).

    [EDIT] iBmpLeft == Linke Koordinte der Position des Bildes
    iBmpTop == Koordinate der oberen Position des Bildes [/Edit]
    Oder sehe ich das falsch?

    Hoffentlich war das kein Mist!

    Gruß,
    Paul.
    😉



  • doch tust du ^^

    nein schertz natürlich 😉

    ich benutze die funktion nur manchmal zum spiegeln. aber wenn dann klappt es 100%.

    aber ich benutze hier die originalmaße. also nichts mit spiegeln.



  • Hilft dir das vielleicht weiter?

    http://xprofan.mxii.com/xprofan/p/probleme-beim-verkleinern-und-blur-hcdA.html
    (ziemlich nach unten scrollen)

    http://msdn.microsoft.com/library/default.asp?url=/library/en-us/gdi/bitmaps_6cth.asp

    Ich such selbst gerade in der Ecke, weil schon das MS Beispielprogramm solche Effekte beim Verkleinern vorführt....



  • meinst du es liegt an den übergebenen flags ?

    soryy kann gerade nicht testen, mache ich ber noch.



  • oh hatte es falsch verstanden.

    habe mit SetStretchBltMode() experimentiert. aber es hat nichts geholfen. da muss man doch was machen können.



  • habs jetzt geschafft. das problem lag an den verwendeten größen. hier noch mal die verbesserte version:

    void CXTGlobal::BltTransparentBitmap(CDC *cDC, CBitmap *bBitmap, int iPosX, int iPosY, int iWidth, int iHight, COLORREF cTransparent, UINT uFlags, int iBmpWidth, int iBmpHeight)
    {
    	COLORREF	crOldBack = cDC->SetBkColor(RGB(255, 255, 255)); 
    	COLORREF	crOldText = cDC->SetTextColor(RGB(0, 0, 0));
    	CDC			dcImage, dcTrans; 
    	CBitmap		*pOldBitmapImage, *pOldBitmapTrans, bitmapTrans;
    	CRect		rStretchPos;
    
    	// Create two memory dcs for the image and the mask 
    	dcImage.CreateCompatibleDC(cDC); 
    	dcTrans.CreateCompatibleDC(cDC); 
    
    	// Select the image into the appropriate dc 
    	pOldBitmapImage = dcImage.SelectObject(bBitmap);
    
    	// Build mask based on transparent colour 
    	dcImage.SetBkColor(cTransparent); 
    
    	if (uFlags & BTB_STRETCH)
    	{
    		if ((iBmpWidth == -1) && (iBmpHeight == -1))
    		{
    			iBmpWidth	= iWidth;
    			iBmpHeight	= iHight;
    		}
    
    		rStretchPos.left	= (uFlags & BTB_FLIP_HORIZONTAL) ? (iBmpWidth - 1) : (0);
    		rStretchPos.right	= (uFlags & BTB_FLIP_HORIZONTAL) ? (-iBmpWidth) : (iBmpWidth);
    		rStretchPos.top		= (uFlags & BTB_FLIP_VERTICAL) ? (iBmpHeight - 1) : (0);
    		rStretchPos.bottom	= (uFlags & BTB_FLIP_VERTICAL) ? (-iBmpHeight) : (iBmpHeight);
    	}
    
    	// Is the picture wanted to be smaller?
    	if ((uFlags & BTB_STRETCH) && (iBmpWidth != -1) && (iBmpHeight != -1) && ((iWidth < iBmpWidth) || (iHight < iBmpHeight)))
    	{
    		CRect rNormal;
    
    		// Mirror normal Size, too
    		rNormal.left	= (uFlags & BTB_FLIP_HORIZONTAL) ? (iWidth - 1) : (0);
    		rNormal.right	= (uFlags & BTB_FLIP_HORIZONTAL) ? (-iWidth) : (iWidth);
    		rNormal.top		= (uFlags & BTB_FLIP_VERTICAL) ? (iHight - 1) : (0);
    		rNormal.bottom	= (uFlags & BTB_FLIP_VERTICAL) ? (-iHight) : (iHight);
    
    		// Create the mask bitmap 
    		bitmapTrans.CreateBitmap(iBmpWidth, iBmpHeight, 1, 1, NULL); 
    
    		// Select the mask bitmap into the appropriate dc 
    		pOldBitmapTrans = dcTrans.SelectObject(&bitmapTrans); 
    
    		dcTrans.StretchBlt(0, 0, iWidth, iHight, &dcImage, 0, 0, iBmpWidth, iBmpHeight, SRCCOPY); 
    
    		cDC->StretchBlt(iPosX, iPosY, iWidth, iHight, &dcImage, rStretchPos.left, rStretchPos.top, rStretchPos.right, rStretchPos.bottom, SRCINVERT); 
    		cDC->StretchBlt(iPosX, iPosY, iWidth, iHight, &dcTrans, rNormal.left, rNormal.top, rNormal.right, rNormal.bottom, SRCAND);
    		cDC->StretchBlt(iPosX, iPosY, iWidth, iHight, &dcImage, rStretchPos.left, rStretchPos.top, rStretchPos.right, rStretchPos.bottom, SRCINVERT);
    	}
    	else
    	{
    		// Create the mask bitmap 
    		bitmapTrans.CreateBitmap(iWidth, iHight, 1, 1, NULL); 
    
    		// Select the mask bitmap into the appropriate dc 
    		pOldBitmapTrans = dcTrans.SelectObject(&bitmapTrans); 
    
    		dcTrans.BitBlt(0, 0, iWidth, iHight, &dcImage, 0, 0, SRCCOPY); 
    
    		if (uFlags & BTB_STRETCH)
    		{
    			cDC->StretchBlt(iPosX, iPosY, iWidth, iHight, &dcImage, rStretchPos.left, rStretchPos.top, rStretchPos.right, rStretchPos.bottom, SRCINVERT); 
    			cDC->StretchBlt(iPosX, iPosY, iWidth, iHight, &dcTrans, rStretchPos.left, rStretchPos.top, rStretchPos.right, rStretchPos.bottom, SRCAND);
    			cDC->StretchBlt(iPosX, iPosY, iWidth, iHight, &dcImage, rStretchPos.left, rStretchPos.top, rStretchPos.right, rStretchPos.bottom, SRCINVERT);
    		}
    		else
    		{
    			cDC->BitBlt(iPosX, iPosY, iWidth, iHight, &dcImage, 0, 0, SRCINVERT); 
    			cDC->BitBlt(iPosX, iPosY, iWidth, iHight, &dcTrans, 0, 0, SRCAND);
    			cDC->BitBlt(iPosX, iPosY, iWidth, iHight, &dcImage, 0, 0, SRCINVERT); 
    		}
    	}
    
    	// Restore settings 
    	dcImage.SelectObject(pOldBitmapImage); 
    	dcTrans.SelectObject(pOldBitmapTrans); 
    
    	cDC->SetBkColor(crOldBack); 
    	cDC->SetTextColor(crOldText);
    }
    

    EDIT:
    hatte stretchen nicht berücksichtigt, jetzt passt aber alles


Anmelden zum Antworten