How to Create a Gdiplus::Bitmap from an HBITMAP, retaining the alpha channel information?

久未见 提交于 2019-12-18 06:08:44

问题


When I create a new Gdiplus::Bitmap using the Bitmap::FromHBITMAP function, the resulting Bitmap is opaque - none of the partial transparency from the original HBITMAP is preserved.

Is there a way to create a Gdiplus::Bitmap from an HBITMAP which brings across the alpha channel data?


回答1:


I think working code is more useful than instructions, so:

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



回答2:


It turns out that GDI+ never brings across the alpha channel when creating a Bitmap from an HBITMAP.

The answer is to:

  • Use GetObject passing in a BITMAP and the HBITMAP, to get the width and height (and if the input bitmap is a DIB, the pixel data) of the input HBITMAP.
  • Create a Bitmap of the correct size with 32 bit PARGB pixel format.
  • Use LockBits to get hold of the pixelData memory of your new Bitmap.
  • If you got the pixels from GetObject, copy the ARGB values across using memcpy.
  • Call UnlockBits on the new Bitmap.

In my case, the format of the input HBITMAP is correct for doing a straight memcpy from input bitmap pixel data to the new Bitmap pixel data.

If you didnt get the input pixel data from GetObject, use GetDIBits to get a copy in the correct format.



来源:https://stackoverflow.com/questions/335273/how-to-create-a-gdiplusbitmap-from-an-hbitmap-retaining-the-alpha-channel-inf

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!