¿Cómo crear un Gdiplus :: Bitmap desde un HBITMAP, reteniendo la información del canal alfa?

Cuando creo un nuevo Gdiplus :: Bitmap usando la función Bitmap :: FromHBITMAP, el Bitmap resultante es opaco: no se conserva ninguna de la transparencia parcial del HBITMAP original.

¿Hay una manera de crear un Gdiplus :: Bitmap desde un HBITMAP que traiga los datos del canal alfa?

Creo que el código de trabajo es más útil que las instrucciones, así que:

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

Resulta que GDI + nunca atraviesa el canal alfa al crear un bitmap desde un HBITMAP.

La respuesta es:

  • Utilice GetObject pasando en un BITMAP y el HBITMAP, para obtener el ancho y la altura (y si el bitmap de entrada es un DIB, los datos de píxeles) de la entrada HBITMAP.
  • Cree un bitmap del tamaño correcto con el formato de píxeles PARGB de 32 bits.
  • Use LockBits para controlar la memoria de datos de píxeles de su nuevo bitmap.
  • Si obtuvo los píxeles de GetObject, copie los valores ARGB utilizando memcpy.
  • Llame a UnlockBits en el nuevo bitmap.

En mi caso, el formato de la entrada HBITMAP es correcto para hacer un memcpy directo de los datos de píxeles de bitmap de entrada a los nuevos datos de píxeles de bitmap.

Si no obtuvo los datos de píxeles de entrada de GetObject, use GetDIBits para obtener una copia en el formato correcto.