【发布时间】:2018-04-25 03:23:47
【问题描述】:
我需要绘制具有透明度的 PNG 图像。我使用 GDI、GDI+ 和 WinApi。
为了加载和绘制图像,我一直使用 GDI+,但现在我使用更多“原生”GDI 算法(StretchBlt 等)。
问题是 GDI 无法加载 PNG。我在网上搜索了两种方法:
- 通过 GDI+ 加载
- 使用 WIC。
WIC 似乎太难了(但我期待什么?),所以我选择了第一个。
使用 GDI+ 加载 PNG 图像很容易,只需创建一个 Bitmap 对象,将文件路径传递给构造函数,然后调用 getHBITMAP() 方法接收 HBITMAP 句柄,仅此而已。
问题是Bitmap产生的HBITMAP失去了透明度。
我搜索了如何解决它。有不同的方法 - 例如将Color::Black 作为第一个参数传递等。但它不起作用。
那么,如何加载 PNG 图像并将其转换为具有透明度的 HBITMAP?
我不使用 DrawImage 方法,因为它很慢,GDI 更快
我固定了代码:
我理解我的错误:我必须先将 hdc_mem blit 到 hdcc,然后再对图像进行 blit。我已经做到了,但我有一个新问题¬_¬
我做了一个类来管理上传的图片,这里是代码:
class Imagee
{
HDC hdc; HBITMAP bm;
Imagee(HDC hdc, HBITMAP bm, another args)
{
this->hdc=CreateCompatibleDC(hdc);
this->bm=bm;
SelectObject(this->hdc,this->bm);
}
void draw(int hdcc, int x,int y, int cx, int cy)
{
**StretchBlt(this->hdc,0,0,cx,cy,hdcc,x,y,cx,cy,SRCCOPY); //I'VE ADDED THIS
SelectObject(this->hdc,this->bm); //AND THIS **
StretchBlt(this->hdcc,x,y,cx,cy,hdc,0,0,cx,cy,SRCCOPY);
};
};
Imagee *image;
void render()
{
for(;;)
{
//some draws
//Loading a bitmap via Gdi+, calling a GetHBITMAP function, HBITMAP variable named hbm
if(image==0)
image=new Imagee(hdc_mem, hbm, x, y etc..);
image->draw(hdc_mem, x, y etc..);
StretchBlt(hdc_main,0,0,1920,1080,hdc_mem,0,0,1920,1080,SRCCOPY);
}
我有一个黑屏。看来我不能再调用 SelectObject 了,是吗?
【问题讨论】:
-
为什么需要借助 GDI 进行绘图?您可以为
HDC创建一个Graphics对象,然后将Bitmap传递给Graphics::DrawImage()。请参阅 GDI+ 文档中的 Loading and Displaying Bitmaps。如果您必须求助于 GDI,请参阅 How would I load a PNG image using Win32/GDI (no GDI+ if possible)?。 -
GDI+ 将绘制透明的 png。你还没有表明你有什么问题。 GDI 函数不理解 alpha,但您可以使用
GetHBITMAP(Gdiplus::Color::Transparent, &hBitmap)处理一些特殊情况。 -
@Remy Lebeau Gdi 比 DrawImage 方法更快地绘制图像
-
@Barmak Shemirani 我也试过 Color::Transparent,但没用(我的意思是没有透明度)
-
SRCCOPY不执行 Alpha 混合。一个简单的块传输(SRCCOPY所做的)比 alpha 混合快 很多。鉴于代码,尚不清楚您真正需要什么。代码(如其格式)被严重破坏。获取 Petzold 的Programming Windows® 的副本。