C++ 如何从HBITMAP创建Gdiplus::位图,保留alpha通道信息?

C++ 如何从HBITMAP创建Gdiplus::位图,保留alpha通道信息?,c++,gdi+,bitmap,gdi,C++,Gdi+,Bitmap,Gdi,当我使用Bitmap::FromHBITMAP函数创建一个新的Gdiplus::Bitmap时, 生成的位图是不透明的-原始HBITMAP中的部分透明度不保留 有没有一种方法可以从HBITMAP创建一个Gdiplus::位图,该位图可以跨越alpha通道数据?事实证明,从HBITMAP创建位图时,GDI+从来不会跨越alpha通道 答案是: 使用GetObject传入位图和HBITMAP,以获取输入HBITMAP的宽度和高度(如果输入位图是DIB,则为像素数据) 使用32位PARGB像素格式创

当我使用Bitmap::FromHBITMAP函数创建一个新的Gdiplus::Bitmap时, 生成的位图是不透明的-原始HBITMAP中的部分透明度不保留


有没有一种方法可以从HBITMAP创建一个Gdiplus::位图,该位图可以跨越alpha通道数据?

事实证明,从HBITMAP创建位图时,GDI+从来不会跨越alpha通道

答案是:

  • 使用GetObject传入位图和HBITMAP,以获取输入HBITMAP的宽度和高度(如果输入位图是DIB,则为像素数据)
  • 使用32位PARGB像素格式创建正确大小的位图
  • 使用锁定位获取新位图的像素数据内存
  • 如果从GetObject获得像素,请使用memcpy跨多个对象复制ARGB值
  • 调用新位图上的解锁位
在我的例子中,输入HBITMAP的格式对于从输入位图像素数据到新位图像素数据进行直接memcpy是正确的


如果没有从GetObject获取输入像素数据,请使用GetDIBits以正确的格式获取副本。

我认为工作代码比指令更有用,因此:

#include <GdiPlus.h>
#include <memory>

Gdiplus::Status HBitmapToBitmap( HBITMAP source, Gdiplus::PixelFormat pixel_format, Gdiplus::Bitmap** result_out )
{
  BITMAP source_info = { 0 };
  if( !::GetObject( source, sizeof( source_info ), &source_info ) )
    return Gdiplus::GenericError;

  Gdiplus::Status s;

  std::auto_ptr< Gdiplus::Bitmap > target( new Gdiplus::Bitmap( source_info.bmWidth, source_info.bmHeight, pixel_format ) );
  if( !target.get() )
    return Gdiplus::OutOfMemory;
  if( ( s = target->GetLastStatus() ) != Gdiplus::Ok )
    return s;

  Gdiplus::BitmapData target_info;
  Gdiplus::Rect rect( 0, 0, source_info.bmWidth, source_info.bmHeight );

  s = target->LockBits( &rect, Gdiplus::ImageLockModeWrite, pixel_format, &target_info );
  if( s != Gdiplus::Ok )
    return s;

  if( target_info.Stride != source_info.bmWidthBytes )
    return Gdiplus::InvalidParameter; // pixel_format is wrong!

  CopyMemory( target_info.Scan0, source_info.bmBits, source_info.bmWidthBytes * source_info.bmHeight );

  s = target->UnlockBits( &target_info );
  if( s != Gdiplus::Ok )
    return s;

  *result_out = target.release();

  return Gdiplus::Ok;
}
#包括
#包括
Gdiplus::Status HBitmapToBitmap(HBITMAP源,Gdiplus::PixelFormat像素_格式,Gdiplus::位图**结果_输出)
{
位图源信息={0};
if(!::GetObject(source、sizeof(source\u info)和source\u info))
返回Gdiplus::GenericError;
Gdiplus::状态s;
std::auto_ptrtarget(新的Gdiplus::Bitmap(source_info.bmWidth、source_info.bmHeight、pixel_格式));
如果(!target.get())
返回Gdiplus::OutOfMemory;
如果((s=target->GetLastStatus())!=Gdiplus::Ok)
返回s;
Gdiplus::BitmapData目标信息;
Gdiplus::Rect Rect(0,0,source_info.bmWidth,source_info.bmHeight);
s=target->LockBits(&rect,Gdiplus::ImageLockModeWrite,pixel_格式,&target_信息);
如果(s!=Gdiplus::Ok)
返回s;
if(target_info.Stride!=source_info.bmWidthBytes)
返回Gdiplus::InvalidParameter;//像素_格式错误!
CopyMemory(target_info.Scan0、source_info.bmBits、source_info.bmWidthBytes*source_info.bmHeight);
s=目标->解锁位(&target\u info);
如果(s!=Gdiplus::Ok)
返回s;
*结果_out=target.release();
返回Gdiplus::Ok;
}

您是否确定HBITMAP有一个alpha通道可供启动?例如,您是否使用BI_RGB和32bpp或其他方式将其创建为DIB?是的,它确实具有透明度。它使用::AlphaBlend()函数绘制得很好。(我在C中创建了它#使用新位图(字符串文件名)和.NET位图对象上的调用GetHBitmap())我在
CBitmap
中遇到了类似的问题,我从中检索了
HBITMAP
。在这种情况下,
::GetObject()
left
source\u info.bmBits
设置为NULL。我可以通过调用
myCBitmapPtr->getBitmappits(source\u info.bmWidthBytes*source\u info.bmHeight,target\u info.Scan0)
来解决这个问题。顺便说一句,返回值在您的示例中得到了很好的检查,但是如果
source\u info.bmBits
为空,那么对
copymorry()的调用中存在访问冲突。