【问题标题】:How to Create a Gdiplus::Bitmap from an HBITMAP, retaining the alpha channel information?如何从 HBITMAP 创建 Gdiplus::Bitmap,保留 alpha 通道信息?
【发布时间】:2010-09-25 00:25:00
【问题描述】:

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

有没有办法从 HBITMAP 创建一个 Gdiplus::Bitmap,它会带来 alpha 通道数据?

【问题讨论】:

  • 你确定 HBITMAP 有一个 alpha 通道开始吗?例如,您是否将其创建为具有 BI_RGB 和 32bpp 或其他方式的 DIB?
  • 是的,它确实具有透明度。它使用 ::AlphaBlend() 函数绘制得很好。
  • (我在 C# 中使用 new Bitmap(string filename) 和在 .NET 位图对象上调用 GetHBitmap() 创建了它)

标签: c++ gdi+ bitmap gdi


【解决方案1】:

我认为工作代码比指令更有用,所以:

#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;
}

【讨论】:

  • 我遇到了与CBitmap 类似的问题,我从中检索到了HBITMAP。在这种情况下,::GetObject()source_info.bmBits 设置为 NULL。我可以通过调用myCBitmapPtr-&gt;GetBitmapBits(source_info.bmWidthBytes * source_info.bmHeight, target_info.Scan0) 来解决这个问题
  • 顺便说一句,在您的示例中很好地检查了返回值,但如果 source_info.bmBits 为 NULL,则在对 CopyMemory() 的调用中存在访问冲突。
【解决方案2】:

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

答案是:

  • 使用 GetObject 传入 BITMAP 和 HBITMAP,获取输入 HBITMAP 的宽度和高度(如果输入位图是 DIB,则为像素数据)。
  • 使用 32 位 PARGB 像素格式创建大小正确的位图。
  • 使用 LockBits 获取新位图的 pixelData 内存。
  • 如果您从 GetObject 获取像素,请使用 memcpy 复制 ARGB 值。
  • 在新位图上调用 UnlockBits。

在我的例子中,输入 HBITMAP 的格式对于从输入位图像素数据到新位图像素数据的直接 memcpy 是正确的。

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

【讨论】:

    猜你喜欢
    • 2019-01-03
    • 2018-11-20
    • 2018-02-04
    • 1970-01-01
    • 2010-09-24
    • 2012-09-08
    • 2011-06-05
    • 2018-04-25
    • 2012-01-02
    相关资源
    最近更新 更多