如何通过 Bitmap::GetHBITMAP 将位图转换为带有 alpha 的 HBITMAP?
Posted
技术标签:
【中文标题】如何通过 Bitmap::GetHBITMAP 将位图转换为带有 alpha 的 HBITMAP?【英文标题】:How to convert Bitmap to HBITMAP with alpha via Bitmap::GetHBITMAP? 【发布时间】: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® 的副本。
【参考方案1】:
解决
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)
BITMAP btm;
GetObject(bm,sizeof(BITMAP),&btm)
BLENDFUNCTION bf
//initialize bf
AlphaBlend(hdcc,x,y,cx,cy,his->hdcc,0,0,btm.bmWidth,btm.bmHeight,bf);
;
;
Imagee *image;
void render()
for(;;)
//здесь я загружая через гди+ битмам, конвертирую его в хбитмап, записывая в перменную HBITMAP hbm
if(image==0)
image=new Imagee(hdc_mem, hbm, x, y и т.д.);
image->draw(hdc_mem, x, y и т.д.);
StretchBlt(hdc_main,0,0,1920,1080,hdc_mem,0,0,1920,1080,SRCCOPY); //hdc_main главный дс, hdc_mem буфер
感谢 ru.***.com
【讨论】:
以上是关于如何通过 Bitmap::GetHBITMAP 将位图转换为带有 alpha 的 HBITMAP?的主要内容,如果未能解决你的问题,请参考以下文章