Как создать Gdiplus :: Bitmap из HBITMAP, сохраняя информацию альфа-канала? - PullRequest
7 голосов
/ 02 декабря 2008

Когда я создаю новый Gdiplus :: Bitmap, используя функцию Bitmap :: FromHBITMAP, результирующий точечный рисунок непрозрачен - ни одна из частичных прозрачностей из исходного HBITMAP не сохраняется.

Есть ли способ создать Gdiplus :: Bitmap из HBITMAP, который переносит данные альфа-канала?

Ответы [ 2 ]

11 голосов
/ 02 мая 2011

Мне кажется, рабочий код более полезен, чем инструкции, поэтому:

#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;
}
5 голосов
/ 05 декабря 2008

Оказывается, что GDI + никогда не переносит альфа-канал при создании растрового изображения из HBITMAP.

Ответ:

  • Используйте GetObject, передавая BITMAP и HBITMAP, чтобы получить ширину и высоту (и, если входной битовый массив представляет собой DIB, данные пикселей) входного HBITMAP.
  • Создание растрового изображения правильного размера с 32-битным пиксельным форматом PARGB.
  • Используйте LockBits для захвата памяти pixelData вашего нового растрового изображения.
  • Если вы получили пиксели из GetObject, скопируйте значения ARGB через memcpy.
  • Вызовите UnlockBits на новом растровом изображении.

В моем случае формат входного HBITMAP является правильным для выполнения прямой memcpy из входных данных растрового пикселя в новые данные растрового пикселя.

Если вы не получили данные входных пикселей из GetObject, используйте GetDIBits, чтобы получить копию в правильном формате.

...