如何通过 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?的主要内容,如果未能解决你的问题,请参考以下文章

如何通过 Chrome 扩展将 CSS 注入网页?

如何通过变量/方法将Django模板代码注入模板?

如何通过传入连接将手机与计算机连接?

如何通过javascript将日期转换为毫秒? [复制]

如何通过jquery将表单数据与图像一起传递? [复制]

如何通过反射将参数传递给方法