如何用GDI +绘制透明的BMP

时间:2012-07-27 08:49:04

标签: c++ transparency gdi+ bmp

我正在编辑一些旧的GDI代码以使用GDI +,并且在绘制具有透明背景的BMP文件时遇到了问题。旧的GDI代码没有使用任何明显的额外代码来绘制背景透明,所以我想知道如何使用GDI +实现这一点。

我目前的代码如下所示

HINSTANCE hinstance = GetModuleHandle(NULL);
bmp = Gdiplus::Bitmap::FromResource(hinstance, MAKEINTRESOURCEW(IDB_BMP));
Gdiplus::Graphics graphics(pDC->m_hDC);
graphics.DrawImage(&bmp, posX, posY);

我还尝试使用clone方法从资源创建一个新的位图,并将位图绘制到新创建的位图,但都没有帮助。两次我都使用PixelFormat32bppPARGB。

然后我尝试使用alpha混合,但这样整个图像变得透明,而不仅仅是背景:

Gdiplus::ColorMatrix clrMatrix = { 
    1.0f, 0.0f, 0.0f, 0.0f, 0.0f,
    0.0f, 1.0f, 0.0f, 0.0f, 0.0f,
    0.0f, 0.0f, 1.0f, 0.0f, 0.0f,
    0.0f, 0.0f, 0.0f, 0.5f, 0.0f,
    0.0f, 0.0f, 0.0f, 0.0f, 1.0f
};

Gdiplus::ImageAttributes imgAttr;
imgAttr.SetColorMatrix(&clrMatrix);

graphics.DrawImage(&bmp, destRect, 0, 0, width(), height(), Gdiplus::UnitPixel, &imgAttr);

透明度信息已包含在图像中,但我不知道如何在绘制图像时应用它。如何实现这一目标?

3 个答案:

答案 0 :(得分:1)

最简单的解决方案是使用除BMP之外的某种格式。

您需要包含alpha数据的位,并且您需要Bitmap采用具有alpha数据的格式。当您使用GDI +加载BMP时,即使BMP具有Alpha通道,它也将始终使用不带alpha的格式。我相信数据存在于图像位中,但它没有被使用。

克隆或绘制到PixelFormat32bppPARGB位图时的问题是GDI +会将图像数据转换为新格式,这意味着丢弃alpha数据。

假设它正确加载了这些位,你需要做的是将这些位直接复制到另一个具有正确格式的位图。您可以使用Bitmap::LockBitsBitmap::UnlockBits执行此操作。 (确保使用其原生像素格式锁定每个位图,以便不进行转换。)

答案 1 :(得分:1)

迟到的回答但是:

ImageAttributes imAtt;    
imAtt.SetColorKey(Color(255,255,255), Color(255,255,255), ColorAdjustTypeBitmap);  

white (255,255,255)透明放在您使用此图像属性的任何位图上。

答案 2 :(得分:0)

我遇到了同样的问题。透明BMP未正确显示,遗憾的是,PNG无法直接从资源加载(除非添加了相当多的代码,将它们复制到流中并从流中加载它们)。我想避免这个代码。
我使用的位图也只使用两种颜色(背景和徽标)。拥有alpha通道意味着我需要使用更高的颜色深度而不是仅仅2位颜色深度来保存它们。

Evan的答案正是我一直在寻找: - )

我使用左上角像素的颜色作为透明色,而不是白色:

Gdiplus::Color ColourOfTopLeftPixel;
Gdiplus::Status eStatus = m_pBitmap->GetPixel(0, 0, &ColourOfTopLeftPixel);
_ASSERTE(eStatus == Gdiplus::Ok);

// The following makes every pixel with the same colour as the top left pixel (ColourOfTopLeftPixel) transparent.
Gdiplus::ImageAttributes ImgAtt;
ImgAtt.SetColorKey(ColourOfTopLeftPixel, ColourOfTopLeftPixel, Gdiplus::ColorAdjustTypeBitmap);